FreeBASIC  0.91.0
ast-node-const.bas
Go to the documentation of this file.
1 '' AST constant nodes
2 '' l = NULL; 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 '' const = 0?
12 function astConstEqZero( byval n as ASTNODE ptr ) as integer
13  assert( astIsCONST( n ) )
14  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
15  function = (n->val.f = 0.0)
16  else
17  function = (n->val.i = 0)
18  end if
19 end function
20 
21 '' const >= 0?
22 function astConstGeZero( byval n as ASTNODE ptr ) as integer
23  assert( astIsCONST( n ) )
24  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
25  function = (n->val.f >= 0.0)
26  else
27  function = (n->val.i >= 0)
28  end if
29 end function
30 
31 function astNewCONSTstr( byval v as zstring ptr ) as ASTNODE ptr
32  dim as FBSYMBOL ptr tc = any
33 
34  '' assuming no escape sequences are used
35  tc = symbAllocStrConst( v, -1 )
36  if( tc = NULL ) then
37  exit function
38  end if
39 
40  function = astNewVAR( tc )
41 end function
42 
43 function astNewCONSTwstr( byval v as wstring ptr ) as ASTNODE ptr
44  dim as FBSYMBOL ptr tc = any
45 
46  '' assuming no escape sequences are used
47  tc = symbAllocWstrConst( v, -1 )
48  if( tc = NULL ) then
49  exit function
50  end if
51 
52  function = astNewVAR( tc )
53 end function
54 
55 function astNewCONSTi _
56  ( _
57  byval value as longint, _
58  byval dtype as integer, _
59  byval subtype as FBSYMBOL ptr _
60  ) as ASTNODE ptr
61 
62  dim as ASTNODE ptr n = any
63 
64  n = astNewNode( AST_NODECLASS_CONST, FB_DATATYPE_LONGINT, NULL )
65  n->val.i = value
66 
67  n = astNewCONV( dtype, subtype, n, AST_CONVOPT_DONTCHKPTR )
68  assert( n )
69  assert( n->class = AST_NODECLASS_CONST )
70 
71  function = n
72 end function
73 
74 function astNewCONSTf _
75  ( _
76  byval value as double, _
77  byval dtype as integer _
78  ) as ASTNODE ptr
79 
80  dim as ASTNODE ptr n = any
81 
82  n = astNewNode( AST_NODECLASS_CONST, FB_DATATYPE_DOUBLE )
83  n->val.f = value
84 
85  function = astNewCONV( dtype, NULL, n )
86 end function
87 
88 function astNewCONST _
89  ( _
90  byval v as FBVALUE ptr, _
91  byval dtype as integer, _
92  byval subtype as FBSYMBOL ptr _
93  ) as ASTNODE ptr
94 
95  if( typeGetClass( dtype ) = FB_DATACLASS_FPOINT ) then
96  function = astNewCONSTf( v->f, dtype )
97  else
98  function = astNewCONSTi( v->i, dtype, subtype )
99  end if
100 
101 end function
102 
103 function astNewCONSTz _
104  ( _
105  byval dtype as integer, _
106  byval subtype as FBSYMBOL ptr _
107  ) as ASTNODE ptr
108 
109  dim as ASTNODE ptr tree = any
110  dim as FBSYMBOL ptr fld = any
111 
112  select case as const( typeGetDtAndPtrOnly( dtype ) )
113  case FB_DATATYPE_VOID
114  '' A CONST expression with VOID type doesn't make sense,
115  '' but some callers of astNewCONSTz() can call it for SUBs,
116  '' which have a VOID result type.
117  function = NULL
118 
119  case FB_DATATYPE_STRING, FB_DATATYPE_FIXSTR, FB_DATATYPE_CHAR
120  function = astNewCONSTstr( NULL )
121 
122  case FB_DATATYPE_WCHAR
123  function = astNewCONSTwstr( NULL )
124 
125  case FB_DATATYPE_STRUCT
126  '' Build a TYPEINI tree for this struct, with a CONST( 0 )
127  '' initializer for each member
128  tree = astTypeIniBegin( FB_DATATYPE_STRUCT, subtype, TRUE )
129  astTypeIniScopeBegin( tree, NULL )
130 
131  fld = symbUdtGetFirstField( subtype )
132  while( fld )
133  '' field = CONST( 0 )
134  astTypeIniAddAssign( tree, astNewCONSTz( symbGetFullType( fld ), symbGetSubtype( fld ) ), fld )
135  fld = symbUdtGetNextInitableField( fld )
136  wend
137 
138  astTypeIniScopeEnd( tree, NULL )
139  astTypeIniEnd( tree, FALSE )
140 
141  function = tree
142 
143  case else
144  if( dtype = FB_DATATYPE_INVALID ) then
145  dtype = FB_DATATYPE_INTEGER
146  end if
147 
148  if( typeGetClass( dtype ) = FB_DATACLASS_FPOINT ) then
149  function = astNewCONSTf( 0.0, dtype )
150  else
151  function = astNewCONSTi( 0, dtype, subtype )
152  end if
153  end select
154 
155 end function
156 
157 function astLoadCONST( byval n as ASTNODE ptr ) as IRVREG ptr
158  dim as integer dtype = any
159 
160  if( ast.doemit ) then
161  dtype = astGetDataType( n )
162  if( typeGetClass( dtype ) = FB_DATACLASS_FPOINT ) then
163  function = irAllocVrImmF( dtype, n->subtype, n->val.f )
164  else
165  function = irAllocVrImm( dtype, n->subtype, n->val.i )
166  end if
167  end if
168 end function
169 
170 function astConstFlushToInt( byval n as ASTNODE ptr ) as longint
171  n = astNewCONV( FB_DATATYPE_INTEGER, NULL, n )
172 
173  assert( astIsCONST( n ) )
174  function = n->val.i
175 
176  astDelNode( n )
177 end function
178 
179 function astConstFlushToStr( byval n as ASTNODE ptr ) as string
180  assert( astIsCONST( n ) )
181 
182  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
183  if( typeGetDtAndPtrOnly( n->dtype ) = FB_DATATYPE_DOUBLE ) then
184  function = str( n->val.f )
185  else
186  function = str( csng( n->val.f ) )
187  end if
188  elseif( typeIsSigned( n->dtype ) ) then
189  function = str( n->val.i )
190  else
191  function = str( cunsg( n->val.i ) )
192  end if
193 
194  astDelNode( n )
195 end function
196 
197 function astConstFlushToWstr( byval n as ASTNODE ptr ) as wstring ptr
198  static as wstring * 64+1 w
199 
200  assert( astIsCONST( n ) )
201 
202  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
203  if( typeGetDtAndPtrOnly( n->dtype ) = FB_DATATYPE_DOUBLE ) then
204  w = wstr( n->val.f )
205  else
206  w = wstr( csng( n->val.f ) )
207  end if
208  elseif( typeIsSigned( n->dtype ) ) then
209  w = wstr( n->val.i )
210  else
211  w = wstr( cunsg( n->val.i ) )
212  end if
213 
214  astDelNode( n )
215  function = @w
216 end function
217 
218 function astConstGetAsInt64( byval n as ASTNODE ptr ) as longint
219  assert( astIsCONST( n ) )
220 
221  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
222  function = clngint( n->val.f )
223  elseif( typeIsSigned( n->dtype ) ) then
224  function = n->val.i
225  else
226  function = cunsg( n->val.i )
227  end if
228 end function
229 
230 function astConstGetAsDouble( byval n as ASTNODE ptr ) as double
231  assert( astIsCONST( n ) )
232 
233  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
234  function = n->val.f
235  elseif( typeIsSigned( n->dtype ) ) then
236  function = cdbl( n->val.i )
237  else
238  function = cdbl( cunsg( n->val.i ) )
239  end if
240 end function
241 
242 function astBuildConst( byval sym as FBSYMBOL ptr ) as ASTNODE ptr
243  dim as integer dtype = any
244  dim as FBSYMBOL ptr subtype = any
245 
246  assert( symbIsConst( sym ) )
247  dtype = symbGetFullType( sym )
248  subtype = symbGetSubType( sym )
249 
250  select case( typeGetDtAndPtrOnly( dtype ) )
251  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
252  function = astNewVAR( symbGetConstStr( sym ) )
253  case else
254  function = astNewCONST( symbGetConstVal( sym ), dtype, subtype )
255  end select
256 end function
257 
258 function astConvertRawCONSTi _
259  ( _
260  byval dtype as integer, _
261  byval subtype as FBSYMBOL ptr, _
262  byval l as ASTNODE ptr _
263  ) as ASTNODE ptr
264 
265  assert( typeGetClass( l->dtype ) = FB_DATACLASS_INTEGER )
266 
267  '' Pretend the CONST is a 64bit value for a moment, then do a CONV to
268  '' the destination type. This is useful for code that stores values into
269  '' the 64bit ASTNODE.val.i field directly and wants to convert it to
270  '' a certain type, possibly with truncation.
271  ''
272  '' The reason for having this is that the compiler now uses 64bit
273  '' LONGINTs for all the internal constant evaluation etc. If someone
274  '' was compiling something like "&hFFFFFFFFu + &hFFFFFFFFu", the 64bit
275  '' value temporarily stored would be &h1FFFFFFFE which is too big to
276  '' fit in 32bit. If compiling that for 32bit, the stored value must be
277  '' converted from 64bit LONGINT to some 32bit type (INTEGER/LONG) in
278  '' order to be truncated. This is done here with the help of
279  '' astNewCONV(). When compiling for 64bit, it would be converted from
280  '' 64bit LONGINT to 64bit INTEGER, thus stay the same.
281 
282  l->dtype = iif( typeIsSigned( l->dtype ), _
283  FB_DATATYPE_LONGINT, FB_DATATYPE_ULONGINT )
284  l->subtype = NULL
285 
286  var old_warn_convoverflow = ast.warn_convoverflow
287  ast.warn_convoverflow = FALSE
288 
289  l = astNewCONV( dtype, subtype, l, AST_CONVOPT_DONTCHKPTR )
290 
291  ast.warn_convoverflow = old_warn_convoverflow
292 
293  function = l
294 end function
295