[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