New page '__THISCALL'
New page '__THISCALL'
@Jeff,
There is a typo on the link name of the new page '__THISCALL':
- KeyPgThicsall instead of KeyPgThiscall.
After fixing for the page '__THISCALL':
- its link name (I do not have the rights to do so),
- and also the link to the 'This' page ([[KeyThis|This]] -> [[KeyPgThis|This]]),
- and also the name of the example file (.../thicall.bas -> .../thiscall.bas),
then only one link to this so fixed '__THISCALL' page will need to be corrected in another page:
- in the CatPgProcedures page (value="KeyPgThicsall|Thiscall" -> value="KeyPgThiscall|Thiscall").
There is a typo on the link name of the new page '__THISCALL':
- KeyPgThicsall instead of KeyPgThiscall.
After fixing for the page '__THISCALL':
- its link name (I do not have the rights to do so),
- and also the link to the 'This' page ([[KeyThis|This]] -> [[KeyPgThis|This]]),
- and also the name of the example file (.../thicall.bas -> .../thiscall.bas),
then only one link to this so fixed '__THISCALL' page will need to be corrected in another page:
- in the CatPgProcedures page (value="KeyPgThicsall|Thiscall" -> value="KeyPgThiscall|Thiscall").
Re: New page '__THISCALL'
Thanks, fxm. My errors you listed are corrected now.
Re: New page '__THISCALL'
I did not previously create this page myself because I had no information or even knowledge on the subject, and in addition the '__THISCALL' name syntax rather made me think of an internal feature command.
Re: New page '__THISCALL'
It's sort of internal, and developmental for sure. If the feature is ever finished (for win 32-bit gas), then should not need to explicitly specify it. But just needed something to work with in code while under development, which is why I left on the '__' double underscore prefix. In theory it should seldom if ever appear in user code, so will probably have that name forever.
Re: New page '__THISCALL'
fbc 1.10.0 has new updates to the __THISCALL calling convention.
__THISCALL is a calling convention for x86 targets where the first integral argument is passed in the ECX register instead of on the stack. All other arguments are passed right to left and callee cleans up the stack (like STDCALL).
On win32 x86, mingw+gcc will use __THISCALL as the default calling convention for non-static member procedures in classes passing the hidden 'this' parameter by ECX register instead of pushing to the stack.
As of fbc 1.10.0, default calling convention on win32 x86 inside an extern "c++" block for non-static member procedures is __THISCALL.
__THISCALL can be explicitly specified for normal procedures and static member procedures to override the default calling convention.
Other calling conventions (CDECL/STDCALL/etc) can be explicitly specified to override the default __THISCALL calling convention on non-static member procedures.
__THISCALL is a calling convention for x86 targets where the first integral argument is passed in the ECX register instead of on the stack. All other arguments are passed right to left and callee cleans up the stack (like STDCALL).
On win32 x86, mingw+gcc will use __THISCALL as the default calling convention for non-static member procedures in classes passing the hidden 'this' parameter by ECX register instead of pushing to the stack.
As of fbc 1.10.0, default calling convention on win32 x86 inside an extern "c++" block for non-static member procedures is __THISCALL.
__THISCALL can be explicitly specified for normal procedures and static member procedures to override the default calling convention.
Other calling conventions (CDECL/STDCALL/etc) can be explicitly specified to override the default __THISCALL calling convention on non-static member procedures.
Re: New page '__THISCALL'
- It can be specified at both the declaration and the definition.
- The calling convention of the declaration and definition need to match - could be cdecl/stdcall/pascal/__thiscall
- If inside extern "c++" and also on win32 / x86, and it's a non-static member procedure, and no other calling convention is given, the default is __thiscall
Code: Select all
extern "c++"
type T extends object
declare constructor() '' __thiscall is default
end type
constructor T() '' __thiscall is default
end constructor
end extern
Code: Select all
extern "c++"
type T extends object
declare constructor() '' __thiscall is default
end type
end extern
constructor T __thiscall()
end constructor
Re: New page '__THISCALL'
Documentation page updated:
- KeyPgThiscall → fxm [updated for fbc 1.10.0]
- KeyPgThiscall → fxm [updated for fbc 1.10.0]
Re: New page '__THISCALL'
Here are examples (for x86) to show low level cdecl/stdcall/pascall/__thiscall differences:
CDECL - Arguments pushed right to left, caller clean-up
STDCALL - Arguments pushed right to left, callee clean-up
PASCAL - Arguments pushed left to right, callee clean-up
THISCALL - Arguments pushed right to left, left-most argument in ECX
WIN32 x86: callee clean-up
Linux x86: caller clean-up
CDECL - Arguments pushed right to left, caller clean-up
Code: Select all
function Sub2LongCdecl naked CDECL _
( byval a as long, byval b as long ) as long
asm
mov eax, dword ptr [esp+4] '' argument 1 on stack
sub eax, dword ptr [esp+8] '' argument 2 on stack
ret '' caller cleans up stack
end asm '' result returned in EAX
end function
dim as long a = 17, b = 3
'' CDECL - Arguments pushed right to left, caller clean-up
'' push [b]
'' push [a]
'' call Sub2LongCdecl
'' add esp, 8
print Sub2LongCdecl( a, b )
Code: Select all
function Sub2LongStdcall naked STDCALL _
( byval a as long, byval b as long ) as long
asm
mov eax, dword ptr [esp+4] '' argument 1 on stack
sub eax, dword ptr [esp+8] '' argument 2 on stack
ret 8 '' callee cleans up stack
end asm '' result returned in EAX
end function
dim as long a = 17, b = 3
'' STDCALL - Arguments pushed right to left, callee clean-up
'' push [b]
'' push [a]
'' call Sub2LongStdCall
print Sub2LongStdCall( a, b )
Code: Select all
function Sub2LongPascal naked PASCAL _
( byval a as long, byval b as long ) as long
asm
mov eax, dword ptr [esp+8] '' argument 1 on stack
sub eax, dword ptr [esp+4] '' argument 2 on stack
ret 8 '' callee cleans up stack
end asm '' result returned in EAX
end function
dim as long a = 17, b = 3
'' PASCAL - Arguments pushed left to right, callee clean-up
'' push [a]
'' push [b]
'' call Sub2LongPascal
print Sub2LongPascal( a, b )
WIN32 x86: callee clean-up
Code: Select all
#cmdline "-target win32"
function Sub2LongThiscall naked __THISCALL _
( byval a as long, byval b as long ) as long
asm
mov eax, ecx '' argument 1 in ECX
sub eax, dword ptr [esp+4] '' argument 2 on stack
ret 4 '' callee cleans up stack
end asm '' result returned in EAX
end function
dim as long a = 17, b = 3
'' THISCALL - Arguments pushed right to left, left-most argument in ECX, callee clean-up
'' push [b]
'' mov ecx, [a]
'' call Sub2LongThiscall
print Sub2LongThiscall( a, b )
Code: Select all
#cmdline "-target linux"
function Sub2LongThiscall naked __THISCALL _
( byval a as long, byval b as long ) as long
asm
mov eax, ecx '' argument 1 in ECX
sub eax, dword ptr [esp+4] '' argument 2 on stack
ret '' caller cleans up stack
end asm '' result returned in EAX
end function
dim as long a = 17, b = 3
'' THISCALL - Arguments pushed right to left, left-most argument in ECX, caller clean-up
'' push [b]
'' mov ecx, [a]
'' call Sub2LongThiscall
'' add esp, 4
print Sub2LongThiscall( a, b )
Re: New page '__THISCALL'
Primary purpose of this feature was to provide ABI compatibility for mingw+gcc. However, gcc allows thiscall calling convention as an extension for normal procedures and other targets / platforms, and the rules may be inconsistent across targets / platforms. I don't know all the rules and I have not researched or tested this feature and all targets.
Potential issues and bugs:
Potential issues and bugs:
- Confirmation that __thiscall is completely ignored on 64 bit targets
- Determine any other 32-bit targets that should ignore or support __thiscall? ARM? freebsd x86? etc...
- VARARGS - functions taking a variable number of arguments
- fbc should not allow on win32 x86
- if not allowed, then automatically fallback to CDECL/STDCALL? or a warning?
- supported on other x86 targets? then that will need to be added to gas backend
- handling of non-integral left most argument - what is behaviour / error if argument is not byte/short/long?
- REDIM and ERASE expect object contructor/destructor to be CDECL, so using arrays is not possible if ctor/dtor is __THISCALL
- more testing, at least on all the targets that make up the 'offical' release binaries
Re: New page '__THISCALL'
I made a change that feels like should be more user friendly when dealing with calling conventions:
- calling convention of the procedure definition is implied by the declaration
- if there is no declaration, then usual defaults apply.
A simple example (which would previously fail to compile on fbc 1.09 windows):
- calling convention of the procedure definition is implied by the declaration
- if there is no declaration, then usual defaults apply.
This will be same behaviour for cdecl/pascal/stdcall in declarations making the calling convention on the definition optional.coderJeff wrote: ↑Oct 23, 2022 0:05 - If definition is outside the extern "c++" block, then __thiscall isrequiredoptional on the definition (if the default for the non-static member procedure was __thiscall
Code: Select all
extern "c++" type T extends object declare constructor() '' __thiscall is default end type end extern constructor T() '' __thiscall is implied by declaration. end constructor
A simple example (which would previously fail to compile on fbc 1.09 windows):
Code: Select all
declare sub proc cdecl ()
sub proc () '' cdecl implied by declaration, regardless of current target
end sub
-
- Posts: 8586
- Joined: May 28, 2005 3:28
- Contact:
Re: New page '__THISCALL'
12 years to late but better as never.
I remenber if I wrote the FreeBASIC Steinberg ASIO interface for 32-bit Windows the magic was putting the this pointer in ECX register instead pushing it on the stack.
viewtopic.php?p=148306#p148306
Joshy
I remenber if I wrote the FreeBASIC Steinberg ASIO interface for 32-bit Windows the magic was putting the this pointer in ECX register instead pushing it on the stack.
viewtopic.php?p=148306#p148306
Joshy