Skip to content

Commit 3e7cdd6

Browse files
authored
Merge pull request #105 from jayrm/mangling
Name mangling on win target #890: Fix Bad @n stdcall suffix for non-trivial byval type parameters with -gen gcc Changes in this pull request are based on, and related to: #828 32bit Integer/Long mangling reversed By default, fbc's Long/ULong data type maps to c's int type, and since Integer/Uinteger are meant to be (consistently) 64bits in fbc-64bit, there is no other type that (by default) that can map to c's long int, which is 32bit even on Win64. So, in Win64, to allow calling an external library that needs a 'long int' parameter there is the following, non-portable mangling modifier. It is ignored for all targets except Win64. map fbc's 32bit 'LONG' type to Win64's 32bit 'long' type type cxxlongint as long alias "long"
2 parents 75288fa + e07d3bf commit 3e7cdd6

File tree

7 files changed

+167
-121
lines changed

7 files changed

+167
-121
lines changed

changelog.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Version 1.06.0
22

33
[changed]
4+
- Name mangling of Integer/Long parameters was reversed on 32bit to match 64bit, so the same FB and C++ code will be compatible on both 32bit and 64bit. Integer is mangled as C++ long (except on Win64), Long is mangled as C++ int.
45
- Adjusted warning text for "mixed bool/nonbool operands" warning
56
- test-suite uses libfbcunit for unit testing framework
67
- SELECT CASE AS CONST respects data type and will show overflow warnings on out-of-range constants
@@ -9,6 +10,7 @@ Version 1.06.0
910
- WSTRING can be a return type, but only for prototypes (DECLARE) and function pointers, this allows getting PROCPTR() of all fb built-in run time functions
1011

1112
[added]
13+
- Name mangling of Long parameters on Win64 are mangled to C++ int by default and to C++ long with a modifier in the form 'as [u]long alias "long"'. The data type size is still 32bit but allows calling external C++ library expecting a C++ long.
1214
- -noobjinfo option to disable the writing/reading of compile-time library and other linking options from/to .o and .a files. This also disables the use of fbextra.x (the supplemental linker script) for discarding the .fbctinf sections, which is useful when using the gold linker that doesn't support this kind of linker script.
1315
- Linux console Inkey() now recognizes F11 and F12
1416
- 2D render through OpenGL on Windows and Linux via screencontrol (angros47)
@@ -69,6 +71,7 @@ Version 1.06.0
6971
- #822, #814, #842: Compiler crash when initializing static/shared reference (DIM SHARED/STATIC BYREF) with non-constant initializer (e.g. another reference, or dynamic array element)
7072
- ASM backend: Fix bad code generated for comparisons such as IF @globalvar = 0 THEN
7173
- #884: FORMATing dates can deadlock under Unix
74+
- #890: Fix Bad @N stdcall suffix for non-trivial byval type parameters with -gen gcc
7275
- #642, #886: CASTs involving CONST qualifiers solved out too early allowing invalid statements to be compiled
7376
- #801: *@(expr) solved to (expr) did not cleanly remove null ptr checks allowing invalid datatype assignment with -exx. *PTRCHK(@expr) solves to (expr).
7477
- #880: Overload binary operators now support covariant arguments, overloaded procedure resolution changed especially with respect to CONST and non-CONST parameters

src/compiler/ir-hlc.bas

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ declare sub _emitDBG _
223223
( _
224224
byval op as integer, _
225225
byval proc as FBSYMBOL ptr, _
226-
byval lnum as integer, _
227-
ByVal filename As zstring ptr = 0 _
226+
byval lnum as integer, _
227+
ByVal filename As zstring ptr = 0 _
228228
)
229229

230230
declare sub exprFreeNode( byval n as EXPRNODE ptr )
@@ -505,11 +505,13 @@ private function hNeedAlias( byval proc as FBSYMBOL ptr ) as integer
505505
function = TRUE
506506

