FreeBASIC  0.91.0
symb-mangling.bas
Go to the documentation of this file.
1 '' symbol mangling module (compatible with the GCC 3.x ABI)
2 ''
3 '' chng: may/2006 written [v1ctor]
4 
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "flist.bi"
9 #include once "hash.bi"
10 #include once "ir.bi"
11 
13  idx as integer
14  dtype as integer
15  subtype as FBSYMBOL ptr
16 end type
17 
19  flist as TFLIST '' of FB_MANGLEABBR
20  cnt as integer
21 
22  tempstr as zstring * 6 + 10 + 1
23  uniqueidcount as integer
24  uniquelabelcount as integer
25  profilelabelcount as integer
26 end type
27 
28 const FB_INITMANGARGS = 96
29 
30 declare function hDoCppMangling( byval sym as FBSYMBOL ptr ) as integer
31 declare sub hMangleProc( byval sym as FBSYMBOL ptr )
32 declare sub hMangleVariable( byval sym as FBSYMBOL ptr )
33 declare sub hGetProcParamsTypeCode _
34  ( _
35  byref mangled as string, _
36  byval sym as FBSYMBOL ptr _
37  )
38 declare sub hMangleNamespace _
39  ( _
40  byref mangled as string, _
41  byval ns as FBSYMBOL ptr, _
42  byval dohashing as integer, _
43  byval isconst as integer _
44  )
45 
46 '' inside a namespace or class?
47 #define hIsNested(s) (symbGetNamespace( s ) <> @symbGetGlobalNamespc( ))
48 
49 '' globals
50  dim shared as FB_MANGLECTX ctx
51 
54  ctx.cnt = 0
55  ctx.uniqueidcount = 0
58 end sub
59 
61  flistEnd( @ctx.flist )
62 end sub
63 
64 function symbUniqueId( ) as zstring ptr
65  if( env.clopt.backend = FB_BACKEND_GCC ) then
66  ctx.tempstr = "tmp$"
67  ctx.tempstr += str( ctx.uniqueidcount )
68  else
69  ctx.tempstr = "Lt_"
71  end if
72 
73  ctx.uniqueidcount += 1
74 
75  function = @ctx.tempstr
76 end function
77 
78 function symbUniqueLabel( ) as zstring ptr
79  if( env.clopt.backend = FB_BACKEND_GCC ) then
80  ctx.tempstr = "label$"
83  else
84  ctx.tempstr = ".Lt_"
86  ctx.uniqueidcount += 1
87  end if
88 
89  function = @ctx.tempstr
90 end function
91 
92 function symbMakeProfileLabelName( ) as zstring ptr
95  function = @ctx.tempstr
96 end function
97 
98 function symbGetDBGName( byval sym as FBSYMBOL ptr ) as zstring ptr
99  '' GDB will demangle the symbols automatically
100  if( hDoCppMangling( sym ) ) then
101  select case as const symbGetClass( sym )
102  '' but UDT's, they shouldn't include any mangling at all..
103  case FB_SYMBCLASS_ENUM, FB_SYMBCLASS_STRUCT, _
104  FB_SYMBCLASS_CLASS, FB_SYMBCLASS_NAMESPACE
105 
106  '' check if an alias wasn't given
107  dim as zstring ptr res = sym->id.alias
108  if( res = NULL ) then
109  res = sym->id.name
110  end if
111 
112  return res
113 
114  case else
115  return symbGetMangledName( sym )
116  end select
117  end if
118 
119  '' no mangling, return as-is
120  function = sym->id.name
121 end function
122 
123 sub symbSetName( byval s as FBSYMBOL ptr, byval name_ as zstring ptr )
124  dim as integer slen = any
125 
126  '' assuming only params will change names, no mangling reseted
127 
128  if( s->id.name <> NULL ) then
129  poolDelItem( @symb.namepool, s->id.name ) 'ZstrFree( s->id.name )
130  end if
131 
132  slen = len( *name_ )
133  if( slen = 0 ) then
134  s->id.name = NULL
135  else
136  s->id.name = poolNewItem( @symb.namepool, slen + 1 ) 'ZStrAllocate( slen )
137  *s->id.name = *name_
138  end if
139 end sub
140 
141 sub symbSetMangledId( byval sym as FBSYMBOL ptr, byref mangled as string )
142  assert( sym->id.mangled = NULL )
143  sym->id.mangled = ZStrAllocate( len( mangled ) )
144  *sym->id.mangled = mangled
145 end sub
146 
147 sub hMangleUdtId( byref mangled as string, byval sym as FBSYMBOL ptr )
148  '' <length><id>E
149  if( sym->id.alias ) then
150  mangled += str( len( *sym->id.alias ) )
151  mangled += *sym->id.alias
152  else
153  mangled += str( len( *sym->id.name ) )
154  mangled += *sym->id.name
155  end if
156 end sub
157 
158 function symbGetMangledName( byval sym as FBSYMBOL ptr ) as zstring ptr
159  if( sym->id.mangled ) then
160  return sym->id.mangled
161  end if
162 
163  select case as const( symbGetClass( sym ) )
164  case FB_SYMBCLASS_PROC
165  hMangleProc( sym )
166  case FB_SYMBCLASS_ENUM, FB_SYMBCLASS_STRUCT, FB_SYMBCLASS_FWDREF, _
167  FB_SYMBCLASS_CLASS, FB_SYMBCLASS_NAMESPACE
168  dim as string mangled
169  hMangleNamespace( mangled, symbGetNamespace( sym ), TRUE, FALSE )
170  hMangleUdtId( mangled, sym )
171  if( hIsNested( sym ) ) then
172  mangled += "E"
173  end if
174  symbSetMangledId( sym, mangled )
175  case FB_SYMBCLASS_VAR
176  hMangleVariable( sym )
177  case else
178  return sym->id.alias
179  end select
180 
181  '' Periods in symbol names? not allowed in C, must be replaced.
182  if( env.clopt.backend = FB_BACKEND_GCC ) then
183  if( fbLangOptIsSet( FB_LANG_OPT_PERIODS ) ) then
184  hReplaceChar( sym->id.mangled, asc( "." ), asc( "$" ) )
185  end if
186  end if
187 
188  function = sym->id.mangled
189 end function
190 
192  ctx.cnt = 0
193 end sub
194 
196  '' reset abbreviation list
197  flistReset( @ctx.flist )
198  ctx.cnt = 0
199 end sub
200 
201 function hAbbrevFind _
202  ( _
203  byval dtype as integer, _
204  byval subtype as FBSYMBOL ptr _
205  ) as integer
206 
207  dim as FB_MANGLEABBR ptr n = any
208 
209  if( ctx.cnt = 0 ) then
210  return -1
211  end if
212 
213  '' builtin?
214  if( subtype = NULL ) then
215  if( typeIsPtr( dtype ) = FALSE ) then
216  if( typeGet( dtype ) <> FB_DATATYPE_STRING ) then
217  return -1
218  end if
219  end if
220  end if
221 
222  '' for each item..
223  n = flistGetHead( @ctx.flist )
224  do while( n <> NULL )
225  '' same type?
226  if( n->subtype = subtype ) then
227  if( astGetFullType( n ) = dtype ) then
228  return n->idx
229  end if
230  end if
231 
232  n = flistGetNext( n )
233  loop
234 
235  function = -1
236 end function
237 
238 function hAbbrevAdd _
239  ( _
240  byval dtype as integer, _
241  byval subtype as FBSYMBOL ptr _
242  ) as FB_MANGLEABBR ptr
243 
244  dim as FB_MANGLEABBR ptr n = any
245 
246  n = flistNewItem( @ctx.flist )
247  n->idx = ctx.cnt
248 
249  astGetFullType( n ) = dtype
250  n->subtype = subtype
251 
252  ctx.cnt += 1
253 
254  function = n
255 end function
256 
257 sub hAbbrevGet( byref mangled as string, byval idx as integer )
258  mangled += "S"
259 
260  if( idx > 0 ) then
261  if( idx <= 10 ) then
262  mangled += chr( asc( "0" ) + (idx - 1) )
263  elseif( idx <= 33 ) then
264  mangled += chr( asc( "A" ) + (idx - 11) )
265  else
266  '' 2 digits are enough for 333 abbreviations
267  mangled += chr( idx \ 33 )
268  idx mod= 33
269  if( idx <= 10 ) then
270  mangled += chr( asc( "0" ) + (idx - 1) )
271  elseif( idx <= 33 ) then
272  mangled += chr( asc( "A" ) + (idx - 11) )
273  end if
274  end if
275  end if
276 
277  mangled += "_"
278 end sub
279 
280 function hMangleBuiltInType( byval dtype as integer ) as zstring ptr
281  assert( dtype = typeGetDtOnly( dtype ) )
282 
283  '' STRING isn't mangled as built-in type, but as UDT, but it still needs
284  '' to be handled from here because this function is also used to mangle
285  '' type suffixes under the C backend, and that includes STRINGs...
286  if( dtype = FB_DATATYPE_STRING ) then
287  return @"8FBSTRING"
288  end if
289 
290  if( fbCpuTypeIs64bit( ) ) then
291  '' By default on x86 we mangle INTEGER to "int", but on 64bit
292  '' our INTEGER becomes 64bit, while int stays 32bit, so we
293  '' really shouldn't use the same mangling in that case.
294  ''
295  '' Mangling the 64bit INTEGER as "long long" would conflict
296  '' with the LONGINT mangling though (we cannot allow separate
297  '' INTEGER/LONGINT overloads in code but then generate the same
298  '' mangled id for them, the assembler/linker would complain).
299  ''
300  '' Besides that, our LONG stays 32bit always, but "long" on
301  '' 64bit Linux changes to 64bit, so we shouldn't mangle LONG
302  '' to "long" in that case. It would still be possible on 64bit
303  '' Windows, because there "long" stays 32bit, but it seems best
304  '' to mangle LONG to "int" on 64bit consistently, since "int"
305  '' stays 32bit on both Linux and Windows.
306  ''
307  '' That allows 64bit INTEGER to be mangled as 64bit long on
308  '' Linux & co, making GCC compatibility easier, it's only Win64
309  '' where we need a custom mangling.
310  ''
311  '' Itanium C++ ABI compatible mangling of non-C++ built-in
312  '' types (vendor extended types):
313  '' u <length-of-id> <id>
314 
315  if( env.target.options and FB_TARGETOPT_UNIX ) then
316  select case( dtype )
317  case FB_DATATYPE_INTEGER : return @"l" '' long
318  case FB_DATATYPE_UINT : return @"m" '' unsigned long
319  end select
320  else
321  select case( dtype )
322  case FB_DATATYPE_INTEGER : return @"u7INTEGER" '' seems like a good choice
323  case FB_DATATYPE_UINT : return @"u8UINTEGER"
324  end select
325  end if
326 
327  select case( dtype )
328  case FB_DATATYPE_LONG : return @"i" '' int
329  case FB_DATATYPE_ULONG : return @"j" '' unsigned int
330  end select
331  else
332  select case( dtype )
333  case FB_DATATYPE_INTEGER : return @"i" '' int
334  case FB_DATATYPE_UINT : return @"j" '' unsigned int
335  case FB_DATATYPE_LONG : return @"l" '' long
336  case FB_DATATYPE_ULONG : return @"m" '' unsigned long
337  end select
338  end if
339 
340  static as zstring ptr typecodes(0 to FB_DATATYPES-1) => _
341  { _
342  @"v", _ '' void
343  @"a", _ '' byte (signed char)
344  @"h", _ '' ubyte (unsigned char)
345  @"c", _ '' char
346  @"s", _ '' short
347  @"t", _ '' ushort
348  @"w", _ '' wchar
349  NULL, _ '' integer
350  NULL, _ '' uinteger
351  NULL, _ '' enum
352  NULL, _ '' bitfield
353  NULL, _ '' long
354  NULL, _ '' ulong
355  @"x", _ '' longint (long long)
356  @"y", _ '' ulongint (unsigned long long)
357  @"f", _ '' single
358  @"d", _ '' double
359  NULL, _ '' var-len string
360  NULL, _ '' fix-len string
361  NULL, _ '' struct
362  NULL, _ '' namespace
363  NULL, _ '' function
364  NULL, _ '' fwd-ref
365  NULL _ '' pointer
366  }
367 
368  assert( typecodes(dtype) <> NULL )
369  function = typecodes(dtype)
370 end function
371 
372 sub symbMangleType _
373  ( _
374  byref mangled as string, _
375  byval dtype as integer, _
376  byval subtype as FBSYMBOL ptr _
377  )
378 
379  dim as FBSYMBOL ptr ns = any
380 
381  '' Lookup abbreviation for this type/namespace (if the current procedure
382  '' name already contains the type somewhere, it can be referred to
383  '' through an index instead of by repeating the full name)
384  dim as integer idx = hAbbrevFind( dtype, subtype )
385  if( idx <> -1 ) then
386  hAbbrevGet( mangled, idx )
387  exit sub
388  end if
389 
390  '' forward type?
391  if( typeGet( dtype ) = FB_DATATYPE_FWDREF ) then
392  dtype = typeJoin( dtype and (not FB_DATATYPE_INVALID), FB_DATATYPE_STRUCT )
393  end if
394 
395  select case as const( dtype )
396  case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM ', FB_DATATYPE_CLASS
397  ns = symbGetNamespace( subtype )
398  if( ns = @symbGetGlobalNamespc( ) ) then
399  hMangleUdtId( mangled, subtype )
400  else
401  mangled += "N"
402  symbMangleType( mangled, symbGetFullType( ns ), ns )
403  hMangleUdtId( mangled, subtype )
404  mangled += "E"
405  end if
406 
407  case FB_DATATYPE_NAMESPC
408  if( subtype = @symbGetGlobalNamespc( ) ) then
409  exit sub
410  end if
411 
412  ns = symbGetNamespace( subtype )
413  if( ns ) then
414  symbMangleType( mangled, FB_DATATYPE_NAMESPC, ns )
415  end if
416  hMangleUdtId( mangled, subtype )
417 
418  case FB_DATATYPE_FUNCTION
419  '' F(byref)(const)(return_type)(params - recursive, reuses hash)E
420  mangled += "F"
421 
422  '' return BYREF?
423  if( symbProcReturnsByref( subtype ) ) then
424  '' const?
425  if( typeIsConst( symbGetFullType( subtype ) ) ) then
426  mangled += "RK"
427  else
428  mangled += "R"
429  end if
430  else
431  '' const?
432  if( typeIsConst( symbGetFullType( subtype ) ) ) then
433  mangled += "K"
434  end if
435  end if
436 
437  symbMangleType( mangled, symbGetFullType( subtype ), symbGetSubtype( subtype ) )
438  hGetProcParamsTypeCode( mangled, subtype )
439 
440  mangled += "E"
441 
442  case else
443  '' builtin?
444  if( dtype = typeGetDtOnly( dtype ) ) then
445  mangled += *hMangleBuiltInType( dtype )
446  exit sub
447  end if
448 
449  '' reference?
450  if( typeIsRef( dtype ) ) then
451  '' const?
452  if( typeIsConst( dtype ) ) then
453  mangled += "RK"
454  else
455  mangled + = "R"
456  end if
457  symbMangleType( mangled, typeUnsetIsRef( dtype ), subtype )
458 
459  '' array?
460  elseif( typeIsArray( dtype ) ) then
461  mangled += "A"
462  symbMangleType( mangled, typeUnsetIsArray( dtype ), subtype )
463 
464  '' pointer? (must be checked/emitted before CONST)
465  elseif( typeIsPtr( dtype ) ) then
466  '' const?
467  if( typeIsConstAt( dtype, 1 ) ) then
468  mangled += "PK"
469  else
470  mangled += "P"
471  end if
472 
473  symbMangleType( mangled, typeDeref( dtype ), subtype )
474 
475  '' const..
476  else
477  '' note: nothing is added (as in C++) because it's not a 'const ptr'
478  symbMangleType( mangled, typeUnsetIsConst( dtype ), subtype )
479  end if
480 
481  end select
482 
484 end sub
485 
486 sub symbMangleParam( byref mangled as string, byval param as FBSYMBOL ptr )
487  dim as integer dtype = any
488 
489  dtype = symbGetFullType( param )
490 
491  select case as const( symbGetParamMode( param ) )
492  '' by reference (or descriptor)?
493  case FB_PARAMMODE_BYREF
494  dtype = typeSetIsRef( dtype )
495 
496  case FB_PARAMMODE_BYDESC
497  dtype = typeSetIsRefAndArray( dtype )
498 
499  '' var arg?
500  case FB_PARAMMODE_VARARG
501  mangled += "z"
502  exit sub
503 
504  end select
505 
506  symbMangleType( mangled, dtype, symbGetSubtype( param ) )
507 end sub
508 
509 function hAddUnderscore( ) as integer
510  '' C backend? don't add underscores; gcc will already do it.
511  if( env.clopt.backend = FB_BACKEND_GCC ) then
512  function = FALSE
513  else
514  '' For ASM, add underscores if the target requires it
515  function = ((env.target.options and FB_TARGETOPT_UNDERSCORE) <> 0)
516  end if
517 end function
518 
519 function hDoCppMangling( byval sym as FBSYMBOL ptr ) as integer
520  '' C++?
521  if( symbGetMangling( sym ) = FB_MANGLING_CPP ) then
522  return TRUE
523  end if
524 
525  '' RTL or exclude parent?
526  if( (symbGetStats( sym ) and (FB_SYMBSTATS_RTL or _
527  FB_SYMBSTATS_EXCLPARENT)) <> 0 ) then
528  return FALSE
529  end if
530 
531  '' inside a namespace or class?
532  if( symbGetNamespace( sym ) <> @symbGetGlobalNamespc( ) ) then
533  return TRUE
534  end if
535 
536  if( sym->class = FB_SYMBCLASS_PROC ) then
537  '' overloaded? (this will handle operators too)
538  if( symbIsOverloaded( sym ) ) then
539  return TRUE
540  end if
541  end if
542 
543  function = FALSE
544 end function
545 
546 sub hMangleNamespace _
547  ( _
548  byref mangled as string, _
549  byval ns as FBSYMBOL ptr, _
550  byval dohashing as integer, _
551  byval isconst as integer _
552  )
553 
554  static as FBSYMBOL ptr nsStk(0 to FB_MAXNAMESPCRECLEVEL-1)
555  dim as integer tos = any
556 
557  if( ns = NULL ) then
558  exit sub
559  end if
560 
561  if( ns = @symbGetGlobalNamespc( ) ) then
562  exit sub
563  end if
564 
565  if( dohashing ) then
566  '' Just add the abbreviation for this if not yet done
567  if( hAbbrevFind( symbGetFullType( ns ), ns ) = -1 ) then
568  hAbbrevAdd( symbGetFullType( ns ), ns )
569  end if
570  end if
571 
572  '' create a stack
573  tos = -1
574  do
575  tos += 1
576  nsStk(tos) = ns
577  ns = symbGetNamespace( ns )
578  loop until( ns = @symbGetGlobalNamespc( ) )
579 
580  '' return the chain starting from base parent
581  mangled += "N"
582  if( isconst ) then
583  mangled += "K"
584  end if
585  do
586  ns = nsStk(tos)
587  hMangleUdtId( mangled, ns )
588  tos -= 1
589  loop until( tos < 0 )
590 end sub
591 
592 sub hMangleVariable( byval sym as FBSYMBOL ptr )
593  static as string id
594  static as integer varcounter
595  dim as string mangled
596  dim as zstring ptr p = any
597  dim as integer docpp = any, isglobal = any
598 
599  '' local? no mangling
600  if( sym->scope > FB_MAINSCOPE ) then
601  docpp = FALSE
602  else
603  docpp = hDoCppMangling( sym )
604  end if
605 
606  '' prefix
607  '' public global/static?
608  if( sym->attrib and (FB_SYMBATTRIB_PUBLIC or FB_SYMBATTRIB_EXTERN or _
609  FB_SYMBATTRIB_SHARED or FB_SYMBATTRIB_COMMON or _
610  FB_SYMBATTRIB_STATIC) ) then
611  '' LLVM: @ prefix for global symbols
612  if( env.clopt.backend = FB_BACKEND_LLVM ) then
613  mangled += "@"
614  end if
615 
616  select case( env.clopt.target )
617  case FB_COMPTARGET_WIN32, FB_COMPTARGET_CYGWIN
618  '' Win32 import? Don't add the prefix under the C backend; it will use
619  '' __declspec(dllimport) instead in order to let gcc do it.
620  if( (env.clopt.backend = FB_BACKEND_GAS) and symbIsImport( sym ) ) then
621  mangled += "__imp_"
622  end if
623  end select
624 
625  '' Win32 underscore prefix
626  if( hAddUnderscore( ) ) then
627  mangled += "_"
628  end if
629 
630  if( docpp ) then
631  '' Note: This adds the _Z prefix to all global variables,
632  '' unlike GCC, which does C++ mangling only for globals inside
633  '' namespaces, but not globals from the toplevel namespace.
634  mangled += "_Z"
635 
636  if( sym->stats and FB_SYMBSTATS_RTTITABLE ) then
637  mangled += "TS"
638  elseif( sym->stats and FB_SYMBSTATS_VTABLE ) then
639  mangled += "TV"
640  end if
641  end if
642  else
643  '' LLVM: % prefix for local symbols
644  if( env.clopt.backend = FB_BACKEND_LLVM ) then
645  mangled += "%"
646  end if
647  end if
648 
649  '' namespace
650  if( docpp ) then
651  hMangleNamespace( mangled, symbGetNamespace( sym ), FALSE, FALSE )
652  end if
653 
654  '' class (once static member variables are added)
655 
656  '' rtti/vtables don't have an id, their mangled name is just the prefixes
657  '' plus the parent UDT namespace(s), all done above already
658  if( sym->stats and (FB_SYMBSTATS_RTTITABLE or FB_SYMBSTATS_VTABLE) ) then
659  id = ""
660  '' id
661  elseif( sym->stats and FB_SYMBSTATS_HASALIAS ) then
662  '' Explicit var ALIAS given, overriding the default id
663  id = *sym->id.alias
664  else
665  '' shared, public, extern or inside a ns?
666  isglobal = ((sym->attrib and (FB_SYMBATTRIB_PUBLIC or FB_SYMBATTRIB_EXTERN or _
667  FB_SYMBATTRIB_SHARED or FB_SYMBATTRIB_COMMON)) <> 0)
668 
669  if( isglobal or docpp ) then
670  '' BASIC? use the upper-cased name
671  if( symbGetMangling( sym ) = FB_MANGLING_BASIC ) then
672  id = *sym->id.name
673  if( env.clopt.backend = FB_BACKEND_GCC ) then
674  id += "$"
675  end if
676  '' else, the case-sensitive name saved in the alias..
677  else
678  id = *sym->id.alias
679  end if
680 
681  '' suffixed?
682  if( symbIsSuffixed( sym ) ) then
683  id += *hMangleBuiltInType( symbGetType( sym ) )
684  if( env.clopt.backend = FB_BACKEND_GCC ) then
685  id += "$"
686  end if
687  end if
688  else
689  select case( env.clopt.backend )
690  case FB_BACKEND_GCC
691  '' ir-hlc emits statics with dtors as globals,
692  '' so they need a unique name. Other statics are
693  '' still emitted locally, so they can keep their
694  '' own name, like other local vars.
695  if( symbIsStatic( sym ) and symbHasDtor( sym ) ) then
696  id = *symbUniqueId( )
697  else
698  if( symbGetMangling( sym ) = FB_MANGLING_BASIC ) then
699  '' BASIC mangling, use the upper-cased name
700  id = *sym->id.name
701 
702  '' Using '$' to prevent collision with C keywords etc.
703  '' ('$' isn't allowed as part of FB ids)
704  id += "$"
705 
706  '' Type suffix?
707  if( symbIsSuffixed( sym ) ) then
708  '' Encode the type to prevent collisions with other variables
709  '' using the same base id but different type suffix.
710  id += *hMangleBuiltInType( symbGetType( sym ) )
711  id += "$"
712  end if
713 
714  '' Append the scope level to prevent collisions with symbols
715  '' from parent scopes or from the toplevel namespace.
716  '' Note: locals from the main scope will start at level 0,
717  '' while locals from procedures start at level 1,
718  '' but that's ok as long as globals aren't suffixed with
719  '' a level at all.
720  id += str( sym->scope )
721  else
722  '' Use the case-sensitive name saved in the alias
723  id = *sym->id.alias
724  end if
725  end if
726  case FB_BACKEND_LLVM
727  if( symbGetMangling( sym ) = FB_MANGLING_BASIC ) then
728  '' BASIC mangling, use the upper-cased name
729  id = *sym->id.name
730 
731  '' Type suffix?
732  if( symbIsSuffixed( sym ) ) then
733  id += *hMangleBuiltInType( symbGetType( sym ) )
734  end if
735 
736  '' Make the symbol unique - LLVM IR doesn't have scopes.
737  '' (appending the scope level wouldn't be enough due to
738  '' conflicts between sibling scopes)
739  id += "." + str( varcounter )
740  varcounter += 1
741  else
742  '' Use the case-sensitive name saved in the alias
743  id = *sym->id.alias
744  end if
745  case else '' ASM backend
746  if( symbIsStatic( sym ) ) then
747  id = *symbUniqueId( )
748  else
749  id = *irProcGetFrameRegName( )
750  end if
751  end select
752  end if
753  end if
754 
755  if( len( id ) > 0 ) then
756  '' id length (C++ only) followed by the id itself
757  if( docpp ) then
758  mangled += str( len( id ) )
759  end if
760  mangled += id
761  end if
762 
763  if( docpp ) then
764  '' nested? (namespace or class)
765  if( hIsNested( sym ) ) then
766  mangled += "E"
767  end if
768  end if
769 
770  symbSetMangledId( sym, mangled )
771 end sub
772 
774  ( _
775  byref mangled as string, _
776  byval sym as FBSYMBOL ptr _
777  )
778 
779  dim as FBSYMBOL ptr param = any
780  dim as integer dtype = any
781 
782  param = symbGetProcHeadParam( sym )
783  if( param <> NULL ) then
784  '' instance pointer? skip..
785  if( symbIsParamInstance( param ) ) then
786  param = symbGetParamNext( param )
787  end if
788  end if
789 
790  '' no params?
791  if( param = NULL ) then
792  '' void
793  mangled += "v"
794  exit sub
795  end if
796 
797  '' for each param...
798  do
799  symbMangleParam( mangled, param )
800  param = symbGetParamNext( param )
801  loop while( param )
802 end sub
803 
804 function hGetOperatorName( byval proc as FBSYMBOL ptr ) as const zstring ptr
805  ''
806  '' Most operators follow the "Operator Encodings" section of the
807  '' Itanium C++ ABI.
808  ''
809  '' However, FB has some operators that C++ doesn't have, these "custom"
810  '' operators should use the predefined scheme of the ABI, to allow
811  '' C++-compatible tools to demangle them:
812  '' v <num-args> <length> <name>
813  '' where <num-args> is the operand count as a single decimal
814  '' digit, and <length> is the length of <name>.
815  ''
816  select case as const symbGetProcOpOvl( proc )
817  case AST_OP_ASSIGN
818  function = @"aS"
819 
820  case AST_OP_ADD
821  function = @"pl"
822 
823  case AST_OP_ADD_SELF
824  function = @"pL"
825 
826  case AST_OP_SUB
827  function = @"mi"
828 
829  case AST_OP_SUB_SELF
830  function = @"mI"
831 
832  case AST_OP_MUL
833  function = @"ml"
834 
835  case AST_OP_MUL_SELF
836  function = @"mL"
837 
838  case AST_OP_DIV
839  function = @"dv"
840 
841  case AST_OP_DIV_SELF
842  function = @"dV"
843 
844  case AST_OP_INTDIV
845  function = @"v24idiv"
846 
847  case AST_OP_INTDIV_SELF
848  function = @"v28selfidiv"
849 
850  case AST_OP_MOD
851  function = @"rm"
852 
853  case AST_OP_MOD_SELF
854  function = @"rM"
855 
856  case AST_OP_AND
857  function = @"an"
858 
859  case AST_OP_AND_SELF
860  function = @"aN"
861 
862  case AST_OP_OR
863  function = @"or"
864 
865  case AST_OP_OR_SELF
866  function = @"oR"
867 
868  '' Note: The ANDALSO/ORELSE operators can't currently be
869  '' overloaded, much less the self versions
870  case AST_OP_ANDALSO
871  function = @"aa"
872 
873  case AST_OP_ANDALSO_SELF
874  function = @"aA" '' FB-specific
875 
876  case AST_OP_ORELSE
877  function = @"oo"
878 
879  case AST_OP_ORELSE_SELF
880  function = @"oO" '' FB-specific
881 
882  case AST_OP_XOR
883  function = @"eo"
884 
885  case AST_OP_XOR_SELF
886  function = @"eO"
887 
888  case AST_OP_EQV
889  function = @"v23eqv"
890 
891  case AST_OP_EQV_SELF
892  function = @"v27selfeqv"
893 
894  case AST_OP_IMP
895  function = @"v23imp"
896 
897  case AST_OP_IMP_SELF
898  function = @"v27selfimp"
899 
900  case AST_OP_SHL
901  function = @"ls"
902 
903  case AST_OP_SHL_SELF
904  function = @"lS"
905 
906  case AST_OP_SHR
907  function = @"rs"
908 
909  case AST_OP_SHR_SELF
910  function = @"rS"
911 
912  case AST_OP_POW
913  function = @"v23pow"
914 
915  case AST_OP_POW_SELF
916  function = @"v27selfpow"
917 
918  case AST_OP_CONCAT
919  function = @"v23cat"
920 
921  case AST_OP_CONCAT_SELF
922  function = @"v27selfcat"
923 
924  case AST_OP_EQ
925  function = @"eq"
926 
927  case AST_OP_GT
928  function = @"gt"
929 
930  case AST_OP_LT
931  function = @"lt"
932 
933  case AST_OP_NE
934  function = @"ne"
935 
936  case AST_OP_GE
937  function = @"ge"
938 
939  case AST_OP_LE
940  function = @"le"
941 
942  case AST_OP_NOT
943  function = @"co"
944 
945  case AST_OP_NEG
946  function = @"ng"
947 
948  case AST_OP_PLUS
949  function = @"ps"
950 
951  case AST_OP_ABS
952  function = @"v13abs"
953 
954  case AST_OP_FIX
955  function = @"v13fix"
956 
957  case AST_OP_FRAC
958  function = @"v14frac"
959 
960  case AST_OP_SGN
961  function = @"v13sgn"
962 
963  case AST_OP_FLOOR
964  function = @"v13int"
965 
966  case AST_OP_EXP
967  function = @"v13exp"
968 
969  case AST_OP_LOG
970  function = @"v13log"
971 
972  case AST_OP_SIN
973  function = @"v13sin"
974 
975  case AST_OP_ASIN
976  function = @"v14asin"
977 
978  case AST_OP_COS
979  function = @"v13cos"
980 
981  case AST_OP_ACOS
982  function = @"v14acos"
983 
984  case AST_OP_TAN
985  function = @"v13tan"
986 
987  case AST_OP_ATAN
988  function = @"v13atn"
989 
990  case AST_OP_NEW, AST_OP_NEW_SELF
991  function = @"nw"
992 
993  case AST_OP_NEW_VEC, AST_OP_NEW_VEC_SELF
994  function = @"na"
995 
996  case AST_OP_DEL, AST_OP_DEL_SELF
997  function = @"dl"
998 
999  case AST_OP_DEL_VEC, AST_OP_DEL_VEC_SELF
1000  function = @"da"
1001 
1002  case AST_OP_DEREF
1003  function = @"de"
1004 
1005  case AST_OP_FLDDEREF
1006  function = @"pt"
1007 
1008  case AST_OP_PTRINDEX
1009  function = @"ix"
1010 
1011  case AST_OP_ADDROF
1012  function = @"ad"
1013 
1014  case AST_OP_FOR
1015  '' operator T.for( [ as T ] )
1016  if( symbGetProcParams( proc ) = 2 ) then
1017  function = @"v13for"
1018  else
1019  assert( symbGetProcParams( proc ) = 1 )
1020  function = @"v03for"
1021  end if
1022 
1023  case AST_OP_STEP
1024  '' operator T.step( [ as T ] )
1025  if( symbGetProcParams( proc ) = 2 ) then
1026  function = @"v14step"
1027  else
1028  assert( symbGetProcParams( proc ) = 1 )
1029  function = @"v04step"
1030  end if
1031 
1032  case AST_OP_NEXT
1033  '' operator T.next( as T [ , as T ] )
1034  if( symbGetProcParams( proc ) = 3 ) then
1035  function = @"v24next"
1036  else
1037  assert( symbGetProcParams( proc ) = 2 )
1038  function = @"v14next"
1039  end if
1040 
1041  end select
1042 end function
1043 
1044 sub hMangleProc( byval sym as FBSYMBOL ptr )
1045  dim as string mangled
1046  dim as integer length = any, docpp = any
1047  dim as zstring ptr id = any
1048 
1049  docpp = hDoCppMangling( sym )
1050 
1052 
1053  '' LLVM: @ prefix for global symbols
1054  if( env.clopt.backend = FB_BACKEND_LLVM ) then
1055  mangled += "@"
1056 
1057  '' Going to add @N stdcall suffix below?
1058  if( sym->proc.mode = FB_FUNCMODE_STDCALL ) then
1059  '' In LLVM, @ is a special char, identifiers using it must be quoted
1060  mangled += """"
1061  end if
1062  end if
1063 
1064  '' Win32 underscore prefix
1065  if( hAddUnderscore( ) ) then
1066  mangled += "_"
1067  end if
1068 
1069  '' C++ prefix
1070  if( docpp ) then
1071  mangled += "_Z"
1072  end if
1073 
1074  '' namespace or class
1075  if( docpp ) then
1076  hMangleNamespace( mangled, symbGetNamespace( sym ), TRUE, symbIsConstant( sym ) )
1077  end if
1078 
1079  '' id
1080  if( (sym->stats and FB_SYMBSTATS_HASALIAS) <> 0 ) then
1081  '' Explicit proc ALIAS given, overriding the default id
1082  '' (even for constructors, operators and properties)
1083  '' id length (C++ only)
1084  if( docpp ) then
1085  mangled += str( len( *sym->id.alias ) )
1086  end if
1087  '' id
1088  mangled += *sym->id.alias
1089  elseif( symbIsOperator( sym ) ) then
1090  if( symbGetProcOpOvl( sym ) = AST_OP_CAST ) then
1091  mangled += "cv"
1092  '' mangle the return type
1093  symbMangleType( mangled, symbGetFullType( sym ), symbGetSubtype( sym ) )
1094  else
1095  mangled += *hGetOperatorName( sym )
1096  end if
1097  elseif( symbIsConstructor( sym ) ) then
1098  mangled += "C1"
1099  elseif( symbIsDestructor( sym ) ) then
1100  mangled += "D1"
1101  else
1102  if( symbGetMangling( sym ) = FB_MANGLING_BASIC ) then
1103  '' BASIC, use the upper-cased name
1104  id = sym->id.name
1105  else
1106  '' use the case-sensitive name saved in the alias
1107  id = sym->id.alias
1108  end if
1109 
1110  '' id length (C++ only)
1111  if( docpp ) then
1112  length = len( *id )
1113  if( symbIsProperty( sym ) ) then
1114  length += 7 '' __get__ or __set__ (see below)
1115  end if
1116  mangled += str( length )
1117  end if
1118 
1119  '' id
1120  mangled += *id
1121  if( symbIsProperty( sym ) ) then
1122  '' custom property mangling,
1123  '' since the base id is the same for setters/getters
1124  '' GET?
1125  if( symbGetType( sym ) = FB_DATATYPE_VOID ) then
1126  mangled += "__set__"
1127  else
1128  mangled += "__get__"
1129  end if
1130  end if
1131  end if
1132 
1133  '' params
1134  if( docpp ) then
1135  '' nested? (namespace or class)
1136  if( hIsNested( sym ) ) then
1137  mangled += "E"
1138  end if
1139  hGetProcParamsTypeCode( mangled, sym )
1140  end if
1141 
1142  '' @N win32 stdcall suffix
1143  if( sym->proc.mode = FB_FUNCMODE_STDCALL ) then
1144  '' But not for the C backend, because gcc will do it already.
1145  if( env.clopt.backend <> FB_BACKEND_GCC ) then
1146  mangled += "@" + str( symbCalcProcParamsLen( sym ) )
1147  end if
1148 
1149  if( env.clopt.backend = FB_BACKEND_LLVM ) then
1150  '' In LLVM, @ is a special char, identifiers using it must be quoted
1151  mangled += """"
1152  end if
1153  end if
1154 
1156 
1157  symbSetMangledId( sym, mangled )
1158 end sub
1159