[LLVMdev] Pass a struct on windows
Duncan Sands
baldrick at free.fr
Thu Aug 11 04:55:10 PDT 2011
Hi Wei, this is a FAQ. The LLVM code generators do *not* try to produce ABI
conformant code. Instead, your front-end must produce LLVM IR which is already
ABI conformant. For example, on a platform where a function returning a struct
should return it via a hidden pointer, the IR function should be declared with
an explicit pointer argument for returning it; while on platforms for which it
should be returned in registers, the IR function should be declared to return
a struct. Yes, this is very annoying.
Ciao, Duncan.
> I made a simple test about aggregates in llvm IR. My simple LLVM code
> is running as expected under linux 32/64, but not under windows 32.
> After searched on the web on multiple return values, I'm still not sure if
> this test case can be flagged as the ABI issue. Or this would be a llvm
> code generator bug on window 32. The complete IR is attached as a text file
> and I checked the test with lli.
>
> (1) Pass a struct of type {void*, uint64_t} by pointer (in fact this is
> generated from Clang 3.0).
> The returned value of @call_by_pointer is 4 as expected, on both windows XP ia32
> and linux ubuntu x64 I tested.
>
> %0 = type { i8*, i64 }
>
> define void @foo_by_pointer(%0* %agg_addr, i8*, i64) nounwind {
> entry:
> %agg_addr.0 = getelementptr inbounds %0* %agg_addr, i32 0, i32 0
> store i8* %0, i8** %agg_addr.0, align 8
> %agg_addr.1 = getelementptr inbounds %0* %agg_addr, i32 0, i32 1
> store i64 %1, i64* %agg_addr.1, align 8
> ret void
> }
>
> define i64 @call_by_pointer() {
> %a_ptr = alloca float, align 4
> %a_opq = bitcast float* %a_ptr to i8*
> %agg_addr = alloca %0, align 8
> call void @foo_by_pointer(%0* %agg_addr, i8* %a_opq, i64 4)
> %agg_addr.1 = getelementptr inbounds %0* %agg_addr, i32 0, i32 1
> %result.1 = load i64* %agg_addr.1, align 8
> ret i64 %result.1
> }
>
> (2) Pass the struct by value (minor modifications on above code).
> The only difference is that we build the structure inside callee @foo_by_value
> and pass it by value to the caller @call_by_value. The returned value of
> @call_by_value is a random number on windows XP ia32. But on linux
> ubuntu x64 it is correct, 4.
>
> define %0 @foo_by_value(i8*, i64) nounwind {
> entry:
> %agg_addr = alloca %0, align 8
> %agg_addr.0 = getelementptr inbounds %0* %agg_addr, i32 0, i32 0
> store i8* %0, i8** %agg_addr.0, align 8
> %agg_addr.1 = getelementptr inbounds %0* %agg_addr, i32 0, i32 1
> store i64 %1, i64* %agg_addr.1, align 8
> %result = load %0* %agg_addr, align 8
> ret %0 %result
> }
>
> define i64 @call_by_value() {
> %a_ptr = alloca float, align 4
> %a_opq = bitcast float* %a_ptr to i8*
> %result = call %0 @foo_by_value(i8* %a_opq, i64 4)
> %agg_addr = alloca %0, align 8
> store %0 %result, %0* %agg_addr, align 8
> %agg_addr.1 = getelementptr inbounds %0* %agg_addr, i32 0, i32 1
> %result.1 = load i64* %agg_addr.1, align 8
> ret i64 %result.1
> }
>
> Is this a LLVM bug? Or call_by_value with foo_by_valye is invalid LLVM code?
>
> Thanks,
>
> Wei
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list