Commit c59ee3157f

Andrew Kelley <andrew@ziglang.org>
2021-10-29 02:05:17
C backend: fix ptrtoint and wrap_errunion_err
1 parent 9ed955e
Changed files (4)
src
codegen
test
src/codegen/c.zig
@@ -1117,9 +1117,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
             .float_to_int,
             .fptrunc,
             .fpext,
-            .ptrtoint,
             => try airSimpleCast(f, inst),
 
+            .ptrtoint => try airPtrToInt(f, inst),
+
             .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.Unordered)),
             .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.Monotonic)),
             .atomic_store_release   => try airAtomicStore(f, inst, toMemoryOrder(.Release)),
@@ -2264,15 +2265,18 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
     return local;
 }
 fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
-    if (f.liveness.isUnused(inst))
-        return CValue.none;
+    if (f.liveness.isUnused(inst)) return CValue.none;
 
     const writer = f.object.writer();
     const ty_op = f.air.instructions.items(.data)[inst].ty_op;
     const operand = try f.resolveInst(ty_op.operand);
+    const err_un_ty = f.air.typeOfIndex(inst);
+    const payload_ty = err_un_ty.errorUnionPayload();
+    if (!payload_ty.hasCodeGenBits()) {
+        return operand;
+    }
 
-    const inst_ty = f.air.typeOfIndex(inst);
-    const local = try f.allocLocal(inst_ty, .Const);
+    const local = try f.allocLocal(err_un_ty, .Const);
     try writer.writeAll(" = { .error = ");
     try f.writeCValue(writer, operand);
     try writer.writeAll(" };\n");
@@ -2343,8 +2347,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
 /// Emits a local variable with the result type and initializes it
 /// with the operand.
 fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
-    if (f.liveness.isUnused(inst))
-        return CValue.none;
+    if (f.liveness.isUnused(inst)) return CValue.none;
 
     const inst_ty = f.air.typeOfIndex(inst);
     const local = try f.allocLocal(inst_ty, .Const);
@@ -2358,6 +2361,21 @@ fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
     return local;
 }
 
+fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
+    if (f.liveness.isUnused(inst)) return CValue.none;
+
+    const inst_ty = f.air.typeOfIndex(inst);
+    const local = try f.allocLocal(inst_ty, .Const);
+    const un_op = f.air.instructions.items(.data)[inst].un_op;
+    const writer = f.object.writer();
+    const operand = try f.resolveInst(un_op);
+
+    try writer.writeAll(" = ");
+    try f.writeCValue(writer, operand);
+    try writer.writeAll(";\n");
+    return local;
+}
+
 fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
     if (f.liveness.isUnused(inst)) return CValue.none;
 
test/behavior/if.zig
@@ -73,18 +73,3 @@ test "const result loc, runtime if cond, else unreachable" {
     const x = if (t) Num.Two else unreachable;
     try expect(x == .Two);
 }
-
-test "if copies its payload" {
-    const S = struct {
-        fn doTheTest() !void {
-            var tmp: ?i32 = 10;
-            if (tmp) |value| {
-                // Modify the original variable
-                tmp = null;
-                try expect(value == 10);
-            } else unreachable;
-        }
-    };
-    try S.doTheTest();
-    comptime try S.doTheTest();
-}
test/behavior/if_llvm.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+
+test "if copies its payload" {
+    const S = struct {
+        fn doTheTest() !void {
+            var tmp: ?i32 = 10;
+            if (tmp) |value| {
+                // Modify the original variable
+                tmp = null;
+                try expect(value == 10);
+            } else unreachable;
+        }
+    };
+    try S.doTheTest();
+    comptime try S.doTheTest();
+}
test/behavior.zig
@@ -2,7 +2,7 @@ const builtin = @import("builtin");
 
 test {
     // Tests that pass for stage1, stage2, and the C backend.
-    {}
+    _ = @import("behavior/if.zig");
 
     if (builtin.object_format != .c) {
         // Tests that pass for stage1 and stage2 but not the C backend.
@@ -43,7 +43,7 @@ test {
         _ = @import("behavior/generics.zig");
         _ = @import("behavior/hasdecl.zig");
         _ = @import("behavior/hasfield.zig");
-        _ = @import("behavior/if.zig");
+        _ = @import("behavior/if_llvm.zig");
         _ = @import("behavior/math.zig");
         _ = @import("behavior/maximum_minimum.zig");
         _ = @import("behavior/member_func.zig");