Ramkumar Ramachandra
2014-Aug-26 19:37 UTC
[LLVMdev] [BUG] Varargs example in LangRef segfaults
Hi,
So the Variable Argument Handling Intrinsics section of the LangRef
(http://llvm.org/docs/LangRef.html#variable-argument-handling-intrinsics)
lists an example that segfaults. Try the following on x86_64:
-- 8< --
define i32 @test(i32 %X, ...) {
; Initialize variable argument processing
%ap = alloca i8*
%ap2 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap2)
; Read a single integer argument
%tmp = va_arg i8** %ap, i32
; Demonstrate usage of llvm.va_copy and llvm.va_end
%aq = alloca i8*
%aq2 = bitcast i8** %aq to i8*
call void @llvm.va_copy(i8* %aq2, i8* %ap2)
call void @llvm.va_end(i8* %aq2)
; Stop processing of arguments.
call void @llvm.va_end(i8* %ap2)
ret i32 %tmp
}
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< --
It happens because va_arg is apparently not implemented properly on
X86 (I saw tests/Codegen/X86/vaargs.ll). What should be done about the
situation?
1. Update the LangRef.
2. Fix va_arg for x86.
If (2) is the way to go, I'll take a stab at it.
Thanks.
Ram
The problem is that the type of the va_list is platform-specific. No IR example will work on all platforms, unless you overallocate. The LangRef should probably be updated to use the SysV x86_64 va_list as that is the most common and mention in an IR comment that the type depends on the platform. On Tue, Aug 26, 2014 at 12:37 PM, Ramkumar Ramachandra <artagnon at gmail.com> wrote:> Hi, > > So the Variable Argument Handling Intrinsics section of the LangRef > (http://llvm.org/docs/LangRef.html#variable-argument-handling-intrinsics) > lists an example that segfaults. Try the following on x86_64: > > -- 8< -- > define i32 @test(i32 %X, ...) { > ; Initialize variable argument processing > %ap = alloca i8* > %ap2 = bitcast i8** %ap to i8* > call void @llvm.va_start(i8* %ap2) > > ; Read a single integer argument > %tmp = va_arg i8** %ap, i32 > > ; Demonstrate usage of llvm.va_copy and llvm.va_end > %aq = alloca i8* > %aq2 = bitcast i8** %aq to i8* > call void @llvm.va_copy(i8* %aq2, i8* %ap2) > call void @llvm.va_end(i8* %aq2) > > ; Stop processing of arguments. > call void @llvm.va_end(i8* %ap2) > ret i32 %tmp > } > > 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< -- > > It happens because va_arg is apparently not implemented properly on > X86 (I saw tests/Codegen/X86/vaargs.ll). What should be done about the > situation? > 1. Update the LangRef. > 2. Fix va_arg for x86. > > If (2) is the way to go, I'll take a stab at it. > > Thanks. > > Ram > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140826/3e6271e3/attachment.html>
Ramkumar Ramachandra
2014-Aug-26 21:36 UTC
[LLVMdev] [BUG] Varargs example in LangRef segfaults
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?
Possibly Parallel Threads
- [LLVMdev] [PATCH] LangRef: va_arg doesn't work on X86_64; update example
- R-3.4.2: make check stops at line 698 of tests/reg-tests-1d.R
- R-3.4.2: make check stops at line 698 of tests/reg-tests-1d.R
- R-3.4.2: make check stops at line 698 of tests/reg-tests-1d.R
- R-3.4.2: make check stops at line 698 of tests/reg-tests-1d.R