Commit c4baa6696e

Cody Tapscott <topolarity@tapscott.me>
2022-02-16 19:02:59
cbe: Add `writeCValueDeref` and small re-factor
1 parent 1a84c23
Changed files (1)
src
codegen
src/codegen/c.zig
@@ -291,6 +291,19 @@ pub const Function = struct {
         }
     }
 
+    fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
+        switch (c_value) {
+            .constant => |inst| {
+                const ty = f.air.typeOf(inst);
+                const val = f.air.value(inst).?;
+                try w.writeAll("(*");
+                try f.object.dg.renderValue(w, ty, val);
+                return w.writeByte(')');
+            },
+            else => return f.object.dg.writeCValueDeref(w, c_value),
+        }
+    }
+
     fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
         return f.object.dg.fail(format, args);
     }
@@ -1259,6 +1272,28 @@ pub const DeclGen = struct {
         }
     }
 
+    fn writeCValueDeref(dg: DeclGen, w: anytype, c_value: CValue) !void {
+        switch (c_value) {
+            .none => unreachable,
+            .local => |i| return w.print("(*t{d})", .{i}),
+            .local_ref => |i| return w.print("t{d}", .{i}),
+            .constant => unreachable,
+            .arg => |i| return w.print("(*a{d})", .{i}),
+            .decl => |decl| {
+                try w.writeAll("(*");
+                try dg.renderDeclName(decl, w);
+                return w.writeByte(')');
+            },
+            .decl_ref => |decl| return dg.renderDeclName(decl, w),
+            .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),
+            .bytes => |bytes| {
+                try w.writeAll("(*");
+                try w.writeAll(bytes);
+                return w.writeByte(')');
+            },
+        }
+    }
+
     fn renderDeclName(dg: DeclGen, decl: *Decl, writer: anytype) !void {
         if (dg.module.decl_exports.get(decl)) |exports| {
             return writer.writeAll(exports[0].options.name);
@@ -1493,10 +1528,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
             .optional_payload_ptr     => try airOptionalPayload(f, inst),
             .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst),
 
-            .is_err          => try airIsErr(f, inst, "", ".", "!="),
-            .is_non_err      => try airIsErr(f, inst, "", ".", "=="),
-            .is_err_ptr      => try airIsErr(f, inst, "*", "->", "!="),
-            .is_non_err_ptr  => try airIsErr(f, inst, "*", "->", "=="),
+            .is_err          => try airIsErr(f, inst, false, "!="),
+            .is_non_err      => try airIsErr(f, inst, false, "=="),
+            .is_err_ptr      => try airIsErr(f, inst, true, "!="),
+            .is_non_err_ptr  => try airIsErr(f, inst, true, "=="),
 
             .is_null         => try airIsNull(f, inst, "==", ""),
             .is_non_null     => try airIsNull(f, inst, "!=", ""),
@@ -1800,8 +1835,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
                 try f.writeCValue(writer, local);
                 try writer.writeAll("));\n");
             } else {
-                try writer.writeAll(" = *");
-                try f.writeCValue(writer, operand);
+                try writer.writeAll(" = ");
+                try f.writeCValueDeref(writer, operand);
                 try writer.writeAll(";\n");
             }
         },
@@ -1916,33 +1951,15 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue, dest_child_type: Type) !CVa
         return CValue.none;
 
     const writer = f.object.writer();
-    switch (dest_ptr) {
-        .local_ref => |i| {
-            const dest: CValue = .{ .local = i };
-            try writer.writeAll("memset(&");
-            try f.writeCValue(writer, dest);
-            try writer.writeAll(", 0xaa, sizeof(");
-            try f.writeCValue(writer, dest);
-            try writer.writeAll("));\n");
-        },
-        .decl_ref => |decl| {
-            const dest: CValue = .{ .decl = decl };
-            try writer.writeAll("memset(&");
-            try f.writeCValue(writer, dest);
-            try writer.writeAll(", 0xaa, sizeof(");
-            try f.writeCValue(writer, dest);
-            try writer.writeAll("));\n");
-        },
-        else => {
-            const indirection = if (dest_child_type.zigTypeTag() == .Array) "" else "*";
-
-            try writer.writeAll("memset(");
-            try f.writeCValue(writer, dest_ptr);
-            try writer.print(", 0xaa, sizeof({s}", .{indirection});
-            try f.writeCValue(writer, dest_ptr);
-            try writer.writeAll("));\n");
-        },
+    try writer.writeAll("memset(");
+    try f.writeCValue(writer, dest_ptr);
+    try writer.writeAll(", 0xaa, sizeof(");
+    if (dest_child_type.zigTypeTag() == .Array) {
+        try f.writeCValue(writer, dest_ptr);
+    } else {
+        try f.writeCValueDeref(writer, dest_ptr);
     }
+    try writer.writeAll("));\n");
     return CValue.none;
 }
 
