[LLVMdev] [BUG] Varargs example in LangRef segfaults
Reid Kleckner
rnk at google.com
Tue Aug 26 14:51:11 PDT 2014
va_arg of struct types is not implemented in the x86_64 backend:
// Decide which area this value should be read from.
// TODO: Implement the AMD64 ABI in its entirety. This simple
// selection mechanism works only for the basic types.
if (ArgVT == MVT::f80) {
llvm_unreachable("va_arg for f80 not yet implemented");
} else if (ArgVT.isFloatingPoint() && ArgSize <= 16 /*bytes*/) {
ArgMode = 2; // Argument passed in XMM register. Use fp_offset.
} else if (ArgVT.isInteger() && ArgSize <= 32 /*bytes*/) {
ArgMode = 1; // Argument passed in GPR64 register(s). Use gp_offset.
} else {
llvm_unreachable("Unhandled argument type in LowerVAARG");
}
So Clang lowers it manually.
If you only use builtin types such as integers, pointers, floats, and
doubles, then va_arg works.
On Tue, Aug 26, 2014 at 2:36 PM, Ramkumar Ramachandra <artagnon at gmail.com>
wrote:
> So I've written out this sample based on what Clang emitted:
>
> -- 8< --
> %struct.__va_list_tag = type { i32, i32, i8*, i8* }
>
> define i32 @test(i32 %X, ...) {
> ; Initialize variable argument processing
> %ap = alloca %struct.__va_list_tag
> %ap2 = bitcast %struct.__va_list_tag* %ap to i8*
> %retptr = alloca i32
> call void @llvm.va_start(i8* %ap2)
>
> ; Read a single integer argument
> %idxptr = getelementptr inbounds %struct.__va_list_tag* %ap, i32 0, i32 0
> %idx = load i32* %idxptr
> %tmp = getelementptr inbounds %struct.__va_list_tag* %ap, i32 0, i32 3
> %extract = load i8** %tmp
> %rawel = getelementptr i8* %extract, i32 %idx
> %elptr = bitcast i8* %rawel to i32*
> %newidx = add i32 %idx, 8
> store i32 %idx, i32* %idxptr
>
> ; Store that argument in el
> %el = load i32* %elptr
> store i32 %el, i32* %retptr
> %ret = load i32* %retptr
>
> ; Stop processing of arguments.
> call void @llvm.va_end(i8* %ap2)
> ret i32 %ret
> }
>
> define i32 @main() {
> %call = call i32 (i32, ...)* @test(i32 1, i32 3)
> ret i32 %call
> }
>
> declare void @llvm.va_start(i8*)
> declare void @llvm.va_copy(i8*, i8*)
> declare void @llvm.va_end(i8*)
> -- 8< --
>
> Can we include (a neater version of) this in the LangRef? Can it not
> be simplified?
>
> I understand that %struct.__va_list_tag will be different for each
> platform, so the user can't gep into the structure in a
> platform-independent manner, but what's the problem with this?
>
> %ap = alloca_va_list
> %ap2 = bitcast %struct.__va_list_tag* %ap to i8*
> call void @llvm.va_start(i8* %ap2)
> va_arg %ap i32
> call void @llvm.va_end(i8* %ap2)
>
> All we need is a sort of global %struct.__va_list_tag, right?
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140826/5d0b3e44/attachment.html>
More information about the llvm-dev
mailing list