FreeBASIC  0.91.0
symb-data.bas
Go to the documentation of this file.
1 '' symbol table data type module
2 ''
3 '' chng: feb/2006 moved off ir.bas [v1ctor]
4 ''
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 
9 '' same order as FB_DATATYPE
10 dim shared symb_dtypeTB( 0 to FB_DATATYPES-1 ) as SYMB_DATATYPE => _
11 { _
12  ( FB_DATACLASS_UNKNOWN, 0, FALSE, 0, FB_DATATYPE_VOID , -1 , @"any" ), _
13  ( FB_DATACLASS_INTEGER, 1, TRUE , 10, FB_DATATYPE_BYTE , FB_SIZETYPE_INT8 , @"byte" ), _
14  ( FB_DATACLASS_INTEGER, 1, FALSE, 15, FB_DATATYPE_UBYTE , FB_SIZETYPE_UINT8 , @"ubyte" ), _
15  ( FB_DATACLASS_INTEGER, 1, FALSE, 0, FB_DATATYPE_UBYTE , FB_SIZETYPE_UINT8 , @"zstring" ), _
16  ( FB_DATACLASS_INTEGER, 2, TRUE , 20, FB_DATATYPE_SHORT , FB_SIZETYPE_INT16 , @"short" ), _
17  ( FB_DATACLASS_INTEGER, 2, FALSE, 25, FB_DATATYPE_USHORT , FB_SIZETYPE_UINT16 , @"ushort" ), _
18  ( FB_DATACLASS_INTEGER, 2, FALSE, 0, -1 , -1 , @"wstring" ), _
19  ( FB_DATACLASS_INTEGER, -1, TRUE , -1, FB_DATATYPE_INTEGER , -1 , @"integer" ), _
20  ( FB_DATACLASS_INTEGER, -1, FALSE, -1, FB_DATATYPE_UINT , -1 , @"uinteger" ), _
21  ( FB_DATACLASS_INTEGER, -1, TRUE , 0, FB_DATATYPE_INTEGER , -1 , @"enum" ), _
22  ( FB_DATACLASS_INTEGER, -1, FALSE, 0, FB_DATATYPE_UINT , -1 , @"bitfield" ), _
23  ( FB_DATACLASS_INTEGER, 4, TRUE , 40, FB_DATATYPE_LONG , FB_SIZETYPE_INT32 , @"long" ), _
24  ( FB_DATACLASS_INTEGER, 4, FALSE, 45, FB_DATATYPE_ULONG , FB_SIZETYPE_UINT32 , @"ulong" ), _
25  ( FB_DATACLASS_INTEGER, 8, TRUE , 80, FB_DATATYPE_LONGINT , FB_SIZETYPE_INT64 , @"longint" ), _
26  ( FB_DATACLASS_INTEGER, 8, FALSE, 85, FB_DATATYPE_ULONGINT, FB_SIZETYPE_UINT64 , @"ulongint" ), _
27  ( FB_DATACLASS_FPOINT , 4, TRUE , 0, FB_DATATYPE_SINGLE , FB_SIZETYPE_FLOAT32, @"single" ), _
28  ( FB_DATACLASS_FPOINT , 8, TRUE , 0, FB_DATATYPE_DOUBLE , FB_SIZETYPE_FLOAT64, @"double" ), _
29  ( FB_DATACLASS_STRING , -1, FALSE, 0, FB_DATATYPE_STRING , -1 , @"string" ), _
30  ( FB_DATACLASS_STRING , 1, FALSE, 0, FB_DATATYPE_FIXSTR , -1 , @"string" ), _
31  ( FB_DATACLASS_UDT , 0, FALSE, 0, FB_DATATYPE_STRUCT , -1 , @"type" ), _
32  ( FB_DATACLASS_UDT , 0, FALSE, 0, FB_DATATYPE_NAMESPC , -1 , @"namepace" ), _
33  ( FB_DATACLASS_INTEGER, 0, FALSE, 0, FB_DATATYPE_UINT , -1 , @"function" ), _ '' FB_DATATYPE_FUNCTION has zero size, so function pointer arithmetic is disallowed (-> symbCalcDerefLen())
34  ( FB_DATACLASS_UNKNOWN, 0, FALSE, 0, FB_DATATYPE_VOID , -1 , @"fwdref" ), _
35  ( FB_DATACLASS_INTEGER, -1, FALSE, 0, FB_DATATYPE_UINT , -1 , @"pointer" ), _
36  ( FB_DATACLASS_INTEGER, 16, FALSE, 0, FB_DATATYPE_XMMWORD , -1 , @"xmmword" ) _
37 }
38 
39 '' Note: the integer type ranking values are just arbitrary numbers, except
40 '' that they allow comparisons of the form
41 '' typeGetIntRank( a ) < typeGetIntRank( b )
42 '' to determine which type takes precedence. As long as the order is maintained,
43 '' the numbers can be changed.
44 ''
45 '' For the small types it should be:
46 '' byte < ubyte < short < ushort < others
47 ''
48 '' For the bigger types, it depends on whether the target is 32bit or 64bit:
49 '' 32bit: long < integer < ulong < uinteger < longint < ulongint
50 '' 64bit: long < ulong < longint < integer < ulongint < uinteger
51 ''
52 '' Note: As in C, unsigned types are treated as if they had more precision,
53 '' even though they store the same number of bits. (for the sake of a '+' BOP's
54 '' result type being the same no matter whether we're doing signed + unsigned
55 '' or unsigned + signed, we need to have this kind of rule to decide)
56 
57 dim shared symb_dtypeMatchTB( FB_DATATYPE_BYTE to FB_DATATYPE_DOUBLE, FB_DATATYPE_BYTE to FB_DATATYPE_DOUBLE ) as integer
58 
59 declare function closestType _
60  ( _
61  byval dtype as FB_DATATYPE, _
62  byval dtype1 as FB_DATATYPE, _
63  byval dtype2 as FB_DATATYPE _
64  ) as FB_DATATYPE
65 
67  if( fbCpuTypeIs64bit( ) ) then
68  '' 64bit
69  symb_dtypeTB(FB_DATATYPE_INTEGER ).size = 8
70  symb_dtypeTB(FB_DATATYPE_UINT ).size = 8
71  symb_dtypeTB(FB_DATATYPE_ENUM ).size = 8
72  symb_dtypeTB(FB_DATATYPE_BITFIELD).size = 8
73  symb_dtypeTB(FB_DATATYPE_STRING ).size = 24
74  symb_dtypeTB(FB_DATATYPE_POINTER ).size = 8
75 
76  symb_dtypeTB(FB_DATATYPE_INTEGER ).sizetype = FB_SIZETYPE_INT64
77  symb_dtypeTB(FB_DATATYPE_UINT ).sizetype = FB_SIZETYPE_UINT64
78  symb_dtypeTB(FB_DATATYPE_ENUM ).sizetype = FB_SIZETYPE_INT64
79  symb_dtypeTB(FB_DATATYPE_BITFIELD).sizetype = FB_SIZETYPE_UINT64
80  symb_dtypeTB(FB_DATATYPE_POINTER ).sizetype = FB_SIZETYPE_UINT64
81 
82  symb_dtypeTB(FB_DATATYPE_INTEGER ).intrank = 81
83  symb_dtypeTB(FB_DATATYPE_UINT ).intrank = 86
84  else
85  '' 32bit
86  symb_dtypeTB(FB_DATATYPE_INTEGER ).size = 4
87  symb_dtypeTB(FB_DATATYPE_UINT ).size = 4
88  symb_dtypeTB(FB_DATATYPE_ENUM ).size = 4
89  symb_dtypeTB(FB_DATATYPE_BITFIELD).size = 4
90  symb_dtypeTB(FB_DATATYPE_STRING ).size = 12
91  symb_dtypeTB(FB_DATATYPE_POINTER ).size = 4
92 
93  symb_dtypeTB(FB_DATATYPE_INTEGER ).sizetype = FB_SIZETYPE_INT32
94  symb_dtypeTB(FB_DATATYPE_UINT ).sizetype = FB_SIZETYPE_UINT32
95  symb_dtypeTB(FB_DATATYPE_ENUM ).sizetype = FB_SIZETYPE_INT32
96  symb_dtypeTB(FB_DATATYPE_BITFIELD).sizetype = FB_SIZETYPE_UINT32
97  symb_dtypeTB(FB_DATATYPE_POINTER ).sizetype = FB_SIZETYPE_UINT32
98 
99  symb_dtypeTB(FB_DATATYPE_INTEGER ).intrank = 41
100  symb_dtypeTB(FB_DATATYPE_UINT ).intrank = 46
101  end if
102 
103  '' Remap wchar to target-specific type
104  '' (all fields except the name, so symbTypeToStr() returns WSTRING
105  '' instead of USHORT/ULONG...)
106  symb_dtypeTB(FB_DATATYPE_WCHAR).class = symb_dtypeTB(env.target.wchar).class
107  symb_dtypeTB(FB_DATATYPE_WCHAR).size = symb_dtypeTB(env.target.wchar).size
108  symb_dtypeTB(FB_DATATYPE_WCHAR).signed = symb_dtypeTB(env.target.wchar).signed
109  symb_dtypeTB(FB_DATATYPE_WCHAR).remaptype = symb_dtypeTB(env.target.wchar).remaptype
110 
111 
112  '' Create symb_dtypeMatchTB(), used to score overload resolutions
113  const NUMTYPES = FB_DATATYPE_DOUBLE - FB_DATATYPE_BYTE + 1
114  dim as FB_DATATYPE rank(0 to NUMTYPES - 1)
115 
116  dim as FB_DATATYPE dtype1 = any, dtype2 = any
117  dim as integer i = any, j = any
118 
119  for dtype1 = FB_DATATYPE_BYTE to FB_DATATYPE_DOUBLE
120 
121  '' fill the rank() table with data types
122  for dtype2 = FB_DATATYPE_BYTE to FB_DATATYPE_DOUBLE
123  rank(dtype2 - FB_DATATYPE_BYTE) = dtype2
124  next
125 
126  '' sort the table in order of closeness
127  for i = 0 to NUMTYPES - 2
128  for j = i + 1 to NUMTYPES - 1
129  if( closestType( dtype1, rank(i), rank(j) ) = rank(j) ) then
130  swap rank(i), rank(j)
131  end if
132  next
133  next
134 
135  '' populate symb_dtypeMatchTB() with ranking numbers
136  for i = 0 to NUMTYPES - 1
137  dtype2 = rank(i)
138  symb_dtypeMatchTB( dtype1, dtype2 ) = i
139  next
140 
141  next
142 
143 end sub
144 
145 sub typeMax _
146  ( _
147  byval ldtype as integer, _
148  byval lsubtype as FBSYMBOL ptr, _
149  byval rdtype as integer, _
150  byval rsubtype as FBSYMBOL ptr, _
151  byref dtype as integer, _
152  byref subtype as FBSYMBOL ptr _
153  )
154 
155  dim as integer dtype1 = any, dtype2 = any
156 
157  '' Same type?
158  if( (typeGetDtAndPtrOnly( ldtype ) = typeGetDtAndPtrOnly( rdtype )) and _
159  (lsubtype = rsubtype) ) then
160  dtype = ldtype
161  subtype = lsubtype
162  exit sub
163  end if
164 
165  dtype1 = symb_dtypeTB(typeGet( ldtype )).remaptype
166  dtype2 = symb_dtypeTB(typeGet( rdtype )).remaptype
167 
168  if( dtype1 = dtype2 ) then
169  '' Different types, but they remapped to the same,
170  '' will this ever happen? (special cases such as enums and
171  '' pointers should already have been handled by the caller)
172  '' Return the generic remapped type, since we don't
173  '' know which side to prefer
174  dtype = dtype1
175  subtype = NULL
176 
177  '' If both are integers (only basic integers will appear, since it's
178  '' the remap types), decide based on integer rank
179  elseif( (typeGetClass( dtype1 ) = FB_DATACLASS_INTEGER) and _
180  (typeGetClass( dtype2 ) = FB_DATACLASS_INTEGER) ) then
181  if( typeGetIntRank( dtype1 ) > typeGetIntRank( dtype2 ) ) then
182  dtype = ldtype
183  subtype = lsubtype
184  else
185  dtype = rdtype
186  subtype = rsubtype
187  end if
188 
189  '' Otherwise (i.e. floats are involved), decide based on FB_DATATYPE
190  '' enum order (this lets SINGLE/DOUBLE win over integers, and also
191  '' DOUBLE over SINGLE)
192  elseif( dtype1 > dtype2 ) then
193  dtype = ldtype
194  subtype = lsubtype
195  else
196  dtype = rdtype
197  subtype = rsubtype
198  end if
199 
200 end sub
201 
202 '':::::
203 function typeRemap _
204  ( _
205  byval dtype as integer, _
206  byval subtype as FBSYMBOL ptr _
207  ) as integer
208 
209  dim as integer nd = any
210 
211  select case typeGet( dtype )
212  case FB_DATATYPE_BITFIELD
213  nd = subtype->typ
214  case else
215  nd = symb_dtypeTB(dtype).remaptype
216  end select
217 
218  function = typeJoin( dtype, nd )
219 
220 end function
221 
222 '':::::
223 function typeToSigned _
224  ( _
225  byval dtype as integer _
226  ) as integer
227 
228  dim as integer dt = typeGet( dtype ), nd = any
229 
230  if( symb_dtypeTB(dt).class <> FB_DATACLASS_INTEGER ) then
231  return dtype
232  end if
233 
234  select case as const dt
235  case FB_DATATYPE_UBYTE, FB_DATATYPE_CHAR
236  nd = FB_DATATYPE_BYTE
237 
238  case FB_DATATYPE_USHORT
239  nd = FB_DATATYPE_SHORT
240 
241  case FB_DATATYPE_UINT
242  nd = FB_DATATYPE_INTEGER
243 
244  case FB_DATATYPE_WCHAR
245  return typeToSigned( env.target.wchar )
246 
247  case FB_DATATYPE_ULONG, FB_DATATYPE_POINTER
248  nd = FB_DATATYPE_LONG
249 
250  case FB_DATATYPE_ULONGINT
251  nd = FB_DATATYPE_LONGINT
252 
253  case else
254  nd = dtype
255  end select
256 
257  function = typeJoin( dtype, nd )
258 
259 end function
260 
261 '':::::
262 function typeToUnsigned _
263  ( _
264  byval dtype as integer _
265  ) as integer
266 
267  dim as integer dt = typeGet( dtype ), nd = any
268 
269  if( symb_dtypeTB(dt).class <> FB_DATACLASS_INTEGER ) then
270  return dtype
271  end if
272 
273  select case as const dt
274  case FB_DATATYPE_BYTE
275  nd = FB_DATATYPE_UBYTE
276 
277  case FB_DATATYPE_SHORT
278  nd = FB_DATATYPE_USHORT
279 
280  case FB_DATATYPE_INTEGER, FB_DATATYPE_ENUM
281  nd = FB_DATATYPE_UINT
282 
283  case FB_DATATYPE_LONG, FB_DATATYPE_POINTER
284  nd = FB_DATATYPE_ULONG
285 
286  case FB_DATATYPE_LONGINT
287  nd = FB_DATATYPE_ULONGINT
288 
289  case else
290  nd = dtype
291  end select
292 
293  function = typeJoin( dtype, nd )
294 
295 end function
296 
297 function typeHasCtor _
298  ( _
299  byval dtype as integer, _
300  byval subtype as FBSYMBOL ptr _
301  ) as integer
302 
303  select case( typeGet( dtype ) )
304  case FB_DATATYPE_STRUCT '', FB_DATATYPE_CLASS
305  function = (symbGetCompCtorHead( subtype ) <> NULL)
306  end select
307 
308 end function
309 
310 function typeHasDefCtor _
311  ( _
312  byval dtype as integer, _
313  byval subtype as FBSYMBOL ptr _
314  ) as integer
315 
316  select case( typeGet( dtype ) )
317  case FB_DATATYPE_STRUCT '', FB_DATATYPE_CLASS
318  function = (symbGetCompDefCtor( subtype ) <> NULL)
319  end select
320 
321 end function
322 
323 function typeHasDtor _
324  ( _
325  byval dtype as integer, _
326  byval subtype as FBSYMBOL ptr _
327  ) as integer
328 
329  select case( typeGet( dtype ) )
330  case FB_DATATYPE_STRUCT '', FB_DATATYPE_CLASS
331  function = (symbGetCompDtor( subtype ) <> NULL)
332  end select
333 
334 end function
335 
336 ''
337 '' Replace/merge a type with another type; used to replace forward references
338 '' (FB_DATATYPE_FWDREF) by the real dtype once its known (when the forward
339 '' reference is implemented).
340 ''
341 '' Normal case:
342 ''
343 '' type UDT as UDT_
344 '' dim p as UDT ptr
345 '' type UDT_
346 '' i as integer
347 '' end type
348 ''
349 '' Variable 'p' is a pointer to a forward reference that will be implemented as
350 '' a struct, so we're going to turn typeAddrOf( FB_DATATYPE_FWDREF ) into
351 '' typeAddrOf( FB_DATATYPE_STRUCT ) and replace the subtype too.
352 ''
353 '' Care must be taken in cases like the following:
354 ''
355 '' type typedef as fwdref ptr ptr ptr ptr
356 '' type fwdref as integer ptr ptr ptr ptr ptr
357 ''
358 '' 'typedef' has 4 PTRs, and the forward reference itself will be implemented
359 '' with 5 PTRs. These two cannot be merged because 4+5 would be too many PTRs,
360 '' the limit is 8 (FB_DT_PTRLEVELS).
361 ''
362 function typeMerge _
363  ( _
364  byval dtype1 as integer, _
365  byval dtype2 as integer _
366  ) as integer
367 
368  dim as integer oldptrcount = any, addptrcount = any
369 
370  '' Existing PTR's (pointer to forward ref, e.g. on typedefs/variables)
371  oldptrcount = typeGetPtrCnt( dtype1 )
372 
373  '' and additional PTR's
374  addptrcount = typeGetPtrCnt( dtype2 )
375 
376  '' Too many PTR's after replacing the forward ref with its actual type?
377  if( (oldptrcount + addptrcount) > FB_DT_PTRLEVELS ) then
378  errReport( FB_ERRMSG_TOOMANYPTRINDIRECTIONS )
379  '' Error recovery: use the max. amount of PTRs on the final type
380  oldptrcount = FB_DT_PTRLEVELS - addptrcount
381  end if
382 
383  '' Replace the forward ref with the real type,
384  '' but preserve existing PTRs and CONSTs
385  dtype1 = typeMultAddrOf( dtype2, oldptrcount ) or _
386  typeGetConstMask( dtype1 )
387 
388  function = dtype1
389 end function
390 
391 '' Return the closest (most "compatible") type to dtype,
392 '' out of dtype1 and dtype2
393 function closestType _
394  ( _
395  byval dtype as FB_DATATYPE, _
396  byval dtype1 as FB_DATATYPE, _
397  byval dtype2 as FB_DATATYPE _
398  ) as FB_DATATYPE
399 
400  '' prefer non-bitfield/enum/zstring/wstring, let them be handled elsewhere
401  if( dtype1 <> FB_DATATYPE_ENUM and dtype2 = FB_DATATYPE_ENUM ) then return dtype1
402  if( dtype2 <> FB_DATATYPE_ENUM and dtype1 = FB_DATATYPE_ENUM ) then return dtype2
403 
404  if( dtype1 <> FB_DATATYPE_BITFIELD and dtype2 = FB_DATATYPE_BITFIELD ) then return dtype1
405  if( dtype2 <> FB_DATATYPE_BITFIELD and dtype1 = FB_DATATYPE_BITFIELD ) then return dtype2
406 
407  if( dtype1 <> FB_DATATYPE_CHAR and dtype2 = FB_DATATYPE_CHAR ) then return dtype1
408  if( dtype2 <> FB_DATATYPE_CHAR and dtype1 = FB_DATATYPE_CHAR ) then return dtype2
409 
410  if( dtype1 <> FB_DATATYPE_WCHAR and dtype2 = FB_DATATYPE_WCHAR ) then return dtype1
411  if( dtype2 <> FB_DATATYPE_WCHAR and dtype1 = FB_DATATYPE_WCHAR ) then return dtype2
412 
413 
414  '' prefer same dataclass (integer / floating-point)
415  dim as integer sameclass1 = (typeGetClass(dtype1) = typeGetClass(dtype))
416  dim as integer sameclass2 = (typeGetClass(dtype2) = typeGetClass(dtype))
417 
418  if ( sameclass1 and not sameclass2 ) then return dtype1
419  if ( sameclass2 and not sameclass1 ) then return dtype2
420 
421 
422  '' prefer a type that's at least as large as dtype
423  dim as integer larger1 = (typeGetSize( dtype1 ) >= typeGetSize( dtype ))
424  dim as integer larger2 = (typeGetSize( dtype1 ) >= typeGetSize( dtype ))
425 
426  if( larger1 and not larger2 ) then return dtype1
427  if( larger2 and not larger1 ) then return dtype2
428 
429 
430  '' prefer closer size (if larger, then the smallest; if smaller, then the largest)
431  dim as integer sizediff1 = abs( typeGetSize( dtype1 ) - typeGetSize( dtype ) )
432  dim as integer sizediff2 = abs( typeGetSize( dtype2 ) - typeGetSize( dtype ) )
433 
434  if( sizediff1 < sizediff2 ) then return dtype1
435  if( sizediff2 < sizediff1 ) then return dtype2
436 
437 
438  '' prefer [U]Integer type if both same size
439  dim as integer isint1 = (typeToSigned( dtype1 ) = FB_DATATYPE_INTEGER)
440  dim as integer isint2 = (typeToSigned( dtype2 ) = FB_DATATYPE_INTEGER)
441 
442  if( isint1 and not isint2 ) then return dtype1
443  if( isint2 and not isint1 ) then return dtype2
444 
445 
446  '' prefer same signedness
447  dim as integer samesign1 = (typeIsSigned( dtype1 ) = typeIsSigned( dtype ))
448  dim as integer samesign2 = (typeIsSigned( dtype2 ) = typeIsSigned( dtype ))
449 
450  if( samesign1 and not samesign2 ) then return dtype1
451  if( samesign2 and not samesign1 ) then return dtype2
452 
453 
454  '' should be no other differences
455  assert( dtype1 = dtype2 )
456  return dtype1
457 
458 end function
459