zig
zig copied to clipboard
x86_64 backend crashes on returning packed struct containing zero-sized enum
Zig Version
0.16.0-dev.1234+74900e938
Steps to Reproduce and Observed Behavior
Attempting to compile the following program with the x86-64 backend targeting x86_64-linux results in a SIGSEGV:
const Zero = enum(u0) { my_zero };
const MyStruct = packed struct(u32) {
value: u32,
zst: Zero,
};
pub fn crasher(a: u32, zst: Zero) MyStruct {
return MyStruct{
.value = a,
.zst = zst,
};
}
pub fn main() !void {
const result = crasher(5, .my_zero);
std.debug.print("{}", .{result.value});
}
const std = @import("std");
Doing the same on Zig version 0.15.1 actually results in a compilation error instead:
src/main.zig:8:5: error: emit MIR failed: InvalidInstruction (Zig compiler bug)
pub fn crasher(a: u32, zst: Zero) MyStruct {
~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: error(x86_64_encoder): no encoding found for: none mov m256 imm8s none none
Oddly enough, this compiles and runs successfully when targeting x86_64-windows.
Expected Behavior
The program should successfully compile and print 5 when run, or at least display an error message describing why compilation failed.
Workarounds
Use the LLVM backend instead or do not use zero-sized types.
Stack trace:
❯ zig4 build-exe test.zig
Compiler crash context:
Generating function 'test.crasher'
thread 90926 panic: reached unreachable code
/home/alexrp/Source/ziglang/zig/lib/std/debug.zig:416:14: 0x1c9d6c9 in assert (std.zig)
if (!ok) unreachable; // assertion failure
^
/home/alexrp/Source/ziglang/zig/lib/std/math.zig:1123:11: 0x2872b60 in isPowerOfTwo__anon_249367 (std.zig)
assert(int > 0);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:174053:34: 0x3a75b3e in allocRegOrMemAdvanced (main.zig)
if (std.math.isPowerOfTwo(abi_size) and abi_size <= @as(u32, max_abi_size: switch (ty.zigTypeTag(zcu)) {
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:174038:38: 0x3a7629a in allocRegOrMem (main.zig)
return self.allocRegOrMemAdvanced(self.typeOfIndex(inst), inst, reg_ok);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:179397:51: 0x4efc8b4 in airBitCast (main.zig)
const dst_mcv = try self.allocRegOrMem(inst, true);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:67355:42: 0x4f551ae in genBody (main.zig)
.bitcast => try cg.airBitCast(inst),
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:176497:21: 0x4f01b8d in lowerBlock (main.zig)
try self.genBody(body);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:67360:34: 0x4f554e9 in genBody (main.zig)
try cg.lowerBlock(inst, @ptrCast(cg.air.extra.items[block.end..][0..block.data.body_len]));
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:176497:21: 0x4f01b8d in lowerBlock (main.zig)
try self.genBody(body);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:67360:34: 0x4f554e9 in genBody (main.zig)
try cg.lowerBlock(inst, @ptrCast(cg.air.extra.items[block.end..][0..block.data.body_len]));
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:2269:19: 0x47f7b2d in genMainBody (main.zig)
try cg.genBody(main_body[air_arg_count..]);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:2065:29: 0x402dce8 in gen (main.zig)
try self.genMainBody(zir, func_zir_inst, comptime_args, air_arg_count);
^
/home/alexrp/Source/ziglang/zig/src/codegen/x86_64/CodeGen.zig:991:17: 0x38f0650 in generate (main.zig)
function.gen(&file.zir.?, func_zir.inst, func.comptime_args, call_info.air_arg_count) catch |err| switch (err) {
^
/home/alexrp/Source/ziglang/zig/src/codegen.zig:163:45: 0x2ec6337 in generateFunction (main.zig)
const mir = try CodeGen.generate(lf, pt, src_loc, func_index, air, liveness);
^
/home/alexrp/Source/ziglang/zig/src/Zcu/PerThread.zig:4522:36: 0x2922aaa in runCodegenInner (main.zig)
return codegen.generateFunction(lf, pt, zcu.navSrcLoc(nav), func_index, air, &liveness) catch |err| switch (err) {
^
/home/alexrp/Source/ziglang/zig/src/Zcu/PerThread.zig:4400:46: 0x243605f in runCodegen (main.zig)
const success: bool = if (runCodegenInner(pt, func_index, air)) |mir| success: {
^
/home/alexrp/Source/ziglang/zig/src/Compilation.zig:5881:18: 0x2911cee in workerZcuCodegen (main.zig)
pt.runCodegen(func_index, &air, out);
^
/home/alexrp/Source/ziglang/zig/lib/std/Thread/Pool.zig:180:50: 0x2911fbd in runFn (std.zig)
@call(.auto, func, .{id.?} ++ closure.arguments);
^
/home/alexrp/Source/ziglang/zig/lib/std/Thread/Pool.zig:293:27: 0x2397630 in worker (std.zig)
runnable.runFn(runnable, id);
^
/home/alexrp/Source/ziglang/zig/lib/std/Thread.zig:558:13: 0x21c7a20 in callFn__anon_196835 (std.zig)
@call(.auto, f, args);
^
/home/alexrp/Source/ziglang/zig/lib/std/Thread.zig:830:30: 0x205f149 in entryFn (std.zig)
return callFn(f, args_ptr.*);
^
./nptl/pthread_create.c:448:8: 0x74e21c0a27f0 in start_thread (pthread_create.c)
../sysdeps/unix/sysv/linux/x86_64/clone3.S:78:0: 0x74e21c133b5b in __GI___clone3 (../sysdeps/unix/sysv/linux/x86_64/clone3.S)
fish: Job 1, 'zig4 build-exe test.zig' terminated by signal SIGABRT (Abort)
Unsure if frontend or backend bug; labeling as the latter for now.
%16 = bitcast(u0, <repro.Zero, .my_zero>)