authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:06:25+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:06:25+01:00
logc746cbc686c46904a5d381725079a69e38b201cd
tree46dbe180dd40e9cf8dfea6fae933e6f011b4b3ee
parent6be5946ed8026f2a7ae990aced9572f229acecf4

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


13 files changed, 323 insertions(+), 247 deletions(-)

src/arch/aarch64/CodeGen.zig+1-5
......@@ -41,11 +41,7 @@ const c_abi_int_param_regs = abi.c_abi_int_param_regs;
4141const c_abi_int_return_regs = abi.c_abi_int_return_regs;
4242const gp = abi.RegisterClass.gp;
4343
44const InnerError = error{
45 OutOfMemory,
46 CodegenFail,
47 OutOfRegisters,
48};
44const InnerError = codegen.CodeGenError || error{OutOfRegisters};
4945
5046gpa: Allocator,
5147air: Air,
src/arch/arm/CodeGen.zig+1-5
......@@ -42,11 +42,7 @@ const c_abi_int_param_regs = abi.c_abi_int_param_regs;
4242const c_abi_int_return_regs = abi.c_abi_int_return_regs;
4343const gp = abi.RegisterClass.gp;
4444
45const InnerError = error{
46 OutOfMemory,
47 CodegenFail,
48 OutOfRegisters,
49};
45const InnerError = codegen.CodeGenError || error{OutOfRegisters};
5046
5147gpa: Allocator,
5248air: Air,
src/arch/riscv64/CodeGen.zig+5-9
......@@ -21,10 +21,10 @@ const DW = std.dwarf;
2121const leb128 = std.leb;
2222const log = std.log.scoped(.codegen);
2323const build_options = @import("build_options");
24const codegen = @import("../../codegen.zig");
2425
25const Result = @import("../../codegen.zig").Result;
26const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
27const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
26const Result = codegen.Result;
27const DebugInfoOutput = codegen.DebugInfoOutput;
2828
2929const bits = @import("bits.zig");
3030const abi = @import("abi.zig");
......@@ -35,11 +35,7 @@ const Instruction = abi.Instruction;
3535const callee_preserved_regs = abi.callee_preserved_regs;
3636const gp = abi.RegisterClass.gp;
3737
38const InnerError = error{
39 OutOfMemory,
40 CodegenFail,
41 OutOfRegisters,
42};
38const InnerError = codegen.CodeGenError || error{OutOfRegisters};
4339
4440gpa: Allocator,
4541air: Air,
......@@ -225,7 +221,7 @@ pub fn generate(
225221 liveness: Liveness,
226222 code: *std.ArrayList(u8),
227223 debug_output: DebugInfoOutput,
228) GenerateSymbolError!Result {
224) codegen.CodeGenError!Result {
229225 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
230226 @panic("Attempted to compile for architecture that was disabled by build configuration");
231227 }
src/arch/sparc64/CodeGen.zig+1-5
......@@ -38,11 +38,7 @@ const gp = abi.RegisterClass.gp;
3838
3939const Self = @This();
4040
41const InnerError = error{
42 OutOfMemory,
43 CodegenFail,
44 OutOfRegisters,
45};
41const InnerError = codegen.CodeGenError || error{OutOfRegisters};
4642
4743const RegisterView = enum(u1) {
4844 caller,
src/arch/wasm/CodeGen.zig-2
......@@ -733,8 +733,6 @@ const InnerError = error{
733733 OutOfMemory,
734734 /// An error occurred when trying to lower AIR to MIR.
735735 CodegenFail,
736 /// Can occur when dereferencing a pointer that points to a `Decl` of which the analysis has failed
737 AnalysisFail,
738736 /// Compiler implementation could not handle a large integer.
739737 Overflow,
740738};
src/arch/x86_64/CodeGen.zig+19-197
......@@ -40,11 +40,7 @@ const Register = bits.Register;
4040const gp = abi.RegisterClass.gp;
4141const sse = abi.RegisterClass.sse;
4242
43const InnerError = error{
44 OutOfMemory,
45 CodegenFail,
46 OutOfRegisters,
47};
43const InnerError = codegen.CodeGenError || error{OutOfRegisters};
4844
4945gpa: Allocator,
5046air: Air,
......@@ -6683,7 +6679,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
66836679 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
66846680}
66856681
6686pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6682fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
66876683 // First section of indexes correspond to a set number of constant values.
66886684 const ref_int = @enumToInt(inst);
66896685 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
67526748 return mcv;
67536749}
67546750
6755fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue {
6756 log.debug("lowerDeclRef: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
6757 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6758 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
6759
6760 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
6761 if (tv.ty.zigTypeTag() == .Pointer) blk: {
6762 if (tv.ty.castPtrToFn()) |_| break :blk;
6763 if (!tv.ty.elemType2().hasRuntimeBits()) {
6764 return MCValue.none;
6765 }
6766 }
6767
6768 const module = self.bin_file.options.module.?;
6769 const decl = module.declPtr(decl_index);
6770 module.markDeclAlive(decl);
6771
6772 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6773 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
6774 const atom = elf_file.getAtom(atom_index);
6775 return MCValue{ .memory = atom.getOffsetTableAddress(elf_file) };
6776 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6777 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
6778 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
6779 return MCValue{ .linker_load = .{
6780 .type = .got,
6781 .sym_index = sym_index,
6782 } };
6783 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
6784 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
6785 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
6786 return MCValue{ .linker_load = .{
6787 .type = .got,
6788 .sym_index = sym_index,
6789 } };
6790 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6791 const decl_block_index = try p9.seeDecl(decl_index);
6792 const decl_block = p9.getDeclBlock(decl_block_index);
6793 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
6794 return MCValue{ .memory = got_addr };
6795 } else {
6796 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
6797 }
6798}
6799
6800fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
6801 log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
6802 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
6803 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
6804 };
6805 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6806 return MCValue{ .memory = elf_file.getSymbol(local_sym_index).st_value };
6807 } else if (self.bin_file.cast(link.File.MachO)) |_| {
6808 return MCValue{ .linker_load = .{
6809 .type = .direct,
6810 .sym_index = local_sym_index,
6811 } };
6812 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6813 return MCValue{ .linker_load = .{
6814 .type = .direct,
6815 .sym_index = local_sym_index,
6816 } };
6817 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6818 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6819 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
6820 const got_index = local_sym_index; // the plan9 backend returns the got_index
6821 const got_addr = p9.bases.data + got_index * ptr_bytes;
6822 return MCValue{ .memory = got_addr };
6823 } else {
6824 return self.fail("TODO lower unnamed const", .{});
6825 }
6826}
6827
68286751fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6829 var typed_value = arg_tv;
6830 if (typed_value.val.castTag(.runtime_value)) |rt| {
6831 typed_value.val = rt.data;
6832 }
6833 log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
6834 if (typed_value.val.isUndef())
6835 return MCValue{ .undef = {} };
6836 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6837
6838 if (typed_value.val.castTag(.decl_ref)) |payload| {
6839 return self.lowerDeclRef(typed_value, payload.data);
6840 }
6841 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
6842 return self.lowerDeclRef(typed_value, payload.data.decl_index);
6843 }
6844
6845 const target = self.target.*;
6846
6847 switch (typed_value.ty.zigTypeTag()) {
6848 .Void => return MCValue{ .none = {} },
6849 .Pointer => switch (typed_value.ty.ptrSize()) {
6850 .Slice => {},
6851 else => {
6852 switch (typed_value.val.tag()) {
6853 .int_u64 => {
6854 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
6855 },
6856 else => {},
6857 }
6858 },
6752 const mcv: MCValue = switch (try codegen.genTypedValue(
6753 self.bin_file,
6754 self.src_loc,
6755 arg_tv,
6756 self.mod_fn.owner_decl,
6757 )) {
6758 .mcv => |mcv| switch (mcv) {
6759 .none => .none,
6760 .undef => .undef,
6761 .linker_load => |ll| .{ .linker_load = ll },
6762 .immediate => |imm| .{ .immediate = imm },
6763 .memory => |addr| .{ .memory = addr },
68596764 },
6860 .Int => {
6861 const info = typed_value.ty.intInfo(self.target.*);
6862 if (info.bits <= ptr_bits and info.signedness == .signed) {
6863 return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) };
6864 }
6865 if (!(info.bits > ptr_bits or info.signedness == .signed)) {
6866 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
6867 }
6868 },
6869 .Bool => {
6870 return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) };
6871 },
6872 .Optional => {
6873 if (typed_value.ty.isPtrLikeOptional()) {
6874 if (typed_value.val.isNull())
6875 return MCValue{ .immediate = 0 };
6876
6877 var buf: Type.Payload.ElemType = undefined;
6878 return self.genTypedValue(.{
6879 .ty = typed_value.ty.optionalChild(&buf),
6880 .val = typed_value.val,
6881 });
6882 } else if (typed_value.ty.abiSize(self.target.*) == 1) {
6883 return MCValue{ .immediate = @boolToInt(!typed_value.val.isNull()) };
6884 }
6885 },
6886 .Enum => {
6887 if (typed_value.val.castTag(.enum_field_index)) |field_index| {
6888 switch (typed_value.ty.tag()) {
6889 .enum_simple => {
6890 return MCValue{ .immediate = field_index.data };
6891 },
6892 .enum_full, .enum_nonexhaustive => {
6893 const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
6894 if (enum_full.values.count() != 0) {
6895 const tag_val = enum_full.values.keys()[field_index.data];
6896 return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val });
6897 } else {
6898 return MCValue{ .immediate = field_index.data };
6899 }
6900 },
6901 else => unreachable,
6902 }
6903 } else {
6904 var int_tag_buffer: Type.Payload.Bits = undefined;
6905 const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
6906 return self.genTypedValue(.{ .ty = int_tag_ty, .val = typed_value.val });
6907 }
6765 .fail => |msg| {
6766 self.err_msg = msg;
6767 return error.CodegenFail;
69086768 },
6909 .ErrorSet => {
6910 switch (typed_value.val.tag()) {
6911 .@"error" => {
6912 const err_name = typed_value.val.castTag(.@"error").?.data.name;
6913 const module = self.bin_file.options.module.?;
6914 const global_error_set = module.global_error_set;
6915 const error_index = global_error_set.get(err_name).?;
6916 return MCValue{ .immediate = error_index };
6917 },
6918 else => {
6919 // In this case we are rendering an error union which has a 0 bits payload.
6920 return MCValue{ .immediate = 0 };
6921 },
6922 }
6923 },
6924 .ErrorUnion => {
6925 const error_type = typed_value.ty.errorUnionSet();
6926 const payload_type = typed_value.ty.errorUnionPayload();
6927 const is_pl = typed_value.val.errorUnionIsPayload();
6928
6929 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
6930 // We use the error type directly as the type.
6931 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
6932 return self.genTypedValue(.{ .ty = error_type, .val = err_val });
6933 }
6934 },
6935
6936 .ComptimeInt => unreachable,
6937 .ComptimeFloat => unreachable,
6938 .Type => unreachable,
6939 .EnumLiteral => unreachable,
6940 .NoReturn => unreachable,
6941 .Undefined => unreachable,
6942 .Null => unreachable,
6943 .Opaque => unreachable,
6944
6945 else => {},
6946 }
6947
6948 return self.lowerUnnamedConst(typed_value);
6769 };
6770 return mcv;
69496771}
69506772
69516773const CallMCValues = struct {
src/codegen.zig+288-19
......@@ -29,13 +29,14 @@ pub const Result = union(enum) {
2929 fail: *ErrorMsg,
3030};
3131
32pub const GenerateSymbolError = error{
32pub const CodeGenError = error{
3333 OutOfMemory,
3434 Overflow,
35 /// A Decl that this symbol depends on had a semantic analysis failure.
36 AnalysisFail,
35 CodegenFail,
3736};
3837
38pub const GenerateSymbolError = CodeGenError;
39
3940pub const DebugInfoOutput = union(enum) {
4041 dwarf: *link.File.Dwarf.DeclState,
4142 /// the plan9 debuginfo output is a bytecode with 4 opcodes
......@@ -63,19 +64,6 @@ pub const DebugInfoOutput = union(enum) {
6364 none,
6465};
6566
66/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
67/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
68/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
69/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
70pub const LinkerLoad = struct {
71 type: enum {
72 got,
73 direct,
74 import,
75 },
76 sym_index: u32,
77};
78
7967pub fn generateFunction(
8068 bin_file: *link.File,
8169 src_loc: Module.SrcLoc,
......@@ -84,7 +72,7 @@ pub fn generateFunction(
8472 liveness: Liveness,
8573 code: *std.ArrayList(u8),
8674 debug_output: DebugInfoOutput,
87) GenerateSymbolError!Result {
75) CodeGenError!Result {
8876 switch (bin_file.options.target.cpu.arch) {
8977 .arm,
9078 .armeb,
......@@ -120,7 +108,7 @@ pub fn generateSymbol(
120108 code: *std.ArrayList(u8),
121109 debug_output: DebugInfoOutput,
122110 reloc_info: RelocInfo,
123) GenerateSymbolError!Result {
111) CodeGenError!Result {
124112 const tracy = trace(@src());
125113 defer tracy.end();
126114
......@@ -823,7 +811,7 @@ fn lowerDeclRef(
823811 code: *std.ArrayList(u8),
824812 debug_output: DebugInfoOutput,
825813 reloc_info: RelocInfo,
826) GenerateSymbolError!Result {
814) CodeGenError!Result {
827815 const target = bin_file.options.target;
828816 const module = bin_file.options.module.?;
829817 if (typed_value.ty.isSlice()) {
......@@ -880,6 +868,287 @@ fn lowerDeclRef(
880868 return Result.ok;
881869}
882870
871/// Helper struct to denote that the value is in memory but requires a linker relocation fixup:
872/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
873/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
874/// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
875pub const LinkerLoad = struct {
876 type: enum {
877 got,
878 direct,
879 import,
880 },
881 sym_index: u32,
882};
883
884pub const GenResult = union(enum) {
885 mcv: MCValue,
886 fail: *ErrorMsg,
887
888 const MCValue = union(enum) {
889 none,
890 undef,
891 /// The bit-width of the immediate may be smaller than `u64`. For example, on 32-bit targets
892 /// such as ARM, the immediate will never exceed 32-bits.
893 immediate: u64,
894 linker_load: LinkerLoad,
895 /// Direct by-address reference to memory location.
896 memory: u64,
897 };
898
899 fn mcv(val: MCValue) GenResult {
900 return .{ .mcv = val };
901 }
902
903 fn fail(
904 gpa: Allocator,
905 src_loc: Module.SrcLoc,
906 comptime format: []const u8,
907 args: anytype,
908 ) Allocator.Error!GenResult {
909 const msg = try ErrorMsg.create(gpa, src_loc, format, args);
910 return .{ .fail = msg };
911 }
912};
913
914fn genDeclRef(
915 bin_file: *link.File,
916 src_loc: Module.SrcLoc,
917 tv: TypedValue,
918 decl_index: Module.Decl.Index,
919) CodeGenError!GenResult {
920 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
921
922 const target = bin_file.options.target;
923 const ptr_bits = target.cpu.arch.ptrBitWidth();
924 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
925
926 const module = bin_file.options.module.?;
927 const decl = module.declPtr(decl_index);
928
929 if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) {
930 const imm: u64 = switch (ptr_bytes) {
931 1 => 0xaa,
932 2 => 0xaaaa,
933 4 => 0xaaaaaaaa,
934 8 => 0xaaaaaaaaaaaaaaaa,
935 else => unreachable,
936 };
937 return GenResult.mcv(.{ .immediate = imm });
938 }
939
940 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
941 if (tv.ty.zigTypeTag() == .Pointer) blk: {
942 if (tv.ty.castPtrToFn()) |_| break :blk;
943 if (!tv.ty.elemType2().hasRuntimeBits()) {
944 return GenResult.mcv(.none);
945 }
946 }
947
948 module.markDeclAlive(decl);
949
950 if (bin_file.cast(link.File.Elf)) |elf_file| {
951 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
952 const atom = elf_file.getAtom(atom_index);
953 return GenResult.mcv(.{ .memory = atom.getOffsetTableAddress(elf_file) });
954 } else if (bin_file.cast(link.File.MachO)) |macho_file| {
955 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
956 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
957 return GenResult.mcv(.{ .linker_load = .{
958 .type = .got,
959 .sym_index = sym_index,
960 } });
961 } else if (bin_file.cast(link.File.Coff)) |coff_file| {
962 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
963 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
964 return GenResult.mcv(.{ .linker_load = .{
965 .type = .got,
966 .sym_index = sym_index,
967 } });
968 } else if (bin_file.cast(link.File.Plan9)) |p9| {
969 const decl_block_index = try p9.seeDecl(decl_index);
970 const decl_block = p9.getDeclBlock(decl_block_index);
971 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
972 return GenResult.mcv(.{ .memory = got_addr });
973 } else {
974 return GenResult.fail(bin_file.allocator, src_loc, "TODO genDeclRef for target {}", .{target});
975 }
976}
977
978fn genUnnamedConst(
979 bin_file: *link.File,
980 src_loc: Module.SrcLoc,
981 tv: TypedValue,
982 owner_decl_index: Module.Decl.Index,
983) CodeGenError!GenResult {
984 log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
985
986 const target = bin_file.options.target;
987 const local_sym_index = bin_file.lowerUnnamedConst(tv, owner_decl_index) catch |err| {
988 return GenResult.fail(bin_file.allocator, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)});
989 };
990 if (bin_file.cast(link.File.Elf)) |elf_file| {
991 return GenResult.mcv(.{ .memory = elf_file.getSymbol(local_sym_index).st_value });
992 } else if (bin_file.cast(link.File.MachO)) |_| {
993 return GenResult.mcv(.{ .linker_load = .{
994 .type = .direct,
995 .sym_index = local_sym_index,
996 } });
997 } else if (bin_file.cast(link.File.Coff)) |_| {
998 return GenResult.mcv(.{ .linker_load = .{
999 .type = .direct,
1000 .sym_index = local_sym_index,
1001 } });
1002 } else if (bin_file.cast(link.File.Plan9)) |p9| {
1003 const ptr_bits = target.cpu.arch.ptrBitWidth();
1004 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1005 const got_index = local_sym_index; // the plan9 backend returns the got_index
1006 const got_addr = p9.bases.data + got_index * ptr_bytes;
1007 return GenResult.mcv(.{ .memory = got_addr });
1008 } else {
1009 return GenResult.fail(bin_file.allocator, src_loc, "TODO genUnnamedConst for target {}", .{target});
1010 }
1011}
1012
1013pub fn genTypedValue(
1014 bin_file: *link.File,
1015 src_loc: Module.SrcLoc,
1016 arg_tv: TypedValue,
1017 owner_decl_index: Module.Decl.Index,
1018) CodeGenError!GenResult {
1019 var typed_value = arg_tv;
1020 if (typed_value.val.castTag(.runtime_value)) |rt| {
1021 typed_value.val = rt.data;
1022 }
1023
1024 log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
1025
1026 if (typed_value.val.isUndef())
1027 return GenResult.mcv(.undef);
1028
1029 const target = bin_file.options.target;
1030 const ptr_bits = target.cpu.arch.ptrBitWidth();
1031
1032 if (typed_value.val.castTag(.decl_ref)) |payload| {
1033 return genDeclRef(bin_file, src_loc, typed_value, payload.data);
1034 }
1035 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
1036 return genDeclRef(bin_file, src_loc, typed_value, payload.data.decl_index);
1037 }
1038
1039 switch (typed_value.ty.zigTypeTag()) {
1040 .Void => return GenResult.mcv(.none),
1041 .Pointer => switch (typed_value.ty.ptrSize()) {
1042 .Slice => {},
1043 else => {
1044 switch (typed_value.val.tag()) {
1045 .int_u64 => {
1046 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) });
1047 },
1048 else => {},
1049 }
1050 },
1051 },
1052 .Int => {
1053 const info = typed_value.ty.intInfo(target);
1054 if (info.bits <= ptr_bits and info.signedness == .signed) {
1055 return GenResult.mcv(.{ .immediate = @bitCast(u64, typed_value.val.toSignedInt(target)) });
1056 }
1057 if (!(info.bits > ptr_bits or info.signedness == .signed)) {
1058 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) });
1059 }
1060 },
1061 .Bool => {
1062 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });
1063 },
1064 .Optional => {
1065 if (typed_value.ty.isPtrLikeOptional()) {
1066 if (typed_value.val.isNull())
1067 return GenResult.mcv(.{ .immediate = 0 });
1068
1069 var buf: Type.Payload.ElemType = undefined;
1070 return genTypedValue(bin_file, src_loc, .{
1071 .ty = typed_value.ty.optionalChild(&buf),
1072 .val = typed_value.val,
1073 }, owner_decl_index);
1074 } else if (typed_value.ty.abiSize(target) == 1) {
1075 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull()) });
1076 }
1077 },
1078 .Enum => {
1079 if (typed_value.val.castTag(.enum_field_index)) |field_index| {
1080 switch (typed_value.ty.tag()) {
1081 .enum_simple => {
1082 return GenResult.mcv(.{ .immediate = field_index.data });
1083 },
1084 .enum_full, .enum_nonexhaustive => {
1085 const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
1086 if (enum_full.values.count() != 0) {
1087 const tag_val = enum_full.values.keys()[field_index.data];
1088 return genTypedValue(bin_file, src_loc, .{
1089 .ty = enum_full.tag_ty,
1090 .val = tag_val,
1091 }, owner_decl_index);
1092 } else {
1093 return GenResult.mcv(.{ .immediate = field_index.data });
1094 }
1095 },
1096 else => unreachable,
1097 }
1098 } else {
1099 var int_tag_buffer: Type.Payload.Bits = undefined;
1100 const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
1101 return genTypedValue(bin_file, src_loc, .{
1102 .ty = int_tag_ty,
1103 .val = typed_value.val,
1104 }, owner_decl_index);
1105 }
1106 },
1107 .ErrorSet => {
1108 switch (typed_value.val.tag()) {
1109 .@"error" => {
1110 const err_name = typed_value.val.castTag(.@"error").?.data.name;
1111 const module = bin_file.options.module.?;
1112 const global_error_set = module.global_error_set;
1113 const error_index = global_error_set.get(err_name).?;
1114 return GenResult.mcv(.{ .immediate = error_index });
1115 },
1116 else => {
1117 // In this case we are rendering an error union which has a 0 bits payload.
1118 return GenResult.mcv(.{ .immediate = 0 });
1119 },
1120 }
1121 },
1122 .ErrorUnion => {
1123 const error_type = typed_value.ty.errorUnionSet();
1124 const payload_type = typed_value.ty.errorUnionPayload();
1125 const is_pl = typed_value.val.errorUnionIsPayload();
1126
1127 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
1128 // We use the error type directly as the type.
1129 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
1130 return genTypedValue(bin_file, src_loc, .{
1131 .ty = error_type,
1132 .val = err_val,
1133 }, owner_decl_index);
1134 }
1135 },
1136
1137 .ComptimeInt => unreachable,
1138 .ComptimeFloat => unreachable,
1139 .Type => unreachable,
1140 .EnumLiteral => unreachable,
1141 .NoReturn => unreachable,
1142 .Undefined => unreachable,
1143 .Null => unreachable,
1144 .Opaque => unreachable,
1145
1146 else => {},
1147 }
1148
1149 return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index);
1150}
1151
8831152pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
8841153 const payload_align = payload_ty.abiAlignment(target);
8851154 const error_align = Type.anyerror.abiAlignment(target);
src/link/Coff.zig+1-1
......@@ -1060,7 +1060,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
10601060 decl.analysis = .codegen_failure;
10611061 try mod.failed_decls.put(mod.gpa, decl_index, em);
10621062 log.err("{s}", .{em.msg});
1063 return error.AnalysisFail;
1063 return error.CodegenFail;
10641064 },
10651065 };
10661066
src/link/Elf.zig+1-1
......@@ -2618,7 +2618,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
26182618 decl.analysis = .codegen_failure;
26192619 try mod.failed_decls.put(mod.gpa, decl_index, em);
26202620 log.err("{s}", .{em.msg});
2621 return error.AnalysisFail;
2621 return error.CodegenFail;
26222622 },
26232623 };
26242624
src/link/MachO.zig+1-1
......@@ -2089,7 +2089,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
20892089 decl.analysis = .codegen_failure;
20902090 try module.failed_decls.put(module.gpa, decl_index, em);
20912091 log.err("{s}", .{em.msg});
2092 return error.AnalysisFail;
2092 return error.CodegenFail;
20932093 },
20942094 };
20952095
src/link/Plan9.zig+1-1
......@@ -377,7 +377,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
377377 decl.analysis = .codegen_failure;
378378 try mod.failed_decls.put(mod.gpa, decl_index, em);
379379 log.err("{s}", .{em.msg});
380 return error.AnalysisFail;
380 return error.CodegenFail;
381381 },
382382 };
383383 // duped_code is freed when the unnamed const is freed
src/link/Wasm.zig+1-1
......@@ -1255,7 +1255,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
12551255 .fail => |em| {
12561256 decl.analysis = .codegen_failure;
12571257 try mod.failed_decls.put(mod.gpa, decl_index, em);
1258 return error.AnalysisFail;
1258 return error.CodegenFail;
12591259 },
12601260 };
12611261 };
src/register_manager.zig+3
......@@ -19,6 +19,9 @@ pub const AllocateRegistersError = error{
1919 /// Can happen when spilling an instruction in codegen runs out of
2020 /// memory, so we propagate that error
2121 OutOfMemory,
22 /// Can happen when spilling an instruction in codegen triggers integer
23 /// overflow, so we propagate that error
24 Overflow,
2225 /// Can happen when spilling an instruction triggers a codegen
2326 /// error, so we propagate that error
2427 CodegenFail,