Native calling on x86_64 *nix gcc

Started by
77 comments, last by WitchLord 15 years, 2 months ago
I am currently evaluating the posibility of using AngelScript for a (rather large) project I'm working on. The project consists of a large 'blob-like' library and a bunch of executables that use the various features of the library. I would like to convert all executables into scripts and have a single generic executable that can just load the library and execute the proper script. The main problem I see however is that on x86_64 gcc (Linux and BSD) I would be forced to write a wrapper for each of the ~200 functions that my library currently exports. My question is: are there currently any on-going efforts to develop 'native' function calling for this compiler/architecture combo ? If there is work being done for this are there any estimates as to when it might hit 'mainline' ? I might have a crack at it if nobody else is activelly working on such a thing.
Advertisement
niteice began work on implementing the support for native calling conventions on 64bit x86 GCC, but he got busy with other projects and wasn't able to finish it. He did however send me the first part of the code, that I believe is partly working. It is already in the library in the file as_callfunc_x64_gcc.cpp. You can modify as_config.h to enable it in your project.

If you would like to invest some time and complete what niteice began I would be very grateful. If you're handy with the debugger and disassembler it shouldn't take more than a week to get it up and running.

I would add this support myself if I had a 64bit computer to work on, but unfortunately I do not, and it will likely stay like that for a while yet.

Regards,
Andreas

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

I have a VPS running 64bit linux that I could give you shell access to.
Thanks, droz. Actually I think you've already given me access to your VPS before. I remember using it once to fix some 64bit bugs.

However, I'm not too keen on doing a lot of debugging and dissambly via a terminal. While it's doable, it's a lot more time consuming than when working locally with an appropriate IDE.

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

I'm currently trying to get all samples to work correctly on x86_64/gcc with native calling. Biggest problems I've found so far lie in 'as_callfunc_x64_gcc.cpp' and are mainly related to gcc not generating the expected code for the call-wrappers. For example, the following are declared as global in the above-mentioned file:
register asQWORD rdi __asm__("rdi");register asQWORD rsi __asm__("rsi");register asQWORD rcx __asm__("rcx");register asQWORD r8 __asm__("r8");register asQWORD r9 __asm__("r9");asQWORD iargs[6] = { rdi, rsi, rdx, rcx, r8, r9 };

then later on, before making the actual call, the code goes on to do something like:
iargs[some_index] = some_value;

