diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-03 18:53:13 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-03 18:53:13 +0100 |
| commit | 5b3ea49806f5d0b9034e3eacbef9e19428a5db8a (patch) | |
| tree | 1dff827eed171f6962f0db3f8e048833b2fbe650 /src/arch | |
| parent | 0d2c25ca9d0794b1c822a12f3bdf8e57ede4c840 (diff) | |
| download | zig-5b3ea49806f5d0b9034e3eacbef9e19428a5db8a.tar.gz zig-5b3ea49806f5d0b9034e3eacbef9e19428a5db8a.zip | |
riscv64: use common implementation of genTypedValue
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 158 |
1 files changed, 20 insertions, 138 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index fad5482cbc..c7191145f9 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen); const build_options = @import("build_options"); const codegen = @import("../../codegen.zig"); +const CodeGenError = codegen.CodeGenError; const Result = codegen.Result; const DebugInfoOutput = codegen.DebugInfoOutput; @@ -35,7 +36,7 @@ const Instruction = abi.Instruction; const callee_preserved_regs = abi.callee_preserved_regs; const gp = abi.RegisterClass.gp; -const InnerError = codegen.CodeGenError || error{OutOfRegisters}; +const InnerError = CodeGenError || error{OutOfRegisters}; gpa: Allocator, air: Air, @@ -221,7 +222,7 @@ pub fn generate( liveness: Liveness, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, -) codegen.CodeGenError!Result { +) 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"); } @@ -2548,145 +2549,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } } -fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { - const ptr_bits = self.target.cpu.arch.ptrBitWidth(); - const ptr_bytes: u64 = @divExact(ptr_bits, 8); - const mod = self.bin_file.options.module.?; - const decl = mod.declPtr(decl_index); - mod.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)) |_| { - unreachable; - } else if (self.bin_file.cast(link.File.Coff)) |_| { - return self.fail("TODO codegen COFF const Decl pointer", .{}); - } 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", .{}); - } - _ = tv; -} - fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { - if (typed_value.val.isUndef()) - return MCValue{ .undef = {} }; - - 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.*; - const ptr_bits = self.target.cpu.arch.ptrBitWidth(); - switch (typed_value.ty.zigTypeTag()) { - .Pointer => switch (typed_value.ty.ptrSize()) { - .Slice => { - var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_type = typed_value.ty.slicePtrFieldType(&buf); - const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); - const mod = self.bin_file.options.module.?; - const slice_len = typed_value.val.sliceLen(mod); - // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean - // the Sema code needs to use anonymous Decls or alloca instructions to store data. - const ptr_imm = ptr_mcv.memory; - _ = slice_len; - _ = ptr_imm; - // We need more general support for const data being stored in memory to make this work. - return self.fail("TODO codegen for const slices", .{}); - }, - else => { - if (typed_value.val.tag() == .int_u64) { - return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) }; - } - return self.fail("TODO codegen more kinds of const pointers", .{}); - }, - }, - .Int => { - const info = typed_value.ty.intInfo(self.target.*); - if (info.bits > ptr_bits or info.signedness == .signed) { - return self.fail("TODO const int bigger than ptr and signed int", .{}); - } - return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) }; + const mcv: MCValue = switch (try codegen.genTypedValue( + self.bin_file, + self.src_loc, + typed_value, + self.mod_fn.owner_decl, + )) { + .mcv => |mcv| switch (mcv) { + .none => .none, + .undef => .undef, + .linker_load => unreachable, // TODO + .immediate => |imm| .{ .immediate = imm }, + .memory => |addr| .{ .memory = addr }, }, - .Bool => { - return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; + .fail => |msg| { + self.err_msg = msg; + return error.CodegenFail; }, - .ComptimeInt => unreachable, // semantic analysis prevents this - .ComptimeFloat => unreachable, // semantic analysis prevents this - .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()) }; - } - return self.fail("TODO non pointer optionals", .{}); - }, - .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 sub_val = typed_value.val.castTag(.eu_payload).?.data; - - if (!payload_type.hasRuntimeBits()) { - // We use the error type directly as the type. - return self.genTypedValue(.{ .ty = error_type, .val = sub_val }); - } - - return self.fail("TODO implement error union const of type '{}'", .{typed_value.ty.fmtDebug()}); - }, - else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty.fmtDebug()}), - } + }; + return mcv; } const CallMCValues = struct { |
