@@ -1187,21 +1187,12 @@ def truncate_int_bits(value, signed, bits=64):
11871187 return value & mask
11881188
11891189class LValue (Expression ):
1190- "Somewhere to read or write data"
1190+ """An expression whose C representation is always an LValue, whose address
1191+ is always safe to take, in the sense that the duration that address
1192+ remains valid is intuitively predictable by the user"""
11911193 writable = True
1192-
1193- def write (self , source ):
1194- rt = realtype (self .ctype ())
1195- if isinstance (rt , TEndianInt ):
1196- return (f'{ rt .dmllib_fun ("copy" )} (&{ self .read ()} ,'
1197- + f' { source .read ()} )' )
1198- return '%s = %s' % (self .read (), source .read ())
1199-
1200- @property
1201- def is_stack_allocated (self ):
1202- '''Returns true only if it's known that writing to the lvalue will
1203- write to stack-allocated data'''
1204- return False
1194+ addressable = True
1195+ c_lval = True
12051196
12061197class IfExpr (Expression ):
12071198 priority = 30
@@ -2628,13 +2619,13 @@ def make_simple(cls, site, rh):
26282619 TPtr (TVoid ())],
26292620 TVoid ())))
26302621 if (compat .dml12_misc not in dml .globals .enabled_compat
2631- and not isinstance ( rh , LValue ) ):
2622+ and not rh . addressable ):
26322623 raise ERVAL (rh .site , '&' )
26332624 return AddressOf (site , rh )
26342625
26352626 @property
26362627 def is_pointer_to_stack_allocation (self ):
2637- return isinstance ( self . rh , LValue ) and self .rh .is_stack_allocated
2628+ return self .rh .is_stack_allocated
26382629
26392630def mkAddressOf (site , rh ):
26402631 if dml .globals .compat_dml12_int (site ):
@@ -2672,7 +2663,8 @@ def is_stack_allocated(self):
26722663
26732664 @property
26742665 def is_pointer_to_stack_allocation (self ):
2675- return isinstance (self .type , TArray ) and self .is_stack_allocated
2666+ return (isinstance (safe_realtype_shallow (self .type ), TArray )
2667+ and self .is_stack_allocated )
26762668
26772669mkDereference = Dereference .make
26782670
@@ -2794,7 +2786,7 @@ def mkUnaryPlus(site, rh):
27942786 rh , _ = promote_integer (rh , rhtype )
27952787 else :
27962788 raise ICE (site , "Unexpected arith argument to unary +" )
2797- if isinstance ( rh , LValue ) :
2789+ if rh . addressable or rh . writable :
27982790 # +x is a rvalue
27992791 rh = mkRValue (rh )
28002792 return rh
@@ -2820,7 +2812,7 @@ def make_simple(cls, site, rh):
28202812 rhtype = safe_realtype (rh .ctype ())
28212813 if not isinstance (rhtype , (IntegerType , TPtr )):
28222814 raise EINCTYPE (site , cls .op )
2823- if not isinstance ( rh , LValue ) :
2815+ if not rh . addressable :
28242816 if isinstance (rh , BitSlice ):
28252817 hint = 'try %s= 1' % (cls .base_op [0 ],)
28262818 else :
@@ -4586,11 +4578,13 @@ def read(self):
45864578
45874579mkStaticVariable = StaticVariable
45884580
4589- class StructMember (LValue ):
4581+ class StructMember (Expression ):
45904582 priority = 160
45914583 explicit_type = True
45924584 @auto_init
45934585 def __init__ (self , site , expr , sub , type , op ):
4586+ # Write of StructMembers rely on them being C lvalues
4587+ assert not expr .writable or expr .c_lval
45944588 assert_type (site , expr , Expression )
45954589 assert_type (site , sub , str )
45964590
@@ -4607,11 +4601,12 @@ def read(self):
46074601
46084602 @property
46094603 def is_stack_allocated (self ):
4610- return isinstance ( self . expr , LValue ) and self .expr .is_stack_allocated
4604+ return self .expr .is_stack_allocated
46114605
46124606 @property
46134607 def is_pointer_to_stack_allocation (self ):
4614- return isinstance (self .type , TArray ) and self .is_stack_allocated
4608+ return (isinstance (safe_realtype_shallow (self .type ), TArray )
4609+ and self .is_stack_allocated )
46154610
46164611def try_resolve_len (site , lh ):
46174612 if isinstance (lh , NonValue ):
@@ -4750,18 +4745,28 @@ def is_stack_allocated(self):
47504745
47514746 @property
47524747 def is_pointer_to_stack_allocation (self ):
4753- return isinstance (self .type , TArray ) and self .is_stack_allocated
4748+ return (isinstance (safe_realtype_shallow (self .type ), TArray )
4749+ and self .is_stack_allocated )
47544750
4755- class VectorRef (LValue ):
4751+ class VectorRef (Expression ):
47564752 slots = ('type' ,)
47574753 @auto_init
47584754 def __init__ (self , site , expr , idx ):
4755+ assert not expr .writable or expr .c_lval
47594756 self .type = realtype (self .expr .ctype ()).base
47604757 def read (self ):
47614758 return 'VGET(%s, %s)' % (self .expr .read (), self .idx .read ())
4762- def write (self , source ):
4763- return "VSET(%s, %s, %s)" % (self .expr .read (), self .idx .read (),
4764- source .read ())
4759+ # No need for write, VGET results in an lvalue
4760+
4761+ @property
4762+ def writable (self ):
4763+ return self .expr .writable
4764+ @property
4765+ def addressable (self ):
4766+ return self .expr .addressable
4767+ @property
4768+ def c_lval (self ):
4769+ return self .expr .c_lval
47654770
47664771def mkIndex (site , expr , idx ):
47674772 if isinstance (idx , NonValue ):
@@ -4835,7 +4840,7 @@ def read(self):
48354840
48364841 @property
48374842 def is_pointer_to_stack_allocation (self ):
4838- return (isinstance (self .type , TPtr )
4843+ return (isinstance (safe_realtype_shallow ( self .type ) , TPtr )
48394844 and self .expr .is_pointer_to_stack_allocation )
48404845
48414846def mkCast (site , expr , new_type ):
@@ -5008,12 +5013,17 @@ def explicit_type(self):
50085013 def type (self ):
50095014 assert self .explicit_type
50105015 return self .expr .type
5016+ # Since addressable and readable are False this may only ever be leveraged
5017+ # by DMLC for optimization purposes
5018+ @property
5019+ def c_lval (self ):
5020+ return self .expr .c_lval
50115021 @property
50125022 def is_pointer_to_stack_allocation (self ):
50135023 return self .expr .is_pointer_to_stack_allocation
50145024
50155025def mkRValue (expr ):
5016- if isinstance ( expr , LValue ) or expr .writable :
5026+ if expr . addressable or expr .writable :
50175027 return RValue (expr .site , expr )
50185028 return expr
50195029
0 commit comments