From 9358a7528f74cfa8b45f98e83749b8e695d9a941 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 18 Oct 2023 01:24:17 -0400 Subject: [PATCH] x86_64: fix crashes --- src/arch/x86_64/CodeGen.zig | 55 +++++++++++++++++++++++++------------ test/behavior/basic.zig | 2 +- test/behavior/cast.zig | 1 - test/behavior/fn.zig | 2 +- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 55e872d2fc..a00d562924 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -3798,11 +3798,13 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { } fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { + const mod = self.bin_file.options.module.?; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const result: MCValue = result: { const pl_ty = self.typeOfIndex(inst); - const opt_mcv = try self.resolveInst(ty_op.operand); + if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; + const opt_mcv = try self.resolveInst(ty_op.operand); if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) { switch (opt_mcv) { .register => |reg| try self.truncateRegister(pl_ty, reg), @@ -11521,10 +11523,13 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal .undef => {}, .immediate => |imm| switch (abi_size) { 1, 2, 4 => { - const immediate = if (ty.isSignedInt(mod)) - Immediate.s(@truncate(@as(i64, @bitCast(imm)))) + const immediate = switch (if (ty.isAbiInt(mod)) + ty.intInfo(mod).signedness else - Immediate.u(@as(u32, @intCast(imm))); + .unsigned) { + .signed => Immediate.s(@truncate(@as(i64, @bitCast(imm)))), + .unsigned => Immediate.u(@as(u32, @intCast(imm))), + }; try self.asmMemoryImmediate( .{ ._, .mov }, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base, .disp = disp }), @@ -11586,19 +11591,35 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) }, ), registerAlias(src_reg, part_size)); }, - .register_overflow => |ro| { - try self.genSetMem( - base, - disp + @as(i32, @intCast(ty.structFieldOffset(0, mod))), - ty.structFieldType(0, mod), - .{ .register = ro.reg }, - ); - try self.genSetMem( - base, - disp + @as(i32, @intCast(ty.structFieldOffset(1, mod))), - ty.structFieldType(1, mod), - .{ .eflags = ro.eflags }, - ); + .register_overflow => |ro| switch (ty.zigTypeTag(mod)) { + .Struct => { + try self.genSetMem( + base, + disp + @as(i32, @intCast(ty.structFieldOffset(0, mod))), + ty.structFieldType(0, mod), + .{ .register = ro.reg }, + ); + try self.genSetMem( + base, + disp + @as(i32, @intCast(ty.structFieldOffset(1, mod))), + ty.structFieldType(1, mod), + .{ .eflags = ro.eflags }, + ); + }, + .Optional => { + assert(!ty.optionalReprIsPayload(mod)); + const child_ty = ty.optionalChild(mod); + try self.genSetMem(base, disp, child_ty, .{ .register = ro.reg }); + try self.genSetMem( + base, + disp + @as(i32, @intCast(child_ty.abiSize(mod))), + Type.bool, + .{ .eflags = ro.eflags }, + ); + }, + else => return self.fail("TODO implement genSetMem for {s} of {}", .{ + @tagName(src_mcv), ty.fmt(mod), + }), }, .register_offset, .memory, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 3b27e93402..30b6286658 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -745,12 +745,12 @@ test "auto created variables have correct alignment" { test "extern variable with non-pointer opaque type" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; @export(var_to_export, .{ .name = "opaque_extern_var" }); try expect(@as(*align(1) u32, @ptrCast(&opaque_extern_var)).* == 42); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 91e2812591..c9914005bb 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -2383,7 +2383,6 @@ test "numeric coercions with undefined" { test "15-bit int to float" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; var a: u15 = 42; var b: f32 = @floatFromInt(a); diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index aad7f57590..859be1efda 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -425,8 +425,8 @@ test "implicit cast function to function ptr" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest; const S1 = struct { export fn someFunctionThatReturnsAValue() c_int {