Native calling convention support for mingw x64

Started by
44 comments, last by WitchLord 12 years, 8 months ago
Switching those leads to the following failure even before notcomplexthis call:
-- TestNegateOperator passed
Assertion failed: obj == &factory, file ../../source/test_return_with_cdecl_objfirst.cpp, line 51[/quote]
Advertisement
That's strange. That test doesn't involve the THISCALL calling convention and shouldn't be affected by the change I mentioned.

The function should look like this with the changes I proposed:

asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
{
asCScriptEngine *engine = context->engine;
asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
asQWORD retQW = 0;
void *func = (void*)sysFunc->func;
asUINT paramSize = 0; // QWords
void **vftable;
asQWORD allArgBuffer[64];
asQWORD floatArgBuffer[4];
int callConv = sysFunc->callConv;
if( sysFunc->hostReturnInMemory )
{
// The return is made in memory
callConv++;
// Set the return pointer as the first argument
allArgBuffer[paramSize++] = (asQWORD)retPointer;
}

if( callConv == ICC_THISCALL ||
callConv == ICC_THISCALL_RETURNINMEM ||
callConv == ICC_VIRTUAL_THISCALL ||
callConv == ICC_VIRTUAL_THISCALL_RETURNINMEM )
{
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
}
if( callConv == ICC_CDECL_OBJFIRST ||
callConv == ICC_CDECL_OBJFIRST_RETURNINMEM )
{
// Add the object pointer as the first parameter
allArgBuffer[paramSize++] = (asQWORD)obj;
}
...

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Looks like I did something wrong the first time, indeed. We now pass the 'TestVirtualMethod' test, then the suite crashes with access violation.. I'll have to debug this later tomorrow. Now I'm off to bed, thanks a lot for your help!
Ok, the code now crashes in ExcuteNext while trying to perform the multiple inheritance test:

[EDIT]Oh, well, it actually crashes in X64Call, trying to 'call r14 {ffffffff`ffffffe8}', the function address looks pretty bogus, I must say

[EDIT]Figured out this one:
func = vftable[size_t(func)>>2];
should actually be:
func = vftable[size_t(func)>>3];
AngelScript version: 2.21.0
AngelScript options: AS_64BIT_PTR AS_WIN
-- TestDefaultArg passed
-- TestScriptRetRef passed
-- TestGarbageCollect passed
-- TestFunctionPtr passed
-- TestModule passed
-- TestGetSet passed
-- Test_Addon_ScriptArray passed
-- TestOperator passed
-- TestTemplate passed
func: void Test()
type: class A : I
A@ A()
void i(float)
void a(int)
float f
type: class B : A, I
B@ B()
B@ B(int)
void i(float)
void a(int)
float f
type: interface I
void i(float)
global: float a
global: const float aConst
global: E e
global: float pi
global: I@ i
enum: E
eval = 0
eval2 = 2
typedef: real => float
import: void ImpFunc() from "mod"
-------
reg prop: float f group: <null>
reg prop: const float myConst group: <null>
reg typedef: myFloat => float
reg func: void func(int&in) group: <null>
reg func: void func2() group: test
reg enum: myEnum
value1 = 1
value2 = 2
reg funcdef: void Callback(int, int)
string factory: string
reg type: ref array group: <null>
T[]@ _beh_2_(int&in)
T[]@ _beh_2_(int&in, uint)
T[]@ _beh_2_(int&in, uint, const T&in)
beh(4) void _beh_4_()
beh(5) void _beh_5_()
beh(11) int _beh_11_()
beh(12) void _beh_12_()
beh(13) bool _beh_13_()
beh(14) void _beh_14_(int&in)
beh(15) void _beh_15_(int&in)
beh(10) bool _beh_10_(int&in)
beh(3) T[]@ _beh_3_(int&in, uint)
T& opIndex(uint)
const T& opIndex(uint) const
T[]& opAssign(const T[]&in)
void insertAt(uint, const T&in)
void removeAt(uint)
void insertLast(const T&in)
void removeLast()
uint length() const
void resize(uint)
void sortAsc()
void sortAsc(uint, uint)
void sortDesc()
void sortDesc(uint, uint)
void reverse()
int find(const T&in) const
int find(uint, const T&in) const
reg type: val string group: <null>
beh(1) void _beh_1_()
beh(0) void _beh_0_()
beh(0) void _beh_0_(const string&in)
string& opAssign(const string&in)
string& opAddAssign(const string&in)
bool opEquals(const string&in) const
int opCmp(const string&in) const
string opAdd(const string&in) const
uint length() const
void resize(uint)
uint8& opIndex(uint)
const uint8& opIndex(uint) const
string& opAssign(double)
string& opAddAssign(double)
string opAdd(double) const
string opAdd_r(double) const
string& opAssign(int)
string& opAddAssign(int)
string opAdd(int) const
string opAdd_r(int) const
string& opAssign(uint)
string& opAddAssign(uint)
string opAdd(uint) const
string opAdd_r(uint) const
string& opAssign(bool)
string& opAddAssign(bool)
string opAdd(bool) const
string opAdd_r(bool) const
string substr(uint arg0 = 0, int arg1 = - 1) const
int findFirst(const string&in, uint arg1 = 0) const
int findLast(const string&in, int arg1 = - 1) const
type: interface MyIntf
void func() const

Failed to get the expected result when dumping the module

func: void Test()
type: class A : I
A@ A()
void i(float)
void a(int)
float f
type: class B : A, I
B@ B()
B@ B(int)
void i(float)
void a(int)
float f
type: interface I
void i(float)
global: float a
global: const float aConst
global: E e
global: float pi
global: I@ i
enum: E
eval = 0
eval2 = 2
typedef: real => float
import: void ImpFunc() from "mod"
-------
reg prop: float f group: <null>
reg prop: const float myConst group: <null>
reg typedef: myFloat => float
reg func: void func(int&in) group: <null>
reg func: void func2() group: test
reg enum: myEnum
value1 = 1
value2 = 2
reg funcdef: void Callback(int, int)
string factory: string
reg type: ref array group: <null>
T[]@ _beh_2_(int&in)
T[]@ _beh_2_(int&in, uint)
T[]@ _beh_2_(int&in, uint, const T&in)
beh(4) void _beh_4_()
beh(5) void _beh_5_()
beh(11) int _beh_11_()
beh(12) void _beh_12_()
beh(13) bool _beh_13_()
beh(14) void _beh_14_(int&in)
beh(15) void _beh_15_(int&in)
beh(10) bool _beh_10_(int&in)
beh(3) T[]@ _beh_3_(int&in, uint)
T& opIndex(uint)
const T& opIndex(uint) const
T[]& opAssign(const T[]&in)
void insertAt(uint, const T&in)
void removeAt(uint)
void insertLast(const T&in)
void removeLast()
uint length() const
void resize(uint)
void sortAsc()
void sortAsc(uint, uint)
void sortDesc()
void sortDesc(uint, uint)
void reverse()
int find(const T&in) const
int find(uint, const T&in) const
reg type: val string group: <null>
beh(1) void _beh_1_()
beh(0) void _beh_0_()
beh(0) void _beh_0_(const string&in)
string& opAssign(const string&in)
string& opAddAssign(const string&in)
bool opEquals(const string&in) const
int opCmp(const string&in) const
string opAdd(const string&in) const
uint length() const
void resize(uint)
uint8& opIndex(uint)
const uint8& opIndex(uint) const
string& opAssign(double)
string& opAddAssign(double)
string opAdd(double) const
string opAdd_r(double) const
string& opAssign(int)
string& opAddAssign(int)
string opAdd(int) const
string opAdd_r(int) const
string& opAssign(uint)
string& opAddAssign(uint)
string opAdd(uint) const
string opAdd_r(uint) const
string& opAssign(bool)
string& opAddAssign(bool)
string opAdd(bool) const
string opAdd_r(bool) const
string substr(uint arg0 = 0, int arg1 = - 1) const
int findFirst(const string&in, uint arg1 = 0) const
int findLast(const string&in, int arg1 = - 1) const
type: interface MyIntf
void func() const

Failed to get the expected result when dumping the module

-- TestDump passed
-- TestInheritance passed
-- TestScriptClassMethod passed
-- TestScriptString passed
-- TestSaveLoad passed
-- TestInterface passed
-- TestCastOp passed
-- Test2Modules passed
-- TestFile passed
-- TestArrayObject passed
-- TestCompiler passed
-- TestOptimize passed
-- TestConversion passed
-- TestRegisterType passed
-- TestRefArgument passed
-- TestStream passed
-- TestEnum passed
-- TestDynamicConfig passed
-- TestObjHandle passed
-- TestGlobalVar passed
-- TestScriptStruct passed
-- TestRZ passed
-- TestArray passed
-- TestAny passed
-- TestObjHandle2 passed
-- TestMetaData passed
-- TestDictionary passed
-- TestVector3 passed
-- TestConstObject passed
-- TestImplicitCast passed
-- TestImplicitHandle passed
-- TestFor passed
-- TestRefCast passed
-- TestStdString passed
-- TestStack2 passed
-- TestStdVector passed
-- TestArrayHandle passed
-- TestDict passed
-- TestMultiAssign passed
-- TestException passed
-- TestInt8 passed
-- TestGeneric passed
-- TestBStr passed
-- TestTypedef passed
-- TestImport passed
-- TestAssign passed
-- TestSwitch passed
-- TestExceptionMemory passed
-- TestObject passed
-- TestFactory passed
-- TestFuncOverload passed
-- TestObjZeroSize passed
-- TestSingleton passed
-- TestCondition passed
-- TestObject2 passed
-- TestShark passed
-- TestBool passed
-- TestBits passed
-- TestDestructor passed
-- TestConstructor2 passed
-- TestUnsafeRef passed
-- TestVarType passed
-- TestScriptMath passed
-- TestDebug passed
-- TestGetArgPtr passed
-- TestAutoHandle passed
-- TestObject3 passed
-- TestArrayIntf passed
-- TestConstProperty passed
-- TestSuspend passed
-- TestVector3_2 passed
-- TestNested passed
-- TestConstructor passed
-- TestExecuteScript passed
-- TestCustomMem passed
-- TestPostProcess passed
-- TestArgRef passed
-- TestNotInitialized passed
-- TestConfig passed
-- TestInt64 passed
-- TestImport2 passed
-- TestEnumGlobVar passed
-- TestConfigAccess passed
-- TestDiscard passed
-- TestParser passed
-- TestFloat passed
-- TestTempVar passed
-- TestModuleRef passed
-- TestExecuteString passed
-- TestStack passed
-- TestCreateEngine passed
-- TestLongToken passed
-- TestOutput passed
-- Test2Func passed
-- TestCircularImport passed
-- TestNeverVisited passed
-- TestExecute passed
-- TestCDeclReturn passed
-- TestExecute1Arg passed
-- TestExecute2Args passed
-- TestExecute4Args passed
-- TestExecute4Argsf passed
-- TestExecuteMixedArgs passed
-- TestExecute32Args passed
-- TestExecute32MixedArgs passed
-- TestCDecl_Class passed
-- TestCDecl_ClassA passed
-- TestCDecl_ClassC passed
-- TestCDecl_ClassD passed
-- TestCDecl_ClassK passed
-- TestReturnString passed
-- TestNegateOperator passed
-- TestReturnWithCDeclObjFirst passed
-- TestExecuteThis32MixedArgs passed
-- TestNotComplexThisCall passed
-- TestVirtualMethod passed
-- TestMultipleInheritance passed
TestVirtualInheritance: GNUC: AngelScript cannot detect virtual inheritance thus this test doesn't apply
-- TestVirtualInheritance passed
-- TestStdcall4Args passed
-- TestNotComplexStdcall passed
---------
MEMORY STATISTICS
number of allocations : 382545
max allocated memory at any one time : 247820
max number of simultaneous allocations: 2531
total amount of allocated memory : 50077271
medium size of allocations : 130
--------------------------------------------
All of the tests passed with success.

Press any key to quit.


Should I worry about those 'Failed to get the expected result when dumping the module' messages?

[EDIT]No, I should not :P scriptstdstring.cpp:
r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 );


No wonder the expected uin64 isn't returned..

Now, the only remaining question is whether stdcall should be enabled for x64 mingw or not..

[EDIT]just tried it and stdcall seems to work fine. Ok, here's the patch against the current AS trunk, which adds support for native calling convention to x64 mingw builds. Thanks for your help!
Excellent! Congratulations!

Thank you for all the hard work. I'll be sure to add this to the SVN right away.



[EDIT] Checked in under revision 939.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement