fastcc and ExecutionEngine::getPointerToFunction()

Yesterday I realised that if a Function has the calling convention set to "fast", then it is a bad idea to call it through the function pointer one gets from ExecutionEngine::getPointerToFunction().

The problem is that when calling it from my C++ program, the call will be made C-style, while the function expects to be called the fastcc way.

Could LLVM either warn the user of this, or solve it for the user?

One approach would be that getPointerToFunction() asserts that the function has default calling convention. This way, the user would be alerted.

Another approach would be that if getPointerToFunction() detects that the function does not have default calling convention, it produces a wrapper function, and returns a pointer to that.

My question is, is there code that would get into trouble because of
this?

For example, someone who is aware of this might be doing inline asm to produce a fastcc call through the pointer.

Or, someone might rely on the function actually being located on the returned address, and not necessarily calling it. This would break if the address to the wrapper is returned instead.

Any thoughts on this?

On a side note: wouldn't it be nice if the VerifierPass checks that calling conventions on calls and functions in a module match up?

Hans

Er... Sending this to the list instead of the parent...

I agree with you OvermindDL1,

SInce the language I'm going to be working on doesn't support varargs, it would be nice to be able to ditch the C calling convention for fastcc in all occurrances for an added speed boost. I also will need to add my own library calling convention on one platform I plan on supporting which will be register-loaded as well.

--Sam Crow

I agree with you OvermindDL1,

SInce the language I'm going to be working on doesn't support varargs, it would be nice to be able to ditch the C calling convention for fastcc in all occurrances for an added speed boost. I also will need to add my own library calling convention on one platform I plan on supporting which will be register-loaded as well.

Are you going to be calling the JITted function from C++, or from your language?

If the former, you'll need the function you're calling from C++ to
have a calling convention that C++ understands. You could always
write a helper function with the C calling convention that does
nothing but call the real function which has the fastcc convention.
Of course this would only give you a performance win if the real
target function is also called from other JITted code, or if it's
written out to bitcode and llc'd later with calls into it from other
bitcode.

Hello Kenneth,

I'd like to be able to call the generated bitcode from lli as well as opt and then llc. I'm not sure that counts.

All of the code would be generated internally to the language my team is going to be working on. Our langauge is extensible so we'll be adding to the syntax more often than to the linked bitcodes but definitely varargs will not be added. The first draft of all of the generated bitcode is translated to LLVM Assembly by LLVM-GCC but we will be hand-tuning the code to make it endian-neutral and hope to make it platform-agnostic bitcode as well.

Does that explain what we're trying to do?

--Sam

So you won't be calling it from C++ code?

If a function's callers are all implemented in your language, then the
function can have the fastcc convention and all calls to it can also
use the fastcc convention. (Calls have to have the same calling
convention as callees). If you have code in your language that JITs
the function in question and gets a function pointer, it can make the
call through that function pointer with the fastcc convention as well
if the target function has the fastcc convention.

If you try to call it through the function pointer from C++, however,
you'll need the target of that call to have the C calling convention.
In that case, a helper function for use from C++ code is your best
bet.

Thanks Kenneth!

Our runtime library may be written in C or have C bindings of C++ so I'll keep in mind what you said. The function pointers should all point to code that was generated by our language so that will simplify matters.

Thanks again,

--Sam

Hans Wennborg wrote:

Yesterday I realised that if a Function has the calling convention set
to "fast", then it is a bad idea to call it through the function pointer
one gets from ExecutionEngine::getPointerToFunction().

The problem is that when calling it from my C++ program, the call will
be made C-style, while the function expects to be called the fastcc way.

Could LLVM either warn the user of this, or solve it for the user?

One approach would be that getPointerToFunction() asserts that the
function has default calling convention. This way, the user would be
alerted.

Another approach would be that if getPointerToFunction() detects that
the function does not have default calling convention, it produces a
wrapper function, and returns a pointer to that.

My question is, is there code that would get into trouble because of
this?

Sure. You could be passing it in as a function pointer to another function, that's planning to call it with fastcc calling convention.

Or worse, you might be planning to call it with _stdcall (say, on Windows) and discarding the calling convention would be actively harmful.

In other words, please don't do this. Produce an llvm::Function to thunk if you must.

Nick

I very much agree with Nick here. There are a multitude of things you may be wanting to do and ways that you might want to call your fastcc function and while this is, unfortunately, irritating and hard to track down the first couple of times you make the mistake - the benefit is well worth it.

-eric

Eric Christopher wrote:

Sure. You could be passing it in as a function pointer to another function, that's planning to call it with fastcc calling convention.

Or worse, you might be planning to call it with _stdcall (say, on Windows) and discarding the calling convention would be actively harmful.

In other words, please don't do this. Produce an llvm::Function to thunk if you must.

I very much agree with Nick here. There are a multitude of things you may be wanting to do and ways that you might want to call your fastcc function and while this is, unfortunately, irritating and hard to track down the first couple of times you make the mistake - the benefit is well worth it.

Ok, I get your points. Won't touch this :slight_smile:

Hans