Skip to content

c-stack-cdecl assumes arguments are passed on stack #1163

Closed
@nikomatsakis

Description

@nikomatsakis

In the x86_64 architecture (and others as well), the first few integer arguments are passed in registers rather than being pushed on the stack. Currently, c-stack-cdecl works by allocating some space on the C stack and then writing the arguments into that space. A small shim (upcall_call_c_stack()) then switches the stack pointer over and invokes the function, which will then find the arguments on the stack as expected. Naturally this fails when the function doesn't expect its arguments on the stack. For now, I have worked around the issue by having upcall_call_c_stack() on x86_64 load the registers from the stack, but this will only work for very simple cases. In an ideal world, LLVM should handle the details of the calling convention for us, just as it does for a typical "invoke" instruction. However, this is a bit tricky since the default invoke instruction does not switch stacks!

One possible solution would be to generate a shim function S for each function F that we would like to call on the c-stack. If F takes arguments of type X and Y and returns a type Z, the shim function would work like:

void S(struct F_Args { X x; Y y; Z *z; } *args) {
    *args->z = F(args->x, args->y);
}

We can then have some hand-coded assembly that swaps the stack pointer and invokes S on the C-stack. S has a known signature so this should be easy. LLVM ought to then generate the right code to unpack the arguments and put them where they belong. The downside of this trick is that this results in copying the arguments more than is needed.

Another option might be to add a new calling convention to LLVM. The problem is we would need to generate a new calling convention for each target architecture. On the other hand, that may not be such a big hurdle. I don't know how one defines calling conventions in LLVM or how flexible that system is.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions