Commit caa3d6a4f4

Jacob Young <jacobly0@users.noreply.github.com>
2023-04-07 06:45:14
x86_64: fix constant pointers to zero-bit types
These non-dereferencable pointers still need to have the correct alignment and non-null-ness.
1 parent 3b22ce8
Changed files (3)
src
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -1080,7 +1080,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
 
             .constant => unreachable, // excluded from function bodies
             .const_ty => unreachable, // excluded from function bodies
-            .unreach  => self.finishAirBookkeeping(),
+            .unreach  => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),
 
             .optional_payload           => try self.airOptionalPayload(inst),
             .optional_payload_ptr       => try self.airOptionalPayloadPtr(inst),
@@ -6273,6 +6273,15 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
 
     const block_data = self.blocks.getPtr(inst).?;
     const target_branch = self.branch_stack.pop();
+
+    log.debug("airBlock: %{d}", .{inst});
+    log.debug("Upper branches:", .{});
+    for (self.branch_stack.items) |bs| {
+        log.debug("{}", .{bs.fmtDebug()});
+    }
+    log.debug("Block branch: {}", .{block_data.branch.fmtDebug()});
+    log.debug("Target branch: {}", .{target_branch.fmtDebug()});
+
     try self.canonicaliseBranches(true, &block_data.branch, &target_branch, false, false);
 
     for (block_data.relocs.items) |reloc| try self.performReloc(reloc);
@@ -6444,7 +6453,7 @@ fn canonicaliseBranches(
             // If integer overflow occurs, the question is: why wasn't the instruction marked dead?
             break :blk self.getResolvedInstValue(target_key).?.*;
         };
-        log.debug("consolidating target_entry {d} {}=>{}", .{ target_key, target_value, canon_mcv });
+        log.debug("consolidating target_entry %{d} {}=>{}", .{ target_key, target_value, canon_mcv });
         // TODO handle the case where the destination stack offset / register has something
         // going on there.
         assert(!hazard_map.contains(target_value));
@@ -6466,7 +6475,7 @@ fn canonicaliseBranches(
         const parent_mcv =
             if (canon_value != .dead) self.getResolvedInstValue(canon_key).?.* else undefined;
         if (canon_value != .dead) {
-            log.debug("consolidating canon_entry {d} {}=>{}", .{ canon_key, parent_mcv, canon_value });
+            log.debug("consolidating canon_entry %{d} {}=>{}", .{ canon_key, parent_mcv, canon_value });
             // TODO handle the case where the destination stack offset / register has something
             // going on there.
             assert(!hazard_map.contains(parent_mcv));
src/codegen.zig
@@ -966,7 +966,7 @@ fn genDeclRef(
     const module = bin_file.options.module.?;
     const decl = module.declPtr(decl_index);
 
-    if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) {
+    if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
         const imm: u64 = switch (ptr_bytes) {
             1 => 0xaa,
             2 => 0xaaaa,
@@ -978,10 +978,14 @@ fn genDeclRef(
     }
 
     // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
-    if (tv.ty.zigTypeTag() == .Pointer) blk: {
-        if (tv.ty.castPtrToFn()) |_| break :blk;
-        if (!tv.ty.elemType2().hasRuntimeBits()) {
-            return GenResult.mcv(.none);
+    if (tv.ty.castPtrToFn()) |fn_ty| {
+        if (fn_ty.fnInfo().is_generic) {
+            return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(target) });
+        }
+    } else if (tv.ty.zigTypeTag() == .Pointer) {
+        const elem_ty = tv.ty.elemType2();
+        if (!elem_ty.hasRuntimeBits()) {
+            return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(target) });
         }
     }
 
test/behavior/pointers.zig
@@ -506,7 +506,6 @@ test "ptrToInt on a generic function" {
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
     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_x86_64) return error.SkipZigTest;
 
     const S = struct {
         fn generic(i: anytype) @TypeOf(i) {