507507
'' For stdcall with @N suffix, if the function has a hidden UDT result
508-
'' pointer parameter, we need the alias to get the correct @N suffix.
509-
'' (gcc would calculate the parameter into the @N suffix, since it
510-
'' doesn't know that the parameter is the special result parameter)
508+
'' pointer parameter, or UDT's passed byval, we need the alias to get
509+
'' the correct @N suffix. (gcc could calculate the wrong value into the
510+
'' @N suffix, since it doesn't known about the special result parameter
511+
'' or byval UDTs). It should be safe to always generate the alias
512+
'' ourselves since we already must control for the special cases.
511513
case FB_FUNCMODE_STDCALL
512-
function = symbProcReturnsOnStack( proc )
514+
function = TRUE
513515
end select
514516
end function
515517

@@ -3159,15 +3161,15 @@ private sub _emitDBG _
31593161
( _
31603162
byval op as integer, _
31613163
byval proc as FBSYMBOL ptr, _
3162-
byval lnum as integer, _
3163-
ByVal filename As zstring ptr _
3164+
byval lnum as integer, _
3165+
ByVal filename As zstring ptr _
31643166
)
31653167

31663168
if( op = AST_OP_DBG_LINEINI ) then
3167-
ctx.linenum = lnum
3169+
ctx.linenum = lnum
31683170
if( filename <> NULL ) then
31693171
hUpdateCurrentFileName( filename )
3170-
end if
3172+
end if
31713173
end if
31723174

31733175
end sub

src/compiler/parser-decl-symbtype.bas

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,48 @@ function hIntegerTypeFromBitSize _
393393

394394
end function
395395

396+
private function cMangleModifier _
397+
( _
398+
) as integer
399+
400+
function = FALSE
401+
402+
'' currently, cMangleModifier() returns true/false, because
403+
'' we are checking for one case only. And the FB_DATATYPE
404+
'' stored in the upper bits of the dtype in FB_DT_MANGLEMASK
405+
'' was selected for convenience. In future, it might be
406+
'' better to have a new FB_MANGLE_DATATYPE enum for tracking
407+
'' the desired mapping stored in the upper bits of the
408+
'' dtype, especially if there are some mappings that can't
409+
'' be found in existing FB_DATATYPE. To support additional
410+
'' checks and mappings, should probably pass a dtype
411+
'' parameter in to this procedure to be updated or returned.
412+
413+
'' ALIAS?
414+
if( lexGetToken( ) = FB_TK_ALIAS ) then
415+
lexSkipToken( )
416+
417+
'' "long"?
418+
if( lexGetClass( ) = FB_TKCLASS_STRLITERAL ) then
419+
select case lcase( *lexGetText( ) )
420+
case "long"
421+
'' only Win64 is affected by ths modifer
422+
function = fbIs64bit( ) and ((env.target.options and FB_TARGETOPT_UNIX) = 0)
423+
case ""
424+
errReport( FB_ERRMSG_EMPTYALIASSTRING )
425+
case else
426+
errReport( FB_ERRMSG_SYNTAXERROR )
427+
end select
428+
429+
lexSkipToken( )
430+
else
431+
errReport( FB_ERRMSG_SYNTAXERROR )
432+
end if
433+
434+
end if
435+
436+
end function
437+
396438
'':::::
397439
''SymbolType = CONST? UNSIGNED? (
398440
'' ANY
@@ -528,10 +570,16 @@ function cSymbolType _
528570
case FB_TK_LONG
529571
lexSkipToken( )
530572
dtype = FB_DATATYPE_LONG
573+
if( cMangleModifier() ) then
574+
dtype = typeSetMangleDt( dtype, FB_DATATYPE_INTEGER )
575+
end if
531576

532577
case FB_TK_ULONG
533578
lexSkipToken( )
534579
dtype = FB_DATATYPE_ULONG
580+
if( cMangleModifier() ) then
581+
dtype = typeSetMangleDt( dtype, FB_DATATYPE_UINT )
582+
end if
535583

536584
case FB_TK_LONGINT
537585
lexSkipToken( )
@@ -668,7 +716,11 @@ function cSymbolType _
668716
dtype = FB_DATATYPE_UINT
669717

670718
case FB_DATATYPE_LONG
671-
dtype = FB_DATATYPE_ULONG
719+
if( typeHasMangleDt( dtype ) ) then
720+
dtype = typeSetMangleDt( FB_DATATYPE_ULONG, FB_DATATYPE_UINT )
721+
else
722+
dtype = FB_DATATYPE_ULONG
723+
end if
672724

673725
case FB_DATATYPE_LONGINT
674726
dtype = FB_DATATYPE_ULONGINT

src/compiler/symb-mangling.bas

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ function hMangleBuiltInType _
319319
byref add_abbrev as integer _
320320
) as zstring ptr
321321

322-
assert( dtype = typeGetDtOnly( dtype ) )
322+
assert( dtype = (typeGetDtOnly( dtype ) or (dtype and FB_DT_MANGLEMASK)) )
323323

324324
''
325325
'' Plain unqualified C++ built-in types are not considered for abbreviation.
@@ -336,74 +336,81 @@ function hMangleBuiltInType _
336336
return @"8FBSTRING"
337337
end if
338338

339-
if( fbIs64bit( ) ) then
340-
'' By default on x86 we mangle INTEGER to "int", but on 64bit
341-
'' our INTEGER becomes 64bit, while int stays 32bit, so we
342-
'' really shouldn't use the same mangling in that case.
343-
''
344-
'' Mangling the 64bit INTEGER as "long long" would conflict
345-
'' with the LONGINT mangling though (we cannot allow separate
346-
'' INTEGER/LONGINT overloads in code but then generate the same
347-
'' mangled id for them, the assembler/linker would complain).
348-
''
349-
'' Besides that, our LONG stays 32bit always, but "long" on
350-
'' 64bit Linux changes to 64bit, so we shouldn't mangle LONG
351-
'' to "long" in that case. It would still be possible on 64bit
352-
'' Windows, because there "long" stays 32bit, but it seems best
353-
'' to mangle LONG to "int" on 64bit consistently, since "int"
354-
'' stays 32bit on both Linux and Windows.
355-
''
356-
'' That allows 64bit INTEGER to be mangled as 64bit long on
357-
'' Linux & co, making GCC compatibility easier, it's only Win64
358-
'' where we need a custom mangling.
359-
''
360-
'' Itanium C++ ABI compatible mangling of non-C++ built-in
361-
'' types (vendor extended types):
362-
'' u <length-of-id> <id>
363-
364-
if( env.target.options and FB_TARGETOPT_UNIX ) then
339+
''
340+
'' Integer/Long mangling:
341+
''
342+
'' 32bit 64bit
343+
'' Integer long long (Unix) or INTEGER (Windows)
344+
'' Long int int
345+
'' LongInt long long long long
346+
''
347+
'' - Fundamental problem: FB and C++ types are different, an exact mapping
348+
'' is impossible
349+
''
350+
'' - mangling should match the C/C++ binding recommendations, i.e. use Long
351+
'' for int and Integer for things like ssize_t. On linux-x86_64 Integer
352+
'' can be mangled as long, but on win64 the only 64bit integer type is
353+
'' long long and that's already used for LongInt. So it seems that we have
354+
'' to use a custom mangling for that case (INTEGER).
355+
''
356+
'' - 32bit fbc used to mangle Integer as int and Long as long, but to match
357+
'' 64bit fbc it was reversed, allowing the same FB and C++ code to work
358+
'' together on both 32bit and 64bit.
359+
''
360+
'' - as special expection for windows 64bit, to get a 32bit type that will
361+
'' mangle to C++ long, allow 'as [u]long alias "[u]long"' declarations.
362+
'' The size of LONG/ULONG does not change, it's 32bit, only the mangling,
363+
'' so fbc programs can call C++ code requiring 'long int' arguments.
364+
365+
if( fbIs64bit( ) and ((env.target.options and FB_TARGETOPT_UNIX) = 0) ) then
366+
'' Windows 64bit
367+
368+
'' check for remapping of dtype mangling
369+
if( typeHasMangleDt( dtype ) ) then
370+
dtype = typeGetMangleDt( dtype )
371+
'' Windows 64bit
365372
select case( dtype )
366373
case FB_DATATYPE_INTEGER : return @"l" '' long
367374
case FB_DATATYPE_UINT : return @"m" '' unsigned long
368375
end select
369376
else
377+
'' Itanium C++ ABI compatible mangling of non-C++ built-in types (vendor extended types):
378+
'' u <length-of-id> <id>
370379
select case( dtype )
371380
case FB_DATATYPE_INTEGER : add_abbrev = TRUE : return @"u7INTEGER" '' seems like a good choice
372381
case FB_DATATYPE_UINT : add_abbrev = TRUE : return @"u8UINTEGER"
373382
end select
374383
end if
375384

376-
select case( dtype )
377-
case FB_DATATYPE_LONG : return @"i" '' int
378-
case FB_DATATYPE_ULONG : return @"j" '' unsigned int
379-
end select
380385
else
386+
'' 32bit, Unix 64bit
381387
select case( dtype )
382-
case FB_DATATYPE_INTEGER : return @"i" '' int
383-
case FB_DATATYPE_UINT : return @"j" '' unsigned int
384-
case FB_DATATYPE_LONG : return @"l" '' long
385-
case FB_DATATYPE_ULONG : return @"m" '' unsigned long
388+
case FB_DATATYPE_INTEGER : return @"l" '' long
389+
case FB_DATATYPE_UINT : return @"m" '' unsigned long
386390
end select
387391
end if
388392

393+
'' dtype should be a FB_DATATYPE by now
394+
assert( dtype = typeGetDtOnly( dtype ) )
395+
389396
static as zstring ptr typecodes(0 to FB_DATATYPES-1) => _
390397
{ _
391398
@"v", _ '' void
392399
@"b", _ '' boolean
393-
@"a", _ '' byte (signed char)
394-
@"h", _ '' ubyte (unsigned char)
400+
@"a", _ '' Byte: signed char
401+
@"h", _ '' UByte: unsigned char
395402
@"c", _ '' char
396403
@"s", _ '' short
397404
@"t", _ '' ushort
398405
@"w", _ '' wchar
399-
NULL, _ '' integer
400-
NULL, _ '' uinteger
406+
NULL, _ '' Integer
407+
NULL, _ '' UInteger
401408
NULL, _ '' enum
402-
NULL, _ '' long
403-
NULL, _ '' ulong
404-
@"x", _ '' longint (long long)
405-
@"y", _ '' ulongint (unsigned long long)
406-
@"f", _ '' single
409+
@"i", _ '' Long: int
410+
@"j", _ '' ULong: unsigned int
411+
@"x", _ '' LongInt: long long
412+
@"y", _ '' ULongInt: unsigned long long
413+
@"f", _ '' Single: float
407414
@"d", _ '' double
408415
NULL, _ '' var-len string
409416
NULL, _ '' fix-len string
@@ -493,7 +500,7 @@ sub symbMangleType _
493500
''
494501
'' Plain type without reference/pointer/const bits
495502
''
496-
assert( dtype = typeGetDtOnly( dtype ) )
503+
assert( dtype = (typeGetDtOnly( dtype ) or (dtype and FB_DT_MANGLEMASK)) )
497504

498505
select case( dtype )
499506
case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM

src/compiler/symb.bi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,16 @@ const FB_DT_TYPEMASK = &b00000000000000000000000000011111 '' max 32 built-in d
5757
const FB_DT_PTRMASK = &b00000000000000000000000111100000 '' level of pointer indirection
5858
const FB_DT_CONSTMASK = &b00000000000000111111111000000000 '' PTRLEVELS + 1 bit-masks
5959
const FB_DATATYPE_REFERENCE = &b00000000000010000000000000000000 '' used for mangling BYREF parameters
60+
const FB_DT_MANGLEMASK = &b00000001111100000000000000000000 '' used to modify mangling for builtin types
6061
const FB_DATATYPE_INVALID = &b10000000000000000000000000000000
6162

6263
const FB_DT_PTRLEVELS = 8 '' max levels of pointer indirection
6364

6465
const FB_DT_PTRPOS = 5
6566
const FB_DT_CONSTPOS = FB_DT_PTRPOS + 4
6667

68+
const FB_DT_MANGLEPOS = 20
69+
6770
enum FB_OVLPROC_MATCH_SCORE
6871
FB_OVLPROC_NO_MATCH = 0
6972
FB_OVLPROC_LOWEST_MATCH = 1
@@ -2492,6 +2495,10 @@ declare sub symbProcRecalcRealType( byval proc as FBSYMBOL ptr )
24922495
#define typeSetIsRef( dt ) (dt or FB_DATATYPE_REFERENCE)
24932496
#define typeUnsetIsRef( dt ) (dt and not FB_DATATYPE_REFERENCE)
24942497

2498+
#define typeHasMangleDt( dt ) (((dt and FB_DT_MANGLEMASK) <> 0))
2499+
#define typeGetMangleDt( dt ) ((dt and FB_DT_MANGLEMASK) shr FB_DT_MANGLEPOS)
2500+
#define typeSetMangleDt( dt, mangle_dt ) ((dt and not FB_DT_MANGLEMASK) or ((mangle_dt shl FB_DT_MANGLEPOS) and FB_DT_MANGLEMASK ))
2501+
24952502
declare sub symbForEachGlobal _
24962503
( _
24972504
byval symclass as integer, _

0 commit comments

Comments
 (0)