Commit 1f5617ac07

Andrew Kelley <andrew@ziglang.org>
2021-03-27 07:46:37
stage2: implement bitwise expr and error literals
1 parent da731e1
src/astgen.zig
@@ -367,6 +367,9 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
         .array_cat => return simpleBinOp(mod, scope, rl, node, .array_cat),
         .array_mult => return simpleBinOp(mod, scope, rl, node, .array_mul),
 
+        .error_union => return simpleBinOp(mod, scope, rl, node, .error_union_type),
+        .merge_error_sets => return simpleBinOp(mod, scope, rl, node, .merge_error_sets),
+
         .bool_and => return boolBinOp(mod, scope, rl, node, .bool_br_and),
         .bool_or => return boolBinOp(mod, scope, rl, node, .bool_br_or),
 
@@ -515,40 +518,11 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
             const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
             return blockExpr(mod, scope, rl, node, statements);
         },
-        .enum_literal => {
-            const ident_token = main_tokens[node];
-            const string_bytes = &gz.zir_code.string_bytes;
-            const str_index = @intCast(u32, string_bytes.items.len);
-            try mod.appendIdentStr(scope, ident_token, string_bytes);
-            try string_bytes.append(mod.gpa, 0);
-            const result = try gz.addStrTok(.enum_literal, str_index, ident_token);
-            return rvalue(mod, scope, rl, result, node);
-        },
-        .error_value => {
-            if (true) @panic("TODO update for zir-memory-layout");
-            const ident_token = node_datas[node].rhs;
-            const name = try mod.identifierTokenString(scope, ident_token);
-            const result = try addZirInstTag(mod, scope, src, .error_value, .{ .name = name });
-            return rvalue(mod, scope, rl, result);
-        },
-        .error_union => {
-            if (true) @panic("TODO update for zir-memory-layout");
-            const error_set = try typeExpr(mod, scope, node_datas[node].lhs);
-            const payload = try typeExpr(mod, scope, node_datas[node].rhs);
-            const result = try addZIRBinOp(mod, scope, src, .error_union_type, error_set, payload);
-            return rvalue(mod, scope, rl, result);
-        },
-        .merge_error_sets => {
-            if (true) @panic("TODO update for zir-memory-layout");
-            const lhs = try typeExpr(mod, scope, node_datas[node].lhs);
-            const rhs = try typeExpr(mod, scope, node_datas[node].rhs);
-            const result = try addZIRBinOp(mod, scope, src, .merge_error_sets, lhs, rhs);
-            return rvalue(mod, scope, rl, result);
-        },
+        .enum_literal => return simpleStrTok(mod, scope, rl, main_tokens[node], node, .enum_literal),
+        .error_value => return simpleStrTok(mod, scope, rl, node_datas[node].rhs, node, .error_value),
         .anyframe_literal => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),
         .anyframe_type => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),
         .@"catch" => {
-            if (true) @panic("TODO update for zir-memory-layout");
             const catch_token = main_tokens[node];
             const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)
                 catch_token + 2
@@ -1597,7 +1571,6 @@ fn containerDecl(
     rl: ResultLoc,
     container_decl: ast.full.ContainerDecl,
 ) InnerError!zir.Inst.Ref {
-    if (true) @panic("TODO update for zir-memory-layout");
     return mod.failTok(scope, container_decl.ast.main_token, "TODO implement container decls", .{});
 }
 
