-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
varargs support #1030
Comments
I am not 100% sure that we actually want too support this. It's not really a goal of Cretonne to be a C compiler nor to support all of LLVM's semantics. I don't think varargs support is needed to be a code generator for the Rust compiler, and WebAssembly doesn't require it either. |
What if we didn't do all of the Also, for completeness, it looks like varargs will eventually be needed for Rust; see rust-lang/rfcs#2137. Though it's not yet implemented even for the LLVM backend, so we won't have to worry about it for a while. |
Hmm, the Rust varargs callee use case seems even more obscure than inline assembly. I don't think we should commit to a design for this until we have a more clear need for it. It's not simple to do varargs correctly. Some ABIs require the caller to place arguments in multiple locations. SPARC even requires some floating point values to be passed in three different locations under some circumstances. Intel avoids that by instead requiring crazy code in the callee for dealing with floating point arguments in registers. If we have to do it, so be it, but a half-hearted attempt is just going to be buggy like LLVM's va_arg instruction. |
I agree. I believe all of your stated concerns above could be addressed by the design I sketched here. I also agree that we don't have to do anything about this right now. |
Unfortunately for us, rustc is making progress on implementing variadic functions: rust-lang/rust#49878. |
The implementation proposed that I'm working on uses the LLVM |
Calling variadic functions is necessary for libstd: rust-lang/rustc_codegen_cranelift#146 (not very urgent for me, might be able to just panic at runtime) |
Which architectures and OSes would need to be supported? |
Calling variadic functions is certainly easier than the callee side. On many platforms it's the same as non-vararg. On x86-64 System V for example, everything is the same as non-vararg, except that you also need to set the let rax = isa.register_info().parse_regunit("rax");
ArgumentLoc::Reg(rax) So what we need to do is to make sure that works, and package it into a friendlier interface. My rough idea is to put it into something like On the callee side, Rust is still working on implementing this using LLVM, so there's not a lot of Rust code using it yet :-). |
Oh, one other difference between vararg and non-vararg on the caller side in C is that |
How would that work with |
You'd declare the function with the extra argument too; that's the |
Does rust-lang/rustc_codegen_cranelift@53e51ac seem like a good way to support this? (I know I forgot setting |
@bjorn3 I don't know much about IMO there are three things that need solving (one I have still yet to do in rustc for LLVM):
The last one is still WIP see rust-lang/rust#57760 Is this issue only focused on a subset of the above three? Also note, depending on how the last two are supported in |
Cranelift is more low level than LLVM. Eg it doesn't support structs, but expects you to implement them yourself. Implementing the call side of variadic functions can be done as a producer of cranelift ir. It is however possible to implement it in cranelift in the future.
This issue is about both.
|
Exactly, I'm specifically referring to the implementation of |
I'm not sure I see how a frontend could implement varargs manually. How would I implement a calling convention without access to registers? e.g. for floating point |
|
That doesn't work if you pass different numbers of args in the same program, e.g. int printf(const char *format, ...);
int main() {
printf("hello world\n");
printf("some int here: %d", 2);
} |
What I did for cg_clif is dont tell cranelift_module about the varargs and then use declare_func_in_func once per vararg call. That will give a unique FuncRef every time. I then changed the associates Signature (which is also unique) to match the varargs. |
and Cranelift allows that?? I can try it out, I'm surprised that cranelift allows you to modify the signature though haha |
Yes, the |
How do I set registers? I found RegDiversions::reg to get the current register of a Value and InstBuilder::regmove to move from one register to another, but I don't know how to get a // float_variadic is an integer, builder is a FunctionBuilder
let float_ir = builder.ins().iconst(types::I8, float_variadic);
let target = self.module.isa();
if target.name() != "x86" {
unimplemented!("variadic args for architectures other than x86");
}
let reginfo = target.register_info();
let al = reginfo.parse_regunit("al").expect("al register should exist on x86");
let diversions: RegDiversions = unimplemented!(); // how do I get this?
let locations: ValueLocations = unimplemented!(); // how do I get this?
let current_reg = diversions.reg(float_ir, &locations);
builder.ins().regmove(float_ir, current_reg, al); |
RegDiversions is only used when regalloc is running or has already ran. For your usecase you will want to use |
Are there any updates with this? Implementing varargs as a frontend with Cranelift is extremely cumbersome. |
There hasn't been any change since the last comment here. Also do you need just support for calling variadic functions or also defining them? The former is a lot easier to support than the latter. |
Just calling them. |
In order to compile C code that calls
printf
in libc, we need to implement the caller side of varargs. And in order to compile printf itself, we need to implement the callee side.The text was updated successfully, but these errors were encountered: