Commit a369e8af9e

Koakuma <koachan@protonmail.com>
2022-12-10 14:57:42
stage2: sparc64: Add more types for genTypedValue
1 parent e9204f8
Changed files (1)
src
arch
sparc64
src/arch/sparc64/CodeGen.zig
@@ -3862,27 +3862,48 @@ fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_t
 }
 
 fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
-    if (typed_value.val.isUndef())
+    var tv = typed_value;
+    log.debug("genTypedValue: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() });
+
+    if (tv.val.castTag(.runtime_value)) |rt| {
+        tv.val = rt.data;
+    }
+
+    if (tv.val.isUndef())
         return MCValue{ .undef = {} };
 
-    if (typed_value.val.castTag(.decl_ref)) |payload| {
-        return self.lowerDeclRef(typed_value, payload.data);
+    if (tv.val.castTag(.decl_ref)) |payload| {
+        return self.lowerDeclRef(tv, payload.data);
     }
-    if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
-        return self.lowerDeclRef(typed_value, payload.data.decl_index);
+    if (tv.val.castTag(.decl_ref_mut)) |payload| {
+        return self.lowerDeclRef(tv, payload.data.decl_index);
     }
     const target = self.target.*;
 
-    switch (typed_value.ty.zigTypeTag()) {
+    switch (tv.ty.zigTypeTag()) {
+        .Pointer => switch (tv.ty.ptrSize()) {
+            .Slice => {},
+            else => {
+                switch (tv.val.tag()) {
+                    .int_u64 => {
+                        return MCValue{ .immediate = tv.val.toUnsignedInt(target) };
+                    },
+                    else => {},
+                }
+            },
+        },
+        .Bool => {
+            return MCValue{ .immediate = @boolToInt(tv.val.toBool()) };
+        },
         .Int => {
-            const info = typed_value.ty.intInfo(self.target.*);
+            const info = tv.ty.intInfo(self.target.*);
             if (info.bits <= 64) {
                 const unsigned = switch (info.signedness) {
                     .signed => blk: {
-                        const signed = typed_value.val.toSignedInt(target);
+                        const signed = tv.val.toSignedInt(target);
                         break :blk @bitCast(u64, signed);
                     },
-                    .unsigned => typed_value.val.toUnsignedInt(target),
+                    .unsigned => tv.val.toUnsignedInt(target),
                 };
 
                 return MCValue{ .immediate = unsigned };
@@ -3890,38 +3911,84 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
                 return self.fail("TODO implement int genTypedValue of > 64 bits", .{});
             }
         },
+        .Optional => {
+            if (tv.ty.isPtrLikeOptional()) {
+                if (tv.val.isNull())
+                    return MCValue{ .immediate = 0 };
+
+                var buf: Type.Payload.ElemType = undefined;
+                return self.genTypedValue(.{
+                    .ty = tv.ty.optionalChild(&buf),
+                    .val = tv.val,
+                });
+            } else if (tv.ty.abiSize(self.target.*) == 1) {
+                return MCValue{ .immediate = @boolToInt(tv.val.isNull()) };
+            }
+        },
+        .Enum => {
+            if (tv.val.castTag(.enum_field_index)) |field_index| {
+                switch (tv.ty.tag()) {
+                    .enum_simple => {
+                        return MCValue{ .immediate = field_index.data };
+                    },
+                    .enum_full, .enum_nonexhaustive => {
+                        const enum_full = tv.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 = tv.ty.intTagType(&int_tag_buffer);
+                return self.genTypedValue(.{ .ty = int_tag_ty, .val = tv.val });
+            }
+        },
         .ErrorSet => {
-            const err_name = typed_value.val.castTag(.@"error").?.data.name;
+            const err_name = tv.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 };
         },
         .ErrorUnion => {
-            const error_type = typed_value.ty.errorUnionSet();
-            const payload_type = typed_value.ty.errorUnionPayload();
+            const error_type = tv.ty.errorUnionSet();
+            const payload_type = tv.ty.errorUnionPayload();
 
-            if (typed_value.val.castTag(.eu_payload)) |pl| {
+            if (tv.val.castTag(.eu_payload)) |pl| {
                 if (!payload_type.hasRuntimeBits()) {
                     // We use the error type directly as the type.
                     return MCValue{ .immediate = 0 };
                 }
 
                 _ = pl;
-                return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty.fmtDebug()});
+                return self.fail("TODO implement error union const of type '{}' (non-error)", .{tv.ty.fmtDebug()});
             } else {
                 if (!payload_type.hasRuntimeBits()) {
                     // We use the error type directly as the type.
-                    return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
+                    return self.genTypedValue(.{ .ty = error_type, .val = tv.val });
                 }
 
-                return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty.fmtDebug()});
+                return self.fail("TODO implement error union const of type '{}' (error)", .{tv.ty.fmtDebug()});
             }
         },
         .ComptimeInt => unreachable, // semantic analysis prevents this
         .ComptimeFloat => unreachable, // semantic analysis prevents this
-        else => return self.fail("TODO implement const of type '{}'", .{typed_value.ty.fmtDebug()}),
+        .Type => unreachable,
+        .EnumLiteral => unreachable,
+        .Void => unreachable,
+        .NoReturn => unreachable,
+        .Undefined => unreachable,
+        .Null => unreachable,
+        .Opaque => unreachable,
+        else => {},
     }
+
+    return self.fail("TODO implement const of type '{}'", .{tv.ty.fmtDebug()});
 }
 
 fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {