x86_64: fix constant pointers to zero-bit types

These non-dereferencable pointers still need to have the correct
alignment and non-null-ness.
This commit is contained in:
Jacob Young 2023-04-07 00:45:14 -04:00
parent 3b22ce8264
commit caa3d6a4f4
3 changed files with 21 additions and 9 deletions

View File

@ -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));

View File

@ -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) });
}
}

View File

@ -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) {