| author | |
| committer | |
| log | d24be85be88737db8399b492931647056c547614 |
| tree | e6079e363a2b5bcdc1b100b1149c313b13197f41 |
| parent | 568f333681e6ecf8c60c5bbe04ea1e494d966d48 |
5 files changed, 270 insertions(+), 135 deletions(-)
BRANCH_TODO+1-1| ... | @@ -18,7 +18,6 @@ Merge TODO list: | ... | @@ -18,7 +18,6 @@ Merge TODO list: |
| 18 | 18 | ||
| 19 | Performance optimizations to look into: | 19 | Performance optimizations to look into: |
| 20 | * don't store end index for blocks; rely on last instruction being noreturn | 20 | * don't store end index for blocks; rely on last instruction being noreturn |
| 21 | * introduce special form for function call statement with 0 or 1 parameters | ||
| 22 | * look into not storing the field name of field access as a string in zir | 21 | * look into not storing the field name of field access as a string in zir |
| 23 | instructions. or, look into introducing interning to string_bytes (local | 22 | instructions. or, look into introducing interning to string_bytes (local |
| 24 | to the owner Decl), or, look into allowing field access based on a token/node | 23 | to the owner Decl), or, look into allowing field access based on a token/node |
| ... | @@ -31,3 +30,4 @@ Performance optimizations to look into: | ... | @@ -31,3 +30,4 @@ Performance optimizations to look into: |
| 31 | function ZIR. | 30 | function ZIR. |
| 32 | * enum literals can use small strings | 31 | * enum literals can use small strings |
| 33 | * string literals can use small strings | 32 | * string literals can use small strings |
| 33 | * don't need the Sema coercion on condbr condition, it's done with result locations |
src/Module.zig+14| ... | @@ -1307,6 +1307,7 @@ pub const Scope = struct { | ... | @@ -1307,6 +1307,7 @@ pub const Scope = struct { |
| 1307 | /// Note that this returns a `zir.Inst.Index` not a ref. | 1307 | /// Note that this returns a `zir.Inst.Index` not a ref. |
| 1308 | /// Leaves the `payload_index` field undefined. | 1308 | /// Leaves the `payload_index` field undefined. |
| 1309 | pub fn addCondBr(gz: *GenZir, node: ast.Node.Index) !zir.Inst.Index { | 1309 | pub fn addCondBr(gz: *GenZir, node: ast.Node.Index) !zir.Inst.Index { |
| 1310 | try gz.instructions.ensureCapacity(gz.zir_code.gpa, gz.instructions.items.len + 1); | ||
| 1310 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); | 1311 | const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len); |
| 1311 | try gz.zir_code.instructions.append(gz.zir_code.gpa, .{ | 1312 | try gz.zir_code.instructions.append(gz.zir_code.gpa, .{ |
| 1312 | .tag = .condbr, | 1313 | .tag = .condbr, |
| ... | @@ -1315,6 +1316,7 @@ pub const Scope = struct { | ... | @@ -1315,6 +1316,7 @@ pub const Scope = struct { |
| 1315 | .payload_index = undefined, | 1316 | .payload_index = undefined, |
| 1316 | } }, | 1317 | } }, |
| 1317 | }); | 1318 | }); |
| 1319 | gz.instructions.appendAssumeCapacity(new_index); | ||
| 1318 | return new_index; | 1320 | return new_index; |
| 1319 | } | 1321 | } |
| 1320 | 1322 | ||
| ... | @@ -1398,6 +1400,14 @@ pub const WipZirCode = struct { | ... | @@ -1398,6 +1400,14 @@ pub const WipZirCode = struct { |
| 1398 | return result; | 1400 | return result; |
| 1399 | } | 1401 | } |
| 1400 | 1402 | ||
| 1403 | pub fn refIsNoReturn(wzc: WipZirCode, zir_inst_ref: zir.Inst.Ref) bool { | ||
| 1404 | if (zir_inst_ref >= wzc.ref_start_index) { | ||
| 1405 | const zir_inst = zir_inst_ref - wzc.ref_start_index; | ||
| 1406 | return wzc.instructions.items(.tag)[zir_inst].isNoReturn(); | ||
| 1407 | } | ||
| 1408 | return false; | ||
| 1409 | } | ||
| 1410 | |||
| 1401 | pub fn deinit(wzc: *WipZirCode) void { | 1411 | pub fn deinit(wzc: *WipZirCode) void { |
| 1402 | wzc.instructions.deinit(wzc.gpa); | 1412 | wzc.instructions.deinit(wzc.gpa); |
| 1403 | wzc.extra.deinit(wzc.gpa); | 1413 | wzc.extra.deinit(wzc.gpa); |
| ... | @@ -2290,6 +2300,7 @@ fn astgenAndSemaFn( | ... | @@ -2290,6 +2300,7 @@ fn astgenAndSemaFn( |
| 2290 | .decl = decl, | 2300 | .decl = decl, |
| 2291 | .arena = &decl_arena.allocator, | 2301 | .arena = &decl_arena.allocator, |
| 2292 | .gpa = mod.gpa, | 2302 | .gpa = mod.gpa, |
| 2303 | .ref_start_index = @intCast(u32, zir.const_inst_list.len + param_count), | ||
| 2293 | }; | 2304 | }; |
| 2294 | defer wip_zir_code.deinit(); | 2305 | defer wip_zir_code.deinit(); |
| 2295 | 2306 | ||
| ... | @@ -3199,6 +3210,9 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void { | ... | @@ -3199,6 +3210,9 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void { |
| 3199 | }; | 3210 | }; |
| 3200 | defer inner_block.instructions.deinit(mod.gpa); | 3211 | defer inner_block.instructions.deinit(mod.gpa); |
| 3201 | 3212 | ||
| 3213 | // TZIR currently requires the arg parameters to be the first N instructions | ||
| 3214 | try inner_block.instructions.appendSlice(mod.gpa, param_inst_list); | ||
| 3215 | |||
| 3202 | func.state = .in_progress; | 3216 | func.state = .in_progress; |
| 3203 | log.debug("set {s} to in_progress", .{decl.name}); | 3217 | log.debug("set {s} to in_progress", .{decl.name}); |
| 3204 | 3218 |
src/Sema.zig+13-15| ... | @@ -218,7 +218,7 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde | ... | @@ -218,7 +218,7 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde |
| 218 | // tail call them here. | 218 | // tail call them here. |
| 219 | .condbr => return sema.zirCondbr(block, inst), | 219 | .condbr => return sema.zirCondbr(block, inst), |
| 220 | .@"break" => return sema.zirBreak(block, inst), | 220 | .@"break" => return sema.zirBreak(block, inst), |
| 221 | .break_void_tok => return sema.zirBreakVoidTok(block, inst), | 221 | .break_void_node => return sema.zirBreakVoidNode(block, inst), |
| 222 | .break_flat => return sema.code.instructions.items(.data)[inst].un_node.operand, | 222 | .break_flat => return sema.code.instructions.items(.data)[inst].un_node.operand, |
| 223 | .compile_error => return sema.zirCompileError(block, inst), | 223 | .compile_error => return sema.zirCompileError(block, inst), |
| 224 | .ret_coerce => return sema.zirRetTok(block, inst, true), | 224 | .ret_coerce => return sema.zirRetTok(block, inst, true), |
| ... | @@ -955,20 +955,18 @@ fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!z | ... | @@ -955,20 +955,18 @@ fn zirBreak(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!z |
| 955 | const tracy = trace(@src()); | 955 | const tracy = trace(@src()); |
| 956 | defer tracy.end(); | 956 | defer tracy.end(); |
| 957 | 957 | ||
| 958 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 958 | const inst_data = sema.code.instructions.items(.data)[inst].@"break"; |
| 959 | const operand = try sema.resolveInst(bin_inst.rhs); | 959 | const operand = try sema.resolveInst(inst_data.operand); |
| 960 | const zir_block = bin_inst.lhs; | 960 | return sema.analyzeBreak(block, sema.src, inst_data.block_inst, operand); |
| 961 | return sema.analyzeBreak(block, sema.src, zir_block, operand); | ||
| 962 | } | 961 | } |
| 963 | 962 | ||
| 964 | fn zirBreakVoidTok(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index { | 963 | fn zirBreakVoidNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!zir.Inst.Index { |
| 965 | const tracy = trace(@src()); | 964 | const tracy = trace(@src()); |
| 966 | defer tracy.end(); | 965 | defer tracy.end(); |
| 967 | 966 | ||
| 968 | const inst_data = sema.code.instructions.items(.data)[inst].un_tok; | 967 | const inst_data = sema.code.instructions.items(.data)[inst].break_void_node; |
| 969 | const zir_block = inst_data.operand; | ||
| 970 | const void_inst = try sema.mod.constVoid(sema.arena, .unneeded); | 968 | const void_inst = try sema.mod.constVoid(sema.arena, .unneeded); |
| 971 | return sema.analyzeBreak(block, inst_data.src(), zir_block, void_inst); | 969 | return sema.analyzeBreak(block, inst_data.src(), inst_data.block_inst, void_inst); |
| 972 | } | 970 | } |
| 973 | 971 | ||
| 974 | fn analyzeBreak( | 972 | fn analyzeBreak( |
| ... | @@ -982,7 +980,6 @@ fn analyzeBreak( | ... | @@ -982,7 +980,6 @@ fn analyzeBreak( |
| 982 | while (true) { | 980 | while (true) { |
| 983 | if (block.label) |*label| { | 981 | if (block.label) |*label| { |
| 984 | if (label.zir_block == zir_block) { | 982 | if (label.zir_block == zir_block) { |
| 985 | try sema.requireFunctionBlock(block, src); | ||
| 986 | // Here we add a br instruction, but we over-allocate a little bit | 983 | // Here we add a br instruction, but we over-allocate a little bit |
| 987 | // (if necessary) to make it possible to convert the instruction into | 984 | // (if necessary) to make it possible to convert the instruction into |
| 988 | // a br_block_flat instruction later. | 985 | // a br_block_flat instruction later. |
| ... | @@ -1000,7 +997,7 @@ fn analyzeBreak( | ... | @@ -1000,7 +997,7 @@ fn analyzeBreak( |
| 1000 | .operand = operand, | 997 | .operand = operand, |
| 1001 | .block = label.merges.block_inst, | 998 | .block = label.merges.block_inst, |
| 1002 | }; | 999 | }; |
| 1003 | try block.instructions.append(sema.gpa, &br.base); | 1000 | try start_block.instructions.append(sema.gpa, &br.base); |
| 1004 | try label.merges.results.append(sema.gpa, operand); | 1001 | try label.merges.results.append(sema.gpa, operand); |
| 1005 | try label.merges.br_list.append(sema.gpa, br); | 1002 | try label.merges.br_list.append(sema.gpa, br); |
| 1006 | return always_noreturn; | 1003 | return always_noreturn; |
| ... | @@ -2613,10 +2610,11 @@ fn zirCmp( | ... | @@ -2613,10 +2610,11 @@ fn zirCmp( |
| 2613 | const tracy = trace(@src()); | 2610 | const tracy = trace(@src()); |
| 2614 | defer tracy.end(); | 2611 | defer tracy.end(); |
| 2615 | 2612 | ||
| 2616 | const src: LazySrcLoc = .todo; | 2613 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 2617 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 2614 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; |
| 2618 | const lhs = try sema.resolveInst(bin_inst.lhs); | 2615 | const src: LazySrcLoc = inst_data.src(); |
| 2619 | const rhs = try sema.resolveInst(bin_inst.rhs); | 2616 | const lhs = try sema.resolveInst(extra.lhs); |
| 2617 | const rhs = try sema.resolveInst(extra.rhs); | ||
| 2620 | 2618 | ||
| 2621 | const is_equality_cmp = switch (op) { | 2619 | const is_equality_cmp = switch (op) { |
| 2622 | .eq, .neq => true, | 2620 | .eq, .neq => true, |
src/astgen.zig+143-95| ... | @@ -428,12 +428,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -428,12 +428,12 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 428 | .if_simple => return ifExpr(mod, scope, rl, node, tree.ifSimple(node)), | 428 | .if_simple => return ifExpr(mod, scope, rl, node, tree.ifSimple(node)), |
| 429 | .@"if" => return ifExpr(mod, scope, rl, node, tree.ifFull(node)), | 429 | .@"if" => return ifExpr(mod, scope, rl, node, tree.ifFull(node)), |
| 430 | 430 | ||
| 431 | .while_simple => return whileExpr(mod, scope, rl, tree.whileSimple(node)), | 431 | .while_simple => return whileExpr(mod, scope, rl, node, tree.whileSimple(node)), |
| 432 | .while_cont => return whileExpr(mod, scope, rl, tree.whileCont(node)), | 432 | .while_cont => return whileExpr(mod, scope, rl, node, tree.whileCont(node)), |
| 433 | .@"while" => return whileExpr(mod, scope, rl, tree.whileFull(node)), | 433 | .@"while" => return whileExpr(mod, scope, rl, node, tree.whileFull(node)), |
| 434 | 434 | ||
| 435 | .for_simple => return forExpr(mod, scope, rl, tree.forSimple(node)), | 435 | .for_simple => return forExpr(mod, scope, rl, node, tree.forSimple(node)), |
| 436 | .@"for" => return forExpr(mod, scope, rl, tree.forFull(node)), | 436 | .@"for" => return forExpr(mod, scope, rl, node, tree.forFull(node)), |
| 437 | 437 | ||
| 438 | // TODO handling these separately would actually be simpler & have fewer branches | 438 | // TODO handling these separately would actually be simpler & have fewer branches |
| 439 | // once we have a ZIR instruction for each of these 3 cases. | 439 | // once we have a ZIR instruction for each of these 3 cases. |
| ... | @@ -956,7 +956,7 @@ fn labeledBlockExpr( | ... | @@ -956,7 +956,7 @@ fn labeledBlockExpr( |
| 956 | // The code took advantage of the result location as a pointer. | 956 | // The code took advantage of the result location as a pointer. |
| 957 | // Turn the break instruction operands into void. | 957 | // Turn the break instruction operands into void. |
| 958 | for (block_scope.labeled_breaks.items) |br| { | 958 | for (block_scope.labeled_breaks.items) |br| { |
| 959 | zir_datas[br].bin.rhs = 0; | 959 | zir_datas[br].@"break".operand = @enumToInt(zir.Const.void_value); |
| 960 | } | 960 | } |
| 961 | // TODO technically not needed since we changed the tag to break_void but | 961 | // TODO technically not needed since we changed the tag to break_void but |
| 962 | // would be better still to elide the ones that are in this list. | 962 | // would be better still to elide the ones that are in this list. |
| ... | @@ -1169,7 +1169,7 @@ fn blockExprStmts( | ... | @@ -1169,7 +1169,7 @@ fn blockExprStmts( |
| 1169 | .compile_log, | 1169 | .compile_log, |
| 1170 | .ensure_err_payload_void, | 1170 | .ensure_err_payload_void, |
| 1171 | .@"break", | 1171 | .@"break", |
| 1172 | .break_void_tok, | 1172 | .break_void_node, |
| 1173 | .break_flat, | 1173 | .break_flat, |
| 1174 | .condbr, | 1174 | .condbr, |
| 1175 | .compile_error, | 1175 | .compile_error, |
| ... | @@ -1749,13 +1749,13 @@ fn orelseCatchExpr( | ... | @@ -1749,13 +1749,13 @@ fn orelseCatchExpr( |
| 1749 | 1749 | ||
| 1750 | return finishThenElseBlock( | 1750 | return finishThenElseBlock( |
| 1751 | mod, | 1751 | mod, |
| 1752 | scope, | ||
| 1753 | rl, | ||
| 1754 | &block_scope, | 1752 | &block_scope, |
| 1753 | rl, | ||
| 1754 | node, | ||
| 1755 | &then_scope, | 1755 | &then_scope, |
| 1756 | &else_scope, | 1756 | &else_scope, |
| 1757 | &condbr.positionals.then_body, | 1757 | condbr, |
| 1758 | &condbr.positionals.else_body, | 1758 | cond, |
| 1759 | src, | 1759 | src, |
| 1760 | src, | 1760 | src, |
| 1761 | then_result, | 1761 | then_result, |
| ... | @@ -1767,75 +1767,87 @@ fn orelseCatchExpr( | ... | @@ -1767,75 +1767,87 @@ fn orelseCatchExpr( |
| 1767 | 1767 | ||
| 1768 | fn finishThenElseBlock( | 1768 | fn finishThenElseBlock( |
| 1769 | mod: *Module, | 1769 | mod: *Module, |
| 1770 | parent_scope: *Scope, | ||
| 1771 | rl: ResultLoc, | ||
| 1772 | block_scope: *Scope.GenZir, | 1770 | block_scope: *Scope.GenZir, |
| 1771 | rl: ResultLoc, | ||
| 1772 | node: ast.Node.Index, | ||
| 1773 | then_scope: *Scope.GenZir, | 1773 | then_scope: *Scope.GenZir, |
| 1774 | else_scope: *Scope.GenZir, | 1774 | else_scope: *Scope.GenZir, |
| 1775 | then_body: *zir.Body, | 1775 | condbr: zir.Inst.Index, |
| 1776 | else_body: *zir.Body, | 1776 | cond: zir.Inst.Ref, |
| 1777 | then_src: usize, | 1777 | then_src: ast.Node.Index, |
| 1778 | else_src: usize, | 1778 | else_src: ast.Node.Index, |
| 1779 | then_result: zir.Inst.Ref, | 1779 | then_result: zir.Inst.Ref, |
| 1780 | else_result: ?*zir.Inst, | 1780 | else_result: zir.Inst.Ref, |
| 1781 | main_block: zir.Inst.Ref.Block, | 1781 | main_block: zir.Inst.Index, |
| 1782 | then_break_block: zir.Inst.Ref.Block, | 1782 | then_break_block: zir.Inst.Index, |
| 1783 | ) InnerError!zir.Inst.Ref { | 1783 | ) InnerError!zir.Inst.Ref { |
| 1784 | // We now have enough information to decide whether the result instruction should | 1784 | // We now have enough information to decide whether the result instruction should |
| 1785 | // be communicated via result location pointer or break instructions. | 1785 | // be communicated via result location pointer or break instructions. |
| 1786 | const strat = rlStrategy(rl, block_scope); | 1786 | const strat = rlStrategy(rl, block_scope); |
| 1787 | const wzc = block_scope.zir_code; | ||
| 1787 | switch (strat.tag) { | 1788 | switch (strat.tag) { |
| 1788 | .break_void => { | 1789 | .break_void => { |
| 1789 | if (!then_result.tag.isNoReturn()) { | 1790 | if (!wzc.refIsNoReturn(then_result)) { |
| 1790 | _ = try addZirInstTag(mod, &then_scope.base, then_src, .break_void, .{ | 1791 | _ = try then_scope.add(.{ |
| 1791 | .block = then_break_block, | 1792 | .tag = .break_void_node, |
| 1793 | .data = .{ .break_void_node = .{ | ||
| 1794 | .src_node = wzc.decl.nodeIndexToRelative(then_src), | ||
| 1795 | .block_inst = then_break_block, | ||
| 1796 | } }, | ||
| 1792 | }); | 1797 | }); |
| 1793 | } | 1798 | } |
| 1794 | if (else_result) |inst| { | 1799 | const elide_else = if (else_result != 0) wzc.refIsNoReturn(else_result) else false; |
| 1795 | if (!inst.tag.isNoReturn()) { | 1800 | if (!elide_else) { |
| 1796 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ | 1801 | _ = try else_scope.add(.{ |
| 1797 | .block = main_block, | 1802 | .tag = .break_void_node, |
| 1798 | }); | 1803 | .data = .{ .break_void_node = .{ |
| 1799 | } | 1804 | .src_node = wzc.decl.nodeIndexToRelative(else_src), |
| 1800 | } else { | 1805 | .block_inst = main_block, |
| 1801 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ | 1806 | } }, |
| 1802 | .block = main_block, | ||
| 1803 | }); | 1807 | }); |
| 1804 | } | 1808 | } |
| 1805 | assert(!strat.elide_store_to_block_ptr_instructions); | 1809 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 1806 | try then_scope.setBlockBody(then_body); | 1810 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 1807 | try else_scope.setBlockBody(else_body); | 1811 | return wzc.ref_start_index + main_block; |
| 1808 | return &main_block.base; | ||
| 1809 | }, | 1812 | }, |
| 1810 | .break_operand => { | 1813 | .break_operand => { |
| 1811 | if (!then_result.tag.isNoReturn()) { | 1814 | if (!wzc.refIsNoReturn(then_result)) { |
| 1812 | _ = try addZirInstTag(mod, &then_scope.base, then_src, .@"break", .{ | 1815 | _ = try then_scope.add(.{ |
| 1813 | .block = then_break_block, | 1816 | .tag = .@"break", |
| 1814 | .operand = then_result, | 1817 | .data = .{ .@"break" = .{ |
| 1818 | .block_inst = then_break_block, | ||
| 1819 | .operand = then_result, | ||
| 1820 | } }, | ||
| 1815 | }); | 1821 | }); |
| 1816 | } | 1822 | } |
| 1817 | if (else_result) |inst| { | 1823 | if (else_result != 0) { |
| 1818 | if (!inst.tag.isNoReturn()) { | 1824 | if (!wzc.refIsNoReturn(else_result)) { |
| 1819 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .@"break", .{ | 1825 | _ = try else_scope.add(.{ |
| 1820 | .block = main_block, | 1826 | .tag = .@"break", |
| 1821 | .operand = inst, | 1827 | .data = .{ .@"break" = .{ |
| 1828 | .block_inst = main_block, | ||
| 1829 | .operand = else_result, | ||
| 1830 | } }, | ||
| 1822 | }); | 1831 | }); |
| 1823 | } | 1832 | } |
| 1824 | } else { | 1833 | } else { |
| 1825 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ | 1834 | _ = try else_scope.add(.{ |
| 1826 | .block = main_block, | 1835 | .tag = .break_void_node, |
| 1836 | .data = .{ .break_void_node = .{ | ||
| 1837 | .src_node = wzc.decl.nodeIndexToRelative(else_src), | ||
| 1838 | .block_inst = main_block, | ||
| 1839 | } }, | ||
| 1827 | }); | 1840 | }); |
| 1828 | } | 1841 | } |
| 1829 | if (strat.elide_store_to_block_ptr_instructions) { | 1842 | if (strat.elide_store_to_block_ptr_instructions) { |
| 1830 | try copyBodyWithElidedStoreBlockPtr(then_body, then_scope.*); | 1843 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope); |
| 1831 | try copyBodyWithElidedStoreBlockPtr(else_body, else_scope.*); | ||
| 1832 | } else { | 1844 | } else { |
| 1833 | try then_scope.setBlockBody(then_body); | 1845 | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 1834 | try else_scope.setBlockBody(else_body); | ||
| 1835 | } | 1846 | } |
| 1847 | const block_ref = wzc.ref_start_index + main_block; | ||
| 1836 | switch (rl) { | 1848 | switch (rl) { |
| 1837 | .ref => return &main_block.base, | 1849 | .ref => return block_ref, |
| 1838 | else => return rvalue(mod, parent_scope, rl, &main_block.base), | 1850 | else => return rvalue(mod, &block_scope.base, rl, block_ref, node), |
| 1839 | } | 1851 | } |
| 1840 | }, | 1852 | }, |
| 1841 | } | 1853 | } |
| ... | @@ -1951,18 +1963,18 @@ fn simpleBinOp( | ... | @@ -1951,18 +1963,18 @@ fn simpleBinOp( |
| 1951 | mod: *Module, | 1963 | mod: *Module, |
| 1952 | scope: *Scope, | 1964 | scope: *Scope, |
| 1953 | rl: ResultLoc, | 1965 | rl: ResultLoc, |
| 1954 | infix_node: ast.Node.Index, | 1966 | node: ast.Node.Index, |
| 1955 | op_inst_tag: zir.Inst.Tag, | 1967 | op_inst_tag: zir.Inst.Tag, |
| 1956 | ) InnerError!zir.Inst.Ref { | 1968 | ) InnerError!zir.Inst.Ref { |
| 1957 | const tree = scope.tree(); | 1969 | const gz = scope.getGenZir(); |
| 1970 | const tree = gz.tree(); | ||
| 1958 | const node_datas = tree.nodes.items(.data); | 1971 | const node_datas = tree.nodes.items(.data); |
| 1959 | 1972 | ||
| 1960 | const gz = scope.getGenZir(); | 1973 | const result = try gz.addPlNode(op_inst_tag, node, zir.Inst.Bin{ |
| 1961 | const result = try gz.addPlNode(op_inst_tag, infix_node, zir.Inst.Bin{ | 1974 | .lhs = try expr(mod, scope, .none, node_datas[node].lhs), |
| 1962 | .lhs = try expr(mod, scope, .none, node_datas[infix_node].lhs), | 1975 | .rhs = try expr(mod, scope, .none, node_datas[node].rhs), |
| 1963 | .rhs = try expr(mod, scope, .none, node_datas[infix_node].rhs), | ||
| 1964 | }); | 1976 | }); |
| 1965 | return rvalue(mod, scope, rl, result, infix_node); | 1977 | return rvalue(mod, scope, rl, result, node); |
| 1966 | } | 1978 | } |
| 1967 | 1979 | ||
| 1968 | fn boolBinOp( | 1980 | fn boolBinOp( |
| ... | @@ -2000,7 +2012,6 @@ fn ifExpr( | ... | @@ -2000,7 +2012,6 @@ fn ifExpr( |
| 2000 | node: ast.Node.Index, | 2012 | node: ast.Node.Index, |
| 2001 | if_full: ast.full.If, | 2013 | if_full: ast.full.If, |
| 2002 | ) InnerError!zir.Inst.Ref { | 2014 | ) InnerError!zir.Inst.Ref { |
| 2003 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 2004 | const parent_gz = scope.getGenZir(); | 2015 | const parent_gz = scope.getGenZir(); |
| 2005 | var block_scope: Scope.GenZir = .{ | 2016 | var block_scope: Scope.GenZir = .{ |
| 2006 | .parent = scope, | 2017 | .parent = scope, |
| ... | @@ -2011,8 +2022,6 @@ fn ifExpr( | ... | @@ -2011,8 +2022,6 @@ fn ifExpr( |
| 2011 | setBlockResultLoc(&block_scope, rl); | 2022 | setBlockResultLoc(&block_scope, rl); |
| 2012 | defer block_scope.instructions.deinit(mod.gpa); | 2023 | defer block_scope.instructions.deinit(mod.gpa); |
| 2013 | 2024 | ||
| 2014 | const tree = parent_gz.tree(); | ||
| 2015 | |||
| 2016 | const cond = c: { | 2025 | const cond = c: { |
| 2017 | // TODO https://github.com/ziglang/zig/issues/7929 | 2026 | // TODO https://github.com/ziglang/zig/issues/7929 |
| 2018 | if (if_full.error_token) |error_token| { | 2027 | if (if_full.error_token) |error_token| { |
| ... | @@ -2031,11 +2040,9 @@ fn ifExpr( | ... | @@ -2031,11 +2040,9 @@ fn ifExpr( |
| 2031 | try parent_gz.instructions.append(mod.gpa, block); | 2040 | try parent_gz.instructions.append(mod.gpa, block); |
| 2032 | try block_scope.setBlockBody(block); | 2041 | try block_scope.setBlockBody(block); |
| 2033 | 2042 | ||
| 2034 | const then_src = token_starts[tree.lastToken(if_full.ast.then_expr)]; | ||
| 2035 | var then_scope: Scope.GenZir = .{ | 2043 | var then_scope: Scope.GenZir = .{ |
| 2036 | .parent = scope, | 2044 | .parent = scope, |
| 2037 | .decl = block_scope.decl, | 2045 | .zir_code = parent_gz.zir_code, |
| 2038 | .arena = block_scope.arena, | ||
| 2039 | .force_comptime = block_scope.force_comptime, | 2046 | .force_comptime = block_scope.force_comptime, |
| 2040 | .instructions = .{}, | 2047 | .instructions = .{}, |
| 2041 | }; | 2048 | }; |
| ... | @@ -2052,36 +2059,38 @@ fn ifExpr( | ... | @@ -2052,36 +2059,38 @@ fn ifExpr( |
| 2052 | 2059 | ||
| 2053 | var else_scope: Scope.GenZir = .{ | 2060 | var else_scope: Scope.GenZir = .{ |
| 2054 | .parent = scope, | 2061 | .parent = scope, |
| 2055 | .decl = block_scope.decl, | 2062 | .zir_code = parent_gz.zir_code, |
| 2056 | .arena = block_scope.arena, | ||
| 2057 | .force_comptime = block_scope.force_comptime, | 2063 | .force_comptime = block_scope.force_comptime, |
| 2058 | .instructions = .{}, | 2064 | .instructions = .{}, |
| 2059 | }; | 2065 | }; |
| 2060 | defer else_scope.instructions.deinit(mod.gpa); | 2066 | defer else_scope.instructions.deinit(mod.gpa); |
| 2061 | 2067 | ||
| 2062 | const else_node = if_full.ast.else_expr; | 2068 | const else_node = if_full.ast.else_expr; |
| 2063 | const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: { | 2069 | const else_info: struct { |
| 2070 | src: ast.Node.Index, | ||
| 2071 | result: zir.Inst.Ref, | ||
| 2072 | } = if (else_node != 0) blk: { | ||
| 2064 | block_scope.break_count += 1; | 2073 | block_scope.break_count += 1; |
| 2065 | const sub_scope = &else_scope.base; | 2074 | const sub_scope = &else_scope.base; |
| 2066 | break :blk .{ | 2075 | break :blk .{ |
| 2067 | .src = token_starts[tree.lastToken(else_node)], | 2076 | .src = else_node, |
| 2068 | .result = try expr(mod, sub_scope, block_scope.break_result_loc, else_node), | 2077 | .result = try expr(mod, sub_scope, block_scope.break_result_loc, else_node), |
| 2069 | }; | 2078 | }; |
| 2070 | } else .{ | 2079 | } else .{ |
| 2071 | .src = token_starts[tree.lastToken(if_full.ast.then_expr)], | 2080 | .src = if_full.ast.then_expr, |
| 2072 | .result = null, | 2081 | .result = 0, |
| 2073 | }; | 2082 | }; |
| 2074 | 2083 | ||
| 2075 | return finishThenElseBlock( | 2084 | return finishThenElseBlock( |
| 2076 | mod, | 2085 | mod, |
| 2077 | scope, | ||
| 2078 | rl, | ||
| 2079 | &block_scope, | 2086 | &block_scope, |
| 2087 | rl, | ||
| 2088 | node, | ||
| 2080 | &then_scope, | 2089 | &then_scope, |
| 2081 | &else_scope, | 2090 | &else_scope, |
| 2082 | &condbr.positionals.then_body, | 2091 | condbr, |
| 2083 | &condbr.positionals.else_body, | 2092 | cond, |
| 2084 | then_src, | 2093 | if_full.ast.then_expr, |
| 2085 | else_info.src, | 2094 | else_info.src, |
| 2086 | then_result, | 2095 | then_result, |
| 2087 | else_info.result, | 2096 | else_info.result, |
| ... | @@ -2090,25 +2099,63 @@ fn ifExpr( | ... | @@ -2090,25 +2099,63 @@ fn ifExpr( |
| 2090 | ); | 2099 | ); |
| 2091 | } | 2100 | } |
| 2092 | 2101 | ||
| 2093 | /// Expects to find exactly 1 .store_to_block_ptr instruction. | 2102 | fn setCondBrPayload( |
| 2094 | fn copyBodyWithElidedStoreBlockPtr(body: *zir.Body, scope: Module.Scope.GenZir) !void { | 2103 | condbr: zir.Inst.Index, |
| 2095 | body.* = .{ | 2104 | cond: zir.Inst.Ref, |
| 2096 | .instructions = try scope.arena.alloc(zir.Inst.Ref, scope.instructions.items.len - 1), | 2105 | then_scope: *Scope.GenZir, |
| 2097 | }; | 2106 | else_scope: *Scope.GenZir, |
| 2098 | var dst_index: usize = 0; | 2107 | ) !void { |
| 2099 | for (scope.instructions.items) |src_inst| { | 2108 | const wzc = then_scope.zir_code; |
| 2100 | if (src_inst.tag != .store_to_block_ptr) { | 2109 | |
| 2101 | body.instructions[dst_index] = src_inst; | 2110 | try wzc.extra.ensureCapacity(wzc.gpa, wzc.extra.items.len + |
| 2102 | dst_index += 1; | 2111 | @typeInfo(zir.Inst.CondBr).Struct.fields.len + |
| 2112 | then_scope.instructions.items.len + else_scope.instructions.items.len); | ||
| 2113 | |||
| 2114 | const zir_datas = wzc.instructions.items(.data); | ||
| 2115 | zir_datas[condbr].pl_node.payload_index = wzc.addExtraAssumeCapacity(zir.Inst.CondBr{ | ||
| 2116 | .condition = cond, | ||
| 2117 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), | ||
| 2118 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), | ||
| 2119 | }); | ||
| 2120 | wzc.extra.appendSliceAssumeCapacity(then_scope.instructions.items); | ||
| 2121 | wzc.extra.appendSliceAssumeCapacity(else_scope.instructions.items); | ||
| 2122 | } | ||
| 2123 | |||
| 2124 | /// If `elide_block_store_ptr` is set, expects to find exactly 1 .store_to_block_ptr instruction. | ||
| 2125 | fn setCondBrPayloadElideBlockStorePtr( | ||
| 2126 | condbr: zir.Inst.Index, | ||
| 2127 | cond: zir.Inst.Ref, | ||
| 2128 | then_scope: *Scope.GenZir, | ||
| 2129 | else_scope: *Scope.GenZir, | ||
| 2130 | ) !void { | ||
| 2131 | const wzc = then_scope.zir_code; | ||
| 2132 | |||
| 2133 | try wzc.extra.ensureCapacity(wzc.gpa, wzc.extra.items.len + | ||
| 2134 | @typeInfo(zir.Inst.CondBr).Struct.fields.len + | ||
| 2135 | then_scope.instructions.items.len + else_scope.instructions.items.len - 2); | ||
| 2136 | |||
| 2137 | const zir_datas = wzc.instructions.items(.data); | ||
| 2138 | zir_datas[condbr].pl_node.payload_index = wzc.addExtraAssumeCapacity(zir.Inst.CondBr{ | ||
| 2139 | .condition = cond, | ||
| 2140 | .then_body_len = @intCast(u32, then_scope.instructions.items.len - 1), | ||
| 2141 | .else_body_len = @intCast(u32, else_scope.instructions.items.len - 1), | ||
| 2142 | }); | ||
| 2143 | |||
| 2144 | const zir_tags = wzc.instructions.items(.tag); | ||
| 2145 | for ([_]*Scope.GenZir{ then_scope, else_scope }) |scope| { | ||
| 2146 | for (scope.instructions.items) |src_inst| { | ||
| 2147 | if (zir_tags[src_inst] != .store_to_block_ptr) { | ||
| 2148 | wzc.extra.appendAssumeCapacity(src_inst); | ||
| 2149 | } | ||
| 2103 | } | 2150 | } |
| 2104 | } | 2151 | } |
| 2105 | assert(dst_index == body.instructions.len); | ||
| 2106 | } | 2152 | } |
| 2107 | 2153 | ||
| 2108 | fn whileExpr( | 2154 | fn whileExpr( |
| 2109 | mod: *Module, | 2155 | mod: *Module, |
| 2110 | scope: *Scope, | 2156 | scope: *Scope, |
| 2111 | rl: ResultLoc, | 2157 | rl: ResultLoc, |
| 2158 | node: ast.Node.Index, | ||
| 2112 | while_full: ast.full.While, | 2159 | while_full: ast.full.While, |
| 2113 | ) InnerError!zir.Inst.Ref { | 2160 | ) InnerError!zir.Inst.Ref { |
| 2114 | if (true) @panic("TODO update for zir-memory-layout"); | 2161 | if (true) @panic("TODO update for zir-memory-layout"); |
| ... | @@ -2245,13 +2292,13 @@ fn whileExpr( | ... | @@ -2245,13 +2292,13 @@ fn whileExpr( |
| 2245 | } | 2292 | } |
| 2246 | return finishThenElseBlock( | 2293 | return finishThenElseBlock( |
| 2247 | mod, | 2294 | mod, |
| 2248 | scope, | ||
| 2249 | rl, | ||
| 2250 | &loop_scope, | 2295 | &loop_scope, |
| 2296 | rl, | ||
| 2297 | node, | ||
| 2251 | &then_scope, | 2298 | &then_scope, |
| 2252 | &else_scope, | 2299 | &else_scope, |
| 2253 | &condbr.positionals.then_body, | 2300 | condbr, |
| 2254 | &condbr.positionals.else_body, | 2301 | cond, |
| 2255 | then_src, | 2302 | then_src, |
| 2256 | else_info.src, | 2303 | else_info.src, |
| 2257 | then_result, | 2304 | then_result, |
| ... | @@ -2265,6 +2312,7 @@ fn forExpr( | ... | @@ -2265,6 +2312,7 @@ fn forExpr( |
| 2265 | mod: *Module, | 2312 | mod: *Module, |
| 2266 | scope: *Scope, | 2313 | scope: *Scope, |
| 2267 | rl: ResultLoc, | 2314 | rl: ResultLoc, |
| 2315 | node: ast.Node.Index, | ||
| 2268 | for_full: ast.full.While, | 2316 | for_full: ast.full.While, |
| 2269 | ) InnerError!zir.Inst.Ref { | 2317 | ) InnerError!zir.Inst.Ref { |
| 2270 | if (true) @panic("TODO update for zir-memory-layout"); | 2318 | if (true) @panic("TODO update for zir-memory-layout"); |
| ... | @@ -2442,13 +2490,13 @@ fn forExpr( | ... | @@ -2442,13 +2490,13 @@ fn forExpr( |
| 2442 | } | 2490 | } |
| 2443 | return finishThenElseBlock( | 2491 | return finishThenElseBlock( |
| 2444 | mod, | 2492 | mod, |
| 2445 | scope, | ||
| 2446 | rl, | ||
| 2447 | &loop_scope, | 2493 | &loop_scope, |
| 2494 | rl, | ||
| 2495 | node, | ||
| 2448 | &then_scope, | 2496 | &then_scope, |
| 2449 | &else_scope, | 2497 | &else_scope, |
| 2450 | &condbr.positionals.then_body, | 2498 | condbr, |
| 2451 | &condbr.positionals.else_body, | 2499 | cond, |
| 2452 | then_src, | 2500 | then_src, |
| 2453 | else_info.src, | 2501 | else_info.src, |
| 2454 | then_result, | 2502 | then_result, |
src/zir.zig+99-24| ... | @@ -90,7 +90,7 @@ pub const Code = struct { | ... | @@ -90,7 +90,7 @@ pub const Code = struct { |
| 90 | .arena = &arena.allocator, | 90 | .arena = &arena.allocator, |
| 91 | .scope = scope, | 91 | .scope = scope, |
| 92 | .code = code, | 92 | .code = code, |
| 93 | .indent = 4, | 93 | .indent = 2, |
| 94 | .param_count = param_count, | 94 | .param_count = param_count, |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| ... | @@ -469,15 +469,13 @@ pub const Inst = struct { | ... | @@ -469,15 +469,13 @@ pub const Inst = struct { |
| 469 | /// Uses the `bool_br` union field. | 469 | /// Uses the `bool_br` union field. |
| 470 | bool_br_or, | 470 | bool_br_or, |
| 471 | /// Return a value from a block. | 471 | /// Return a value from a block. |
| 472 | /// Uses the `bin` union field: `lhs` is `Index` to the block (*not* `Ref`!), | 472 | /// Uses the `break` union field. |
| 473 | /// `rhs` is operand. | ||
| 474 | /// Uses the source information from previous instruction. | 473 | /// Uses the source information from previous instruction. |
| 475 | @"break", | 474 | @"break", |
| 476 | /// Same as `break` but has source information in the form of a token, and | 475 | /// Same as `break` but has source information in the form of an AST node, and |
| 477 | /// the operand is assumed to be the void value. | 476 | /// the operand is assumed to be the void value. |
| 478 | /// Uses the `un_tok` union field. | 477 | /// Uses the `break_void_node` union field. |
| 479 | /// Note that the block operand is a `Index`, not `Ref`. | 478 | break_void_node, |
| 480 | break_void_tok, | ||
| 481 | /// Return a value from a block. This is a special form that is only valid | 479 | /// Return a value from a block. This is a special form that is only valid |
| 482 | /// when there is exactly 1 break from a block (this one). This instruction | 480 | /// when there is exactly 1 break from a block (this one). This instruction |
| 483 | /// allows using the return value from `Sema.analyzeBody`. The block is | 481 | /// allows using the return value from `Sema.analyzeBody`. The block is |
| ... | @@ -997,7 +995,7 @@ pub const Inst = struct { | ... | @@ -997,7 +995,7 @@ pub const Inst = struct { |
| 997 | => false, | 995 | => false, |
| 998 | 996 | ||
| 999 | .@"break", | 997 | .@"break", |
| 1000 | .break_void_tok, | 998 | .break_void_node, |
| 1001 | .break_flat, | 999 | .break_flat, |
| 1002 | .condbr, | 1000 | .condbr, |
| 1003 | .compile_error, | 1001 | .compile_error, |
| ... | @@ -1023,10 +1021,9 @@ pub const Inst = struct { | ... | @@ -1023,10 +1021,9 @@ pub const Inst = struct { |
| 1023 | /// This logic is implemented in `Sema.resolveRef`. | 1021 | /// This logic is implemented in `Sema.resolveRef`. |
| 1024 | pub const Ref = u32; | 1022 | pub const Ref = u32; |
| 1025 | 1023 | ||
| 1026 | /// For instructions whose payload fits into 8 bytes, this is used. | 1024 | /// All instructions have an 8-byte payload, which is contained within |
| 1027 | /// When an instruction's payload does not fit, bin_op is used, and | 1025 | /// this union. `Tag` determines which union field is active, as well as |
| 1028 | /// lhs and rhs refer to `Tag`-specific values, with one of the operands | 1026 | /// how to interpret the data within. |
| 1029 | /// used to index into a separate array specific to that instruction. | ||
| 1030 | pub const Data = union { | 1027 | pub const Data = union { |
| 1031 | /// Used for unary operators, with an AST node source location. | 1028 | /// Used for unary operators, with an AST node source location. |
| 1032 | un_node: struct { | 1029 | un_node: struct { |
| ... | @@ -1161,6 +1158,20 @@ pub const Inst = struct { | ... | @@ -1161,6 +1158,20 @@ pub const Inst = struct { |
| 1161 | return .{ .node_offset = self.src_node }; | 1158 | return .{ .node_offset = self.src_node }; |
| 1162 | } | 1159 | } |
| 1163 | }, | 1160 | }, |
| 1161 | break_void_node: struct { | ||
| 1162 | /// Offset from Decl AST node index. | ||
| 1163 | /// `Tag` determines which kind of AST node this points to. | ||
| 1164 | src_node: i32, | ||
| 1165 | block_inst: Index, | ||
| 1166 | |||
| 1167 | pub fn src(self: @This()) LazySrcLoc { | ||
| 1168 | return .{ .node_offset = self.src_node }; | ||
| 1169 | } | ||
| 1170 | }, | ||
| 1171 | @"break": struct { | ||
| 1172 | block_inst: Index, | ||
| 1173 | operand: Ref, | ||
| 1174 | }, | ||
| 1164 | 1175 | ||
| 1165 | // Make sure we don't accidentally add a field to make this union | 1176 | // Make sure we don't accidentally add a field to make this union |
| 1166 | // bigger than expected. Note that in Debug builds, Zig is allowed | 1177 | // bigger than expected. Note that in Debug builds, Zig is allowed |
| ... | @@ -1368,7 +1379,6 @@ const Writer = struct { | ... | @@ -1368,7 +1379,6 @@ const Writer = struct { |
| 1368 | .break_flat, | 1379 | .break_flat, |
| 1369 | => try self.writeUnNode(stream, inst), | 1380 | => try self.writeUnNode(stream, inst), |
| 1370 | 1381 | ||
| 1371 | .break_void_tok, | ||
| 1372 | .is_non_null, | 1382 | .is_non_null, |
| 1373 | .is_null, | 1383 | .is_null, |
| 1374 | .is_non_null_ptr, | 1384 | .is_non_null_ptr, |
| ... | @@ -1394,16 +1404,11 @@ const Writer = struct { | ... | @@ -1394,16 +1404,11 @@ const Writer = struct { |
| 1394 | .int => try self.writeInt(stream, inst), | 1404 | .int => try self.writeInt(stream, inst), |
| 1395 | .str => try self.writeStr(stream, inst), | 1405 | .str => try self.writeStr(stream, inst), |
| 1396 | .elided => try stream.writeAll(")"), | 1406 | .elided => try stream.writeAll(")"), |
| 1407 | .break_void_node => try self.writeBreakVoidNode(stream, inst), | ||
| 1397 | 1408 | ||
| 1398 | .@"asm", | 1409 | .@"asm", |
| 1399 | .asm_volatile, | 1410 | .asm_volatile, |
| 1400 | .block, | ||
| 1401 | .block_comptime, | ||
| 1402 | .call, | ||
| 1403 | .call_chkused, | ||
| 1404 | .call_compile_time, | ||
| 1405 | .compile_log, | 1411 | .compile_log, |
| 1406 | .condbr, | ||
| 1407 | .elem_ptr_node, | 1412 | .elem_ptr_node, |
| 1408 | .elem_val_node, | 1413 | .elem_val_node, |
| 1409 | .field_ptr, | 1414 | .field_ptr, |
| ... | @@ -1441,6 +1446,17 @@ const Writer = struct { | ... | @@ -1441,6 +1446,17 @@ const Writer = struct { |
| 1441 | .xor, | 1446 | .xor, |
| 1442 | => try self.writePlNodeBin(stream, inst), | 1447 | => try self.writePlNodeBin(stream, inst), |
| 1443 | 1448 | ||
| 1449 | .call, | ||
| 1450 | .call_chkused, | ||
| 1451 | .call_compile_time, | ||
| 1452 | => try self.writePlNodeCall(stream, inst), | ||
| 1453 | |||
| 1454 | .block, | ||
| 1455 | .block_comptime, | ||
| 1456 | => try self.writePlNodeBlock(stream, inst), | ||
| 1457 | |||
| 1458 | .condbr => try self.writePlNodeCondBr(stream, inst), | ||
| 1459 | |||
| 1444 | .as_node => try self.writeAs(stream, inst), | 1460 | .as_node => try self.writeAs(stream, inst), |
| 1445 | 1461 | ||
| 1446 | .breakpoint, | 1462 | .breakpoint, |
| ... | @@ -1531,7 +1547,8 @@ const Writer = struct { | ... | @@ -1531,7 +1547,8 @@ const Writer = struct { |
| 1531 | inst: Inst.Index, | 1547 | inst: Inst.Index, |
| 1532 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | 1548 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { |
| 1533 | const inst_data = self.code.instructions.items(.data)[inst].param_type; | 1549 | const inst_data = self.code.instructions.items(.data)[inst].param_type; |
| 1534 | try stream.writeAll("TODO)"); | 1550 | try self.writeInstRef(stream, inst_data.callee); |
| 1551 | try stream.print(", {d})", .{inst_data.param_index}); | ||
| 1535 | } | 1552 | } |
| 1536 | 1553 | ||
| 1537 | fn writePtrTypeSimple( | 1554 | fn writePtrTypeSimple( |
| ... | @@ -1591,6 +1608,53 @@ const Writer = struct { | ... | @@ -1591,6 +1608,53 @@ const Writer = struct { |
| 1591 | try self.writeSrc(stream, inst_data.src()); | 1608 | try self.writeSrc(stream, inst_data.src()); |
| 1592 | } | 1609 | } |
| 1593 | 1610 | ||
| 1611 | fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void { | ||
| 1612 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | ||
| 1613 | const extra = self.code.extraData(Inst.Call, inst_data.payload_index); | ||
| 1614 | const args = self.code.extra[extra.end..][0..extra.data.args_len]; | ||
| 1615 | try self.writeInstRef(stream, extra.data.callee); | ||
| 1616 | try stream.writeAll(", ["); | ||
| 1617 | for (args) |arg, i| { | ||
| 1618 | if (i != 0) try stream.writeAll(", "); | ||
| 1619 | try self.writeInstRef(stream, arg); | ||
| 1620 | } | ||
| 1621 | try stream.writeAll("]) "); | ||
| 1622 | try self.writeSrc(stream, inst_data.src()); | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | fn writePlNodeBlock(self: *Writer, stream: anytype, inst: Inst.Index) !void { | ||
| 1626 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | ||
| 1627 | const extra = self.code.extraData(Inst.Block, inst_data.payload_index); | ||
| 1628 | const body = self.code.extra[extra.end..][0..extra.data.body_len]; | ||
| 1629 | try stream.writeAll("{\n"); | ||
| 1630 | self.indent += 2; | ||
| 1631 | try self.writeBody(stream, body); | ||
| 1632 | self.indent -= 2; | ||
| 1633 | try stream.writeByteNTimes(' ', self.indent); | ||
| 1634 | try stream.writeAll("}) "); | ||
| 1635 | try self.writeSrc(stream, inst_data.src()); | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | fn writePlNodeCondBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { | ||
| 1639 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | ||
| 1640 | const extra = self.code.extraData(Inst.CondBr, inst_data.payload_index); | ||
| 1641 | const then_body = self.code.extra[extra.end..][0..extra.data.then_body_len]; | ||
| 1642 | const else_body = self.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | ||
| 1643 | try self.writeInstRef(stream, extra.data.condition); | ||
| 1644 | try stream.writeAll(", {\n"); | ||
| 1645 | self.indent += 2; | ||
| 1646 | try self.writeBody(stream, then_body); | ||
| 1647 | self.indent -= 2; | ||
| 1648 | try stream.writeByteNTimes(' ', self.indent); | ||
| 1649 | try stream.writeAll("}, {\n"); | ||
| 1650 | self.indent += 2; | ||
| 1651 | try self.writeBody(stream, else_body); | ||
| 1652 | self.indent -= 2; | ||
| 1653 | try stream.writeByteNTimes(' ', self.indent); | ||
| 1654 | try stream.writeAll("}) "); | ||
| 1655 | try self.writeSrc(stream, inst_data.src()); | ||
| 1656 | } | ||
| 1657 | |||
| 1594 | fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 1658 | fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 1595 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 1659 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 1596 | const extra = self.code.extraData(Inst.As, inst_data.payload_index).data; | 1660 | const extra = self.code.extraData(Inst.As, inst_data.payload_index).data; |
| ... | @@ -1671,6 +1735,13 @@ const Writer = struct { | ... | @@ -1671,6 +1735,13 @@ const Writer = struct { |
| 1671 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); | 1735 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); |
| 1672 | } | 1736 | } |
| 1673 | 1737 | ||
| 1738 | fn writeBreakVoidNode(self: *Writer, stream: anytype, inst: Inst.Index) !void { | ||
| 1739 | const inst_data = self.code.instructions.items(.data)[inst].break_void_node; | ||
| 1740 | try self.writeInstIndex(stream, inst_data.block_inst); | ||
| 1741 | try stream.writeAll(") "); | ||
| 1742 | try self.writeSrc(stream, inst_data.src()); | ||
| 1743 | } | ||
| 1744 | |||
| 1674 | fn writeUnreachable(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 1745 | fn writeUnreachable(self: *Writer, stream: anytype, inst: Inst.Index) !void { |
| 1675 | const inst_data = self.code.instructions.items(.data)[inst].@"unreachable"; | 1746 | const inst_data = self.code.instructions.items(.data)[inst].@"unreachable"; |
| 1676 | const safety_str = if (inst_data.safety) "safe" else "unsafe"; | 1747 | const safety_str = if (inst_data.safety) "safe" else "unsafe"; |
| ... | @@ -1686,12 +1757,12 @@ const Writer = struct { | ... | @@ -1686,12 +1757,12 @@ const Writer = struct { |
| 1686 | var_args: bool, | 1757 | var_args: bool, |
| 1687 | cc: Inst.Ref, | 1758 | cc: Inst.Ref, |
| 1688 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { | 1759 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { |
| 1689 | try stream.writeAll("("); | 1760 | try stream.writeAll("["); |
| 1690 | for (param_types) |param_type, i| { | 1761 | for (param_types) |param_type, i| { |
| 1691 | if (i != 0) try stream.writeAll(", "); | 1762 | if (i != 0) try stream.writeAll(", "); |
| 1692 | try self.writeInstRef(stream, param_type); | 1763 | try self.writeInstRef(stream, param_type); |
| 1693 | } | 1764 | } |
| 1694 | try stream.writeAll("), "); | 1765 | try stream.writeAll("], "); |
| 1695 | try self.writeInstRef(stream, ret_ty); | 1766 | try self.writeInstRef(stream, ret_ty); |
| 1696 | try self.writeOptionalInstRef(stream, ", cc=", cc); | 1767 | try self.writeOptionalInstRef(stream, ", cc=", cc); |
| 1697 | try self.writeFlag(stream, ", var_args", var_args); | 1768 | try self.writeFlag(stream, ", var_args", var_args); |
| ... | @@ -1707,7 +1778,7 @@ const Writer = struct { | ... | @@ -1707,7 +1778,7 @@ const Writer = struct { |
| 1707 | try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)}); | 1778 | try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)}); |
| 1708 | } | 1779 | } |
| 1709 | 1780 | ||
| 1710 | fn writeInstRef(self: *Writer, stream: anytype, inst: Inst.Index) !void { | 1781 | fn writeInstRef(self: *Writer, stream: anytype, inst: Inst.Ref) !void { |
| 1711 | var i: usize = inst; | 1782 | var i: usize = inst; |
| 1712 | 1783 | ||
| 1713 | if (i < const_inst_list.len) { | 1784 | if (i < const_inst_list.len) { |
| ... | @@ -1720,7 +1791,11 @@ const Writer = struct { | ... | @@ -1720,7 +1791,11 @@ const Writer = struct { |
| 1720 | } | 1791 | } |
| 1721 | i -= self.param_count; | 1792 | i -= self.param_count; |
| 1722 | 1793 | ||
| 1723 | return stream.print("%{d}", .{i}); | 1794 | return self.writeInstIndex(stream, @intCast(Inst.Index, i)); |
| 1795 | } | ||
| 1796 | |||
| 1797 | fn writeInstIndex(self: *Writer, stream: anytype, inst: Inst.Index) !void { | ||
| 1798 | return stream.print("%{d}", .{inst}); | ||
| 1724 | } | 1799 | } |
| 1725 | 1800 | ||
| 1726 | fn writeOptionalInstRef( | 1801 | fn writeOptionalInstRef( |