sparc64: use common implementation of genTypedValue

This commit is contained in:
Jakub Konka
2023-03-03 18:53:30 +01:00
parent 5b3ea49806
commit f6eeb6c8ce

View File

@@ -19,7 +19,7 @@ const Mir = @import("Mir.zig");
const Emit = @import("Emit.zig");
const Liveness = @import("../../Liveness.zig");
const Type = @import("../../type.zig").Type;
const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
const CodeGenError = codegen.CodeGenError;
const Result = @import("../../codegen.zig").Result;
const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
@@ -38,7 +38,7 @@ const gp = abi.RegisterClass.gp;
const Self = @This();
const InnerError = codegen.CodeGenError || error{OutOfRegisters};
const InnerError = CodeGenError || error{OutOfRegisters};
const RegisterView = enum(u1) {
caller,
@@ -261,7 +261,7 @@ pub fn generate(
liveness: Liveness,
code: *std.ArrayList(u8),
debug_output: DebugInfoOutput,
) GenerateSymbolError!Result {
) CodeGenError!Result {
if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
@panic("Attempted to compile for architecture that was disabled by build configuration");
}
@@ -3894,133 +3894,25 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t
}
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
var tv = typed_value;
log.debug("genTypedValue: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
if (tv.val.castTag(.runtime_value)) |rt| {
tv.val = rt.data;
}
if (tv.val.isUndef())
return MCValue{ .undef = {} };
if (tv.val.castTag(.decl_ref)) |payload| {
return self.lowerDeclRef(tv, payload.data);
}
if (tv.val.castTag(.decl_ref_mut)) |payload| {
return self.lowerDeclRef(tv, payload.data.decl_index);
}
const target = self.target.*;
switch (tv.ty.zigTypeTag()) {
.Pointer => switch (tv.ty.ptrSize()) {
.Slice => {},
else => {
switch (tv.val.tag()) {
.int_u64 => {
return MCValue{ .immediate = tv.val.toUnsignedInt(target) };
},
else => {},
}
},
const mcv: MCValue = switch (try codegen.genTypedValue(
self.bin_file,
self.src_loc,
typed_value,
self.mod_fn.owner_decl,
)) {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.linker_load => unreachable, // TODO
.immediate => |imm| .{ .immediate = imm },
.memory => |addr| .{ .memory = addr },
},
.Bool => {
return MCValue{ .immediate = @boolToInt(tv.val.toBool()) };
.fail => |msg| {
self.err_msg = msg;
return error.CodegenFail;
},
.Int => {
const info = tv.ty.intInfo(self.target.*);
if (info.bits <= 64) {
const unsigned = switch (info.signedness) {
.signed => blk: {
const signed = tv.val.toSignedInt(target);
break :blk @bitCast(u64, signed);
},
.unsigned => tv.val.toUnsignedInt(target),
};
return MCValue{ .immediate = unsigned };
} else {
return self.fail("TODO implement int genTypedValue of > 64 bits", .{});
}
},
.Optional => {
if (tv.ty.isPtrLikeOptional()) {
if (tv.val.isNull())
return MCValue{ .immediate = 0 };
var buf: Type.Payload.ElemType = undefined;
return self.genTypedValue(.{
.ty = tv.ty.optionalChild(&buf),
.val = tv.val,
});
} else if (tv.ty.abiSize(self.target.*) == 1) {
return MCValue{ .immediate = @boolToInt(tv.val.isNull()) };
}
},
.Enum => {
if (tv.val.castTag(.enum_field_index)) |field_index| {
switch (tv.ty.tag()) {
.enum_simple => {
return MCValue{ .immediate = field_index.data };
},
.enum_full, .enum_nonexhaustive => {
const enum_full = tv.ty.cast(Type.Payload.EnumFull).?.data;
if (enum_full.values.count() != 0) {
const tag_val = enum_full.values.keys()[field_index.data];
return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val });
} else {
return MCValue{ .immediate = field_index.data };
}
},
else => unreachable,
}
} else {
var int_tag_buffer: Type.Payload.Bits = undefined;
const int_tag_ty = tv.ty.intTagType(&int_tag_buffer);
return self.genTypedValue(.{ .ty = int_tag_ty, .val = tv.val });
}
},
.ErrorSet => {
const err_name = tv.val.castTag(.@"error").?.data.name;
const module = self.bin_file.options.module.?;
const global_error_set = module.global_error_set;
const error_index = global_error_set.get(err_name).?;
return MCValue{ .immediate = error_index };
},
.ErrorUnion => {
const error_type = tv.ty.errorUnionSet();
const payload_type = tv.ty.errorUnionPayload();
if (tv.val.castTag(.eu_payload)) |pl| {
if (!payload_type.hasRuntimeBits()) {
// We use the error type directly as the type.
return MCValue{ .immediate = 0 };
}
_ = pl;
return self.fail("TODO implement error union const of type '{}' (non-error)", .{tv.ty.fmtDebug()});
} else {
if (!payload_type.hasRuntimeBits()) {
// We use the error type directly as the type.
return self.genTypedValue(.{ .ty = error_type, .val = tv.val });
}
return self.fail("TODO implement error union const of type '{}' (error)", .{tv.ty.fmtDebug()});
}
},
.ComptimeInt => unreachable, // semantic analysis prevents this
.ComptimeFloat => unreachable, // semantic analysis prevents this
.Type => unreachable,
.EnumLiteral => unreachable,
.Void => unreachable,
.NoReturn => unreachable,
.Undefined => unreachable,
.Null => unreachable,
.Opaque => unreachable,
else => {},
}
return self.fail("TODO implement const of type '{}'", .{tv.ty.fmtDebug()});
};
return mcv;
}
fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
@@ -4196,28 +4088,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
}
}
fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue {
// 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 MCValue.none;
}
}
const mod = self.bin_file.options.module.?;
const decl = mod.declPtr(decl_index);
mod.markDeclAlive(decl);
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
const atom = elf_file.getAtom(atom_index);
return MCValue{ .memory = atom.getOffsetTableAddress(elf_file) };
} else {
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
}
}
fn minMax(
self: *Self,
tag: Air.Inst.Tag,