LLVM IR va_arg instruction on Windows x86_64 uses wrong stride for arguments
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Hi everyone! While testing for [this issue](https://github.com/odin-lang/Odin/issues/6911), when I compiled and ran the program on Windows, I noticed inconsistent outputs from when I ran it on Linux.
I looked into it more and I found out that the ``va_arg`` instruction will use a stride of the primitive type for Windows instead of using the stride of a register's size if the primitive type's size is smaller.
Below is a minimum reproducible case program written in LLVM IR (``example.ll``)
```llvm
@str = constant [10 x i8] c"%d %d %d\0A\00"
; This struct is different for every platform. For most platforms,
; it is merely a ptr.
%struct.va_list = type { ptr }
; For Unix x86_64 platforms, va_list is the following struct:
; %struct.va_list = type { i32, i32, ptr, ptr }
define i32 @test(...) {
; Initialize variable argument processing
%ap = alloca %struct.va_list
call void @llvm.va_start.p0(ptr %ap)
; Read a single integer argument
%tmp1 = va_arg ptr %ap, i8
%tmp2 = va_arg ptr %ap, i8
%tmp3 = va_arg ptr %ap, i8
%tmp4 = va_arg ptr %ap, i8
%tmp5 = va_arg ptr %ap, i8
%tmp6 = va_arg ptr %ap, i8
%tmp7 = va_arg ptr %ap, i8
%tmp8 = va_arg ptr %ap, i8
%tmp9 = va_arg ptr %ap, i8
call i32 @printf(ptr @str, i8 %tmp1, i8 %tmp5, i8 %tmp9)
; Stop processing of arguments.
call void @llvm.va_end.p0(ptr %ap)
ret i32 0
}
define i32 @main() {
call i32 @test(i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9)
ret i32 0
}
declare void @llvm.va_start.p0(ptr)
declare void @llvm.va_copy.p0(ptr, ptr)
declare void @llvm.va_end.p0(ptr)
declare void @printf(ptr, ...)
```
On Windows, compile with ``clang example.ll`` and run ``a.exe`` to get ``1 0 2``
Here is an example report and run from my last compilation and execution
```
$ ~/Downloads/clang+llvm-22.1.8-x86_64-pc-windows-msvc/bin/clang.exe --version
clang version 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Users\REDACTED\Downloads\clang+llvm-22.1.8-x86_64-pc-windows-msvc\bin
$ ~/Downloads/clang+llvm-22.1.8-x86_64-pc-windows-msvc/bin/clang.exe example.ll
warning: overriding the module target triple with x86_64-pc-windows-msvc19.51.36248 [-Woverride-module]
1 warning generated.
$ ./a.exe
1 0 2
```
Contributor guide
Research direction
Start by compiling example.ll with clang on Windows and running a.exe to reproduce the 1 0 2 output. Trace how the va_arg instruction handles successive i8 arguments on the x86_64 Windows target, then verify the result against the expected argument sequence and the Linux behavior.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100