| ... | @@ -19,7 +19,7 @@ const Mir = @import("Mir.zig"); | ... | @@ -19,7 +19,7 @@ const Mir = @import("Mir.zig"); |
| 19 | const Emit = @import("Emit.zig"); | 19 | const Emit = @import("Emit.zig"); |
| 20 | const Liveness = @import("../../Liveness.zig"); | 20 | const Liveness = @import("../../Liveness.zig"); |
| 21 | const Type = @import("../../type.zig").Type; | 21 | const Type = @import("../../type.zig").Type; |
| 22 | const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError; | 22 | const CodeGenError = codegen.CodeGenError; |
| 23 | const Result = @import("../../codegen.zig").Result; | 23 | const Result = @import("../../codegen.zig").Result; |
| 24 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; | 24 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| 25 | | 25 | |
| ... | @@ -38,7 +38,7 @@ const gp = abi.RegisterClass.gp; | ... | @@ -38,7 +38,7 @@ const gp = abi.RegisterClass.gp; |
| 38 | | 38 | |
| 39 | const Self = @This(); | 39 | const Self = @This(); |
| 40 | | 40 | |
| 41 | const InnerError = codegen.CodeGenError || error{OutOfRegisters}; | 41 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 42 | | 42 | |
| 43 | const RegisterView = enum(u1) { | 43 | const RegisterView = enum(u1) { |
| 44 | caller, | 44 | caller, |
| ... | @@ -261,7 +261,7 @@ pub fn generate( | ... | @@ -261,7 +261,7 @@ pub fn generate( |
| 261 | liveness: Liveness, | 261 | liveness: Liveness, |
| 262 | code: *std.ArrayList(u8), | 262 | code: *std.ArrayList(u8), |
| 263 | debug_output: DebugInfoOutput, | 263 | debug_output: DebugInfoOutput, |
| 264 | ) GenerateSymbolError!Result { | 264 | ) CodeGenError!Result { |
| 265 | if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { | 265 | if (build_options.skip_non_native and builtin.cpu.arch != bin_file.options.target.cpu.arch) { |
| 266 | @panic("Attempted to compile for architecture that was disabled by build configuration"); | 266 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 267 | } | 267 | } |
| ... | @@ -3894,133 +3894,25 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t | ... | @@ -3894,133 +3894,25 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t |
| 3894 | } | 3894 | } |
| 3895 | | 3895 | |
| 3896 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | 3896 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3897 | var tv = typed_value; | 3897 | const mcv: MCValue = switch (try codegen.genTypedValue( |
| 3898 | log.debug("genTypedValue: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() }); | 3898 | self.bin_file, |
| 3899 | | 3899 | self.src_loc, |
| 3900 | if (tv.val.castTag(.runtime_value)) |rt| { | 3900 | typed_value, |
| 3901 | tv.val = rt.data; | 3901 | self.mod_fn.owner_decl, |
| 3902 | } | 3902 | )) { |
| 3903 | | 3903 | .mcv => |mcv| switch (mcv) { |
| 3904 | if (tv.val.isUndef()) | 3904 | .none => .none, |
| 3905 | return MCValue{ .undef = {} }; | 3905 | .undef => .undef, |
| 3906 | | 3906 | .linker_load => unreachable, // TODO |
| 3907 | if (tv.val.castTag(.decl_ref)) |payload| { | 3907 | .immediate => |imm| .{ .immediate = imm }, |
| 3908 | return self.lowerDeclRef(tv, payload.data); | 3908 | .memory => |addr| .{ .memory = addr }, |
| 3909 | } | | |
| 3910 | if (tv.val.castTag(.decl_ref_mut)) |payload| { | | |
| 3911 | return self.lowerDeclRef(tv, payload.data.decl_index); | | |
| 3912 | } | | |
| 3913 | const target = self.target.*; | | |
| 3914 | | | |
| 3915 | switch (tv.ty.zigTypeTag()) { | | |
| 3916 | .Pointer => switch (tv.ty.ptrSize()) { | | |
| 3917 | .Slice => {}, | | |
| 3918 | else => { | | |
| 3919 | switch (tv.val.tag()) { | | |
| 3920 | .int_u64 => { | | |
| 3921 | return MCValue{ .immediate = tv.val.toUnsignedInt(target) }; | | |
| 3922 | }, | | |
| 3923 | else => {}, | | |
| 3924 | } | | |
| 3925 | }, | | |
| 3926 | }, | | |
| 3927 | .Bool => { | | |
| 3928 | return MCValue{ .immediate = @boolToInt(tv.val.toBool()) }; | | |
| 3929 | }, | | |
| 3930 | .Int => { | | |
| 3931 | const info = tv.ty.intInfo(self.target.*); | | |
| 3932 | if (info.bits <= 64) { | | |
| 3933 | const unsigned = switch (info.signedness) { | | |
| 3934 | .signed => blk: { | | |
| 3935 | const signed = tv.val.toSignedInt(target); | | |
| 3936 | break :blk @bitCast(u64, signed); | | |
| 3937 | }, | | |
| 3938 | .unsigned => tv.val.toUnsignedInt(target), | | |
| 3939 | }; | | |
| 3940 | | | |
| 3941 | return MCValue{ .immediate = unsigned }; | | |
| 3942 | } else { | | |
| 3943 | return self.fail("TODO implement int genTypedValue of > 64 bits", .{}); | | |
| 3944 | } | | |
| 3945 | }, | 3909 | }, |
| 3946 | .Optional => { | 3910 | .fail => |msg| { |
| 3947 | if (tv.ty.isPtrLikeOptional()) { | 3911 | self.err_msg = msg; |
| 3948 | if (tv.val.isNull()) | 3912 | return error.CodegenFail; |
| 3949 | return MCValue{ .immediate = 0 }; | | |
| 3950 | | | |
| 3951 | var buf: Type.Payload.ElemType = undefined; | | |
| 3952 | return self.genTypedValue(.{ | | |
| 3953 | .ty = tv.ty.optionalChild(&buf), | | |
| 3954 | .val = tv.val, | | |
| 3955 | }); | | |
| 3956 | } else if (tv.ty.abiSize(self.target.*) == 1) { | | |
| 3957 | return MCValue{ .immediate = @boolToInt(tv.val.isNull()) }; | | |
| 3958 | } | | |
| 3959 | }, | 3913 | }, |
| 3960 | .Enum => { | 3914 | }; |
| 3961 | if (tv.val.castTag(.enum_field_index)) |field_index| { | 3915 | return mcv; |
| 3962 | switch (tv.ty.tag()) { | | |
| 3963 | .enum_simple => { | | |
| 3964 | return MCValue{ .immediate = field_index.data }; | | |
| 3965 | }, | | |
| 3966 | .enum_full, .enum_nonexhaustive => { | | |
| 3967 | const enum_full = tv.ty.cast(Type.Payload.EnumFull).?.data; | | |
| 3968 | if (enum_full.values.count() != 0) { | | |
| 3969 | const tag_val = enum_full.values.keys()[field_index.data]; | | |
| 3970 | return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val }); | | |
| 3971 | } else { | | |
| 3972 | return MCValue{ .immediate = field_index.data }; | | |
| 3973 | } | | |
| 3974 | }, | | |
| 3975 | else => unreachable, | | |
| 3976 | } | | |
| 3977 | } else { | | |
| 3978 | var int_tag_buffer: Type.Payload.Bits = undefined; | | |
| 3979 | const int_tag_ty = tv.ty.intTagType(&int_tag_buffer); | | |
| 3980 | return self.genTypedValue(.{ .ty = int_tag_ty, .val = tv.val }); | | |
| 3981 | } | | |
| 3982 | }, | | |
| 3983 | .ErrorSet => { | | |
| 3984 | const err_name = tv.val.castTag(.@"error").?.data.name; | | |
| 3985 | const module = self.bin_file.options.module.?; | | |
| 3986 | const global_error_set = module.global_error_set; | | |
| 3987 | const error_index = global_error_set.get(err_name).?; | | |
| 3988 | return MCValue{ .immediate = error_index }; | | |
| 3989 | }, | | |
| 3990 | .ErrorUnion => { | | |
| 3991 | const error_type = tv.ty.errorUnionSet(); | | |
| 3992 | const payload_type = tv.ty.errorUnionPayload(); | | |
| 3993 | | | |
| 3994 | if (tv.val.castTag(.eu_payload)) |pl| { | | |
| 3995 | if (!payload_type.hasRuntimeBits()) { | | |
| 3996 | // We use the error type directly as the type. | | |
| 3997 | return MCValue{ .immediate = 0 }; | | |
| 3998 | } | | |
| 3999 | | | |
| 4000 | _ = pl; | | |
| 4001 | return self.fail("TODO implement error union const of type '{}' (non-error)", .{tv.ty.fmtDebug()}); | | |
| 4002 | } else { | | |
| 4003 | if (!payload_type.hasRuntimeBits()) { | | |
| 4004 | // We use the error type directly as the type. | | |
| 4005 | return self.genTypedValue(.{ .ty = error_type, .val = tv.val }); | | |
| 4006 | } | | |
| 4007 | | | |
| 4008 | return self.fail("TODO implement error union const of type '{}' (error)", .{tv.ty.fmtDebug()}); | | |
| 4009 | } | | |
| 4010 | }, | | |
| 4011 | .ComptimeInt => unreachable, // semantic analysis prevents this | | |
| 4012 | .ComptimeFloat => unreachable, // semantic analysis prevents this | | |
| 4013 | .Type => unreachable, | | |
| 4014 | .EnumLiteral => unreachable, | | |
| 4015 | .Void => unreachable, | | |
| 4016 | .NoReturn => unreachable, | | |
| 4017 | .Undefined => unreachable, | | |
| 4018 | .Null => unreachable, | | |
| 4019 | .Opaque => unreachable, | | |
| 4020 | else => {}, | | |
| 4021 | } | | |
| 4022 | | | |
| 4023 | return self.fail("TODO implement const of type '{}'", .{tv.ty.fmtDebug()}); | | |
| 4024 | } | 3916 | } |
| 4025 | | 3917 | |
| 4026 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { | 3918 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| ... | @@ -4196,28 +4088,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -4196,28 +4088,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 4196 | } | 4088 | } |
| 4197 | } | 4089 | } |
| 4198 | | 4090 | |
| 4199 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) InnerError!MCValue { | | |
| 4200 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? | | |
| 4201 | if (tv.ty.zigTypeTag() == .Pointer) blk: { | | |
| 4202 | if (tv.ty.castPtrToFn()) |_| break :blk; | | |
| 4203 | if (!tv.ty.elemType2().hasRuntimeBits()) { | | |
| 4204 | return MCValue.none; | | |
| 4205 | } | | |
| 4206 | } | | |
| 4207 | | | |
| 4208 | const mod = self.bin_file.options.module.?; | | |
| 4209 | const decl = mod.declPtr(decl_index); | | |
| 4210 | | | |
| 4211 | mod.markDeclAlive(decl); | | |
| 4212 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | | |
| 4213 | const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index); | | |
| 4214 | const atom = elf_file.getAtom(atom_index); | | |
| 4215 | return MCValue{ .memory = atom.getOffsetTableAddress(elf_file) }; | | |
| 4216 | } else { | | |
| 4217 | return self.fail("TODO codegen non-ELF const Decl pointer", .{}); | | |
| 4218 | } | | |
| 4219 | } | | |
| 4220 | | | |
| 4221 | fn minMax( | 4091 | fn minMax( |
| 4222 | self: *Self, | 4092 | self: *Self, |
| 4223 | tag: Air.Inst.Tag, | 4093 | tag: Air.Inst.Tag, |