probably with the expectation that the corresponding register be set to the desired value. Obviously this does not work (at least on my system it doesn't - gcc 4.1.2) which leads all calls to be made with random values in the parameter-passing registers which in turn leads to "bad things (tm)(c)(r)" - all scripts crash on the first call to a function which has more than integers/floats as parameters (for the included samples this is usually one of the string-related functions which take a pointer to a string object as one of their parameters).

After replacing those instances with proper ASM code I was able to advance execution further but I found that incorrect values were popped out of the script stack. For example, here is a backtrace for a crash of the 'tutorial' sample:
#0  0x00007f15bf65edcb in std::string::append () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/libstdc++.so.6#1  0x000000000040691f in std::operator+<char, std::char_traits<char>, std::allocator<char> > (__lhs=@0x10ddde0, __rhs=@0x10e3c2000000000)    at /usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/bits/basic_string.h:2070#2  0x0000000000405fd0 in operator+ (a=@0x10ddde0, b=@0x10e3c2000000000) at ../../../../add_on/scriptstring/scriptstring.cpp:114#3  0x0000000000450b93 in CallCDeclFunction (pArgs=0x10e654c, pArgsType=0x7fffc7add002 "", argSize=4, func=0x405fae) at ../../source/as_callfunc_x64_gcc.cpp:254#4  0x0000000000451c12 in CallSystemFunction (id=37, context=0x10e1db0, objectPointer=0x0) at ../../source/as_callfunc_x64_gcc.cpp:657#5  0x000000000040b456 in asCContext::ExecuteNext (this=0x10e1db0) at ../../source/as_context.cpp:2017#6  0x000000000040f701 in asCContext::Execute (this=0x10e1db0) at ../../source/as_context.cpp:1079#7  0x00000000004024cc in RunApplication () at ../../source/main.cpp:171#8  0x00000000004027b6 in main (argc=1, argv=0x7fffc7add6a8) at ../../source/main.cpp:64

Note the values of the references passed to CScriptString::operator+() (stack frame #2). The first one looked to be correct while the second one did not - it was as if the address was shifted by 32 bits to the left. This appears to be caused by an obvious flaw in the way the x86_64 specific code in the call wrappers accesses the script stack, however I'm not 100% sure that that is the only flawed part involved.

More to follow in the next days :)
It's great to see that progress is being made.

I think it may be a bit easier for you if you start with the tests that are written explicitly for testing the native calling conventions. I've compiled a list of the tests for you, ordering them approximately in increasing complexity:

	// cdecl	if( TestExecute()                 ) goto failed; else printf("-- TestExecute passed\n");	if( TestReturn()                  ) goto failed; else printf("-- TestReturn passed\n");	if( TestReturnF()                 ) goto failed; else printf("-- TestReturnF passed\n");	if( TestReturnD()                 ) goto failed; else printf("-- TestReturnD passed\n");	if( TestExecute1Arg()             ) goto failed; else printf("-- TestExecute1Arg passed\n");	if( TestExecute2Args()            ) goto failed; else printf("-- TestExecute2Args passed\n");	if( TestExecute4Args()            ) goto failed; else printf("-- TestExecute4Args passed\n");	if( TestExecute4Argsf()           ) goto failed; else printf("-- TestExecute4Argsf passed\n");	if( TestExecuteMixedArgs()        ) goto failed; else printf("-- TestExecuteMixedArgs passed\n");	if( TestExecute32Args()           ) goto failed; else printf("-- TestExecute32Args passed\n");	if( TestExecute32MixedArgs()      ) goto failed; else printf("-- TestExecute32MixedArgs passed\n");	if( TestCDecl_Class()             ) goto failed; else printf("-- TestCDecl_Class passed\n");	if( TestCDecl_ClassA()            ) goto failed; else printf("-- TestCDecl_ClassA passed\n");	if( TestCDecl_ClassC()            ) goto failed; else printf("-- TestCDecl_ClassC passed\n");	if( TestCDecl_ClassD()            ) goto failed; else printf("-- TestCDecl_ClassD passed\n");	if( TestReturnString::Test()      ) goto failed; else printf("-- TestReturnString passed\n");	// cdecl_objfirst	if( TestReturnWithCDeclObjFirst() ) goto failed; else printf("-- TestReturnWithCDeclObjFirst passed\n");	// thiscall	if( TestExecuteThis32MixedArgs()  ) goto failed; else printf("-- TestExecuteThis32MixedArgs passed\n");	if( TestNotComplexThisCall()      ) goto failed; else printf("-- TestNotComplexThisCall passed\n");	if( TestVirtualMethod()           ) goto failed; else printf("-- TestVirtualMethod passed\n");	if( TestMultipleInheritance()     ) goto failed; else printf("-- TestMultipleInheritance passed\n");	if( TestVirtualInheritance()      ) goto failed; else printf("-- TestVirtualInheritance passed\n");	// stdcall	if( TestStdcall4Args()            ) goto failed; else printf("-- TestStdcall4Args passed\n");	if( TestNotComplexStdcall()       ) goto failed; else printf("-- TestNotComplexStdcall passed\n");

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

I gave you access to a computer running linux that was on my home network, it wasn't 64bit. If you change your mind in the future just let me know, I'd be more than happy to create you a account.
Ah, then thanks for the offer again. I think gargltk will be able to get this working, but if any future bugs show up on 64bit Linux I may take you up on that offer.

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

Thanks for pointing me to the tests, for some reason I just overlooked the 'tests' directory. I'm pretty sure I'm very close to having this up and running - right now it's passing every test on that list up to TestExecute32Args() which is working fine except that the code currently pushes the parameters to the stack in reverse so the correct values are passed only in the wrong parameters :) Once I get that sorted out I'm pretty sure the rest will fall into place. Hope to post a patch by tomorrow morning. *fingers crossed*
This is great news :D

It will be great to finally announce support for native calling conventions on 64bit Linux. Hopefully soon after that we can get Windows support too.

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