mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 00:19:19 +02:00
+ add function call manager which implements Invoke() for the i386 register calling convention
git-svn-id: trunk@41536 -
This commit is contained in:
parent
c2da9abd17
commit
d7bb4bd411
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -7613,6 +7613,7 @@ packages/rtl-objpas/Makefile.fpc svneol=native#text/plain
|
|||||||
packages/rtl-objpas/Makefile.fpc.fpcmake svneol=native#text/plain
|
packages/rtl-objpas/Makefile.fpc.fpcmake svneol=native#text/plain
|
||||||
packages/rtl-objpas/fpmake.pp svneol=native#text/plain
|
packages/rtl-objpas/fpmake.pp svneol=native#text/plain
|
||||||
packages/rtl-objpas/src/common/varutils.pp svneol=native#text/plain
|
packages/rtl-objpas/src/common/varutils.pp svneol=native#text/plain
|
||||||
|
packages/rtl-objpas/src/i386/invoke.inc svneol=native#text/pascal
|
||||||
packages/rtl-objpas/src/inc/convutil.inc svneol=native#text/plain
|
packages/rtl-objpas/src/inc/convutil.inc svneol=native#text/plain
|
||||||
packages/rtl-objpas/src/inc/convutil.pp svneol=native#text/plain
|
packages/rtl-objpas/src/inc/convutil.pp svneol=native#text/plain
|
||||||
packages/rtl-objpas/src/inc/convutils.pp svneol=native#text/plain
|
packages/rtl-objpas/src/inc/convutils.pp svneol=native#text/plain
|
||||||
|
445
packages/rtl-objpas/src/i386/invoke.inc
Normal file
445
packages/rtl-objpas/src/i386/invoke.inc
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
{%MainUnit ../inc/rtti.pp}
|
||||||
|
|
||||||
|
{
|
||||||
|
This file is part of the Free Pascal run time library.
|
||||||
|
Copyright (C) 2019 Sven Barth
|
||||||
|
member of the Free Pascal development team.
|
||||||
|
|
||||||
|
Function call manager for i386
|
||||||
|
|
||||||
|
See the file COPYING.FPC, included in this distribution,
|
||||||
|
for details about the copyright.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
}
|
||||||
|
|
||||||
|
{$define SYSTEM_HAS_INVOKE}
|
||||||
|
|
||||||
|
function ReturnResultInParam(aType: PTypeInfo): Boolean;
|
||||||
|
var
|
||||||
|
td: PTypeData;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
if Assigned(aType) then begin
|
||||||
|
case aType^.Kind of
|
||||||
|
tkMethod,
|
||||||
|
tkSString,
|
||||||
|
tkAString,
|
||||||
|
tkUString,
|
||||||
|
tkWString,
|
||||||
|
tkInterface,
|
||||||
|
tkDynArray:
|
||||||
|
Result := True;
|
||||||
|
tkArray: begin
|
||||||
|
td := GetTypeData(aType);
|
||||||
|
Result := not (td^.ArrayData.Size in [1, 2, 4]);
|
||||||
|
end;
|
||||||
|
tkRecord: begin
|
||||||
|
td := GetTypeData(aType);
|
||||||
|
Result := not (td^.RecSize in [1, 2, 4]);
|
||||||
|
end;
|
||||||
|
tkSet: begin
|
||||||
|
td := GetTypeData(aType);
|
||||||
|
case td^.OrdType of
|
||||||
|
otUByte:
|
||||||
|
Result := not (td^.SetSize in [1, 2, 4]);
|
||||||
|
otUWord,
|
||||||
|
otULong:
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InvokeKernelRegister(aCodeAddress: CodePointer; aArgs: Pointer; aArgCount: LongInt); assembler; nostackframe;
|
||||||
|
label
|
||||||
|
nostackargs;
|
||||||
|
asm
|
||||||
|
pushl %ebp
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
|
pushl %edi
|
||||||
|
pushl %esi
|
||||||
|
|
||||||
|
pushl %eax
|
||||||
|
pushl %edx
|
||||||
|
|
||||||
|
cmpl $3, %ecx
|
||||||
|
jle nostackargs
|
||||||
|
|
||||||
|
{ copy arguments to stack }
|
||||||
|
|
||||||
|
subl $3, %ecx
|
||||||
|
|
||||||
|
{ allocate count (%ecx) * 4 space on stack }
|
||||||
|
movl %ecx, %eax
|
||||||
|
shll $2, %eax
|
||||||
|
|
||||||
|
sub %eax, %esp
|
||||||
|
|
||||||
|
movl %esp, %edi
|
||||||
|
|
||||||
|
lea 12(%edx), %esi
|
||||||
|
|
||||||
|
cld
|
||||||
|
rep movsd
|
||||||
|
|
||||||
|
nostackargs:
|
||||||
|
|
||||||
|
movl 8(%edx), %ecx
|
||||||
|
movl (%edx), %eax
|
||||||
|
movl 4(%edx), %edx
|
||||||
|
|
||||||
|
call -12(%ebp)
|
||||||
|
|
||||||
|
popl %ecx
|
||||||
|
movl %eax, (%ecx)
|
||||||
|
movl %edx, 4(%ecx)
|
||||||
|
|
||||||
|
popl %ecx
|
||||||
|
|
||||||
|
popl %esi
|
||||||
|
popl %edi
|
||||||
|
|
||||||
|
movl %ebp, %esp
|
||||||
|
popl %ebp
|
||||||
|
end;
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SErrFailedToConvertArg = 'Failed to convert argument %d of type %s';
|
||||||
|
|
||||||
|
procedure SystemInvokeRegister(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
|
||||||
|
aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
|
||||||
|
type
|
||||||
|
PBoolean16 = ^Boolean16;
|
||||||
|
PBoolean32 = ^Boolean32;
|
||||||
|
PBoolean64 = ^Boolean64;
|
||||||
|
PByteBool = ^ByteBool;
|
||||||
|
PQWordBool = ^QWordBool;
|
||||||
|
var
|
||||||
|
regstack: array of PtrUInt;
|
||||||
|
stackargs: array of SizeInt;
|
||||||
|
argcount, regidx, stackidx, stackcnt, i: LongInt;
|
||||||
|
retinparam, isstack: Boolean;
|
||||||
|
td: PTypeData;
|
||||||
|
floatres: Extended;
|
||||||
|
|
||||||
|
procedure AddRegArg(aValue: PtrUInt);
|
||||||
|
begin
|
||||||
|
if regidx < 3 then begin
|
||||||
|
regstack[regidx] := aValue;
|
||||||
|
Inc(regidx);
|
||||||
|
end else begin
|
||||||
|
if 3 + stackidx = Length(regstack) then
|
||||||
|
SetLength(regstack, Length(regstack) * 2);
|
||||||
|
regstack[3 + stackidx] := aValue;
|
||||||
|
Inc(stackidx);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AddStackArg(aValue: PtrUInt);
|
||||||
|
begin
|
||||||
|
if 3 + stackidx = Length(regstack) then
|
||||||
|
SetLength(regstack, Length(regstack) * 2);
|
||||||
|
regstack[3 + stackidx] := aValue;
|
||||||
|
Inc(stackidx);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{ for the register calling convention we always have the registers EAX, EDX, ECX
|
||||||
|
and then the stack; if a parameter does not fit into a register its moved to the
|
||||||
|
next available stack slot and the next parameter gets a chance to be in a register }
|
||||||
|
|
||||||
|
retinparam := ReturnResultInParam(aResultType);
|
||||||
|
|
||||||
|
{ we allocate at least three slots for EAX, ECX and EDX }
|
||||||
|
argcount := Length(aArgs);
|
||||||
|
if retinparam then
|
||||||
|
Inc(argcount);
|
||||||
|
if argcount < 3 then
|
||||||
|
SetLength(regstack, 3)
|
||||||
|
else
|
||||||
|
SetLength(regstack, argcount);
|
||||||
|
|
||||||
|
regidx := 0;
|
||||||
|
stackidx := 0;
|
||||||
|
|
||||||
|
SetLength(stackargs, Length(aArgs));
|
||||||
|
stackcnt := 0;
|
||||||
|
|
||||||
|
{ first pass: handle register parameters }
|
||||||
|
for i := 0 to High(aArgs) do begin
|
||||||
|
if regidx >= 3 then begin
|
||||||
|
{ all register locations already used up }
|
||||||
|
stackargs[stackcnt] := i;
|
||||||
|
Inc(stackcnt);
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
isstack := False;
|
||||||
|
|
||||||
|
if pfArray in aArgs[i].Info.ParamFlags then
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef))
|
||||||
|
else if aArgs[i].Info.ParamFlags * [pfOut, pfVar, pfConstRef] <> [] then
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef))
|
||||||
|
else begin
|
||||||
|
td := GetTypeData(aArgs[i].Info.ParamType);
|
||||||
|
case aArgs[i].Info.ParamType^.Kind of
|
||||||
|
tkSString,
|
||||||
|
tkMethod:
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef));
|
||||||
|
tkArray:
|
||||||
|
if td^.ArrayData.Size <= 4 then
|
||||||
|
isstack := True
|
||||||
|
else
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef));
|
||||||
|
tkRecord:
|
||||||
|
if td^.RecSize <= 4 then
|
||||||
|
isstack := True
|
||||||
|
else
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef));
|
||||||
|
tkObject,
|
||||||
|
tkWString,
|
||||||
|
tkUString,
|
||||||
|
tkAString,
|
||||||
|
tkDynArray,
|
||||||
|
tkClass,
|
||||||
|
tkClassRef,
|
||||||
|
tkInterface,
|
||||||
|
tkInterfaceRaw,
|
||||||
|
tkProcVar,
|
||||||
|
tkPointer:
|
||||||
|
AddRegArg(PPtrUInt(aArgs[i].ValueRef)^);
|
||||||
|
tkInt64,
|
||||||
|
tkQWord:
|
||||||
|
isstack := True;
|
||||||
|
tkSet: begin
|
||||||
|
case td^.OrdType of
|
||||||
|
otUByte: begin
|
||||||
|
case td^.SetSize of
|
||||||
|
0, 1:
|
||||||
|
AddRegArg(PByte(aArgs[i].ValueRef)^);
|
||||||
|
2:
|
||||||
|
AddRegArg(PWord(aArgs[i].ValueRef)^);
|
||||||
|
3:
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef));
|
||||||
|
4:
|
||||||
|
AddRegArg(PLongWord(aArgs[i].ValueRef)^);
|
||||||
|
else
|
||||||
|
AddRegArg(PtrUInt(aArgs[i].ValueRef));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
otUWord:
|
||||||
|
AddRegArg(PWord(aArgs[i].ValueRef)^);
|
||||||
|
otULong:
|
||||||
|
AddRegArg(PLongWord(aArgs[i].ValueRef)^);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
tkEnumeration,
|
||||||
|
tkInteger: begin
|
||||||
|
case td^.OrdType of
|
||||||
|
otSByte: AddRegArg(PShortInt(aArgs[i].ValueRef)^);
|
||||||
|
otUByte: AddRegArg(PByte(aArgs[i].ValueRef)^);
|
||||||
|
otSWord: AddRegArg(PSmallInt(aArgs[i].ValueRef)^);
|
||||||
|
otUWord: AddRegArg(PWord(aArgs[i].ValueRef)^);
|
||||||
|
otSLong: AddRegArg(PLongInt(aArgs[i].ValueRef)^);
|
||||||
|
otULong: AddRegArg(PLongWord(aArgs[i].ValueRef)^);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
tkBool: begin
|
||||||
|
case td^.OrdType of
|
||||||
|
otUByte: AddRegArg(ShortInt(System.PBoolean(aArgs[i].ValueRef)^));
|
||||||
|
otUWord: AddRegArg(Byte(PBoolean16(aArgs[i].ValueRef)^));
|
||||||
|
otULong: AddRegArg(SmallInt(PBoolean32(aArgs[i].ValueRef)^));
|
||||||
|
otUQWord: isstack := True;
|
||||||
|
otSByte: AddRegArg(Word(PByteBool(aArgs[i].ValueRef)^));
|
||||||
|
otSWord: AddRegArg(LongInt(PWordBool(aArgs[i].ValueRef)^));
|
||||||
|
otSLong: AddRegArg(LongWord(PLongBool(aArgs[i].ValueRef)^));
|
||||||
|
otSQWord: isstack := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
tkFloat:
|
||||||
|
{ all float types are passed in on stack }
|
||||||
|
isstack := True;
|
||||||
|
else
|
||||||
|
raise EInvocationError.CreateFmt(SErrFailedToConvertArg, [i, aArgs[i].Info.ParamType^.Name]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if isstack then begin
|
||||||
|
stackargs[stackcnt] := i;
|
||||||
|
Inc(stackcnt);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ then add the result parameter reference (if any) }
|
||||||
|
if Assigned(aResultType) and retinparam then
|
||||||
|
AddRegArg(PtrUInt(aResultValue));
|
||||||
|
|
||||||
|
{ second pass: handle stack arguments from right to left }
|
||||||
|
if stackcnt > 0 then begin
|
||||||
|
for i := stackcnt - 1 downto 0 do begin
|
||||||
|
if pfArray in aArgs[stackargs[i]].Info.ParamFlags then
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef))
|
||||||
|
else if aArgs[stackargs[i]].Info.ParamFlags * [pfOut, pfVar, pfConstRef] <> [] then
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef))
|
||||||
|
else begin
|
||||||
|
td := GetTypeData(aArgs[stackargs[i]].Info.ParamType);
|
||||||
|
case aArgs[stackargs[i]].Info.ParamType^.Kind of
|
||||||
|
tkSString,
|
||||||
|
tkMethod:
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef));
|
||||||
|
tkArray:
|
||||||
|
if td^.ArrayData.Size <= 4 then
|
||||||
|
AddStackArg(PPtrUInt(aArgs[stackargs[i]].ValueRef)^)
|
||||||
|
else
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef));
|
||||||
|
tkRecord:
|
||||||
|
if td^.RecSize <= 4 then
|
||||||
|
AddStackArg(PPtrUInt(aArgs[stackargs[i]].ValueRef)^)
|
||||||
|
else
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef));
|
||||||
|
tkObject,
|
||||||
|
tkWString,
|
||||||
|
tkUString,
|
||||||
|
tkAString,
|
||||||
|
tkDynArray,
|
||||||
|
tkClass,
|
||||||
|
tkClassRef,
|
||||||
|
tkInterface,
|
||||||
|
tkInterfaceRaw,
|
||||||
|
tkProcVar,
|
||||||
|
tkPointer:
|
||||||
|
AddStackArg(PPtrUInt(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
tkInt64,
|
||||||
|
tkQWord: begin
|
||||||
|
AddStackArg(PInt32(PInt64(aArgs[stackargs[i]].ValueRef))[0]);
|
||||||
|
AddStackArg(PInt32(PInt64(aArgs[stackargs[i]].ValueRef))[1]);
|
||||||
|
end;
|
||||||
|
tkSet: begin
|
||||||
|
case td^.OrdType of
|
||||||
|
otUByte: begin
|
||||||
|
case td^.SetSize of
|
||||||
|
0, 1:
|
||||||
|
AddStackArg(PByte(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
2:
|
||||||
|
AddStackArg(PWord(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
3:
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef));
|
||||||
|
4:
|
||||||
|
AddStackArg(PLongWord(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
else
|
||||||
|
AddStackArg(PtrUInt(aArgs[stackargs[i]].ValueRef));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
otUWord:
|
||||||
|
AddStackArg(PWord(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
otULong:
|
||||||
|
AddStackArg(PLongWord(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
tkEnumeration,
|
||||||
|
tkInteger: begin
|
||||||
|
case td^.OrdType of
|
||||||
|
otSByte: AddStackArg(PShortInt(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
otUByte: AddStackArg(PByte(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
otSWord: AddStackArg(PSmallInt(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
otUWord: AddStackArg(PWord(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
otSLong: AddStackArg(PLongInt(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
otULong: AddStackArg(PLongWord(aArgs[stackargs[i]].ValueRef)^);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
tkBool: begin
|
||||||
|
case td^.OrdType of
|
||||||
|
otUByte: AddStackArg(ShortInt(System.PBoolean(aArgs[stackargs[i]].ValueRef)^));
|
||||||
|
otUWord: AddStackArg(Byte(PBoolean16(aArgs[stackargs[i]].ValueRef)^));
|
||||||
|
otULong: AddStackArg(SmallInt(PBoolean32(aArgs[stackargs[i]].ValueRef)^));
|
||||||
|
otUQWord: AddStackArg(QWord(PBoolean64(aArgs[stackargs[i]].ValueRef)));
|
||||||
|
otSByte: AddStackArg(Word(PByteBool(aArgs[stackargs[i]].ValueRef)^));
|
||||||
|
otSWord: AddStackArg(LongInt(PWordBool(aArgs[stackargs[i]].ValueRef)^));
|
||||||
|
otSLong: AddStackArg(LongWord(PLongBool(aArgs[stackargs[i]].ValueRef)^));
|
||||||
|
otSQWord: AddStackArg(PtrUInt(PQWordBool(aArgs[stackargs[i]].ValueRef)));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
tkFloat: begin
|
||||||
|
case td^.FloatType of
|
||||||
|
ftCurr : begin
|
||||||
|
AddStackArg(PInt32(PCurrency(aArgs[stackargs[i]].ValueRef))[0]);
|
||||||
|
AddStackArg(PInt32(PCurrency(aArgs[stackargs[i]].ValueRef))[1]);
|
||||||
|
end;
|
||||||
|
ftSingle : AddStackArg(PInt32(PSingle(aArgs[stackargs[i]].ValueRef))^);
|
||||||
|
ftDouble : begin
|
||||||
|
AddStackArg(PInt32(PDouble(aArgs[stackargs[i]].ValueRef))[0]);
|
||||||
|
AddStackArg(PInt32(PDouble(aArgs[stackargs[i]].ValueRef))[1]);
|
||||||
|
end;
|
||||||
|
ftExtended: begin
|
||||||
|
AddStackArg(PInt32(PExtended(aArgs[stackargs[i]].ValueRef))[0]);
|
||||||
|
AddStackArg(PInt32(PExtended(aArgs[stackargs[i]].ValueRef))[1]);
|
||||||
|
AddStackArg(PWord(PExtended(aArgs[stackargs[i]].ValueRef))[4]);
|
||||||
|
end;
|
||||||
|
ftComp : begin
|
||||||
|
AddStackArg(PInt32(PComp(aArgs[stackargs[i]].ValueRef))[0]);
|
||||||
|
AddStackArg(PInt32(PComp(aArgs[stackargs[i]].ValueRef))[1]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
raise EInvocationError.CreateFmt(SErrFailedToConvertArg, [stackargs[i], aArgs[stackargs[i]].Info.ParamType^.Name]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
InvokeKernelRegister(aCodeAddress, @regstack[0], 3 + stackidx);
|
||||||
|
|
||||||
|
if Assigned(aResultType) and not retinparam then begin
|
||||||
|
if aResultType^.Kind = tkFloat then begin
|
||||||
|
td := GetTypeData(aResultType);
|
||||||
|
asm
|
||||||
|
lea floatres, %eax
|
||||||
|
fstpt (%eax)
|
||||||
|
end ['eax'];
|
||||||
|
case td^.FloatType of
|
||||||
|
ftSingle:
|
||||||
|
PSingle(aResultValue)^ := floatres;
|
||||||
|
ftDouble:
|
||||||
|
PDouble(aResultValue)^ := floatres;
|
||||||
|
ftExtended:
|
||||||
|
PExtended(aResultValue)^ := floatres;
|
||||||
|
ftCurr:
|
||||||
|
PCurrency(aResultValue)^ := floatres / 10000;
|
||||||
|
ftComp:
|
||||||
|
PComp(aResultValue)^ := floatres;
|
||||||
|
end;
|
||||||
|
end else if aResultType^.Kind in [tkQWord, tkInt64] then
|
||||||
|
PQWord(aResultValue)^ := regstack[0] or (QWord(regstack[1]) shl 32)
|
||||||
|
else
|
||||||
|
PPtrUInt(aResultValue)^ := regstack[0];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure SystemInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
|
||||||
|
aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
|
||||||
|
begin
|
||||||
|
case aCallConv of
|
||||||
|
ccReg:
|
||||||
|
SystemInvokeRegister(aCodeAddress, aArgs, aCallConv, aResultType, aResultValue, aFlags);
|
||||||
|
otherwise
|
||||||
|
Assert(False, 'Unsupported calling convention');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
SystemFunctionCallManager: TFunctionCallManager = (
|
||||||
|
Invoke: @SystemInvoke;
|
||||||
|
CreateCallbackProc: Nil;
|
||||||
|
CreateCallbackMethod: Nil;
|
||||||
|
);
|
||||||
|
|
||||||
|
procedure InitSystemFunctionCallManager;
|
||||||
|
begin
|
||||||
|
SetFunctionCallManager([ccReg{, ccCdecl, ccPascal, ccStdCall}], SystemFunctionCallManager);
|
||||||
|
end;
|
@ -3552,7 +3552,7 @@ begin
|
|||||||
end;}
|
end;}
|
||||||
|
|
||||||
{$ifndef InLazIDE}
|
{$ifndef InLazIDE}
|
||||||
{$if defined(CPUX86_64) and defined(WIN64)}
|
{$if defined(CPUI386) or (defined(CPUX86_64) and defined(WIN64))}
|
||||||
{$I invoke.inc}
|
{$I invoke.inc}
|
||||||
{$endif}
|
{$endif}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
Loading…
Reference in New Issue
Block a user