Skip to content

Commit 0540479

Browse files
authored
Merge pull request #304 from jayrm/thiscall
- github # 303 Add deleting destructor for c++ ABI - github # 304 thiscall calling convention (-gen gcc only)
2 parents 180516f + eed449c commit 0540479

36 files changed

+1669
-73
lines changed

changelog.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Version 1.08.0
4646
- only write debug line information for statements and don't write comments / empty lines / directives for top level source code in assembly debug ouput
4747
- optimize byref 'm += s' string concatenations to fb_StrConcatByref() which will check for same string descriptor at run-time which can't be determined at compile time for byref parameters.
4848
- github #298: allow command line options passed to as, gcc, ld to be longer than 128 characters by using string types internally
49+
- sf.net #923: implicitly emit the deleting destrutor for extern "c++" mangling for better g++ ABI compatibility
4950

5051
[added]
5152
- extern "rtlib": respects the parent namespace, uses default fb calling convention and C style name mangling
@@ -66,6 +67,7 @@ Version 1.08.0
6667
- '-w suffix' or '-w pedantic' command line option enabled 'Suffix ignored' warning for built-in in string functions
6768
- __FB_UNIQUEID_PUSH__(), __FB_UNIQUEID__(), __FB_UNIQUEID_POP__(), __FB_ARG_LEFTOF__(), __FB_ARG_RIGHTOF__(), __FB_JOIN__() builtin macros
6869
- __FB_ARG_COUNT__() builtin macro
70+
- __thiscall keyword to specify the 'thiscall' calling convention (-gen gcc only)
6971
- __FB_QUOTE__(), __FB_UNQUOTE__(), __FB_EVAL__() builtin macros
7072
- rtlib: REDIM [PRESERVE] will generate run time error if attempting to resize static (fixed length) arrays.
7173
- gas64 emitter for x86_64 (SARG), added '-gen gas64' command line option to select

src/compiler/ast-helper.bas

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function astBuildVarDtorCall overload _
153153
'' UDT var with dtor?
154154
if( symbHasDtor( s ) ) then
155155
if( check_access ) then
156-
if( symbCheckAccess( symbGetCompDtor( symbGetSubtype( s ) ) ) = FALSE ) then
156+
if( symbCheckAccess( symbGetCompDtor1( symbGetSubtype( s ) ) ) = FALSE ) then
157157
errReport( FB_ERRMSG_NOACCESSTODTOR )
158158
end if
159159
end if
@@ -543,7 +543,7 @@ function astBuildDtorCall _
543543
dim as ASTNODE ptr callexpr = any
544544

545545
'' Can be virtual
546-
dtor = symbGetCompDtor( sym )
546+
dtor = symbGetCompDtor1( sym )
547547
if( ignore_virtual ) then
548548
callexpr = astNewCALL( dtor )
549549
else

src/compiler/ast-node-call.bas

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ function astLoadCALL( byval n as ASTNODE ptr ) as IRVREG ptr
204204

205205
'' cdecl: pushed arguments must be popped by caller
206206
'' pascal/stdcall: callee does it instead
207+
'' thiscall: could be either depending on target !!! TODO !!!
207208
argbytes = symbCalcArgLen( l->dtype, l->subtype, arg->arg.mode )
208209
if( symbGetProcMode( proc ) = FB_FUNCMODE_CDECL ) then
209210
bytestopop += argbytes
@@ -230,7 +231,7 @@ function astLoadCALL( byval n as ASTNODE ptr ) as IRVREG ptr
230231
if( symbProcReturnsOnStack( proc ) ) then
231232
'' Pop hidden ptr if cdecl and target doesn't want the callee
232233
'' to do it, despite it being cdecl.
233-
if( (symbGetProcMode( proc ) = FB_FUNCMODE_CDECL) and _
234+
if( ((symbGetProcMode( proc ) = FB_FUNCMODE_CDECL) or (symbGetProcMode( proc ) = FB_FUNCMODE_THISCALL)) and _
234235
((env.target.options and FB_TARGETOPT_CALLEEPOPSHIDDENPTR) = 0) ) then
235236
bytestopop += env.pointersize
236237
end if

src/compiler/ast-node-proc.bas

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ declare function hInitVptr _
3333
) as ASTNODE ptr
3434
declare sub hCallCtors( byval n as ASTNODE ptr, byval sym as FBSYMBOL ptr )
3535
declare sub hCallDtors( byval proc as FBSYMBOL ptr )
36+
declare sub hCallDeleteDtor( byval proc as FBSYMBOL ptr )
3637
declare sub hGenStaticInstancesDtors( byval proc as FBSYMBOL ptr )
3738
declare sub hGenGlobalInstancesCtor( )
3839

