aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-11-23 15:55:55 -0500
committerGitHub <noreply@github.com>2021-11-23 15:55:55 -0500
commit57e1f6a89f044e731fe60ce15e98b496dcbaa74f (patch)
tree53476730474c176f05286b814495da372a23fa62 /src/codegen
parent8f1e417757f2172485cdea792580e2a2afb53ffa (diff)
parent7ee02b5e70c99159e861cd94adac4707a3315959 (diff)
downloadzig-57e1f6a89f044e731fe60ce15e98b496dcbaa74f.tar.gz
zig-57e1f6a89f044e731fe60ce15e98b496dcbaa74f.zip
Merge pull request #10166 from Scibuild/master
C backend: errors and optionals
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig64
1 files changed, 56 insertions, 8 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 3aef5a8f92..5695d22d45 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1162,12 +1162,13 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.slice => try airSlice(f, inst),
- .cmp_eq => try airBinOp(f, inst, " == "),
.cmp_gt => try airBinOp(f, inst, " > "),
.cmp_gte => try airBinOp(f, inst, " >= "),
.cmp_lt => try airBinOp(f, inst, " < "),
.cmp_lte => try airBinOp(f, inst, " <= "),
- .cmp_neq => try airBinOp(f, inst, " != "),
+
+ .cmp_eq => try airEquality(f, inst, "((", "=="),
+ .cmp_neq => try airEquality(f, inst, "!((", "!="),
// bool_and and bool_or are non-short-circuit operations
.bool_and => try airBinOp(f, inst, " & "),
@@ -1257,9 +1258,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.slice_elem_ptr => try airSliceElemPtr(f, inst),
.array_elem_val => try airArrayElemVal(f, inst),
- .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst),
+ .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, ""),
.unwrap_errunion_err => try airUnwrapErrUnionErr(f, inst),
- .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst),
+ .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, "&"),
.unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst),
.wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
.wrap_errunion_err => try airWrapErrUnionErr(f, inst),
@@ -1908,6 +1909,54 @@ fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue
return local;
}
+fn airEquality(
+ f: *Function,
+ inst: Air.Inst.Index,
+ negate_prefix: []const u8,
+ eq_op_str: []const u8,
+) !CValue {
+ if (f.liveness.isUnused(inst)) return CValue.none;
+
+ const bin_op = f.air.instructions.items(.data)[inst].bin_op;
+ const lhs = try f.resolveInst(bin_op.lhs);
+ const rhs = try f.resolveInst(bin_op.rhs);
+
+ const writer = f.object.writer();
+ const inst_ty = f.air.typeOfIndex(inst);
+ const local = try f.allocLocal(inst_ty, .Const);
+
+ try writer.writeAll(" = ");
+
+ const lhs_ty = f.air.typeOf(bin_op.lhs);
+ if (lhs_ty.tag() == .optional) {
+ // (A && B) || (C && (A == B))
+ // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
+
+ try writer.writeAll(negate_prefix);
+ try f.writeCValue(writer, lhs);
+ try writer.writeAll(".is_null && ");
+ try f.writeCValue(writer, rhs);
+ try writer.writeAll(".is_null) || (");
+ try f.writeCValue(writer, lhs);
+ try writer.writeAll(".payload == ");
+ try f.writeCValue(writer, rhs);
+ try writer.writeAll(".payload && ");
+ try f.writeCValue(writer, lhs);
+ try writer.writeAll(".is_null == ");
+ try f.writeCValue(writer, rhs);
+ try writer.writeAll(".is_null));\n");
+
+ return local;
+ }
+
+ try f.writeCValue(writer, lhs);
+ try writer.writeAll(eq_op_str);
+ try f.writeCValue(writer, rhs);
+ try writer.writeAll(";\n");
+
+ return local;
+}
+
fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
if (f.liveness.isUnused(inst))
return CValue.none;
@@ -2104,8 +2153,8 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
const writer = f.object.writer();
const inst_ty = f.air.typeOfIndex(inst);
- if (inst_ty.zigTypeTag() == .Pointer and
- f.air.typeOf(ty_op.operand).zigTypeTag() == .Pointer)
+ if (inst_ty.isPtrAtRuntime() and
+ f.air.typeOf(ty_op.operand).isPtrAtRuntime())
{
const local = try f.allocLocal(inst_ty, .Const);
try writer.writeAll(" = (");
@@ -2503,7 +2552,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
-fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
+fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: []const u8) !CValue {
if (f.liveness.isUnused(inst))
return CValue.none;
@@ -2519,7 +2568,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.air.typeOfIndex(inst);
const maybe_deref = if (operand_ty.zigTypeTag() == .Pointer) "->" else ".";
- const maybe_addrof = if (inst_ty.zigTypeTag() == .Pointer) "&" else "";
const local = try f.allocLocal(inst_ty, .Const);
try writer.print(" = {s}(", .{maybe_addrof});