@@ -1607,8 +1580,9 @@ fn errorSetDecl(
     rl: ResultLoc,
     node: ast.Node.Index,
 ) InnerError!zir.Inst.Ref {
-    if (true) @panic("TODO update for zir-memory-layout");
-    const tree = scope.tree();
+    if (true) @panic("TODO update for zir-memory-layout branch");
+    const gz = scope.getGenZir();
+    const tree = gz.tree();
     const main_tokens = tree.nodes.items(.main_token);
     const token_tags = tree.tokens.items(.tag);
 
@@ -1905,6 +1879,23 @@ fn simpleBinOp(
     return rvalue(mod, scope, rl, result, node);
 }
 
+fn simpleStrTok(
+    mod: *Module,
+    scope: *Scope,
+    rl: ResultLoc,
+    ident_token: ast.TokenIndex,
+    node: ast.Node.Index,
+    op_inst_tag: zir.Inst.Tag,
+) InnerError!zir.Inst.Ref {
+    const gz = scope.getGenZir();
+    const string_bytes = &gz.zir_code.string_bytes;
+    const str_index = @intCast(u32, string_bytes.items.len);
+    try mod.appendIdentStr(scope, ident_token, string_bytes);
+    try string_bytes.append(mod.gpa, 0);
+    const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);
+    return rvalue(mod, scope, rl, result, node);
+}
+
 fn boolBinOp(
     mod: *Module,
     scope: *Scope,
src/Module.zig
@@ -1599,7 +1599,7 @@ pub const SrcLoc = struct {
                 const token_starts = tree.tokens.items(.start);
                 return token_starts[tok_index];
             },
-            .node_offset => |node_off| {
+            .node_offset, .node_offset_bin_op => |node_off| {
                 const decl = src_loc.container.decl;
                 const node = decl.relativeToNodeIndex(node_off);
                 const tree = decl.container.file_scope.base.tree();
@@ -1660,9 +1660,28 @@ pub const SrcLoc = struct {
                 const token_starts = tree.tokens.items(.start);
                 return token_starts[tok_index];
             },
-            .node_offset_bin_op => @panic("TODO"),
-            .node_offset_bin_lhs => @panic("TODO"),
-            .node_offset_bin_rhs => @panic("TODO"),
+            .node_offset_bin_lhs => |node_off| {
+                const decl = src_loc.container.decl;
+                const node = decl.relativeToNodeIndex(node_off);
+                const tree = decl.container.file_scope.base.tree();
+                const node_datas = tree.nodes.items(.data);
+                const src_node = node_datas[node].lhs;
+                const main_tokens = tree.nodes.items(.main_token);
+                const tok_index = main_tokens[src_node];
+                const token_starts = tree.tokens.items(.start);
+                return token_starts[tok_index];
+            },
+            .node_offset_bin_rhs => |node_off| {
+                const decl = src_loc.container.decl;
+                const node = decl.relativeToNodeIndex(node_off);
+                const tree = decl.container.file_scope.base.tree();
+                const node_datas = tree.nodes.items(.data);
+                const src_node = node_datas[node].rhs;
+                const main_tokens = tree.nodes.items(.main_token);
+                const tok_index = main_tokens[src_node];
+                const token_starts = tree.tokens.items(.start);
+                return token_starts[tok_index];
+            },
         }
     }
 };
src/Sema.zig
@@ -133,9 +133,9 @@ pub fn analyzeBody(
             .as_node => try sema.zirAsNode(block, inst),
             .@"asm" => try sema.zirAsm(block, inst, false),
             .asm_volatile => try sema.zirAsm(block, inst, true),
-            .bit_and => try sema.zirBitwise(block, inst),
+            .bit_and => try sema.zirBitwise(block, inst, .bit_and),
             .bit_not => try sema.zirBitNot(block, inst),
-            .bit_or => try sema.zirBitwise(block, inst),
+            .bit_or => try sema.zirBitwise(block, inst, .bit_or),
             .bitcast => try sema.zirBitcast(block, inst),
             .bitcast_ref => try sema.zirBitcastRef(block, inst),
             .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
@@ -227,7 +227,7 @@ pub fn analyzeBody(
             .subwrap => try sema.zirArithmetic(block, inst),
             .typeof => try sema.zirTypeof(block, inst),
             .typeof_peer => try sema.zirTypeofPeer(block, inst),
-            .xor => try sema.zirBitwise(block, inst),
+            .xor => try sema.zirBitwise(block, inst, .xor),
             // TODO
             //.switchbr => try sema.zirSwitchBr(block, inst, false),
             //.switchbr_ref => try sema.zirSwitchBr(block, inst, true),
@@ -1390,23 +1390,28 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
     const tracy = trace(@src());
     defer tracy.end();
 
-    const bin_inst = sema.code.instructions.items(.data)[inst].bin;
-    const error_union = try sema.resolveType(block, .unneeded, bin_inst.lhs);
-    const payload = try sema.resolveType(block, .unneeded, bin_inst.rhs);
+    const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+    const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
+    const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
+    const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+    const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
+    const error_union = try sema.resolveType(block, lhs_src, extra.lhs);
+    const payload = try sema.resolveType(block, rhs_src, extra.rhs);
 
     if (error_union.zigTypeTag() != .ErrorSet) {
-        return sema.mod.fail(&block.base, .todo, "expected error set type, found {}", .{error_union.elemType()});
+        return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{
+            error_union.elemType(),
+        });
     }
     const err_union_ty = try sema.mod.errorUnionType(sema.arena, error_union, payload);
-
-    return sema.mod.constType(sema.arena, .unneeded, err_union_ty);
+    return sema.mod.constType(sema.arena, src, err_union_ty);
 }
 
 fn zirErrorSet(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
     const tracy = trace(@src());
     defer tracy.end();
 
-    if (true) @panic("TODO update zirErrorSet in zir-memory-layout branch");
+    if (true) @panic("TODO update for zir-memory-layout branch");
 
     // The owner Decl arena will store the hashmap.
     var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
@@ -1459,19 +1464,21 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
     const tracy = trace(@src());
     defer tracy.end();
 
-    if (true) @panic("TODO update zirMergeErrorSets in zir-memory-layout branch");
-
-    const bin_inst = sema.code.instructions.items(.data)[inst].bin;
-    const lhs_ty = try sema.resolveType(block, .unneeded, bin_inst.lhs);
-    const rhs_ty = try sema.resolveType(block, .unneeded, bin_inst.rhs);
+    const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+    const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
+    const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
+    const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+    const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
+    const lhs_ty = try sema.resolveType(block, lhs_src, extra.lhs);
+    const rhs_ty = try sema.resolveType(block, rhs_src, extra.rhs);
     if (rhs_ty.zigTypeTag() != .ErrorSet)
-        return sema.mod.fail(&block.base, inst.positionals.rhs.src, "expected error set type, found {}", .{rhs_ty});
+        return sema.mod.fail(&block.base, rhs_src, "expected error set type, found {}", .{rhs_ty});
     if (lhs_ty.zigTypeTag() != .ErrorSet)
-        return sema.mod.fail(&block.base, inst.positionals.lhs.src, "expected error set type, found {}", .{lhs_ty});
+        return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{lhs_ty});
 
     // anything merged with anyerror is anyerror
     if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror)
-        return sema.mod.constInst(sema.arena, inst.base.src, .{
+        return sema.mod.constInst(sema.arena, src, .{
             .ty = Type.initTag(.type),
             .val = Value.initTag(.anyerror_type),
         });
@@ -1533,7 +1540,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inn
     });
     payload.data.decl = new_decl;
 
-    return sema.analyzeDeclVal(block, inst.base.src, new_decl);
+    return sema.analyzeDeclVal(block, src, new_decl);
 }
 
 fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
@@ -2442,21 +2449,27 @@ fn zirShr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*In
     return sema.mod.fail(&block.base, sema.src, "TODO implement zirShr", .{});
 }
 
-fn zirBitwise(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
+fn zirBitwise(
+    sema: *Sema,
+    block: *Scope.Block,
+    inst: zir.Inst.Index,
+    ir_tag: ir.Inst.Tag,
+) InnerError!*Inst {
     const tracy = trace(@src());
     defer tracy.end();
 
-    if (true) @panic("TODO rework with zir-memory-layout in mind");
-
-    const bin_inst = sema.code.instructions.items(.data)[inst].bin;
-    const src: LazySrcLoc = .todo;
-    const lhs = try sema.resolveInst(bin_inst.lhs);
-    const rhs = try sema.resolveInst(bin_inst.rhs);
+    const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+    const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
+    const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+    const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
+    const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
+    const lhs = try sema.resolveInst(extra.lhs);
+    const rhs = try sema.resolveInst(extra.rhs);
 
     const instructions = &[_]*Inst{ lhs, rhs };
     const resolved_type = try sema.resolvePeerTypes(block, src, instructions);
-    const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs.src);
-    const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs.src);
+    const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
+    const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
 
     const scalar_type = if (resolved_type.zigTypeTag() == .Vector)
         resolved_type.elemType()
@@ -2499,13 +2512,6 @@ fn zirBitwise(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
     }
 
     try sema.requireRuntimeBlock(block, src);
-    const ir_tag = switch (inst.base.tag) {
-        .bit_and => Inst.Tag.bit_and,
-        .bit_or => Inst.Tag.bit_or,
-        .xor => Inst.Tag.xor,
-        else => unreachable,
-    };
-
     return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
 }
 
src/zir.zig
@@ -312,8 +312,12 @@ pub const Inst = struct {
         /// Uses the `un_node` field.
         ensure_result_non_error,
         /// Create a `E!T` type.
+        /// Uses the `pl_node` field with `Bin` payload.
         error_union_type,
-        /// Create an error set. extra[lhs..rhs]. The values are token index offsets.
+        /// Create an error set. TODO can't we just do this in astgen? reconsider
+        /// memory layout of error sets. if astgen wants to make Sema do the work,
+        /// this ZIR instruction could just be an AST node index. If astgen wants to
+        /// do the work, it could use a const instruction.
         error_set,
         /// `error.Foo` syntax. Uses the `str_tok` field of the Data union.
         error_value,
@@ -393,6 +397,7 @@ pub const Inst = struct {
         /// Uses the `node` field.
         repeat_inline,
         /// Merge two error sets into one, `E1 || E2`.
+        /// Uses the `pl_node` field with payload `Bin`.
         merge_error_sets,
         /// Ambiguously remainder division or modulus. If the computation would possibly have
         /// a different value depending on whether the operation is remainder division or modulus,
@@ -1368,14 +1373,11 @@ const Writer = struct {
         try stream.print("= {s}(", .{@tagName(tags[inst])});
         switch (tag) {
             .array_type,
-            .bit_and,
-            .bit_or,
             .as,
             .coerce_result_ptr,
             .elem_ptr,
             .elem_val,
             .intcast,
-            .merge_error_sets,
             .store,
             .store_to_block_ptr,
             => try self.writeBin(stream, inst),
@@ -1481,6 +1483,10 @@ const Writer = struct {
             .shr,
             .xor,
             .store_node,
+            .error_union_type,
+            .merge_error_sets,
+            .bit_and,
+            .bit_or,
             => try self.writePlNodeBin(stream, inst),
 
             .call,
@@ -1530,7 +1536,6 @@ const Writer = struct {
             .bitcast,
             .bitcast_ref,
             .bitcast_result_ptr,
-            .error_union_type,
             .error_set,
             .store_to_inferred_ptr,
             => try stream.writeAll("TODO)"),
test/stage2/arm.zig
@@ -184,103 +184,103 @@ pub fn addCases(ctx: *TestContext) !void {
         );
 
         // Bitwise And
-        //case.addCompareOutput(
-        //    \\export fn _start() noreturn {
-        //    \\    print(8, 9);
-        //    \\    print(3, 7);
-        //    \\    exit();
-        //    \\}
-        //    \\
-        //    \\fn print(a: u32, b: u32) void {
-        //    \\    asm volatile ("svc #0"
-        //    \\        :
-        //    \\        : [number] "{r7}" (4),
-        //    \\          [arg3] "{r2}" (a & b),
-        //    \\          [arg1] "{r0}" (1),
-        //    \\          [arg2] "{r1}" (@ptrToInt("123456789"))
-        //    \\        : "memory"
-        //    \\    );
-        //    \\    return;
-        //    \\}
-        //    \\
-        //    \\fn exit() noreturn {
-        //    \\    asm volatile ("svc #0"
-        //    \\        :
-        //    \\        : [number] "{r7}" (1),
-        //    \\          [arg1] "{r0}" (0)
-        //    \\        : "memory"
-        //    \\    );
-        //    \\    unreachable;
-        //    \\}
-        //,
-        //    "12345678123",
-        //);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print(8, 9);
+            \\    print(3, 7);
+            \\    exit();
+            \\}
+            \\
+            \\fn print(a: u32, b: u32) void {
+            \\    asm volatile ("svc #0"
+            \\        :
+            \\        : [number] "{r7}" (4),
+            \\          [arg3] "{r2}" (a & b),
+            \\          [arg1] "{r0}" (1),
+            \\          [arg2] "{r1}" (@ptrToInt("123456789"))
+            \\        : "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("svc #0"
+            \\        :
+            \\        : [number] "{r7}" (1),
+            \\          [arg1] "{r0}" (0)
+            \\        : "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "12345678123",
+        );
 
         // Bitwise Or
-        //case.addCompareOutput(
-        //    \\export fn _start() noreturn {
-        //    \\    print(4, 2);
-        //    \\    print(3, 7);
-        //    \\    exit();
-        //    \\}
-        //    \\
-        //    \\fn print(a: u32, b: u32) void {
-        //    \\    asm volatile ("svc #0"
-        //    \\        :
-        //    \\        : [number] "{r7}" (4),
-        //    \\          [arg3] "{r2}" (a | b),
-        //    \\          [arg1] "{r0}" (1),
-        //    \\          [arg2] "{r1}" (@ptrToInt("123456789"))
-        //    \\        : "memory"
-        //    \\    );
-        //    \\    return;
-        //    \\}
-        //    \\
-        //    \\fn exit() noreturn {
-        //    \\    asm volatile ("svc #0"
-        //    \\        :
-        //    \\        : [number] "{r7}" (1),
-        //    \\          [arg1] "{r0}" (0)
-        //    \\        : "memory"
-        //    \\    );
-        //    \\    unreachable;
-        //    \\}
-        //,
-        //    "1234561234567",
-        //);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print(4, 2);
+            \\    print(3, 7);
+            \\    exit();
+            \\}
+            \\
+            \\fn print(a: u32, b: u32) void {
+            \\    asm volatile ("svc #0"
+            \\        :
+            \\        : [number] "{r7}" (4),
+            \\          [arg3] "{r2}" (a | b),
+            \\          [arg1] "{r0}" (1),
+            \\          [arg2] "{r1}" (@ptrToInt("123456789"))
+            \\        : "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("svc #0"
+            \\        :
+            \\        : [number] "{r7}" (1),
+            \\          [arg1] "{r0}" (0)
+            \\        : "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "1234561234567",
+        );
 
         // Bitwise Xor
-        //case.addCompareOutput(
-        //    \\export fn _start() noreturn {
-        //    \\    print(42, 42);
-        //    \\    print(3, 5);
-        //    \\    exit();
-        //    \\}
-        //    \\
-        //    \\fn print(a: u32, b: u32) void {
-        //    \\    asm volatile ("svc #0"
-        //    \\        :
-        //    \\        : [number] "{r7}" (4),
-        //    \\          [arg3] "{r2}" (a ^ b),
-        //    \\          [arg1] "{r0}" (1),
-        //    \\          [arg2] "{r1}" (@ptrToInt("123456789"))
-        //    \\        : "memory"
-        //    \\    );
-        //    \\    return;
-        //    \\}
-        //    \\
-        //    \\fn exit() noreturn {
-        //    \\    asm volatile ("svc #0"
-        //    \\        :
-        //    \\        : [number] "{r7}" (1),
-        //    \\          [arg1] "{r0}" (0)
-        //    \\        : "memory"
-        //    \\    );
-        //    \\    unreachable;
-        //    \\}
-        //,
-        //    "123456",
-        //);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print(42, 42);
+            \\    print(3, 5);
+            \\    exit();
+            \\}
+            \\
+            \\fn print(a: u32, b: u32) void {
+            \\    asm volatile ("svc #0"
+            \\        :
+            \\        : [number] "{r7}" (4),
+            \\          [arg3] "{r2}" (a ^ b),
+            \\          [arg1] "{r0}" (1),
+            \\          [arg2] "{r1}" (@ptrToInt("123456789"))
+            \\        : "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("svc #0"
+            \\        :
+            \\        : [number] "{r7}" (1),
+            \\          [arg1] "{r0}" (0)
+            \\        : "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "123456",
+        );
     }
 
     {
test/stage2/test.zig
@@ -1356,53 +1356,53 @@ pub fn addCases(ctx: *TestContext) !void {
             \\}
         , &[_][]const u8{":8:21: error: evaluation exceeded 1000 backwards branches"});
     }
-    //{
-    //    var case = ctx.exe("orelse at comptime", linux_x64);
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\    const i: ?u64 = 0;
-    //        \\    const orelsed = i orelse 5;
-    //        \\    assert(orelsed == 0);
-    //        \\    exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable;
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    ,
-    //        "",
-    //    );
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\    const i: ?u64 = null;
-    //        \\    const orelsed = i orelse 5;
-    //        \\    assert(orelsed == 5);
-    //        \\    exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable;
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    ,
-    //        "",
-    //    );
-    //}
+    {
+        var case = ctx.exe("orelse at comptime", linux_x64);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const i: ?u64 = 0;
+            \\    const orelsed = i orelse 5;
+            \\    assert(orelsed == 0);
+            \\    exit();
+            \\}
+            \\fn assert(b: bool) void {
+            \\    if (!b) unreachable;
+            \\}
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const i: ?u64 = null;
+            \\    const orelsed = i orelse 5;
+            \\    assert(orelsed == 5);
+            \\    exit();
+            \\}
+            \\fn assert(b: bool) void {
+            \\    if (!b) unreachable;
+            \\}
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+    }
 
     {
         var case = ctx.exe("only 1 function and it gets updated", linux_x64);
@@ -1454,113 +1454,117 @@ pub fn addCases(ctx: *TestContext) !void {
             "",
         );
     }
-    //{
-    //    var case = ctx.exe("catch at comptime", linux_x64);
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\    const i: anyerror!u64 = 0;
-    //        \\    const caught = i catch 5;
-    //        \\    assert(caught == 0);
-    //        \\    exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable;
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    ,
-    //        "",
-    //    );
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\    const i: anyerror!u64 = error.B;
-    //        \\    const caught = i catch 5;
-    //        \\    assert(caught == 5);
-    //        \\    exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable;
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    ,
-    //        "",
-    //    );
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\    const a: anyerror!comptime_int = 42;
-    //        \\    const b: *const comptime_int = &(a catch unreachable);
-    //        \\    assert(b.* == 42);
-    //        \\
-    //        \\    exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable; // assertion failure
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    , "");
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\const a: anyerror!u32 = error.B;
-    //        \\_ = &(a catch |err| assert(err == error.B));
-    //        \\exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable;
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    , "");
-    //    case.addCompareOutput(
-    //        \\export fn _start() noreturn {
-    //        \\    const a: anyerror!u32 = error.Bar;
-    //        \\    a catch |err| assert(err == error.Bar);
-    //        \\
-    //        \\    exit();
-    //        \\}
-    //        \\fn assert(b: bool) void {
-    //        \\    if (!b) unreachable;
-    //        \\}
-    //        \\fn exit() noreturn {
-    //        \\    asm volatile ("syscall"
-    //        \\        :
-    //        \\        : [number] "{rax}" (231),
-    //        \\          [arg1] "{rdi}" (0)
-    //        \\        : "rcx", "r11", "memory"
-    //        \\    );
-    //        \\    unreachable;
-    //        \\}
-    //    , "");
-    //}
+    {
+        var case = ctx.exe("catch at comptime", linux_x64);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const i: anyerror!u64 = 0;
+            \\    const caught = i catch 5;
+            \\    assert(caught == 0);
+            \\    exit();
+            \\}
+            \\fn assert(b: bool) void {
+            \\    if (!b) unreachable;
+            \\}
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const i: anyerror!u64 = error.B;
+            \\    const caught = i catch 5;
+            \\    assert(caught == 5);
+            \\    exit();
+            \\}
+            \\fn assert(b: bool) void {
+            \\    if (!b) unreachable;
+            \\}
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        //case.addCompareOutput(
+        //    \\export fn _start() noreturn {
+        //    \\    const a: anyerror!comptime_int = 42;
+        //    \\    const b: *const comptime_int = &(a catch unreachable);
+        //    \\    assert(b.* == 42);
+        //    \\
+        //    \\    exit();
+        //    \\}
+        //    \\fn assert(b: bool) void {
+        //    \\    if (!b) unreachable; // assertion failure
+        //    \\}
+        //    \\fn exit() noreturn {
+        //    \\    asm volatile ("syscall"
+        //    \\        :
+        //    \\        : [number] "{rax}" (231),
+        //    \\          [arg1] "{rdi}" (0)
+        //    \\        : "rcx", "r11", "memory"
+        //    \\    );
+        //    \\    unreachable;
+        //    \\}
+        //, "");
+
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const a: anyerror!u32 = error.B;
+            \\    _ = &(a catch |err| assert(err == error.B));
+            \\    exit();
+            \\}
+            \\fn assert(b: bool) void {
+            \\    if (!b) unreachable;
+            \\}
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        , "");
+
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const a: anyerror!u32 = error.Bar;
+            \\    a catch |err| assert(err == error.Bar);
+            \\
+            \\    exit();
+            \\}
+            \\fn assert(b: bool) void {
+            \\    if (!b) unreachable;
+            \\}
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        , "");
+    }
     //{
     //    var case = ctx.exe("merge error sets", linux_x64);