| ... | ... | @@ -3862,27 +3862,48 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t |
| 3862 | 3862 | } |
| 3863 | 3863 | |
| 3864 | 3864 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3865 | | if (typed_value.val.isUndef()) |
| 3865 | var tv = typed_value; |
| 3866 | log.debug("genTypedValue: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() }); |
| 3867 | |
| 3868 | if (tv.val.castTag(.runtime_value)) |rt| { |
| 3869 | tv.val = rt.data; |
| 3870 | } |
| 3871 | |
| 3872 | if (tv.val.isUndef()) |
| 3866 | 3873 | return MCValue{ .undef = {} }; |
| 3867 | 3874 | |
| 3868 | | if (typed_value.val.castTag(.decl_ref)) |payload| { |
| 3869 | | return self.lowerDeclRef(typed_value, payload.data); |
| 3875 | if (tv.val.castTag(.decl_ref)) |payload| { |
| 3876 | return self.lowerDeclRef(tv, payload.data); |
| 3870 | 3877 | } |
| 3871 | | if (typed_value.val.castTag(.decl_ref_mut)) |payload| { |
| 3872 | | return self.lowerDeclRef(typed_value, payload.data.decl_index); |
| 3878 | if (tv.val.castTag(.decl_ref_mut)) |payload| { |
| 3879 | return self.lowerDeclRef(tv, payload.data.decl_index); |
| 3873 | 3880 | } |
| 3874 | 3881 | const target = self.target.*; |
| 3875 | 3882 | |
| 3876 | | switch (typed_value.ty.zigTypeTag()) { |
| 3883 | switch (tv.ty.zigTypeTag()) { |
| 3884 | .Pointer => switch (tv.ty.ptrSize()) { |
| 3885 | .Slice => {}, |
| 3886 | else => { |
| 3887 | switch (tv.val.tag()) { |
| 3888 | .int_u64 => { |
| 3889 | return MCValue{ .immediate = tv.val.toUnsignedInt(target) }; |
| 3890 | }, |
| 3891 | else => {}, |
| 3892 | } |
| 3893 | }, |
| 3894 | }, |
| 3895 | .Bool => { |
| 3896 | return MCValue{ .immediate = @boolToInt(tv.val.toBool()) }; |
| 3897 | }, |
| 3877 | 3898 | .Int => { |
| 3878 | | const info = typed_value.ty.intInfo(self.target.*); |
| 3899 | const info = tv.ty.intInfo(self.target.*); |
| 3879 | 3900 | if (info.bits <= 64) { |
| 3880 | 3901 | const unsigned = switch (info.signedness) { |
| 3881 | 3902 | .signed => blk: { |
| 3882 | | const signed = typed_value.val.toSignedInt(target); |
| 3903 | const signed = tv.val.toSignedInt(target); |
| 3883 | 3904 | break :blk @bitCast(u64, signed); |
| 3884 | 3905 | }, |
| 3885 | | .unsigned => typed_value.val.toUnsignedInt(target), |
| 3906 | .unsigned => tv.val.toUnsignedInt(target), |
| 3886 | 3907 | }; |
| 3887 | 3908 | |
| 3888 | 3909 | return MCValue{ .immediate = unsigned }; |
| ... | ... | @@ -3890,38 +3911,84 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3890 | 3911 | return self.fail("TODO implement int genTypedValue of > 64 bits", .{}); |
| 3891 | 3912 | } |
| 3892 | 3913 | }, |
| 3914 | .Optional => { |
| 3915 | if (tv.ty.isPtrLikeOptional()) { |
| 3916 | if (tv.val.isNull()) |
| 3917 | return MCValue{ .immediate = 0 }; |
| 3918 | |
| 3919 | var buf: Type.Payload.ElemType = undefined; |
| 3920 | return self.genTypedValue(.{ |
| 3921 | .ty = tv.ty.optionalChild(&buf), |
| 3922 | .val = tv.val, |
| 3923 | }); |
| 3924 | } else if (tv.ty.abiSize(self.target.*) == 1) { |
| 3925 | return MCValue{ .immediate = @boolToInt(tv.val.isNull()) }; |
| 3926 | } |
| 3927 | }, |
| 3928 | .Enum => { |
| 3929 | if (tv.val.castTag(.enum_field_index)) |field_index| { |
| 3930 | switch (tv.ty.tag()) { |
| 3931 | .enum_simple => { |
| 3932 | return MCValue{ .immediate = field_index.data }; |
| 3933 | }, |
| 3934 | .enum_full, .enum_nonexhaustive => { |
| 3935 | const enum_full = tv.ty.cast(Type.Payload.EnumFull).?.data; |
| 3936 | if (enum_full.values.count() != 0) { |
| 3937 | const tag_val = enum_full.values.keys()[field_index.data]; |
| 3938 | return self.genTypedValue(.{ .ty = enum_full.tag_ty, .val = tag_val }); |
| 3939 | } else { |
| 3940 | return MCValue{ .immediate = field_index.data }; |
| 3941 | } |
| 3942 | }, |
| 3943 | else => unreachable, |
| 3944 | } |
| 3945 | } else { |
| 3946 | var int_tag_buffer: Type.Payload.Bits = undefined; |
| 3947 | const int_tag_ty = tv.ty.intTagType(&int_tag_buffer); |
| 3948 | return self.genTypedValue(.{ .ty = int_tag_ty, .val = tv.val }); |
| 3949 | } |
| 3950 | }, |
| 3893 | 3951 | .ErrorSet => { |
| 3894 | | const err_name = typed_value.val.castTag(.@"error").?.data.name; |
| 3952 | const err_name = tv.val.castTag(.@"error").?.data.name; |
| 3895 | 3953 | const module = self.bin_file.options.module.?; |
| 3896 | 3954 | const global_error_set = module.global_error_set; |
| 3897 | 3955 | const error_index = global_error_set.get(err_name).?; |
| 3898 | 3956 | return MCValue{ .immediate = error_index }; |
| 3899 | 3957 | }, |
| 3900 | 3958 | .ErrorUnion => { |
| 3901 | | const error_type = typed_value.ty.errorUnionSet(); |
| 3902 | | const payload_type = typed_value.ty.errorUnionPayload(); |
| 3959 | const error_type = tv.ty.errorUnionSet(); |
| 3960 | const payload_type = tv.ty.errorUnionPayload(); |
| 3903 | 3961 | |
| 3904 | | if (typed_value.val.castTag(.eu_payload)) |pl| { |
| 3962 | if (tv.val.castTag(.eu_payload)) |pl| { |
| 3905 | 3963 | if (!payload_type.hasRuntimeBits()) { |
| 3906 | 3964 | // We use the error type directly as the type. |
| 3907 | 3965 | return MCValue{ .immediate = 0 }; |
| 3908 | 3966 | } |
| 3909 | 3967 | |
| 3910 | 3968 | _ = pl; |
| 3911 | | return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty.fmtDebug()}); |
| 3969 | return self.fail("TODO implement error union const of type '{}' (non-error)", .{tv.ty.fmtDebug()}); |
| 3912 | 3970 | } else { |
| 3913 | 3971 | if (!payload_type.hasRuntimeBits()) { |
| 3914 | 3972 | // We use the error type directly as the type. |
| 3915 | | return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val }); |
| 3973 | return self.genTypedValue(.{ .ty = error_type, .val = tv.val }); |
| 3916 | 3974 | } |
| 3917 | 3975 | |
| 3918 | | return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty.fmtDebug()}); |
| 3976 | return self.fail("TODO implement error union const of type '{}' (error)", .{tv.ty.fmtDebug()}); |
| 3919 | 3977 | } |
| 3920 | 3978 | }, |
| 3921 | 3979 | .ComptimeInt => unreachable, // semantic analysis prevents this |
| 3922 | 3980 | .ComptimeFloat => unreachable, // semantic analysis prevents this |
| 3923 | | else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty.fmtDebug()}), |
| 3981 | .Type => unreachable, |
| 3982 | .EnumLiteral => unreachable, |
| 3983 | .Void => unreachable, |
| 3984 | .NoReturn => unreachable, |
| 3985 | .Undefined => unreachable, |
| 3986 | .Null => unreachable, |
| 3987 | .Opaque => unreachable, |
| 3988 | else => {}, |
| 3924 | 3989 | } |
| 3990 | |
| 3991 | return self.fail("TODO implement const of type '{}'", .{tv.ty.fmtDebug()}); |
| 3925 | 3992 | } |
| 3926 | 3993 | |
| 3927 | 3994 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |