FreeBASIC  0.91.0
ast-node-mem.bas
Go to the documentation of this file.
1 '' AST nodes related to memory operations
2 '' bop (l = destine; r = source or bytes to clear)
3 ''
4 '' chng: sep/2004 written [v1ctor]
5 
6 
7 #include once "fb.bi"
8 #include once "fbint.bi"
9 #include once "ir.bi"
10 #include once "ast.bi"
11 #include once "rtl.bi"
12 
13 function astNewMEM _
14  ( _
15  byval op as integer, _
16  byval l as ASTNODE ptr, _
17  byval r as ASTNODE ptr, _
18  byval bytes as longint _
19  ) as ASTNODE ptr
20 
21  dim as ASTNODE ptr n = any
22 
23  dim as uinteger blkmaxlen = irGetOptionValue( IR_OPTIONVALUE_MAXMEMBLOCKLEN )
24 
25  dim as ulongint lgt = bytes
26  if( op = AST_OP_MEMCLEAR ) then
27  if( astIsCONST( r ) ) then
28  lgt = astConstGetInt( r )
29  else
30  lgt = blkmaxlen + 1
31  end if
32  end if
33 
34  '' when clearing/moving more than IR_MEMBLOCK_MAXLEN bytes, take
35  '' the adress-of and let emit() do the rest
36  if( lgt > blkmaxlen ) then
37  l = astNewADDROF( l )
38 
39  if( op = AST_OP_MEMMOVE ) then
40  r = astNewADDROF( r )
41  end if
42  end if
43 
44  '' alloc new node
45  n = astNewNode( AST_NODECLASS_MEM, FB_DATATYPE_INVALID )
46 
47  n->mem.op = op
48  n->l = l
49  n->r = r
50  n->mem.bytes = bytes
51 
52  function = n
53 end function
54 
55 function hCallCtorList _
56  ( _
57  byval tmp as FBSYMBOL ptr, _
58  byval elementsexpr as ASTNODE ptr, _
59  byval dtype as integer, _
60  byval subtype as FBSYMBOL ptr _
61  ) as ASTNODE ptr
62 
63  dim as FBSYMBOL ptr cnt = any, label = any, iter = any
64  dim as ASTNODE ptr tree = any
65 
66  cnt = symbAddTempVar( FB_DATATYPE_INTEGER )
67  label = symbAddLabel( NULL )
68  iter = symbAddTempVar( typeAddrOf( dtype ), subtype )
69 
70  '' iter = @vector[0]
71  tree = astBuildVarAssign( iter, astNewVAR( tmp ) )
72 
73  '' for cnt = 0 to elements-1
74  '' Note: Using a non-flushing LABEL here because the LABEL node will
75  '' end up as part of an expression tree, not as a "standalone statement"
76 /' non-flushing '/ )
77 
78  '' ctor( *iter )
79  tree = astNewLINK( tree, astBuildCtorCall( subtype, astBuildVarDeref( iter ) ) )
80 
81  '' iter += 1
82  tree = astNewLINK( tree, astBuildVarInc( iter, 1 ) )
83 
84  '' next
85  tree = astBuildForEnd( tree, cnt, label, elementsexpr )
86 
87  '' Wrap into LOOP node so astCloneTree() can clone the label and update
88  '' the loop code, because it's part of the new[] expression, and not
89  '' a standalone statement.
90  function = astNewLOOP( label, tree )
91 end function
92 
93 function hElements _
94  ( _
95  byval elementsexpr as ASTNODE ptr, _
96  byref elementstreecount as integer _
97  ) as ASTNODE ptr
98 
99  if( elementstreecount > 1 ) then
100  function = astCloneTree( elementsexpr )
101  else
102  function = elementsexpr
103  end if
104 
105  elementstreecount -= 1
106  assert( elementstreecount >= 0 )
107 
108 end function
109 
110 function astBuildNewOp _
111  ( _
112  byval op as AST_OP, _
113  byval tmp as FBSYMBOL ptr, _
114  byval elementsexpr as ASTNODE ptr, _
115  byval initexpr as ASTNODE ptr, _
116  byval dtype as integer, _
117  byval subtype as FBSYMBOL ptr, _
118  byval do_clear as integer, _
119  byval newexpr as ASTNODE ptr _
120  ) as ASTNODE ptr
121 
122  enum
123  INIT_TYPEINI = 0
124  INIT_CTORCALL
125  INIT_DEFCTOR
126  INIT_DEFCTORLIST
127  INIT_CLEAR
128  INIT_NONE
129  end enum
130 
131  dim as ASTNODE ptr lenexpr = any, tree = any
132  dim as integer save_elmts = any, init = any, elementstreecount = any
133 
134  init = INIT_NONE
135  tree = NULL
136  save_elmts = FALSE
137  elementstreecount = 0
138 
139  '' explicit initialization?
140  if( initexpr ) then
141  '' Just an UDT initializer?
142  if( typeHasCtor( dtype, subtype ) = FALSE ) then
143  init = INIT_TYPEINI
144  '' really a CTORCALL? (check due to error recovery)
145  elseif( astIsCALLCTOR( initexpr ) ) then
146  '' Explicit ctor call
147  init = INIT_CTORCALL
148  end if
149  else
150  '' If there is a default constructor, call it
151  if( typeHasDefCtor( dtype, subtype ) ) then
152  if( op = AST_OP_NEW_VEC ) then
153  init = INIT_DEFCTORLIST
154  elementstreecount += 1
155  else
156  init = INIT_DEFCTOR
157  end if
158  '' Zero-initialize the buffer?
159  elseif( do_clear ) then
160  init = INIT_CLEAR
161  elementstreecount += 1
162  end if
163  end if
164 
165  '' new[] stores the element count, if there is a destructor,
166  '' so delete[] knows how many objects to destroy
167  if( op = AST_OP_NEW_VEC ) then
168  save_elmts = typeHasDtor( dtype, subtype )
169  end if
170 
171  if( newexpr = NULL ) then
172  elementstreecount += 1
173  end if
174 
175  if( save_elmts ) then
176  elementstreecount += 1
177  end if
178 
179  '' If the elementsexpr will be cloned, take care of side-effects
180  if( elementstreecount > 1 ) then
181  '' side-effect?
182  if( astIsClassOnTree( AST_NODECLASS_CALL, elementsexpr ) ) then
183  tree = astRemSideFx( elementsexpr )
184  end if
185  end if
186 
187  '' address not already given? (placement new)
188  if( newexpr = NULL ) then
189  '' elements * sizeof( type )
190  lenexpr = astNewBOP( AST_OP_MUL, hElements( elementsexpr, elementstreecount ), _
191  astNewCONSTi( symbCalcLen( dtype, subtype ), FB_DATATYPE_UINT ) )
192 
193  if( save_elmts ) then
194  '' length + sizeof( integer ) (to store the vector size)
195  lenexpr = astNewBOP( AST_OP_ADD, lenexpr, _
196  astNewCONSTi( typeGetSize( FB_DATATYPE_INTEGER ), FB_DATATYPE_UINT ) )
197  end if
198 
199  newexpr = rtlMemNewOp( op, lenexpr, dtype, subtype )
200  if( newexpr = NULL ) then
201  return NULL
202  end if
203  end if
204 
205  '' tempptr = new( len )
206  tree = astNewLINK( tree, astBuildVarAssign( tmp, newexpr ) )
207 
208  '' save elements count?
209  if( save_elmts ) then
210  '' *tempptr = elements
211  tree = astNewLINK( tree, _
212  astNewASSIGN( _
213  astNewDEREF( astNewVAR( tmp, , typeAddrOf( FB_DATATYPE_INTEGER ) ) ), _
214  hElements( elementsexpr, elementstreecount ) ) )
215 
216  '' tempptr += len( integer )
217  tree = astNewLINK( tree, _
218  astNewSelfBOP( AST_OP_ADD_SELF, _
219  astNewVAR( tmp, , typeAddrOf( FB_DATATYPE_VOID ) ), _
220  astNewCONSTi( typeGetSize( FB_DATATYPE_INTEGER ) ), _
221  NULL ) )
222  end if
223 
224  select case as const( init )
225  case INIT_TYPEINI
226  assert( astIsTYPEINI( initexpr ) )
227  initexpr = astTypeIniFlush( initexpr, tmp, _
228  AST_INIOPT_ISINI or AST_INIOPT_DODEREF )
229 
230  case INIT_CTORCALL
231  initexpr = astPatchCtorCall( astCALLCTORToCALL( initexpr ), _
232  astNewDEREF( astNewVAR( tmp ) ) )
233 
234  case INIT_DEFCTOR
235  initexpr = astBuildCtorCall( subtype, astNewDEREF( astNewVAR( tmp ) ) )
236 
237  case INIT_DEFCTORLIST
238  initexpr = hCallCtorList( tmp, hElements( elementsexpr, elementstreecount ), dtype, subtype )
239 
240  case INIT_CLEAR
241  '' elements * sizeof( type )
242  lenexpr = astNewBOP( AST_OP_MUL, hElements( elementsexpr, elementstreecount ), _
243  astNewCONSTi( symbCalcLen( dtype, subtype ), FB_DATATYPE_UINT ) )
244 
245  initexpr = astNewMEM( AST_OP_MEMCLEAR, _
246  astNewDEREF( astNewVAR( tmp ) ), _
247  astNewCONV( FB_DATATYPE_UINT, NULL, lenexpr ) )
248 
249  case else
250  initexpr = NULL
251 
252  end select
253 
254  function = astNewLINK( tree, initexpr )
255 end function
256 
257 function hCallDtorList _
258  ( _
259  byval ptrexpr as ASTNODE ptr, _
260  byval dtype as integer, _
261  byval subtype as FBSYMBOL ptr _
262  ) as ASTNODE ptr
263 
264  dim as FBSYMBOL ptr cnt = any, label = any, iter = any, elmts = any
265  dim as ASTNODE ptr tree = any, expr = any
266 
267  cnt = symbAddTempVar( FB_DATATYPE_INTEGER )
268  label = symbAddLabel( NULL )
269  iter = symbAddTempVar( typeAddrOf( dtype ), subtype )
270  elmts = symbAddTempVar( FB_DATATYPE_INTEGER )
271 
272  '' DELETE[]'s counter is at: cast(integer ptr, vector)[-1]
273 
274  '' elmts = *cast( integer ptr, cast( any ptr, vector ) + -sizeof( integer ) )
275  '' (using AST_CONVOPT_DONTCHKPTR to support derived UDT pointers)
276  tree = astBuildVarAssign( elmts, astNewDEREF( _
277  astNewCONV( typeAddrOf( FB_DATATYPE_INTEGER ), NULL, _
278  astNewBOP( AST_OP_ADD, _
279  astCloneTree( ptrexpr ), _
280  astNewCONSTi( -typeGetSize( FB_DATATYPE_INTEGER ) ) ), _
281  AST_CONVOPT_DONTCHKPTR ) ) )
282 
283  '' iter = @vector[elmts]
284  tree = astNewLINK( tree, astBuildVarAssign( iter, _
285  astNewBOP( AST_OP_ADD, ptrexpr, astNewVAR( elmts ), NULL, _
286  AST_OPOPT_DEFAULT or AST_OPOPT_DOPTRARITH ) ) )
287 
288  '' for cnt = 0 to elmts-1
289  tree = astBuildForBegin( tree, cnt, label, 0 )
290 
291  '' iter -= 1
292  tree = astNewLINK( tree, astBuildVarInc( iter, -1 ) )
293 
294  '' dtor( *iter )
295  tree = astNewLINK( tree, astBuildDtorCall( subtype, astBuildVarDeref( iter ) ) )
296 
297  '' next
298  tree = astBuildForEnd( tree, cnt, label, astNewVAR( elmts ) )
299 
300  function = tree
301 end function
302 
303 function astBuildDeleteOp _
304  ( _
305  byval op as AST_OP, _
306  byval ptrexpr as ASTNODE ptr, _
307  byval dtype as integer, _
308  byval subtype as FBSYMBOL ptr _
309  ) as ASTNODE ptr
310 
311  dim as ASTNODE ptr tree = any
312  dim as FBSYMBOL ptr label = any
313 
314  tree = NULL
315 
316  '' side-effect?
317  if( astIsClassOnTree( AST_NODECLASS_CALL, ptrexpr ) ) then
318  tree = astRemSideFx( ptrexpr )
319  end if
320 
321  '' if ptr <> NULL then
322  label = symbAddLabel( NULL )
323  tree = astNewLINK( tree, _
324  astNewBOP( AST_OP_EQ, _
325  astCloneTree( ptrexpr ), _
326  astNewCONSTi( 0 ), _
327  label, AST_OPOPT_NONE ) )
328 
329  '' call dtors?
330  if( typeHasDtor( dtype, subtype ) ) then
331  if( op = AST_OP_DEL_VEC ) then
332  tree = astNewLINK( tree, hCallDtorList( astCloneTree( ptrexpr ), dtype, subtype ) )
333  '' ptr -= len( integer )
334  ptrexpr = astNewBOP( AST_OP_SUB, ptrexpr, astNewCONSTi( typeGetSize( FB_DATATYPE_INTEGER ) ) )
335  else
336  tree = astNewLINK( tree, astBuildDtorCall( subtype, astNewDEREF( astCloneTree( ptrexpr ) ) ) )
337  end if
338  end if
339 
340  '' delete( ptr )
341  tree = astNewLINK( tree, rtlMemDeleteOp( op, ptrexpr, dtype, subtype ) )
342 
343  '' end if
344  tree = astNewLINK( tree, astNewLABEL( label ) )
345 
346  function = tree
347 end function
348 
349 function astLoadMEM( byval n as ASTNODE ptr ) as IRVREG ptr
350  dim as ASTNODE ptr l = any, r = any
351  dim as IRVREG ptr v1 = any, v2 = any
352 
353  l = n->l
354  r = n->r
355 
356  if( l = NULL ) then
357  return NULL
358  end if
359 
360  v1 = astLoad( l )
361  astDelNode( l )
362 
363  if( r <> NULL ) then
364  v2 = astLoad( r )
365  astDelNode( r )
366  else
367  v2 = NULL
368  end if
369 
370  if( ast.doemit ) then
371  irEmitMEM( n->mem.op, v1, v2, n->mem.bytes )
372  end if
373 
374  function = NULL
375 end function
376