calling va_arg functions on win32 seems to require explicit stack alignment?

target datalayout = “e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32”
target triple = “i686-pc-windows-msvc”

declare void @llvm.va_start(i8**)
declare void @llvm.va_end(i8**)

define i64 @foo(…) {
%va = alloca i8*, i32 16 ; 4 words should be enough?
call void @llvm.va_start(i8** %va)
%x = va_arg i8** %va, i64
call void @llvm.va_end(i8** %va)
ret i64 %x
}

;; should return 123
define i32 @main() {
%val0 = call i64(…) @foo(i64 123)
%res = trunc i64 %val0 to i32
ret i32 %res
}

Running this returns mostly 0, but sometimes 123.

$ while sleep 1; do lli bug.ll; echo $?; done
123
0
0
0
123
0
0

Adding { alignstack=8 } to main makes it always return 123.

Is this a bug or just a missing piece of documentation?

Cheers,

– nikodemus

Looks like the LLVM va_arg instruction is broken on 32-bit Windows, probably because we think i64 is aligned on the stack, when it is not.

Ok :slight_smile:

Re. http://lists.llvm.org/pipermail/llvm-dev/2017-August/116337.html

  • Given current status quo #1 would be less frustrating. It seems that everyone implements it actually on their own without using the LLVM provided bits and bobs – now it’s offering false hope but not really delivering…

  • If wishes were horses #4 would lead to least duplicated effort across projects once it was in place… and if ponys were in the offering then ccc (and maybe fastcc) calling conventions that pass structs in accordance with the target ABI would be really nice. :slight_smile: That seems to be another thing that every frontend that cares currently has to implement on their own.

  • #2 and #3 seem like halfway houses. Fine spots if you’re on your way to #4, but not much to write home about as final destinations.

Cheers,

– nikodemus