@@ -500,7 +501,7 @@ sub astProcBegin( byval sym as FBSYMBOL ptr, byval ismain as integer )
500501
astNewVAR( symbGetParamVar( argv ) ) )
501502

502503
'' Destructor?
503-
elseif( symbIsDestructor( sym ) and enable_implicit_code ) then
504+
elseif( (symbIsDestructor0( sym ) or symbIsDestructor1( sym )) and enable_implicit_code ) then
504505
''
505506
'' If the UDT has a vptr, reset it at the top of destructors,
506507
'' such that the vptr always matches the type of object that
@@ -672,13 +673,18 @@ function astProcEnd( byval callrtexit as integer ) as integer
672673
res = (symbCheckLabels(symbGetProcSymbTbHead(parser.currproc)) = 0)
673674

674675
if( res ) then
675-
'' Destructor?
676-
if( symbIsDestructor( sym ) and enable_implicit_code ) then
676+
'' Complete Destructor?
677+
if( symbIsDestructor1( sym ) and enable_implicit_code ) then
677678
'' Call destructors, behind the exit label, so they'll
678679
'' always be called, even with early returns.
679680
hCallDtors( sym )
680681
end if
681682

683+
'' Deleting Destructor?
684+
if( symbIsDestructor0( sym ) and enable_implicit_code ) then
685+
hCallDeleteDtor( sym )
686+
end if
687+
682688
'' update proc's breaks list, adding calls to destructors when needed
683689
if( n->block.breaklist.head <> NULL ) then
684690
res = astScopeUpdBreakList( n )
@@ -1272,6 +1278,26 @@ private sub hCallFieldDtors _
12721278

12731279
end sub
12741280

