authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:53:13+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-03 18:53:13+01:00
log5b3ea49806f5d0b9034e3eacbef9e19428a5db8a
tree1dff827eed171f6962f0db3f8e048833b2fbe650
parent0d2c25ca9d0794b1c822a12f3bdf8e57ede4c840

riscv64: use common implementation of genTypedValue


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

src/arch/riscv64/CodeGen.zig+20-138
...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);
23const build_options = @import("build_options");23const build_options = @import("build_options");
24const codegen = @import("../../codegen.zig");24const codegen = @import("../../codegen.zig");
2525
26const CodeGenError = codegen.CodeGenError;
26const Result = codegen.Result;27const Result = codegen.Result;
27const DebugInfoOutput = codegen.DebugInfoOutput;28const DebugInfoOutput = codegen.DebugInfoOutput;
2829
...@@ -35,7 +36,7 @@ const Instruction = abi.Instruction;...@@ -35,7 +36,7 @@ const Instruction = abi.Instruction;
35const callee_preserved_regs = abi.callee_preserved_regs;36const callee_preserved_regs = abi.callee_preserved_regs;
36const gp = abi.RegisterClass.gp;37const gp = abi.RegisterClass.gp;
3738
38const InnerError = codegen.CodeGenError || error{OutOfRegisters};39const InnerError = CodeGenError || error{OutOfRegisters};
3940
40gpa: Allocator,41gpa: Allocator,
41air: Air,42air: Air,
...@@ -221,7 +222,7 @@ pub fn generate(...@@ -221,7 +222,7 @@ pub fn generate(
221 liveness: Liveness,222 liveness: Liveness,
222 code: *std.ArrayList(u8),223 code: *std.ArrayList(u8),
223 debug_output: DebugInfoOutput,224 debug_output: DebugInfoOutput,
224) codegen.CodeGenError!Result {225) CodeGenError!Result {
225 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {226 if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) {
226 @panic("Attempted to compile for architecture that was disabled by build configuration");227 @panic("Attempted to compile for architecture that was disabled by build configuration");
227 }228 }
...@@ -2548,145 +2549,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -2548,145 +2549,26 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
2548 }2549 }
2549}2550}
25502551
2551fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue {
2552 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
2553 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
2554 const mod = self.bin_file.options.module.?;
2555 const decl = mod.declPtr(decl_index);
2556 mod.markDeclAlive(decl);
2557 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
2558 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
2559 const atom = elf_file.getAtom(atom_index);
2560 return MCValue{ .memory = atom.getOffsetTableAddress(elf_file) };
2561 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2562 unreachable;
2563 } else if (self.bin_file.cast(link.File.Coff)) |_| {
2564 return self.fail("TODO codegen COFF const Decl pointer", .{});
2565 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2566 const decl_block_index = try p9.seeDecl(decl_index);
2567 const decl_block = p9.getDeclBlock(decl_block_index);
2568 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
2569 return MCValue{ .memory = got_addr };
2570 } else {
2571 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
2572 }
2573 _ = tv;
2574}
2575
2576fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {2552fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2577 if (typed_value.val.isUndef())2553 const mcv: MCValue = switch (try codegen.genTypedValue(
2578 return MCValue{ .undef = {} };2554 self.bin_file,
25792555 self.src_loc,
2580 if (typed_value.val.castTag(.decl_ref)) |payload| {2556 typed_value,
2581 return self.lowerDeclRef(typed_value, payload.data);2557 self.mod_fn.owner_decl,
2582 }2558 )) {
2583 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {2559 .mcv => |mcv| switch (mcv) {
2584 return self.lowerDeclRef(typed_value, payload.data.decl_index);2560 .none => .none,
2585 }2561 .undef => .undef,
2586 const target = self.target.*;2562 .linker_load => unreachable, // TODO
2587 const ptr_bits = self.target.cpu.arch.ptrBitWidth();2563 .immediate => |imm| .{ .immediate = imm },
2588 switch (typed_value.ty.zigTypeTag()) {2564 .memory => |addr| .{ .memory = addr },
2589 .Pointer => switch (typed_value.ty.ptrSize()) {
2590 .Slice => {
2591 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2592 const ptr_type = typed_value.ty.slicePtrFieldType(&buf);
2593 const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });
2594 const mod = self.bin_file.options.module.?;
2595 const slice_len = typed_value.val.sliceLen(mod);
2596 // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean
2597 // the Sema code needs to use anonymous Decls or alloca instructions to store data.
2598 const ptr_imm = ptr_mcv.memory;
2599 _ = slice_len;
2600 _ = ptr_imm;
2601 // We need more general support for const data being stored in memory to make this work.
2602 return self.fail("TODO codegen for const slices", .{});
2603 },
2604 else => {
2605 if (typed_value.val.tag() == .int_u64) {
2606 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
2607 }
2608 return self.fail("TODO codegen more kinds of const pointers", .{});
2609 },
2610 },
2611 .Int => {
2612 const info = typed_value.ty.intInfo(self.target.*);
2613 if (info.bits > ptr_bits or info.signedness == .signed) {
2614 return self.fail("TODO const int bigger than ptr and signed int", .{});
2615 }
2616 return MCValue{ .immediate = typed_value.val.toUnsignedInt(target) };
2617 },2565 },
2618 .Bool => {2566 .fail => |msg| {
2619 return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) };2567 self.err_msg = msg;
2568 return error.CodegenFail;
2620 },2569 },
2621 .ComptimeInt => unreachable, // semantic analysis prevents this2570 };
2622 .ComptimeFloat => unreachable, // semantic analysis prevents this2571 return mcv;
2623 .Optional => {
2624 if (typed_value.ty.isPtrLikeOptional()) {
2625 if (typed_value.val.isNull())
2626 return MCValue{ .immediate = 0 };
2627
2628 var buf: Type.Payload.ElemType = undefined;
2629 return self.genTypedValue(.{
2630 .ty = typed_value.ty.optionalChild(&buf),
2631 .val = typed_value.val,
2632 });
2633 } else if (typed_value.ty.abiSize(self.target.*) == 1) {
2634 return MCValue{ .immediate = @boolToInt(typed_value.val.isNull()) };
2635 }
2636 return self.fail("TODO non pointer optionals", .{});
2637 },
2638 .Enum => {
2639 if (typed_value.val.castTag(.enum_field_index)) |field_index| {
2640 switch (typed_value.ty.tag()) {
2641 .enum_simple => {
2642 return MCValue{ .immediate = field_index.data };
2643 },
2644 .enum_full, .enum_nonexhaustive => {
2645 const enum_full = typed_value.ty.cast(Type.Payload.EnumFull).?.data;
2646 if (enum_full.values.count() != 0) {
2647 const tag_val = enum_full.values.keys()[field_index.data];
2648 return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val });
2649 } else {
2650 return MCValue{ .immediate = field_index.data };
2651 }
2652 },
2653 else => unreachable,
2654 }
2655 } else {
2656 var int_tag_buffer: Type.Payload.Bits = undefined;
2657 const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
2658 return self.genTypedValue(.{ .ty = int_tag_ty, .val = typed_value.val });
2659 }
2660 },
2661 .ErrorSet => {
2662 switch (typed_value.val.tag()) {
2663 .@"error" => {
2664 const err_name = typed_value.val.castTag(.@"error").?.data.name;
2665 const module = self.bin_file.options.module.?;
2666 const global_error_set = module.global_error_set;
2667 const error_index = global_error_set.get(err_name).?;
2668 return MCValue{ .immediate = error_index };
2669 },
2670 else => {
2671 // In this case we are rendering an error union which has a 0 bits payload.
2672 return MCValue{ .immediate = 0 };
2673 },
2674 }
2675 },
2676 .ErrorUnion => {
2677 const error_type = typed_value.ty.errorUnionSet();
2678 const payload_type = typed_value.ty.errorUnionPayload();
2679 const sub_val = typed_value.val.castTag(.eu_payload).?.data;
2680
2681 if (!payload_type.hasRuntimeBits()) {
2682 // We use the error type directly as the type.
2683 return self.genTypedValue(.{ .ty = error_type, .val = sub_val });
2684 }
2685
2686 return self.fail("TODO implement error union const of type '{}'", .{typed_value.ty.fmtDebug()});
2687 },
2688 else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty.fmtDebug()}),
2689 }
2690}2572}
26912573
2692const CallMCValues = struct {2574const CallMCValues = struct {