authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:46:08+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:46:08+01:00
log0d2c25ca9d0794b1c822a12f3bdf8e57ede4c840
treeb5a1bddf2af80d7510052d59313df187421703c6
parentd8d8842190214cf727611b965e830ccbfffb52d1

aarch64: use common implementation of genTypedValue


1 files changed, 20 insertions(+), 195 deletions(-)

src/arch/aarch64/CodeGen.zig+20-195
......@@ -23,7 +23,7 @@ const leb128 = std.leb;
2323const log = std.log.scoped(.codegen);
2424const build_options = @import("build_options");
2525
26const GenerateSymbolError = codegen.GenerateSymbolError;
26const CodeGenError = codegen.CodeGenError;
2727const Result = codegen.Result;
2828const DebugInfoOutput = codegen.DebugInfoOutput;
2929
......@@ -41,7 +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 = codegen.CodeGenError || error{OutOfRegisters};
44const InnerError = CodeGenError || error{OutOfRegisters};
4545
4646gpa: Allocator,
4747air: Air,
......@@ -333,7 +333,7 @@ pub fn generate(
333333 liveness: Liveness,
334334 code: *std.ArrayList(u8),
335335 debug_output: DebugInfoOutput,
336) GenerateSymbolError!Result {
336) CodeGenError!Result {
337337 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
338338 @panic("Attempted to compile for architecture that was disabled by build configuration");
339339 }
......@@ -6133,201 +6133,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
61336133 }
61346134}
61356135
6136fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue {
6137 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6138 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
6139
6140 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
6141 if (tv.ty.zigTypeTag() == .Pointer) blk: {
6142 if (tv.ty.castPtrToFn()) |_| break :blk;
6143 if (!tv.ty.elemType2().hasRuntimeBits()) {
6144 return MCValue.none;
6145 }
6146 }
6147
6148 const mod = self.bin_file.options.module.?;
6149 const decl = mod.declPtr(decl_index);
6150 mod.markDeclAlive(decl);
6151
6152 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6153 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
6154 const atom = elf_file.getAtom(atom_index);
6155 return MCValue{ .memory = atom.getOffsetTableAddress(elf_file) };
6156 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6157 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
6158 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
6159 return MCValue{ .linker_load = .{
6160 .type = .got,
6161 .sym_index = sym_index,
6162 } };
6163 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
6164 const atom_index = try coff_file.getOrCreateAtomForDecl(decl_index);
6165 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
6166 return MCValue{ .linker_load = .{
6167 .type = .got,
6168 .sym_index = sym_index,
6169 } };
6170 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6171 const decl_block_index = try p9.seeDecl(decl_index);
6172 const decl_block = p9.getDeclBlock(decl_block_index);
6173 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
6174 return MCValue{ .memory = got_addr };
6175 } else {
6176 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
6177 }
6178}
6179
6180fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
6181 log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
6182 const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
6183 return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
6184 };
6185 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6186 return MCValue{ .memory = elf_file.getSymbol(local_sym_index).st_value };
6187 } else if (self.bin_file.cast(link.File.MachO)) |_| {
6188 return MCValue{ .linker_load = .{
6189 .type = .direct,
6190 .sym_index = local_sym_index,
6191 } };
6192 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6193 return MCValue{ .linker_load = .{
6194 .type = .direct,
6195 .sym_index = local_sym_index,
6196 } };
6197 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
6198 return self.fail("TODO lower unnamed const in Plan9", .{});
6199 } else {
6200 return self.fail("TODO lower unnamed const", .{});
6201 }
6202}
6203
62046136fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6205 var typed_value = arg_tv;
6206 if (typed_value.val.castTag(.runtime_value)) |rt| {
6207 typed_value.val = rt.data;
6208 }
6209 log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() });
6210 if (typed_value.val.isUndef())
6211 return MCValue{ .undef = {} };
6212
6213 if (typed_value.val.castTag(.decl_ref)) |payload| {
6214 return self.lowerDeclRef(typed_value, payload.data);
6215 }
6216 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
6217 return self.lowerDeclRef(typed_value, payload.data.decl_index);
6218 }
6219 const target = self.target.*;
6220
6221 switch (typed_value.ty.zigTypeTag()) {
6222 .Pointer => switch (typed_value.ty.ptrSize()) {
6223 .Slice => {},
6224 else => {
6225 switch (typed_value.val.tag()) {
6226 .int_u64 => {
6227 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
6228 },
6229 else => {},
6230 }
6231 },
6137 const mcv: MCValue = switch (try codegen.genTypedValue(
6138 self.bin_file,
6139 self.src_loc,
6140 arg_tv,
6141 self.mod_fn.owner_decl,
6142 )) {
6143 .mcv => |mcv| switch (mcv) {
6144 .none => .none,
6145 .undef => .undef,
6146 .linker_load => |ll| .{ .linker_load = ll },
6147 .immediate => |imm| .{ .immediate = imm },
6148 .memory => |addr| .{ .memory = addr },
62326149 },
6233 .Int => {
6234 const info = typed_value.ty.intInfo(self.target.*);
6235 if (info.bits <= 64) {
6236 const unsigned = switch (info.signedness) {
6237 .signed => blk: {
6238 const signed = typed_value.val.toSignedInt(target);
6239 break :blk @bitCast(u64, signed);
6240 },
6241 .unsigned => typed_value.val.toUnsignedInt(target),
6242 };
6243
6244 return MCValue{ .immediate = unsigned };
6245 }
6150 .fail => |msg| {
6151 self.err_msg = msg;
6152 return error.CodegenFail;
62466153 },
6247 .Bool => {
6248 return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) };
6249 },
6250 .Optional => {
6251 if (typed_value.ty.isPtrLikeOptional()) {
6252 if (typed_value.val.isNull())
6253 return MCValue{ .immediate = 0 };
6254
6255 var buf: Type.Payload.ElemType = undefined;
6256 return self.genTypedValue(.{
6257 .ty = typed_value.ty.optionalChild(&buf),
6258 .val = typed_value.val,
6259 });
6260 } else if (typed_value.ty.abiSize(self.target.*) == 1) {
6261 return MCValue{ .immediate = @boolToInt(typed_value.val.isNull()) };
6262 }
6263 },
6264 .Enum => {
6265 if (typed_value.val.castTag(.enum_field_index)) |field_index| {
6266 switch (typed_value.ty.tag()) {
6267 .enum_simple => {
6268 return MCValue{ .immediate = field_index.data };
6269 },
6270 .enum_full, .enum_nonexhaustive => {
6271 const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
6272 if (enum_full.values.count() != 0) {
6273 const tag_val = enum_full.values.keys()[field_index.data];
6274 return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val });
6275 } else {
6276 return MCValue{ .immediate = field_index.data };
6277 }
6278 },
6279 else => unreachable,
6280 }
6281 } else {
6282 var int_tag_buffer: Type.Payload.Bits = undefined;
6283 const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
6284 return self.genTypedValue(.{ .ty = int_tag_ty, .val = typed_value.val });
6285 }
6286 },
6287 .ErrorSet => {
6288 switch (typed_value.val.tag()) {
6289 .@"error" => {
6290 const err_name = typed_value.val.castTag(.@"error").?.data.name;
6291 const module = self.bin_file.options.module.?;
6292 const global_error_set = module.global_error_set;
6293 const error_index = global_error_set.get(err_name).?;
6294 return MCValue{ .immediate = error_index };
6295 },
6296 else => {
6297 // In this case we are rendering an error union which has a 0 bits payload.
6298 return MCValue{ .immediate = 0 };
6299 },
6300 }
6301 },
6302 .ErrorUnion => {
6303 const error_type = typed_value.ty.errorUnionSet();
6304 const payload_type = typed_value.ty.errorUnionPayload();
6305
6306 const is_pl = typed_value.val.errorUnionIsPayload();
6307
6308 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
6309 // We use the error type directly as the type.
6310 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
6311 return self.genTypedValue(.{ .ty = error_type, .val = err_val });
6312 }
6313
6314 return self.lowerUnnamedConst(typed_value);
6315 },
6316
6317 .ComptimeInt => unreachable, // semantic analysis prevents this
6318 .ComptimeFloat => unreachable, // semantic analysis prevents this
6319 .Type => unreachable,
6320 .EnumLiteral => unreachable,
6321 .Void => unreachable,
6322 .NoReturn => unreachable,
6323 .Undefined => unreachable,
6324 .Null => unreachable,
6325 .Opaque => unreachable,
6326
6327 else => {},
6328 }
6329
6330 return self.lowerUnnamedConst(typed_value);
6154 };
6155 return mcv;
63316156}
63326157
63336158const CallMCValues = struct {