1281+
private sub hCallDeleteDtor _
1282+
( _
1283+
byval proc as FBSYMBOL ptr _
1284+
)
1285+
1286+
dim as FBSYMBOL ptr parent = any, dtor1 = any, this_ = any
1287+
dim as ASTNODE ptr thisptr = any, tree = any
1288+
1289+
parent = symbGetNamespace( proc )
1290+
dtor1 = symbGetCompDtor1( parent )
1291+
if( dtor1 = NULL ) then
1292+
exit sub
1293+
end if
1294+
this_ = symbGetParamVar( symbGetProcHeadParam( proc ) )
1295+
thisptr = astNewADDROF( astBuildVarField( this_ ) )
1296+
tree = astBuildDeleteOp( AST_OP_DEL, thisptr )
1297+
astAdd( tree )
1298+
1299+
end sub
1300+
12751301
private sub hCallBaseDtor _
12761302
( _
12771303
byval parent as FBSYMBOL ptr, _
@@ -1296,7 +1322,7 @@ private sub hCallBaseDtor _
12961322
'' Just like derived classes are not responsible for initializing their
12971323
'' base class, they shouldn't be made responsible for cleaning it up.
12981324

1299-
dtor = symbGetCompDtor( symbGetSubtype( base_ ) )
1325+
dtor = symbGetCompDtor1( symbGetSubtype( base_ ) )
13001326
if( dtor = NULL ) then
13011327
exit sub
13021328
end if

src/compiler/error.bas

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ private function hMakeParamDesc _
878878
pname = strptr( s )
879879
'' method?
880880
elseif( (proc->pattrib and (FB_PROCATTRIB_CONSTRUCTOR or _
881-
FB_PROCATTRIB_DESTRUCTOR or _
881+
FB_PROCATTRIB_DESTRUCTOR1 or FB_PROCATTRIB_DESTRUCTOR0 or _
882882
FB_PROCATTRIB_OPERATOR)) <> 0 ) then
883883
s = symbMethodToStr( proc )
884884
pname = strptr( s )

src/compiler/fb.bas

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ sub fbSetOption( byval opt as integer, byval value as integer )
623623
env.clopt.gosubsetjmp = value
624624
case FB_COMPOPT_VALISTASPTR
625625
env.clopt.valistasptr = value
626+
case FB_COMPOPT_NOTHISCALL
627+
env.clopt.nothiscall = value
626628
case FB_COMPOPT_EXPORT
627629
env.clopt.export = value
628630
case FB_COMPOPT_MSBITFIELDS
@@ -719,6 +721,8 @@ function fbGetOption( byval opt as integer ) as integer
719721
function = env.clopt.gosubsetjmp
720722
case FB_COMPOPT_VALISTASPTR
721723
function = env.clopt.valistasptr
724+
case FB_COMPOPT_NOTHISCALL
725+
function = env.clopt.valistasptr
722726
case FB_COMPOPT_EXPORT
723727
function = env.clopt.export
724728
case FB_COMPOPT_MSBITFIELDS

src/compiler/fb.bi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ enum FB_COMPOPT
9696
'' the rest
9797
FB_COMPOPT_GOSUBSETJMP '' boolean: implement GOSUB using setjmp/longjump?
9898
FB_COMPOPT_VALISTASPTR '' boolean: implement CVA_* using pointer expressions only?
99+
FB_COMPOPT_NOTHISCALL '' boolean: don't use 'thiscall' calling convention?
99100
FB_COMPOPT_EXPORT '' boolean: export all symbols declared as EXPORT?
100101
FB_COMPOPT_MSBITFIELDS '' boolean: use M$'s bitfields packing?
101102
FB_COMPOPT_MULTITHREADED '' boolean: -mt
@@ -289,6 +290,7 @@ type FBCMMLINEOPT
289290
'' the rest
290291
gosubsetjmp as integer '' implement GOSUB using setjmp/longjump? (default = false)
291292
valistasptr as integer '' implement CVA_* using pointer expressions only?
293+
nothiscall as integer '' do not use thiscall calling convention (default = false)
292294
export as integer '' export all symbols declared as EXPORT (default = true)
293295
msbitfields as integer '' use M$'s bitfields packing
294296
multithreaded as integer '' link against thread-safe runtime library (default = false)

src/compiler/fbc.bas

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,6 +2035,8 @@ private sub handleOpt(byval optid as integer, byref arg as string)
20352035
fbSetOption( FB_COMPOPT_GOSUBSETJMP, TRUE )
20362036
case "valist-as-ptr"
20372037
fbSetOption( FB_COMPOPT_VALISTASPTR, TRUE )
2038+
case "no-thiscall"
2039+
fbSetOption( FB_COMPOPT_NOTHISCALL, TRUE )
20382040
case else
20392041
hFatalInvalidOption( arg )
20402042
end select

src/compiler/fbint.bi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ enum FB_TOKEN
346346
FB_TK_PASCAL
347347
FB_TK_CDECL
348348
FB_TK_STDCALL
349+
FB_TK_THISCALL
349350
FB_TK_ALIAS
350351
FB_TK_LIB
351352
FB_TK_OVERLOAD

src/compiler/ir-hlc.bas

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,13 @@ private function hEmitProcHeader _
555555
'' Linux GCC only accepts this
556556
ln += " __attribute__((stdcall))"
557557
end select
558+
case FB_FUNCMODE_THISCALL
559+
select case( env.clopt.target )
560+
case FB_COMPTARGET_WIN32, FB_COMPTARGET_XBOX
561+
ln += " __thiscall"
562+
case else
563+
ln += " __attribute__((thiscall))"
564+
end select
558565
end select
559566
end if
560567

0 commit comments

Comments
 (0)