llvm backend fails to build multiple var args behavior tests on s390x-linux
Zig Version
0.14.0-dev.1509+fb81522e0
Steps to Reproduce and Observed Behavior
$ ./build/stage3/bin/zig test test/behavior.zig -target s390x-linux-musl --test-cmd qemu-s390x --test-cmd-bin
LLVM ERROR: Cannot select: 0xc7c3270: i32,ch = vaarg 0xd585ec0, FrameIndex:i64<1>, SrcValue:ch<0xa52d3a0>, TargetConstant:i32<4>, var_args.zig:114:13
0xcea2cc0: i64 = FrameIndex<1>
0xde9d860: i32 = TargetConstant<4>
In function: behavior.var_args.test.simple variadic function.S.simple
Aborted (core dumped)
LLVM ERROR: Cannot select: 0xf633a90: i64,ch = vaarg 0xdde0ca0:1, FrameIndex:i64<3>, SrcValue:ch<0xbc25aa0>, TargetConstant:i32<8>, var_args.zig:178:17
0xdfa63d0: i64 = FrameIndex<3>
0xf004670: i32 = TargetConstant<8>
In function: behavior.var_args.test.coerce reference to var arg.S.addPtr
Aborted (core dumped)
LLVM ERROR: Cannot select: 0xc3c2790: i32,ch = vaarg 0x4df2dd0, 0xc4d6f40, SrcValue:ch<0x5af3bf0>, TargetConstant:i32<4>, var_args.zig:222:21
0xc4d6f40: i64,ch = CopyFromReg 0x4df2dd0, Register:i64 %17, var_args.zig:222:21
0xdc765e0: i64 = Register %17
0xc3f76f0: i32 = TargetConstant<4>
In function: behavior.var_args.test.variadic functions.S.vprintf
Aborted (core dumped)
LLVM ERROR: Cannot select: 0xcc62280: i32,ch = vaarg 0xca5cd60:1, FrameIndex:i64<5>, SrcValue:ch<0xa936340>, TargetConstant:i32<4>, var_args.zig:258:17
0xd288b10: i64 = FrameIndex<5>
0xe5927b0: i32 = TargetConstant<4>
In function: behavior.var_args.test.copy VaList.S.add
Aborted (core dumped)
LLVM ERROR: Cannot select: 0xf022ac0: i32,ch = vaarg 0xec43c40:1, FrameIndex:i64<1>, SrcValue:ch<0xb211820>, TargetConstant:i32<4>, var_args.zig:294:13
0xec50ac0: i64 = FrameIndex<1>
0xd8baa40: i32 = TargetConstant<4>
In function: behavior.var_args.test.unused VaList arg.S.thirdArg
Aborted (core dumped)
Expected Behavior
tests passing
The var arg instructions in LLVM don't work properly on most targets because clang doesn't use them. Reimplementing them ourselves like clang does would fix this as well.
I don't think this is an upstream bug. I believe we need to emit code similar to Clang: https://github.com/llvm/llvm-project/blob/1bb52e94621d2cba4f34504697cb0ea83805cb98/clang/lib/CodeGen/Targets/SystemZ.cpp#L246
That's what I meant by clang not using the va_arg instruction, I ran into it when originally implementing the feature and it's the reason why VaList is disabled on many targets.
docs
└─ langref
└─ install generated to doc/langref.html
└─ run exe docgen (langref.html)
└─ WriteFile test_defining_variadic_function.out
└─ run exe doctest (test_defining_variadic_function.out) failure
LLVM ERROR: Cannot select: t8: i32,ch = vaarg t4:1, FrameIndex:i64<3>, SrcValue:ch<0x5fb3670>, TargetConstant:i32<4>, test_defining_variadic_function.zig:11:9
In function: test_defining_variadic_function.add
The following command crashed:
../../../build/debug/bin/zig test ../../../doc/langref/test_defining_variadic_function.zig --zig-lib-dir ../../../lib
error: test failed
error: process exited with error code 1
failed command: /home/ci/zig/.zig-cache/o/4c62e7bce68e4f1586a52bbc316521a7/doctest --zig /home/ci/zig/build/debug/bin/zig --cache-root /home/ci/zig/.zig-cache --zig-lib-dir /home/ci/zig/lib/ -i /home/ci/zig/doc/langref/test_defining_variadic_function.zig -o /home/ci/zig/.zig-cache/o/6e81b0fe13a78fa6f77626332e334669/test_defining_variadic_function.out