FreeBASIC  0.91.0
ast-node-uop.bas
Go to the documentation of this file.
1 '' AST unary operation nodes
2 '' l = operand 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 "rtl.bi"
10 #include once "ast.bi"
11 
12 function hConstUop _
13  ( _
14  byval op as integer, _
15  byval dtype as integer, _
16  byval subtype as FBSYMBOL ptr, _
17  byval l as ASTNODE ptr _
18  ) as ASTNODE ptr
19 
20  if( typeGetClass( l->dtype ) = FB_DATACLASS_FPOINT ) then
21  select case as const( op )
22  case AST_OP_NEG
23  l->val.f = -l->val.f
24  case AST_OP_ABS
25  l->val.f = abs( l->val.f )
26  case AST_OP_SGN
27  l->val.f = sgn( l->val.f )
28  case AST_OP_SIN
29  l->val.f = sin( l->val.f )
30  case AST_OP_ASIN
31  l->val.f = asin( l->val.f )
32  case AST_OP_COS
33  l->val.f = cos( l->val.f )
34  case AST_OP_ACOS
35  l->val.f = acos( l->val.f )
36  case AST_OP_TAN
37  l->val.f = tan( l->val.f )
38  case AST_OP_ATAN
39  l->val.f = atn( l->val.f )
40  case AST_OP_SQRT
41  l->val.f = sqr( l->val.f )
42  case AST_OP_LOG
43  l->val.f = log( l->val.f )
44  case AST_OP_EXP
45  l->val.f = exp( l->val.f )
46  case AST_OP_FLOOR
47  l->val.f = int( l->val.f )
48  case AST_OP_FIX
49  l->val.f = fix( l->val.f )
50  case AST_OP_FRAC
51  l->val.f = frac( l->val.f )
52  case else
53  assert( FALSE )
54  end select
55  else
56  select case as const( op )
57  case AST_OP_NOT
58  l->val.i = not l->val.i
59  case AST_OP_NEG
60  l->val.i = -l->val.i
61  case AST_OP_ABS
62  l->val.i = abs( l->val.i )
63  case AST_OP_SGN
64  l->val.i = sgn( l->val.i )
65  case else
66  assert( FALSE )
67  end select
68 
69  l = astConvertRawCONSTi( dtype, subtype, l )
70  end if
71 
72  function = l
73 end function
74 
75 function astNewUOP _
76  ( _
77  byval op as integer, _
78  byval o as ASTNODE ptr _
79  ) as ASTNODE ptr
80 
81  dim as ASTNODE ptr n = any
82  dim as integer dtype = any, rank = any, intrank = any, uintrank = any
83  dim as FBSYMBOL ptr subtype = any
84 
85  function = NULL
86 
87  if( o = NULL ) then
88  exit function
89  end if
90 
91  '' check op overloading
92  if( symb.globOpOvlTb(op).head <> NULL ) then
93  dim as FBSYMBOL ptr proc = any
94  dim as FB_ERRMSG err_num = any
95  proc = symbFindUopOvlProc( op, o, @err_num )
96  if( proc <> NULL ) then
97  '' build a proc call
98  return astBuildCall( proc, o )
99  else
100  if( err_num <> FB_ERRMSG_OK ) then
101  exit function
102  end if
103  end if
104  end if
105 
106  if( op = AST_OP_SWZ_REPEAT ) then
107  '' alloc new node
108  n = astNewNode( AST_NODECLASS_UOP, o->dtype, o->subtype )
109 
110  n->l = o
111  n->r = NULL
112  n->op.op = op
113  n->op.ex = NULL
114  n->op.options = AST_OPOPT_ALLOCRES
115  return n
116  end if
117 
118  '' string? can't operate
119  if( typeGetClass( o->dtype ) = FB_DATACLASS_STRING ) then
120  exit function
121  end if
122 
123  select case as const( typeGet( o->dtype ) )
124  '' CHAR and WCHAR literals are also from the INTEGER class..
125  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
126  '' only if it's a deref pointer, to allow "NOT *p" etc
127  if( astIsDEREF( o ) = FALSE ) then
128  exit function
129  end if
130 
131  '' UDT?
132  case FB_DATATYPE_STRUCT ', FB_DATATYPE_CLASS
133  '' try to convert to the most precise type
134  '' (astNewCONV() will try symbFindCastOvlProc() which gives
135  '' special treatment to the FB_DATATYPE_VOID)
136  o = astNewCONV( typeJoin( o->dtype, FB_DATATYPE_VOID ), NULL, o )
137  if( o = NULL ) then
138  exit function
139  end if
140 
141  '' Enum operand? Convert to integer (but preserve CONSTs)
142  case FB_DATATYPE_ENUM
143  '' See also astNewBOP() - when doing math on enum constants,
144  '' we don't know whether the resulting integer value will be
145  '' a part of that enum, so it's better to convert to integer.
146  '' For typesafe enums, an error would have to be shown here.
147  o = astNewCONV( typeJoin( o->dtype, FB_DATATYPE_INTEGER ), NULL, o )
148 
149  '' pointer?
150  case FB_DATATYPE_POINTER
151  '' only NOT allowed
152  if( op <> AST_OP_NOT ) then
153  exit function
154  end if
155 
156  end select
157 
158  ''
159  '' Promote smaller integer types to [U]INTEGER before the operation,
160  '' see also astNewBOP()
161  ''
162 
163  if( (env.clopt.lang <> FB_LANG_QB) and _
164  (typeGetClass( o->dtype ) = FB_DATACLASS_INTEGER) ) then
165  rank = typeGetIntRank( typeGetRemapType( o->dtype ) )
166  intrank = typeGetIntRank( FB_DATATYPE_INTEGER )
167  uintrank = typeGetIntRank( FB_DATATYPE_UINT )
168 
169  '' o < INTEGER?
170  if( rank < intrank ) then
171  o = astNewCONV( typeJoin( o->dtype, FB_DATATYPE_INTEGER ), NULL, o )
172  else
173  '' INTEGER < o < UINTEGER?
174  if( (intrank < rank) and (rank < uintrank) ) then
175  '' Convert to UINTEGER for consistency with
176  '' the above conversion to INTEGER (this can
177  '' happen with ULONG on 32bit, and ULONGINT
178  '' on 64bit, due to the ranking order)
179  o = astNewCONV( typeJoin( o->dtype, FB_DATATYPE_UINT ), NULL, o )
180  end if
181  end if
182  end if
183 
184  '' Result type normally is the same as the operand
185  dtype = o->dtype
186  subtype = o->subtype
187 
188  select case as const op
189  '' NOT can only operate on integers
190  case AST_OP_NOT
191  if( typeGetClass( o->dtype ) <> FB_DATACLASS_INTEGER ) then
192  o = astNewCONV( typeJoin( o->dtype, FB_DATATYPE_INTEGER ), NULL, o )
193  dtype = o->dtype
194  subtype = o->subtype
195  end if
196 
197  '' with SGN(int) the result is always a signed integer
198  case AST_OP_SGN
199  if( typeGetClass( o->dtype ) = FB_DATACLASS_INTEGER ) then
200  dtype = typeToSigned( dtype )
201  end if
202 
203  '' transcendental can only operate on floats
204  case AST_OP_SIN, AST_OP_ASIN, AST_OP_COS, AST_OP_ACOS, _
205  AST_OP_TAN, AST_OP_ATAN, AST_OP_SQRT, AST_OP_LOG, _
206  AST_OP_EXP
207 
208  if( typeGetClass( o->dtype ) <> FB_DATACLASS_FPOINT ) then
209  o = astNewCONV( typeJoin( o->dtype, FB_DATATYPE_DOUBLE ), NULL, o )
210  dtype = o->dtype
211  subtype = o->subtype
212  end if
213 
214  '' fix and floor only affect floats
215  case AST_OP_FIX, AST_OP_FLOOR
216  '' integer?
217  if( typeGetClass( o->dtype ) = FB_DATACLASS_INTEGER ) then
218  '' return value unchanged (hack: add 0 to prevent passing byref)
219  return astNewBOP( AST_OP_ADD, o, astNewCONSTi( 0, dtype ) )
220  end if
221 
222  '' frac returns 0 for non-floats
223  case AST_OP_FRAC
224  '' integer?
225  if( typeGetClass( o->dtype ) = FB_DATACLASS_INTEGER ) then
226  '' return zero (opimization should eliminate 'AND 0' tree if no classes on o)
227  return astNewBOP( AST_OP_AND, o, astNewCONSTi( 0, dtype ) )
228  end if
229 
230  '' '+'? do nothing..
231  case AST_OP_PLUS
232  return o
233 
234  end select
235 
236  '' constant folding
237  if( astIsCONST( o ) ) then
238  if( op = AST_OP_NEG ) then
239  if( typeIsSigned( o->dtype ) = FALSE ) then
240  '' Check for overflows, for example:
241  '' NEG( cushort( 32769 ) ) is -32769,
242  '' but the lowest short is -32768.
243 
244  '' Highest bit set? (meaning the negation cannot be represented,
245  '' since the highest bit will be overwritten with the sign bit)
246  if( astConstGetUint( o ) > (1ull shl (typeGetBits( dtype ) - 1)) ) then
247  errReportWarn( FB_WARNINGMSG_IMPLICITCONVERSION )
248  end if
249 
250  dtype = typeToSigned( dtype )
251  end if
252  end if
253 
254  o = hConstUop( op, dtype, subtype, o )
255 
256  o->dtype = dtype
257  return o
258  end if
259 
260  '' alloc new node
261 
262  if( irGetOption( IR_OPT_NOINLINEOPS ) ) then
263  select case as const op
264  case AST_OP_SGN, AST_OP_ABS, AST_OP_FIX, AST_OP_FRAC, _
265  AST_OP_SIN, AST_OP_ASIN, AST_OP_COS, AST_OP_ACOS, _
266  AST_OP_TAN, AST_OP_ATAN, AST_OP_SQRT, AST_OP_LOG, _
267  AST_OP_EXP, AST_OP_FLOOR
268  return rtlMathUop( op, o )
269  end select
270  end if
271 
272 
273  n = astNewNode( AST_NODECLASS_UOP, dtype, subtype )
274 
275  n->l = o
276  n->r = NULL
277  n->op.op = op
278  n->op.ex = NULL
279  n->op.options = AST_OPOPT_ALLOCRES
280 
281  function = n
282 end function
283 
284 '':::::
285 function astLoadUOP _
286  ( _
287  byval n as ASTNODE ptr _
288  ) as IRVREG ptr
289 
290  dim as ASTNODE ptr o = any
291  dim as integer op = any
292  dim as IRVREG ptr v1 = any, vr = any
293 
294  o = n->l
295  op = n->op.op
296 
297  if( o = NULL ) then
298  return NULL
299  end if
300 
301  if( o->class = AST_NODECLASS_CONV ) then
302  astUpdateCONVFD2FS( o, n->dtype, TRUE )
303  end if
304 
305  v1 = astLoad( o )
306 
307  if( ast.doemit ) then
308  if( (n->op.options and AST_OPOPT_ALLOCRES) <> 0 ) then
309  vr = irAllocVREG( astGetDataType( o ), o->subtype )
310  v1->vector = n->vector
311  vr->vector = n->vector
312  else
313  vr = NULL
314  v1->vector = n->vector
315  end if
316 
317  irEmitUOP( op, v1, vr )
318 
319  '' "op var" optimizations
320  if( vr = NULL ) then
321  vr = v1
322  end if
323  end if
324 
325  astDelNode( o )
326 
327  function = vr
328 
329 end function
330 
331