Commit 3ec5c9a3bc

Veikka Tuominen <git@vexu.eu>
2021-01-27 11:22:38
stage2 cbe: implement not and some bitwise ops
1 parent 1065203
Changed files (2)
src
codegen
test
stage2
src/codegen/c.zig
@@ -293,6 +293,7 @@ pub const DeclGen = struct {
                 try dg.renderType(w, t.elemType());
                 try w.writeAll(" *");
             },
+            .Null, .Undefined => unreachable, // must be const or comptime
             else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{
                 @tagName(e),
             }),
@@ -387,6 +388,7 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
 
     for (body.instructions) |inst| {
         const result_value = switch (inst.tag) {
+            .constant => unreachable, // excluded from function bodies
             .add => try genBinOp(o, inst.castTag(.add).?, " + "),
             .alloc => try genAlloc(o, inst.castTag(.alloc).?),
             .arg => genArg(o),
@@ -415,8 +417,10 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
             .brvoid => try genBrVoid(o, inst.castTag(.brvoid).?.block),
             .switchbr => try genSwitchBr(o, inst.castTag(.switchbr).?),
             // booland and boolor are non-short-circuit operations
-            .booland => try genBinOp(o, inst.castTag(.booland).?, " & "),
-            .boolor => try genBinOp(o, inst.castTag(.boolor).?, " | "),
+            .booland, .bitand => try genBinOp(o, inst.castTag(.booland).?, " & "),
+            .boolor, .bitor => try genBinOp(o, inst.castTag(.boolor).?, " | "),
+            .xor => try genBinOp(o, inst.castTag(.xor).?, " ^ "),
+            .not => try genUnOp(o, inst.castTag(.not).?, "!"),
             else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
         };
         switch (result_value) {
@@ -541,6 +545,22 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {
     return local;
 }
 
+fn genUnOp(o: *Object, inst: *Inst.UnOp, operator: []const u8) !CValue {
+    if (inst.base.isUnused())
+        return CValue.none;
+
+    const operand = try o.resolveInst(inst.operand);
+
+    const writer = o.writer();
+    const local = try o.allocLocal(inst.base.ty, .Const);
+
+    try writer.print(" = {s}", .{operator});
+    try o.writeCValue(writer, operand);
+    try writer.writeAll(";\n");
+
+    return local;
+}
+
 fn genCall(o: *Object, inst: *Inst.Call) !CValue {
     if (inst.func.castTag(.constant)) |func_inst| {
         const fn_decl = if (func_inst.val.castTag(.extern_fn)) |extern_fn|
test/stage2/cbe.zig
@@ -196,6 +196,13 @@ pub fn addCases(ctx: *TestContext) !void {
             \\    return a - 5;
             \\}
         , "");
+        case.addCompareOutput(
+            \\export fn main() c_int {
+            \\    var a = true;
+            \\    while (!a) {}
+            \\    return 0;
+            \\}
+        , "");
 
         // If expression
         case.addCompareOutput(