FreeBASIC  0.91.0
ast-node-addr.bas
Go to the documentation of this file.
1 '' AST address-of nodes
2 '' l = expression; r = NULL
3 ''
4 '' chng: sep/2004 written [v1ctor]
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "ir.bi"
9 #include once "ast.bi"
10 
11 function astGetOFFSETChildOfs( byval l as ASTNODE ptr ) as longint
12  '' var?
13  if( astIsVAR( l ) ) then
14  function = l->var_.ofs
15  '' array..
16  else
17  function = l->idx.ofs + l->r->var_.ofs + _
18  symbGetArrayDiff( l->sym ) + symbGetOfs( l->sym )
19  end if
20 end function
21 
22 function astNewOFFSET( byval l as ASTNODE ptr ) as ASTNODE ptr
23  dim as ASTNODE ptr n = any
24 
25  if( l = NULL ) then
26  return NULL
27  end if
28 
29  '' alloc new node
30  n = astNewNode( AST_NODECLASS_OFFSET, _
31  typeAddrOf( astGetFullType( l ) ), _
32  l->subtype )
33 
34  '' must preserve the node or optimizations at newDEREF() will fail
35  n->l = l
36  n->sym = l->sym
37 
38  '' must be computed here or optimizations that depend on 0 offset values will fail
39  n->ofs.ofs = astGetOFFSETChildOfs( l )
40 
41  '' access counter must be updated here too
42  '' because the var initializers used with static strings
43  if( l->sym <> NULL ) then
44  symbSetIsAccessed( l->sym )
45  end if
46 
47  function = n
48 end function
49 
50 function astLoadOFFSET( byval n as ASTNODE ptr ) as IRVREG ptr
51  dim as IRVREG ptr vr = any
52  dim as FBSYMBOL ptr sym = any
53  dim as ASTNODE ptr l = any
54 
55  sym = n->sym
56  if( sym <> NULL ) then
57  symbSetIsAccessed( sym )
58  end if
59 
60  if( ast.doemit ) then
61  vr = irAllocVROFS( astGetDataType( n ), n->subtype, sym, n->ofs.ofs )
62  end if
63 
64  l = n->l
65 
66  '' array?
67  if( astIsIDX( l ) ) then
68  astDelNode( l->l )
69  astDelNode( l->r )
70  end if
71 
72  astDelNode( l )
73 
74  function = vr
75 end function
76 
77 sub hRemoveNullPtrCheck( byval l as ASTNODE ptr )
78  dim as ASTNODE ptr n = any, t = any
79 
80  '' ptr checks must be removed because a null pointer is ok
81  '' when taking the address-of an expression
82 
83  n = l->l
84 
85  if( n = NULL ) then
86  exit sub
87  end if
88 
89  select case n->class
90  case AST_NODECLASS_PTRCHK
91  l->l = n->l
92  '' del func call tree
93  astDelTree( n->r )
94  '' del the checking node
95  astDelNode( n )
96 
97  '' remove null-ptr checks in ptr indexing
98  case AST_NODECLASS_BOP
99  do
100  t = n->l
101  select case t->class
102  case AST_NODECLASS_PTRCHK
103  n->l = t->l
104  astDelTree( t->r )
105  astDelNode( t )
106  exit do
107 
108  case AST_NODECLASS_BOP
109  n = t
110 
111  case else
112  exit do
113  end select
114  loop
115  end select
116 end sub
117 
118 function astNewADDROF( byval l as ASTNODE ptr ) as ASTNODE ptr
119  dim as ASTNODE ptr n = any
120  dim as integer dtype = any
121  dim as FBSYMBOL ptr subtype = any
122 
123  if( l = NULL ) then
124  return NULL
125  end if
126 
127  '' skip any casting if they won't do any conversion
128  dim as ASTNODE ptr t = l
129  if( l->class = AST_NODECLASS_CONV ) then
130  if( l->cast.doconv = FALSE ) then
131  t = l->l
132  end if
133  end if
134 
135  n = NULL
136 
137  select case( t->class )
138  case AST_NODECLASS_DEREF
139  if( env.clopt.extraerrchk ) then
141  end if
142 
143  '' astNewDEREF() on a CONST stores the CONST's value into its
144  '' ASTNODE.ptr.ofs field and then uses a NULL lhs.
145  if( t->l ) then
146  '' @*nonconst -> nonconst
147  if( t->ptr.ofs = 0 ) then
148  n = t->l
149  astDelNode( t ) '' DEREF
150  end if
151  else
152  '' @*const -> const
153  n = astNewCONSTi( t->ptr.ofs )
154  astDelNode( t ) '' DEREF
155  end if
156 
157  case AST_NODECLASS_FIELD
158  '' @0->field to const
159  if( t->l->class = AST_NODECLASS_DEREF ) then
160  if( env.clopt.extraerrchk ) then
161  hRemoveNullPtrCheck( t->l )
162  end if
163 
164  '' astNewDEREF() on a CONST stores the CONST's value into its
165  '' ASTNODE.ptr.ofs field and then uses a NULL lhs.
166  if( t->l->l = NULL ) then
167  '' @*const -> const
168  n = astNewCONSTi( t->l->ptr.ofs )
169  astDelNode( t->l ) '' DEREF
170  astDelNode( t ) '' FIELD
171  end if
172  end if
173 
174  case AST_NODECLASS_VAR
175  dim as FBSYMBOL ptr s = any
176 
177  '' module-level or local static scalar? use offset instead
178  s = t->sym
179  if( s <> NULL ) then
180  if( (symbIsLocal( s ) = FALSE) or _
181  ((symbGetAttrib( s ) and (FB_SYMBATTRIB_SHARED or _
182  FB_SYMBATTRIB_COMMON or _
183  FB_SYMBATTRIB_STATIC)) <> 0) ) then
184  n = astNewOFFSET( t )
185  end if
186  end if
187 
188  case AST_NODECLASS_IDX
189  '' try to remove the idx node if it's a constant expr
190  if( t <> l ) then
191  t = astOptimizeTree( t )
192  l->l = t
193  else
194  t = astOptimizeTree( t )
195  l = t
196  end if
197 
198  '' no index expression? it's a const..
199  if( t->l = NULL ) then
200  dim as FBSYMBOL ptr s = any
201  s = t->sym
202  '' module-level or local static scalar? use offset instead
203  if( (symbIsLocal( s ) = FALSE) or _
204  ((symbGetAttrib( s ) and (FB_SYMBATTRIB_SHARED or _
205  FB_SYMBATTRIB_COMMON or _
206  FB_SYMBATTRIB_STATIC)) <> 0) ) then
207  '' can't be dynamic either
208  if( symbGetIsDynamic( s ) = FALSE ) then
209  n = astNewOFFSET( t )
210  end if
211  end if
212  end if
213 
214  end select
215 
216  '' ADDROF's data type should always be determined based on the data type
217  '' of the top level node of its lhs.
218  dtype = typeAddrOf( l->dtype )
219  subtype = l->subtype
220 
221  if( n ) then
222  if( t <> l ) then
223  astDelNode( l ) '' CONV that was skipped above
224  end if
225  return astNewCONV( dtype, subtype, n, AST_CONVOPT_DONTCHKPTR )
226  end if
227 
228  '' alloc new node
229  n = astNewNode( AST_NODECLASS_ADDROF, dtype, subtype )
230  n->op.op = AST_OP_ADDROF
231  n->l = l
232 
233  function = n
234 end function
235 
236 function astLoadADDROF( byval n as ASTNODE ptr ) as IRVREG ptr
237  dim as ASTNODE ptr p = any
238  dim as IRVREG ptr v1 = any, vr = any
239 
240  p = n->l
241  if( p = NULL ) then
242  return NULL
243  end if
244 
245  v1 = astLoad( p )
246 
247  if( ast.doemit ) then
248  '' src is not a reg?
249  if( (irIsREG( v1 ) = FALSE) or _
250  (typeGetClass(v1->dtype) <> FB_DATACLASS_INTEGER) or _
251  (typeGetSize(v1->dtype) <> env.pointersize) ) then
252 
253  vr = irAllocVREG( astGetDataType( n ), n->subtype )
254  irEmitADDR( AST_OP_ADDROF, v1, vr )
255 
256  else
257  vr = v1
258  end if
259  end if
260 
261  astDelNode( p )
262 
263  function = vr
264 end function
265