@@ -611,6 +611,13 @@ trait NameKeyExt {
611
611
FunctionOrigin :: EntryPoint ( idx) => NameKey :: EntryPointLocal ( idx, local_handle) ,
612
612
}
613
613
}
614
+
615
+ fn oob_local ( origin : FunctionOrigin , ty : Handle < crate :: Type > ) -> NameKey {
616
+ match origin {
617
+ FunctionOrigin :: Handle ( handle) => NameKey :: FunctionOobLocal ( handle, ty) ,
618
+ FunctionOrigin :: EntryPoint ( idx) => NameKey :: EntryPointOobLocal ( idx, ty) ,
619
+ }
620
+ }
614
621
}
615
622
616
623
impl NameKeyExt for NameKey { }
@@ -721,6 +728,11 @@ impl<'a> ExpressionContext<'a> {
721
728
index:: bounds_check_iter ( chain, self . module , self . function , self . info )
722
729
}
723
730
731
+ /// See docs for `proc::index::oob_locals`.
732
+ fn oob_locals ( & self ) -> FastHashSet < Handle < crate :: Type > > {
733
+ index:: oob_locals ( self . module , self . function , self . info , self . policies )
734
+ }
735
+
724
736
fn get_packed_vec_kind ( & self , expr_handle : Handle < crate :: Expression > ) -> Option < crate :: Scalar > {
725
737
match self . function . expressions [ expr_handle] {
726
738
crate :: Expression :: AccessIndex { base, index } => {
@@ -928,7 +940,18 @@ impl<W: Write> Writer<W> {
928
940
Ok ( ( ) )
929
941
}
930
942
943
+ /// Writes the local variables of the given function, as well as any extra
944
+ /// out-of-bounds locals that are needed.
945
+ ///
946
+ /// The names of the OOB locals are also added to `self.names` at the same
947
+ /// time.
931
948
fn put_locals ( & mut self , context : & ExpressionContext ) -> BackendResult {
949
+ let oob_locals = context. oob_locals ( ) ;
950
+ for & ty in oob_locals. iter ( ) {
951
+ let name_key = NameKey :: oob_local ( context. origin , ty) ;
952
+ self . names . insert ( name_key, self . namer . call ( "oob" ) ) ;
953
+ }
954
+
932
955
for ( name_key, ty, init) in context
933
956
. function
934
957
. local_variables
@@ -937,6 +960,10 @@ impl<W: Write> Writer<W> {
937
960
let name_key = NameKey :: local ( context. origin , local_handle) ;
938
961
( name_key, local. ty , local. init )
939
962
} )
963
+ . chain ( oob_locals. iter ( ) . map ( |& ty| {
964
+ let name_key = NameKey :: oob_local ( context. origin , ty) ;
965
+ ( name_key, ty, None )
966
+ } ) )
940
967
{
941
968
let ty_name = TypeContext {
942
969
handle : ty,
@@ -1741,7 +1768,39 @@ impl<W: Write> Writer<W> {
1741
1768
{
1742
1769
write ! ( self . out, " ? " ) ?;
1743
1770
self . put_access_chain ( expr_handle, policy, context) ?;
1744
- write ! ( self . out, " : DefaultConstructible()" ) ?;
1771
+ write ! ( self . out, " : " ) ?;
1772
+
1773
+ if context. resolve_type ( base) . pointer_space ( ) . is_some ( ) {
1774
+ // We can't just use `DefaultConstructible` if this is a pointer.
1775
+ // Instead, we create a dummy local variable to serve as pointer
1776
+ // target if the access is out of bounds.
1777
+ let result_ty = context. info [ expr_handle]
1778
+ . ty
1779
+ . inner_with ( & context. module . types )
1780
+ . pointer_base_type ( ) ;
1781
+ let result_ty_handle = match result_ty {
1782
+ Some ( TypeResolution :: Handle ( handle) ) => handle,
1783
+ Some ( TypeResolution :: Value ( _) ) => {
1784
+ // I don't have a succinct argument why this is the case.
1785
+ // It's really up to what the source language lets you do
1786
+ // with pointers. Note that regular loads and stores don't
1787
+ // take this path -- they have dedicated code in `put_load`
1788
+ // and `put_store`.
1789
+ unreachable ! (
1790
+ "Expected type {result_ty:?} of access through pointer type {base:?} to be in the arena" ,
1791
+ ) ;
1792
+ }
1793
+ None => {
1794
+ unreachable ! (
1795
+ "Expected access through pointer type {base:?} to return a pointer, but got {result_ty:?}" ,
1796
+ )
1797
+ }
1798
+ } ;
1799
+ let name_key = NameKey :: oob_local ( context. origin , result_ty_handle) ;
1800
+ self . out . write_str ( & self . names [ & name_key] ) ?;
1801
+ } else {
1802
+ write ! ( self . out, "DefaultConstructible()" ) ?;
1803
+ }
1745
1804
1746
1805
if !is_scoped {
1747
1806
write ! ( self . out, ")" ) ?;
0 commit comments