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);
2424const build_options = @import("build_options");
2525
2626const Result = codegen.Result;
27const GenerateSymbolError = codegen.GenerateSymbolError;
27const CodeGenError = codegen.CodeGenError;
2828const DebugInfoOutput = codegen.DebugInfoOutput;
2929
3030const bits = @import("bits.zig");
......@@ -42,7 +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 = codegen.CodeGenError || error{OutOfRegisters};
45const InnerError = CodeGenError || error{OutOfRegisters};
4646
4747gpa: Allocator,
4848air: Air,
......@@ -339,7 +339,7 @@ pub fn generate(
339339 liveness: Liveness,
340340 code: *std.ArrayList(u8),
341341 debug_output: DebugInfoOutput,
342) GenerateSymbolError!Result {
342) CodeGenError!Result {
343343 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
344344 @panic("Attempted to compile for architecture that was disabled by build configuration");
345345 }
......@@ -6083,178 +6083,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
60836083 }
60846084}
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
61316086fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6132 var typed_value = arg_tv;
6133 if (typed_value.val.castTag(.runtime_value)) |rt| {
6134 typed_value.val = rt.data;
6135 }
6136 log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
6137 if (typed_value.val.isUndef())
6138 return MCValue{ .undef = {} };
6139 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6140
6141 if (typed_value.val.castTag(.decl_ref)) |payload| {
6142 return self.lowerDeclRef(typed_value, payload.data);
6143 }
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 },
6087 const mcv: MCValue = switch (try codegen.genTypedValue(
6088 self.bin_file,
6089 self.src_loc,
6090 arg_tv,
6091 self.mod_fn.owner_decl,
6092 )) {
6093 .mcv => |mcv| switch (mcv) {
6094 .none => .none,
6095 .undef => .undef,
6096 .linker_load => unreachable, // TODO
6097 .immediate => |imm| .{ .immediate = @truncate(u32, imm) },
6098 .memory => |addr| .{ .memory = addr },
61606099 },
6161 .Int => {
6162 const info = typed_value.ty.intInfo(self.target.*);
6163 if (info.bits <= ptr_bits) {
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 }
6100 .fail => |msg| {
6101 self.err_msg = msg;
6102 return error.CodegenFail;
62316103 },
6232 .ErrorUnion => {
6233 const error_type = typed_value.ty.errorUnionSet();
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);
6104 };
6105 return mcv;
62586106}
62596107
62606108const CallMCValues = struct {
src/arch/x86_64/CodeGen.zig+3-3
......@@ -12,12 +12,12 @@ const trace = @import("../../tracy.zig").trace;
1212
1313const Air = @import("../../Air.zig");
1414const Allocator = mem.Allocator;
15const CodeGenError = codegen.CodeGenError;
1516const Compilation = @import("../../Compilation.zig");
1617const DebugInfoOutput = codegen.DebugInfoOutput;
1718const DW = std.dwarf;
1819const ErrorMsg = Module.ErrorMsg;
1920const Result = codegen.Result;
20const GenerateSymbolError = codegen.GenerateSymbolError;
2121const Emit = @import("Emit.zig");
2222const Liveness = @import("../../Liveness.zig");
2323const Mir = @import("Mir.zig");
......@@ -40,7 +40,7 @@ const Register = bits.Register;
4040const gp = abi.RegisterClass.gp;
4141const sse = abi.RegisterClass.sse;
4242
43const InnerError = codegen.CodeGenError || error{OutOfRegisters};
43const InnerError = CodeGenError || error{OutOfRegisters};
4444
4545gpa: Allocator,
4646air: Air,
......@@ -253,7 +253,7 @@ pub fn generate(
253253 liveness: Liveness,
254254 code: *std.ArrayList(u8),
255255 debug_output: DebugInfoOutput,
256) GenerateSymbolError!Result {
256) CodeGenError!Result {
257257 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
258258 @panic("Attempted to compile for architecture that was disabled by build configuration");
259259 }