authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:24:58+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:24:58+01:00
log1024332adc88928299dfc07426f11624ae8ba18b
tree4a648aa23b519cf2d7ee99142ea067c9c8849a6a
parentc746cbc686c46904a5d381725079a69e38b201cd

arm: use common implementation of genTypedValue helper


2 files changed, 23 insertions(+), 175 deletions(-)

src/arch/arm/CodeGen.zig+20-172
...@@ -24,7 +24,7 @@ const log = std.log.scoped(.codegen);...@@ -24,7 +24,7 @@ const log = std.log.scoped(.codegen);
24const build_options = @import("build_options");24const build_options = @import("build_options");
2525
26const Result = codegen.Result;26const Result = codegen.Result;
27const GenerateSymbolError = codegen.GenerateSymbolError;27const CodeGenError = codegen.CodeGenError;
28const DebugInfoOutput = codegen.DebugInfoOutput;28const DebugInfoOutput = codegen.DebugInfoOutput;
2929
30const bits = @import("bits.zig");30const bits = @import("bits.zig");
...@@ -42,7 +42,7 @@ const c_abi_int_param_regs = abi.c_abi_int_param_regs;...@@ -42,7 +42,7 @@ const c_abi_int_param_regs = abi.c_abi_int_param_regs;
42const c_abi_int_return_regs = abi.c_abi_int_return_regs;42const c_abi_int_return_regs = abi.c_abi_int_return_regs;
43const gp = abi.RegisterClass.gp;43const gp = abi.RegisterClass.gp;
4444
45const InnerError = codegen.CodeGenError || error{OutOfRegisters};45const InnerError = CodeGenError || error{OutOfRegisters};
4646
47gpa: Allocator,47gpa: Allocator,
48air: Air,48air: Air,
...@@ -339,7 +339,7 @@ pub fn generate(...@@ -339,7 +339,7 @@ pub fn generate(
339 liveness: Liveness,339 liveness: Liveness,
340 code: *std.ArrayList(u8),340 code: *std.ArrayList(u8),
341 debug_output: DebugInfoOutput,341 debug_output: DebugInfoOutput,
342) GenerateSymbolError!Result {342) CodeGenError!Result {
343 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {343 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
344 @panic("Attempted to compile for architecture that was disabled by build configuration");344 @panic("Attempted to compile for architecture that was disabled by build configuration");
345 }345 }
...@@ -6083,178 +6083,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -6083,178 +6083,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
6083 }6083 }
6084}6084}
60856085
6086fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue {
6087 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6088 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
6089
6090 const mod = self.bin_file.options.module.?;
6091 const decl = mod.declPtr(decl_index);
6092 mod.markDeclAlive(decl);
6093
6094 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6095 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
6096 const atom = elf_file.getAtom(atom_index);
6097 return MCValue{ .memory = atom.getOffsetTableAddress(elf_file) };
6098 } else if (self.bin_file.cast(link.File.MachO)) |_| {
6099 unreachable; // unsupported architecture for MachO
6100 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6101 return self.fail("TODO codegen COFF const Decl pointer", .{});
6102 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6103 const decl_block_index = try p9.seeDecl(decl_index);
6104 const decl_block = p9.getDeclBlock(decl_block_index);
6105 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
6106 return MCValue{ .memory = got_addr };
6107 } else {
6108 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
6109 }
6110
6111 _ = tv;
6112}
6113
6114fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
6115 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
6116 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
6117 };
6118 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6119 return MCValue{ .memory = elf_file.getSymbol(local_sym_index).st_value };
6120 } else if (self.bin_file.cast(link.File.MachO)) |_| {
6121 unreachable;
6122 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6123 return self.fail("TODO lower unnamed const in COFF", .{});
6124 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
6125 return self.fail("TODO lower unnamed const in Plan9", .{});
6126 } else {
6127 return self.fail("TODO lower unnamed const", .{});
6128 }
6129}
6130
6131fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {6086fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6132 var typed_value = arg_tv;6087 const mcv: MCValue = switch (try codegen.genTypedValue(
6133 if (typed_value.val.castTag(.runtime_value)) |rt| {6088 self.bin_file,
6134 typed_value.val = rt.data;6089 self.src_loc,
6135 }6090 arg_tv,
6136 log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });6091 self.mod_fn.owner_decl,
6137 if (typed_value.val.isUndef())6092 )) {
6138 return MCValue{ .undef = {} };6093 .mcv => |mcv| switch (mcv) {
6139 const ptr_bits = self.target.cpu.arch.ptrBitWidth();6094 .none => .none,
61406095 .undef => .undef,
6141 if (typed_value.val.castTag(.decl_ref)) |payload| {6096 .linker_load => unreachable, // TODO
6142 return self.lowerDeclRef(typed_value, payload.data);6097 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },
6143 }6098 .memory => |addr| .{ .memory = addr },
6144 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
6145 return self.lowerDeclRef(typed_value, payload.data.decl_index);
6146 }
6147 const target = self.target.*;
6148
6149 switch (typed_value.ty.zigTypeTag()) {
6150 .Pointer => switch (typed_value.ty.ptrSize()) {
6151 .Slice => {},
6152 else => {
6153 switch (typed_value.val.tag()) {
6154 .int_u64 => {
6155 return MCValue{ .immediate = @intCast(u32, typed_value.val.toUnsignedInt(target)) };
6156 },
6157 else => {},
6158 }
6159 },
6160 },6099 },
6161 .Int => {6100 .fail => |msg| {
6162 const info = typed_value.ty.intInfo(self.target.*);6101 self.err_msg = msg;
6163 if (info.bits <= ptr_bits) {6102 return error.CodegenFail;
6164 const unsigned = switch (info.signedness) {
6165 .signed => blk: {
6166 const signed = @intCast(i32, typed_value.val.toSignedInt(target));
6167 break :blk @bitCast(u32, signed);
6168 },
6169 .unsigned => @intCast(u32, typed_value.val.toUnsignedInt(target)),
6170 };
6171
6172 return MCValue{ .immediate = unsigned };
6173 } else {
6174 return self.lowerUnnamedConst(typed_value);
6175 }
6176 },
6177 .Bool => {
6178 return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) };
6179 },
6180 .Optional => {
6181 if (typed_value.ty.isPtrLikeOptional()) {
6182 if (typed_value.val.isNull())
6183 return MCValue{ .immediate = 0 };
6184
6185 var buf: Type.Payload.ElemType = undefined;
6186 return self.genTypedValue(.{
6187 .ty = typed_value.ty.optionalChild(&buf),
6188 .val = typed_value.val,
6189 });
6190 } else if (typed_value.ty.abiSize(self.target.*) == 1) {
6191 return MCValue{ .immediate = @boolToInt(typed_value.val.isNull()) };
6192 }
6193 },
6194 .Enum => {
6195 if (typed_value.val.castTag(.enum_field_index)) |field_index| {
6196 switch (typed_value.ty.tag()) {
6197 .enum_simple => {
6198 return MCValue{ .immediate = field_index.data };
6199 },
6200 .enum_full, .enum_nonexhaustive => {
6201 const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
6202 if (enum_full.values.count() != 0) {
6203 const tag_val = enum_full.values.keys()[field_index.data];
6204 return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val });
6205 } else {
6206 return MCValue{ .immediate = field_index.data };
6207 }
6208 },
6209 else => unreachable,
6210 }
6211 } else {
6212 var int_tag_buffer: Type.Payload.Bits = undefined;
6213 const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
6214 return self.genTypedValue(.{ .ty = int_tag_ty, .val = typed_value.val });
6215 }
6216 },
6217 .ErrorSet => {
6218 switch (typed_value.val.tag()) {
6219 .@"error" => {
6220 const err_name = typed_value.val.castTag(.@"error").?.data.name;
6221 const module = self.bin_file.options.module.?;
6222 const global_error_set = module.global_error_set;
6223 const error_index = global_error_set.get(err_name).?;
6224 return MCValue{ .immediate = error_index };
6225 },
6226 else => {
6227 // In this case we are rendering an error union which has a 0 bits payload.
6228 return MCValue{ .immediate = 0 };
6229 },
6230 }
6231 },6103 },
6232 .ErrorUnion => {6104 };
6233 const error_type = typed_value.ty.errorUnionSet();6105 return mcv;
6234 const payload_type = typed_value.ty.errorUnionPayload();
6235 const is_pl = typed_value.val.errorUnionIsPayload();
6236
6237 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
6238 // We use the error type directly as the type.
6239 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
6240 return self.genTypedValue(.{ .ty = error_type, .val = err_val });
6241 }
6242 },
6243
6244 .ComptimeInt => unreachable, // semantic analysis prevents this
6245 .ComptimeFloat => unreachable, // semantic analysis prevents this
6246 .Type => unreachable,
6247 .EnumLiteral => unreachable,
6248 .Void => unreachable,
6249 .NoReturn => unreachable,
6250 .Undefined => unreachable,
6251 .Null => unreachable,
6252 .Opaque => unreachable,
6253
6254 else => {},
6255 }
6256
6257 return self.lowerUnnamedConst(typed_value);
6258}6106}
62596107
6260const CallMCValues = struct {6108const CallMCValues = struct {
src/arch/x86_64/CodeGen.zig+3-3
...@@ -12,12 +12,12 @@ const trace = @import("../../tracy.zig").trace;...@@ -12,12 +12,12 @@ const trace = @import("../../tracy.zig").trace;
1212
13const Air = @import("../../Air.zig");13const Air = @import("../../Air.zig");
14const Allocator = mem.Allocator;14const Allocator = mem.Allocator;
15const CodeGenError = codegen.CodeGenError;
15const Compilation = @import("../../Compilation.zig");16const Compilation = @import("../../Compilation.zig");
16const DebugInfoOutput = codegen.DebugInfoOutput;17const DebugInfoOutput = codegen.DebugInfoOutput;
17const DW = std.dwarf;18const DW = std.dwarf;
18const ErrorMsg = Module.ErrorMsg;19const ErrorMsg = Module.ErrorMsg;
19const Result = codegen.Result;20const Result = codegen.Result;
20const GenerateSymbolError = codegen.GenerateSymbolError;
21const Emit = @import("Emit.zig");21const Emit = @import("Emit.zig");
22const Liveness = @import("../../Liveness.zig");22const Liveness = @import("../../Liveness.zig");
23const Mir = @import("Mir.zig");23const Mir = @import("Mir.zig");
...@@ -40,7 +40,7 @@ const Register = bits.Register;...@@ -40,7 +40,7 @@ const Register = bits.Register;
40const gp = abi.RegisterClass.gp;40const gp = abi.RegisterClass.gp;
41const sse = abi.RegisterClass.sse;41const sse = abi.RegisterClass.sse;
4242
43const InnerError = codegen.CodeGenError || error{OutOfRegisters};43const InnerError = CodeGenError || error{OutOfRegisters};
4444
45gpa: Allocator,45gpa: Allocator,
46air: Air,46air: Air,
...@@ -253,7 +253,7 @@ pub fn generate(...@@ -253,7 +253,7 @@ pub fn generate(
253 liveness: Liveness,253 liveness: Liveness,
254 code: *std.ArrayList(u8),254 code: *std.ArrayList(u8),
255 debug_output: DebugInfoOutput,255 debug_output: DebugInfoOutput,
256) GenerateSymbolError!Result {256) CodeGenError!Result {
257 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {257 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
258 @panic("Attempted to compile for architecture that was disabled by build configuration");258 @panic("Attempted to compile for architecture that was disabled by build configuration");
259 }259 }