Advertisement

x64 support & late binding of classes

Started by August 01, 2005 12:23 PM
16 comments, last by WitchLord 19 years, 2 months ago
Hi, first off thanks for such a nice scripting implementation & for sticking with a known syntax. I have a few questions... First off, has any work been done on x64 support? If nothing, what (in code terms) needs to change to support it natively (primarily its calling conventions)? Also, out of interest, has anyone tried tried adapting AS for the PPC ISA? Additionally, say for instance I have a script that creates an native object dynamically but does not register the properties & methods of that object until an instance of that object is constructed. Will the script be able to successfully "late-bind" with the newly exposed properties & methods on the object? Or must all instance properties & methods be registered before they can be declared in a script? Thanks in advance, Will.
There has been some interest in support for 64bit processors, but I don't have access to any such environment to do the development. If AS_MAX_PORTABILITY is used the actual changes to add the support should be quite small, though it can be difficult to find. The major changes that I'm aware of is that pointer sizes are 64bit instead of 32bit.

Is PPC ISA a 64bit processor? If not I think you should be able to run AngelScript on it by compiling the library with the AS_MAX_PORTABILITY mode.

At the moment a script is compiled, all features used has to be known. This includes object types, their behaviours, functions, etc.

It should be possible to configure the engine with null pointers, however. This will allow you to compile the scripts, save the byte code, and then load the pre-compiled byte code when you have the true engine configuration. (As far as I know, nobody has actually tested this yet, so I can't guarantee that it works without problems. Though, if there are any problems doing this, I'll make sure to fix them.)

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

Advertisement
I've been taking a wonder through the source to get a feel for the changes required. As you say AS_MAX_PORTABILITY should work - bar pointer size issues. I suppose the main thing I'm interested in would be how much would need to change in order to support the standard calling conventions under x64. I've dug up the following two links from google that may prove useful:

http://msdn2.microsoft.com/library/7kcdt6fy(en-us,vs.80).aspx
http://blogs.msdn.com/freik/archive/2005/03/17/398200.aspx

Assuming as_callfunc_x86.cpp contains all of the logic it shouldn't be too hard to expose functions in a x64 binary. I'll have a go anyway...

The PPC ISA is 64bit from here on in. The big job certainly sounds like making the code 64bit safe. I'll try compiling the code to target x64 tomorrow to see what I run into.

Cheers,
Will.
I'm pleased that you're willing to give it a try. Having the library support 64bit processors as well, would be a great contribution.

I'll take a look at the articles you mentioned as soon as I can.

If you want to support the native calling conventions, you'll need to port the functions in as_callfunc_x86.cpp. I suggest you create a new file as_callfunc_ppc64.cpp, or something like that.

You may also take a look at "Calling conventions on the x86 platform" to get an idea of things to look for when determining how calling conventions work on your compiler/platform. If you'd like to contribute information to that article, I'd be grateful as well. Maybe I'll expand it to other platforms as well.

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

Well, partial success. Compiling the AS SDK for x64 works, the only required modifications have been defining AS_MAX_PORTABILITY & doubling the size of the char dummy[20] member of asUPtr (obviously as normal pointers have doubled in size). Although I haven't checked to see if this is larger then required, but for now it just works.

Admittedly the script I've tested it with is very simple & without any handles but I wanted to start off without too much complexity.

float global_var = 128;

void DoSomething()
{
global_var *= 2;
print(global_var); // Implemented as a generic function
}

The next step I'm going to try is to see if I can translate the as_callfunc_x86.cpp to a as_callfunc_x64.cpp. The biggest issue I've run into so far is that the x64 compiler included with VS2005 doesn't support inline assembly. So I'm going to have to do a bit of MASM work. Still, all good fun.

If I learn enough about the calling conventions used I may well put together a small document for you to put online. It can only help. Although it seems Microsoft & AMD have been fairly proactive on the subject themselves.

Will.
Theres a rather large set of test apps included in the SDK. You should test the changes with them.
Advertisement
This sounds great. [grin]

Did you really need to increase the size of the dummy? According to this article there are no larger method pointers than 20 bytes (even for 64bit systems). Maybe you'll just need to set it to 21 (so that the array never becomes 0).

There will likely be quite a few pointers where I've assumed a size of 4 bytes. The compiled bytecode will also be changed slightly to include direct pointers to for example global variables and functions, these will also have to be compatible with 64bit pointers.

Once you start converting the as_callfunc_x86.cpp, I suggest you start with the CDECL convention, as that is by far the most important one. Then you can move on to the CDECL_OBJLAST and CDECL_OBJFIRST. Once these 3 calling conventions are implemented, then all others can be emulated with very simple wrappers.

This is exciting, it will be great when I can officially say that the library supports 64bit systems. [grin]

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

Quick update on progress. I've had to spend quite a bit of time getting to grips with the special prolog & epilog rules for x64 function calls. It's important as any form of stack trace & stack unwinding (in case of exceptions) need extra metadata from the assembly. Unfortunately there's not a whole lot of documentation on the subject, so I've had to do a fair bit of disassembly to work out what goes on in different cases.

It now looks like I've got it right. So now it's simply (!) a case of putting the first 4 arguments into registers & spilling the rest onto the stack prior to making the function call. Which hopefully shouldn't take too long to implement...

I double checked the asUPtr size issue. It won't compile with any size smaller then 24 bytes - but it does seem to run okay at that size. I'm not sure but I have a feeling it might be alignment related. Either way it seems that the article is incorrect, unless the compiler is making a big fuss over nothing.

Will.
From what little I had time to read it seems that for the AMD 64bit systems, MSVC chooses fastcall as the standard calling convention. You may want to verify if there is a difference between fastcall and cdecl on that system. If there is then the constant asCALL_FASTCALL needs to be added.

The member pointer size may be 20 bytes, but that would make the other array have a size of 0, which is not allowed. Let's just leave the size of dummy at 24. The size of this type isn't really that important, since it is not used for storage.

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

Yep, fastcall (or rather the x64 variant of it) is the calling convention for everything on x64 in windows. Which undoubtedly makes life somewhat simpler then for the x86.

Because fastcall is supported universally & is the only "legal" calling convention on x64 I'd suggest leaving the AS calling conventions as they are. The x64 compiler simply ignores any cdecl, stdcall & fastcall declarations anyway, so the x64 function calling logic should only need to worry about fastcall & ignore the asCALL_x definitions except for the cases that require attention.

I've completed the assembly required to call into any C-style x64 functions. Although one issue I ran into is the alignment of the stack that AS uses. The x64 stack is 16 byte aligned, which means to keep the assembly manageable, I have to parse the parameters off the AS stack & into a QWORD array which is then passed to the assembly, ready to copy into registers & spill onto the x64 stack.

Obviously the one big thing I haven't touched on yet is the issue of how to pass 64 bit object pointers around within AS. Might I suggest that a new define is added to AS, something like asPTR that is large enough to take the native size of a pointer on a given CPU architecture. This can then be used in those situations where pointers are passed around within AS. Obviously I don't know how you want to handle the impact this will have on bytecode instruction sizes & any thing else non-trivial that may be impacted in the change to supporting 64-bit pointers? I don't know enough at this stage to start hacking the source for it.

Anyways, I'll clean up what I've got & pass it on when it's in a reasonable state. Only issue is that VS2005 is still under beta so I'm not sure if it's legally possible to let its project files out onto the net... But even so, I can make the source available.

How do you want to tackle the pointer issue?

Cheers,
Will.

This topic is closed to new replies.

Advertisement