@@ -2004,8 +2021,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
                 try f.writeCValue(writer, array_src);
                 try writer.writeAll("));\n");
             } else {
-                try writer.writeAll("*");
-                try f.writeCValue(writer, dest_ptr);
+                try f.writeCValueDeref(writer, dest_ptr);
                 try writer.writeAll(" = ");
                 try f.writeCValue(writer, src_val);
                 try writer.writeAll(";\n");
@@ -2852,16 +2868,15 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
         return operand;
     }
 
-    try writer.writeAll("(");
-    try f.writeCValue(writer, operand);
-    try writer.writeAll(")->is_null = false;\n");
+    try f.writeCValueDeref(writer, operand);
+    try writer.writeAll(".is_null = false;\n");
 
     const inst_ty = f.air.typeOfIndex(inst);
     const local = try f.allocLocal(inst_ty, .Const);
-    try writer.writeAll(" = &(");
-    try f.writeCValue(writer, operand);
+    try writer.writeAll(" = &");
+    try f.writeCValueDeref(writer, operand);
 
-    try writer.writeAll(")->payload;\n");
+    try writer.writeAll(".payload;\n");
     return local;
 }
 
@@ -2912,18 +2927,10 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
 
     const inst_ty = f.air.typeOfIndex(inst);
     const local = try f.allocLocal(inst_ty, .Const);
-    switch (struct_ptr) {
-        .local_ref => |i| {
-            try writer.print(" = {s}t{d}.{s}{ };\n", .{
-                addrof, i, payload, fmtIdent(field_name),
-            });
-        },
-        else => {
-            try writer.print(" = {s}", .{addrof});
-            try f.writeCValue(writer, struct_ptr);
-            try writer.print("->{s}{ };\n", .{ payload, fmtIdent(field_name) });
-        },
-    }
+
+    try writer.print(" = {s}", .{addrof});
+    try f.writeCValueDeref(writer, struct_ptr);
+    try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
     return local;
 }
 
@@ -2975,13 +2982,14 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
         }
     }
 
-    const maybe_deref = if (operand_ty.zigTypeTag() == .Pointer) "->" else ".";
-
     const local = try f.allocLocal(inst_ty, .Const);
-    try writer.writeAll(" = (");
-    try f.writeCValue(writer, operand);
-
-    try writer.print("){s}error;\n", .{maybe_deref});
+    try writer.writeAll(" = ");
+    if (operand_ty.zigTypeTag() == .Pointer) {
+        try f.writeCValueDeref(writer, operand);
+    } else {
+        try f.writeCValue(writer, operand);
+    }
+    try writer.writeAll(".error;\n");
     return local;
 }
 
@@ -3069,8 +3077,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
 fn airIsErr(
     f: *Function,
     inst: Air.Inst.Index,
-    deref_prefix: [*:0]const u8,
-    deref_suffix: [*:0]const u8,
+    is_ptr: bool,
     op_str: [*:0]const u8,
 ) !CValue {
     if (f.liveness.isUnused(inst))
@@ -3082,15 +3089,16 @@ fn airIsErr(
     const operand_ty = f.air.typeOf(un_op);
     const local = try f.allocLocal(Type.initTag(.bool), .Const);
     const payload_ty = operand_ty.errorUnionPayload();
-    if (!payload_ty.hasRuntimeBits()) {
-        try writer.print(" = {s}", .{deref_prefix});
-        try f.writeCValue(writer, operand);
-        try writer.print(" {s} 0;\n", .{op_str});
+    try writer.writeAll(" = ");
+    if (is_ptr) {
+        try f.writeCValueDeref(writer, operand);
     } else {
-        try writer.writeAll(" = ");
         try f.writeCValue(writer, operand);
-        try writer.print("{s}error {s} 0;\n", .{ deref_suffix, op_str });
     }
+    if (payload_ty.hasRuntimeBits()) {
+        try writer.writeAll(".error");
+    }
+    try writer.print(" {s} 0;\n", .{op_str});
     return local;
 }