codegen: move gen logic for typed values, consts and decl ref to common codegen

This commit is contained in:
Jakub Konka 2023-03-03 18:06:25 +01:00
parent 6be5946ed8
commit c746cbc686
13 changed files with 323 additions and 247 deletions

View File

@ -41,11 +41,7 @@ const c_abi_int_param_regs = abi.c_abi_int_param_regs;
const c_abi_int_return_regs = abi.c_abi_int_return_regs;
const gp = abi.RegisterClass.gp;
const InnerError = error{
OutOfMemory,
CodegenFail,
OutOfRegisters,
};
const InnerError = codegen.CodeGenError || error{OutOfRegisters};
gpa: Allocator,
air: Air,

View File

@ -42,11 +42,7 @@ const c_abi_int_param_regs = abi.c_abi_int_param_regs;
const c_abi_int_return_regs = abi.c_abi_int_return_regs;
const gp = abi.RegisterClass.gp;
const InnerError = error{
OutOfMemory,
CodegenFail,
OutOfRegisters,
};
const InnerError = codegen.CodeGenError || error{OutOfRegisters};
gpa: Allocator,
air: Air,

View File

@ -21,10 +21,10 @@ const DW = std.dwarf;
const leb128 = std.leb;
const log = std.log.scoped(.codegen);
const build_options = @import("build_options");
const codegen = @import("../../codegen.zig");
const Result = @import("../../codegen.zig").Result;
const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
const Result = codegen.Result;
const DebugInfoOutput = codegen.DebugInfoOutput;
const bits = @import("bits.zig");
const abi = @import("abi.zig");
@ -35,11 +35,7 @@ const Instruction = abi.Instruction;
const callee_preserved_regs = abi.callee_preserved_regs;
const gp = abi.RegisterClass.gp;
const InnerError = error{
OutOfMemory,
CodegenFail,
OutOfRegisters,
};
const InnerError = codegen.CodeGenError || error{OutOfRegisters};
gpa: Allocator,
air: Air,
@ -225,7 +221,7 @@ pub fn generate(
liveness: Liveness,
code: *std.ArrayList(u8),
debug_output: DebugInfoOutput,
) GenerateSymbolError!Result {
) codegen.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");
}

View File

@ -38,11 +38,7 @@ const gp = abi.RegisterClass.gp;
const Self = @This();
const InnerError = error{
OutOfMemory,
CodegenFail,
OutOfRegisters,
};
const InnerError = codegen.CodeGenError || error{OutOfRegisters};
const RegisterView = enum(u1) {
caller,

View File

@ -733,8 +733,6 @@ const InnerError = error{
OutOfMemory,
/// An error occurred when trying to lower AIR to MIR.
CodegenFail,
/// Can occur when dereferencing a pointer that points to a `Decl` of which the analysis has failed
AnalysisFail,
/// Compiler implementation could not handle a large integer.
Overflow,
};

View File

@ -40,11 +40,7 @@ const Register = bits.Register;
const gp = abi.RegisterClass.gp;
const sse = abi.RegisterClass.sse;
const InnerError = error{
OutOfMemory,
CodegenFail,
OutOfRegisters,
};
const InnerError = codegen.CodeGenError || error{OutOfRegisters};
gpa: Allocator,
air: Air,
@ -6683,7 +6679,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
}
pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
// First section of indexes correspond to a set number of constant values.
const ref_int = @enumToInt(inst);
if (ref_int < Air.Inst.Ref.typed_value_map.len) {
@ -6752,200 +6748,26 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
return mcv;
}
fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue {
log.debug("lowerDeclRef: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
// 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 module = self.bin_file.options.module.?;
const decl = module.declPtr(decl_index);
module.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 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
return MCValue{ .linker_load = .{
.type = .got,
.sym_index = sym_index,
} };
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
return MCValue{ .linker_load = .{
.type = .got,
.sym_index = sym_index,
} };
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
const decl_block_index = try p9.seeDecl(decl_index);
const decl_block = p9.getDeclBlock(decl_block_index);
const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
return MCValue{ .memory = got_addr };
} else {
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
}
}
fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
};
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
return MCValue{ .memory = elf_file.getSymbol(local_sym_index).st_value };
} else if (self.bin_file.cast(link.File.MachO)) |_| {
return MCValue{ .linker_load = .{
.type = .direct,
.sym_index = local_sym_index,
} };
} else if (self.bin_file.cast(link.File.Coff)) |_| {
return MCValue{ .linker_load = .{
.type = .direct,
.sym_index = local_sym_index,
} };
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
const got_index = local_sym_index; // the plan9 backend returns the got_index
const got_addr = p9.bases.data + got_index * ptr_bytes;
return MCValue{ .memory = got_addr };
} else {
return self.fail("TODO lower unnamed const", .{});
}
}
fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
var typed_value = arg_tv;
if (typed_value.val.castTag(.runtime_value)) |rt| {
typed_value.val = rt.data;
}
log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
if (typed_value.val.isUndef())
return MCValue{ .undef = {} };
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
if (typed_value.val.castTag(.decl_ref)) |payload| {
return self.lowerDeclRef(typed_value, payload.data);
}
if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
return self.lowerDeclRef(typed_value, payload.data.decl_index);
}
const target = self.target.*;
switch (typed_value.ty.zigTypeTag()) {
.Void => return MCValue{ .none = {} },
.Pointer => switch (typed_value.ty.ptrSize()) {
.Slice => {},
else => {
switch (typed_value.val.tag()) {
.int_u64 => {
return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
},
else => {},
}
},
const mcv: MCValue = switch (try codegen.genTypedValue(
self.bin_file,
self.src_loc,
arg_tv,
self.mod_fn.owner_decl,
)) {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.linker_load => |ll| .{ .linker_load = ll },
.immediate => |imm| .{ .immediate = imm },
.memory => |addr| .{ .memory = addr },
},
.Int => {
const info = typed_value.ty.intInfo(self.target.*);
if (info.bits <= ptr_bits and info.signedness == .signed) {
return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) };
}
if (!(info.bits > ptr_bits or info.signedness == .signed)) {
return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
}
.fail => |msg| {
self.err_msg = msg;
return error.CodegenFail;
},
.Bool => {
return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) };
},
.Optional => {
if (typed_value.ty.isPtrLikeOptional()) {
if (typed_value.val.isNull())
return MCValue{ .immediate = 0 };
var buf: Type.Payload.ElemType = undefined;
return self.genTypedValue(.{
.ty = typed_value.ty.optionalChild(&buf),
.val = typed_value.val,
});
} else if (typed_value.ty.abiSize(self.target.*) == 1) {
return MCValue{ .immediate = @boolToInt(!typed_value.val.isNull()) };
}
},
.Enum => {
if (typed_value.val.castTag(.enum_field_index)) |field_index| {
switch (typed_value.ty.tag()) {
.enum_simple => {
return MCValue{ .immediate = field_index.data };
},
.enum_full, .enum_nonexhaustive => {
const enum_full = typed_value.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 = typed_value.ty.intTagType(&int_tag_buffer);
return self.genTypedValue(.{ .ty = int_tag_ty, .val = typed_value.val });
}
},
.ErrorSet => {
switch (typed_value.val.tag()) {
.@"error" => {
const err_name = typed_value.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 };
},
else => {
// In this case we are rendering an error union which has a 0 bits payload.
return MCValue{ .immediate = 0 };
},
}
},
.ErrorUnion => {
const error_type = typed_value.ty.errorUnionSet();
const payload_type = typed_value.ty.errorUnionPayload();
const is_pl = typed_value.val.errorUnionIsPayload();
if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
// We use the error type directly as the type.
const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
return self.genTypedValue(.{ .ty = error_type, .val = err_val });
}
},
.ComptimeInt => unreachable,
.ComptimeFloat => unreachable,
.Type => unreachable,
.EnumLiteral => unreachable,
.NoReturn => unreachable,
.Undefined => unreachable,
.Null => unreachable,
.Opaque => unreachable,
else => {},
}
return self.lowerUnnamedConst(typed_value);
};
return mcv;
}
const CallMCValues = struct {

View File

@ -29,13 +29,14 @@ pub const Result = union(enum) {
fail: *ErrorMsg,
};
pub const GenerateSymbolError = error{
pub const CodeGenError = error{
OutOfMemory,
Overflow,
/// A Decl that this symbol depends on had a semantic analysis failure.
AnalysisFail,
CodegenFail,
};
pub const GenerateSymbolError = CodeGenError;
pub const DebugInfoOutput = union(enum) {
dwarf: *link.File.Dwarf.DeclState,
/// the plan9 debuginfo output is a bytecode with 4 opcodes
@ -63,19 +64,6 @@ pub const DebugInfoOutput = union(enum) {
none,
};
/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
pub const LinkerLoad = struct {
type: enum {
got,
direct,
import,
},
sym_index: u32,
};
pub fn generateFunction(
bin_file: *link.File,
src_loc: Module.SrcLoc,
@ -84,7 +72,7 @@ pub fn generateFunction(
liveness: Liveness,
code: *std.ArrayList(u8),
debug_output: DebugInfoOutput,
) GenerateSymbolError!Result {
) CodeGenError!Result {
switch (bin_file.options.target.cpu.arch) {
.arm,
.armeb,
@ -120,7 +108,7 @@ pub fn generateSymbol(
code: *std.ArrayList(u8),
debug_output: DebugInfoOutput,
reloc_info: RelocInfo,
) GenerateSymbolError!Result {
) CodeGenError!Result {
const tracy = trace(@src());
defer tracy.end();
@ -823,7 +811,7 @@ fn lowerDeclRef(
code: *std.ArrayList(u8),
debug_output: DebugInfoOutput,
reloc_info: RelocInfo,
) GenerateSymbolError!Result {
) CodeGenError!Result {
const target = bin_file.options.target;
const module = bin_file.options.module.?;
if (typed_value.ty.isSlice()) {
@ -880,6 +868,287 @@ fn lowerDeclRef(
return Result.ok;
}
/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
pub const LinkerLoad = struct {
type: enum {
got,
direct,
import,
},
sym_index: u32,
};
pub const GenResult = union(enum) {
mcv: MCValue,
fail: *ErrorMsg,
const MCValue = union(enum) {
none,
undef,
/// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
/// such as ARM, the immediate will never exceed 32-bits.
immediate: u64,
linker_load: LinkerLoad,
/// Direct by-address reference to memory location.
memory: u64,
};
fn mcv(val: MCValue) GenResult {
return .{ .mcv = val };
}
fn fail(
gpa: Allocator,
src_loc: Module.SrcLoc,
comptime format: []const u8,
args: anytype,
) Allocator.Error!GenResult {
const msg = try ErrorMsg.create(gpa, src_loc, format, args);
return .{ .fail = msg };
}
};
fn genDeclRef(
bin_file: *link.File,
src_loc: Module.SrcLoc,
tv: TypedValue,
decl_index: Module.Decl.Index,
) CodeGenError!GenResult {
log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
const target = bin_file.options.target;
const ptr_bits = target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
const module = bin_file.options.module.?;
const decl = module.declPtr(decl_index);
if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) {
const imm: u64 = switch (ptr_bytes) {
1 => 0xaa,
2 => 0xaaaa,
4 => 0xaaaaaaaa,
8 => 0xaaaaaaaaaaaaaaaa,
else => unreachable,
};
return GenResult.mcv(.{ .immediate = imm });
}
// 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);
}
}
module.markDeclAlive(decl);
if (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 GenResult.mcv(.{ .memory = atom.getOffsetTableAddress(elf_file) });
} else if (bin_file.cast(link.File.MachO)) |macho_file| {
const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
return GenResult.mcv(.{ .linker_load = .{
.type = .got,
.sym_index = sym_index,
} });
} else if (bin_file.cast(link.File.Coff)) |coff_file| {
const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
return GenResult.mcv(.{ .linker_load = .{
.type = .got,
.sym_index = sym_index,
} });
} else if (bin_file.cast(link.File.Plan9)) |p9| {
const decl_block_index = try p9.seeDecl(decl_index);
const decl_block = p9.getDeclBlock(decl_block_index);
const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
return GenResult.mcv(.{ .memory = got_addr });
} else {
return GenResult.fail(bin_file.allocator, src_loc, "TODO genDeclRef for target {}", .{target});
}
}
fn genUnnamedConst(
bin_file: *link.File,
src_loc: Module.SrcLoc,
tv: TypedValue,
owner_decl_index: Module.Decl.Index,
) CodeGenError!GenResult {
log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
const target = bin_file.options.target;
const local_sym_index = bin_file.lowerUnnamedConst(tv, owner_decl_index) catch |err| {
return GenResult.fail(bin_file.allocator, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});
};
if (bin_file.cast(link.File.Elf)) |elf_file| {
return GenResult.mcv(.{ .memory = elf_file.getSymbol(local_sym_index).st_value });
} else if (bin_file.cast(link.File.MachO)) |_| {
return GenResult.mcv(.{ .linker_load = .{
.type = .direct,
.sym_index = local_sym_index,
} });
} else if (bin_file.cast(link.File.Coff)) |_| {
return GenResult.mcv(.{ .linker_load = .{
.type = .direct,
.sym_index = local_sym_index,
} });
} else if (bin_file.cast(link.File.Plan9)) |p9| {
const ptr_bits = target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
const got_index = local_sym_index; // the plan9 backend returns the got_index
const got_addr = p9.bases.data + got_index * ptr_bytes;
return GenResult.mcv(.{ .memory = got_addr });
} else {
return GenResult.fail(bin_file.allocator, src_loc, "TODO genUnnamedConst for target {}", .{target});
}
}
pub fn genTypedValue(
bin_file: *link.File,
src_loc: Module.SrcLoc,
arg_tv: TypedValue,
owner_decl_index: Module.Decl.Index,
) CodeGenError!GenResult {
var typed_value = arg_tv;
if (typed_value.val.castTag(.runtime_value)) |rt| {
typed_value.val = rt.data;
}
log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
if (typed_value.val.isUndef())
return GenResult.mcv(.undef);
const target = bin_file.options.target;
const ptr_bits = target.cpu.arch.ptrBitWidth();
if (typed_value.val.castTag(.decl_ref)) |payload| {
return genDeclRef(bin_file, src_loc, typed_value, payload.data);
}
if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
return genDeclRef(bin_file, src_loc, typed_value, payload.data.decl_index);
}
switch (typed_value.ty.zigTypeTag()) {
.Void => return GenResult.mcv(.none),
.Pointer => switch (typed_value.ty.ptrSize()) {
.Slice => {},
else => {
switch (typed_value.val.tag()) {
.int_u64 => {
return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) });
},
else => {},
}
},
},
.Int => {
const info = typed_value.ty.intInfo(target);
if (info.bits <= ptr_bits and info.signedness == .signed) {
return GenResult.mcv(.{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) });
}
if (!(info.bits > ptr_bits or info.signedness == .signed)) {
return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) });
}
},
.Bool => {
return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });
},
.Optional => {
if (typed_value.ty.isPtrLikeOptional()) {
if (typed_value.val.isNull())
return GenResult.mcv(.{ .immediate = 0 });
var buf: Type.Payload.ElemType = undefined;
return genTypedValue(bin_file, src_loc, .{
.ty = typed_value.ty.optionalChild(&buf),
.val = typed_value.val,
}, owner_decl_index);
} else if (typed_value.ty.abiSize(target) == 1) {
return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull()) });
}
},
.Enum => {
if (typed_value.val.castTag(.enum_field_index)) |field_index| {
switch (typed_value.ty.tag()) {
.enum_simple => {
return GenResult.mcv(.{ .immediate = field_index.data });
},
.enum_full, .enum_nonexhaustive => {
const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
if (enum_full.values.count() != 0) {
const tag_val = enum_full.values.keys()[field_index.data];
return genTypedValue(bin_file, src_loc, .{
.ty = enum_full.tag_ty,
.val = tag_val,
}, owner_decl_index);
} else {
return GenResult.mcv(.{ .immediate = field_index.data });
}
},
else => unreachable,
}
} else {
var int_tag_buffer: Type.Payload.Bits = undefined;
const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
return genTypedValue(bin_file, src_loc, .{
.ty = int_tag_ty,
.val = typed_value.val,
}, owner_decl_index);
}
},
.ErrorSet => {
switch (typed_value.val.tag()) {
.@"error" => {
const err_name = typed_value.val.castTag(.@"error").?.data.name;
const module = bin_file.options.module.?;
const global_error_set = module.global_error_set;
const error_index = global_error_set.get(err_name).?;
return GenResult.mcv(.{ .immediate = error_index });
},
else => {
// In this case we are rendering an error union which has a 0 bits payload.
return GenResult.mcv(.{ .immediate = 0 });
},
}
},
.ErrorUnion => {
const error_type = typed_value.ty.errorUnionSet();
const payload_type = typed_value.ty.errorUnionPayload();
const is_pl = typed_value.val.errorUnionIsPayload();
if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
// We use the error type directly as the type.
const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
return genTypedValue(bin_file, src_loc, .{
.ty = error_type,
.val = err_val,
}, owner_decl_index);
}
},
.ComptimeInt => unreachable,
.ComptimeFloat => unreachable,
.Type => unreachable,
.EnumLiteral => unreachable,
.NoReturn => unreachable,
.Undefined => unreachable,
.Null => unreachable,
.Opaque => unreachable,
else => {},
}
return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index);
}
pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
const payload_align = payload_ty.abiAlignment(target);
const error_align = Type.anyerror.abiAlignment(target);

View File

@ -1060,7 +1060,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
decl.analysis = .codegen_failure;
try mod.failed_decls.put(mod.gpa, decl_index, em);
log.err("{s}", .{em.msg});
return error.AnalysisFail;
return error.CodegenFail;
},
};

View File

@ -2618,7 +2618,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
decl.analysis = .codegen_failure;
try mod.failed_decls.put(mod.gpa, decl_index, em);
log.err("{s}", .{em.msg});
return error.AnalysisFail;
return error.CodegenFail;
},
};

View File

@ -2089,7 +2089,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
decl.analysis = .codegen_failure;
try module.failed_decls.put(module.gpa, decl_index, em);
log.err("{s}", .{em.msg});
return error.AnalysisFail;
return error.CodegenFail;
},
};

View File

@ -377,7 +377,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
decl.analysis = .codegen_failure;
try mod.failed_decls.put(mod.gpa, decl_index, em);
log.err("{s}", .{em.msg});
return error.AnalysisFail;
return error.CodegenFail;
},
};
// duped_code is freed when the unnamed const is freed

View File

@ -1255,7 +1255,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
.fail => |em| {
decl.analysis = .codegen_failure;
try mod.failed_decls.put(mod.gpa, decl_index, em);
return error.AnalysisFail;
return error.CodegenFail;
},
};
};

View File

@ -19,6 +19,9 @@ pub const AllocateRegistersError = error{
/// Can happen when spilling an instruction in codegen runs out of
/// memory, so we propagate that error
OutOfMemory,
/// Can happen when spilling an instruction in codegen triggers integer
/// overflow, so we propagate that error
Overflow,
/// Can happen when spilling an instruction triggers a codegen
/// error, so we propagate that error
CodegenFail,