| ... | @@ -309,7 +309,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr | ... | @@ -309,7 +309,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr |
| 309 | .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?), | 309 | .Catch => return catchExpr(mod, scope, rl, node.castTag(.Catch).?), |
| 310 | .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?), | 310 | .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?), |
| 311 | .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?), | 311 | .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?), |
| 312 | .Switch => return switchExpr(mod, scope, rl, node.castTag(.Switch).?), | 312 | .Switch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Switch", .{}), |
| 313 | .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?), | 313 | .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?), |
| 314 | | 314 | |
| 315 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), | 315 | .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}), |
| ... | @@ -334,11 +334,19 @@ fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.C | ... | @@ -334,11 +334,19 @@ fn comptimeKeyword(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.C |
| 334 | return comptimeExpr(mod, scope, rl, node.expr); | 334 | return comptimeExpr(mod, scope, rl, node.expr); |
| 335 | } | 335 | } |
| 336 | | 336 | |
| 337 | pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst { | 337 | pub fn comptimeExpr( |
| 338 | const tree = parent_scope.tree(); | 338 | mod: *Module, |
| 339 | const src = tree.token_locs[node.firstToken()].start; | 339 | parent_scope: *Scope, |
| | 340 | rl: ResultLoc, |
| | 341 | node: *ast.Node, |
| | 342 | ) InnerError!*zir.Inst { |
| | 343 | // If we are already in a comptime scope, no need to make another one. |
| | 344 | if (parent_scope.isComptime()) { |
| | 345 | return expr(mod, parent_scope, rl, node); |
| | 346 | } |
| 340 | | 347 | |
| 341 | // Optimization for labeled blocks: don't need to have 2 layers of blocks, we can reuse the existing one. | 348 | // Optimization for labeled blocks: don't need to have 2 layers of blocks, |
| | 349 | // we can reuse the existing one. |
| 342 | if (node.castTag(.LabeledBlock)) |block_node| { | 350 | if (node.castTag(.LabeledBlock)) |block_node| { |
| 343 | return labeledBlockExpr(mod, parent_scope, rl, block_node, .block_comptime); | 351 | return labeledBlockExpr(mod, parent_scope, rl, block_node, .block_comptime); |
| 344 | } | 352 | } |
| ... | @@ -348,6 +356,7 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as | ... | @@ -348,6 +356,7 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as |
| 348 | .parent = parent_scope, | 356 | .parent = parent_scope, |
| 349 | .decl = parent_scope.ownerDecl().?, | 357 | .decl = parent_scope.ownerDecl().?, |
| 350 | .arena = parent_scope.arena(), | 358 | .arena = parent_scope.arena(), |
| | 359 | .force_comptime = true, |
| 351 | .instructions = .{}, | 360 | .instructions = .{}, |
| 352 | }; | 361 | }; |
| 353 | defer block_scope.instructions.deinit(mod.gpa); | 362 | defer block_scope.instructions.deinit(mod.gpa); |
| ... | @@ -356,6 +365,9 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as | ... | @@ -356,6 +365,9 @@ pub fn comptimeExpr(mod: *Module, parent_scope: *Scope, rl: ResultLoc, node: *as |
| 356 | // instruction is the block's result value. | 365 | // instruction is the block's result value. |
| 357 | _ = try expr(mod, &block_scope.base, rl, node); | 366 | _ = try expr(mod, &block_scope.base, rl, node); |
| 358 | | 367 | |
| | 368 | const tree = parent_scope.tree(); |
| | 369 | const src = tree.token_locs[node.firstToken()].start; |
| | 370 | |
| 359 | const block = try addZIRInstBlock(mod, parent_scope, src, .block_comptime_flat, .{ | 371 | const block = try addZIRInstBlock(mod, parent_scope, src, .block_comptime_flat, .{ |
| 360 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), | 372 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), |
| 361 | }); | 373 | }); |
| ... | @@ -410,7 +422,7 @@ fn breakExpr( | ... | @@ -410,7 +422,7 @@ fn breakExpr( |
| 410 | try gen_zir.labeled_breaks.append(mod.gpa, br.castTag(.@"break").?); | 422 | try gen_zir.labeled_breaks.append(mod.gpa, br.castTag(.@"break").?); |
| 411 | | 423 | |
| 412 | if (have_store_to_block) { | 424 | if (have_store_to_block) { |
| 413 | const inst_list = parent_scope.cast(Scope.GenZIR).?.instructions.items; | 425 | const inst_list = parent_scope.getGenZIR().instructions.items; |
| 414 | const last_inst = inst_list[inst_list.len - 2]; | 426 | const last_inst = inst_list[inst_list.len - 2]; |
| 415 | const store_inst = last_inst.castTag(.store_to_block_ptr).?; | 427 | const store_inst = last_inst.castTag(.store_to_block_ptr).?; |
| 416 | assert(store_inst.positionals.lhs == gen_zir.rl_ptr.?); | 428 | assert(store_inst.positionals.lhs == gen_zir.rl_ptr.?); |
| ... | @@ -559,6 +571,7 @@ fn labeledBlockExpr( | ... | @@ -559,6 +571,7 @@ fn labeledBlockExpr( |
| 559 | .parent = parent_scope, | 571 | .parent = parent_scope, |
| 560 | .decl = parent_scope.ownerDecl().?, | 572 | .decl = parent_scope.ownerDecl().?, |
| 561 | .arena = gen_zir.arena, | 573 | .arena = gen_zir.arena, |
| | 574 | .force_comptime = parent_scope.isComptime(), |
| 562 | .instructions = .{}, | 575 | .instructions = .{}, |
| 563 | // TODO @as here is working around a stage1 miscompilation bug :( | 576 | // TODO @as here is working around a stage1 miscompilation bug :( |
| 564 | .label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{ | 577 | .label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{ |
| ... | @@ -746,6 +759,7 @@ fn varDecl( | ... | @@ -746,6 +759,7 @@ fn varDecl( |
| 746 | .parent = scope, | 759 | .parent = scope, |
| 747 | .decl = scope.ownerDecl().?, | 760 | .decl = scope.ownerDecl().?, |
| 748 | .arena = scope.arena(), | 761 | .arena = scope.arena(), |
| | 762 | .force_comptime = scope.isComptime(), |
| 749 | .instructions = .{}, | 763 | .instructions = .{}, |
| 750 | }; | 764 | }; |
| 751 | defer init_scope.instructions.deinit(mod.gpa); | 765 | defer init_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1107,6 +1121,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1107,6 +1121,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1107 | .parent = scope, | 1121 | .parent = scope, |
| 1108 | .decl = scope.ownerDecl().?, | 1122 | .decl = scope.ownerDecl().?, |
| 1109 | .arena = scope.arena(), | 1123 | .arena = scope.arena(), |
| | 1124 | .force_comptime = scope.isComptime(), |
| 1110 | .instructions = .{}, | 1125 | .instructions = .{}, |
| 1111 | }; | 1126 | }; |
| 1112 | defer gen_scope.instructions.deinit(mod.gpa); | 1127 | defer gen_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1343,6 +1358,7 @@ fn orelseCatchExpr( | ... | @@ -1343,6 +1358,7 @@ fn orelseCatchExpr( |
| 1343 | .parent = scope, | 1358 | .parent = scope, |
| 1344 | .decl = scope.ownerDecl().?, | 1359 | .decl = scope.ownerDecl().?, |
| 1345 | .arena = scope.arena(), | 1360 | .arena = scope.arena(), |
| | 1361 | .force_comptime = scope.isComptime(), |
| 1346 | .instructions = .{}, | 1362 | .instructions = .{}, |
| 1347 | }; | 1363 | }; |
| 1348 | setBlockResultLoc(&block_scope, rl); | 1364 | setBlockResultLoc(&block_scope, rl); |
| ... | @@ -1367,6 +1383,7 @@ fn orelseCatchExpr( | ... | @@ -1367,6 +1383,7 @@ fn orelseCatchExpr( |
| 1367 | .parent = &block_scope.base, | 1383 | .parent = &block_scope.base, |
| 1368 | .decl = block_scope.decl, | 1384 | .decl = block_scope.decl, |
| 1369 | .arena = block_scope.arena, | 1385 | .arena = block_scope.arena, |
| | 1386 | .force_comptime = block_scope.force_comptime, |
| 1370 | .instructions = .{}, | 1387 | .instructions = .{}, |
| 1371 | }; | 1388 | }; |
| 1372 | defer then_scope.instructions.deinit(mod.gpa); | 1389 | defer then_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1395,6 +1412,7 @@ fn orelseCatchExpr( | ... | @@ -1395,6 +1412,7 @@ fn orelseCatchExpr( |
| 1395 | .parent = &block_scope.base, | 1412 | .parent = &block_scope.base, |
| 1396 | .decl = block_scope.decl, | 1413 | .decl = block_scope.decl, |
| 1397 | .arena = block_scope.arena, | 1414 | .arena = block_scope.arena, |
| | 1415 | .force_comptime = block_scope.force_comptime, |
| 1398 | .instructions = .{}, | 1416 | .instructions = .{}, |
| 1399 | }; | 1417 | }; |
| 1400 | defer else_scope.instructions.deinit(mod.gpa); | 1418 | defer else_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1416,6 +1434,7 @@ fn orelseCatchExpr( | ... | @@ -1416,6 +1434,7 @@ fn orelseCatchExpr( |
| 1416 | then_result, | 1434 | then_result, |
| 1417 | unwrapped_payload, | 1435 | unwrapped_payload, |
| 1418 | block, | 1436 | block, |
| | 1437 | block, |
| 1419 | ); | 1438 | ); |
| 1420 | } | 1439 | } |
| 1421 | | 1440 | |
| ... | @@ -1432,7 +1451,8 @@ fn finishThenElseBlock( | ... | @@ -1432,7 +1451,8 @@ fn finishThenElseBlock( |
| 1432 | else_src: usize, | 1451 | else_src: usize, |
| 1433 | then_result: *zir.Inst, | 1452 | then_result: *zir.Inst, |
| 1434 | else_result: ?*zir.Inst, | 1453 | else_result: ?*zir.Inst, |
| 1435 | block: *zir.Inst.Block, | 1454 | main_block: *zir.Inst.Block, |
| | 1455 | then_break_block: *zir.Inst.Block, |
| 1436 | ) InnerError!*zir.Inst { | 1456 | ) InnerError!*zir.Inst { |
| 1437 | // We now have enough information to decide whether the result instruction should | 1457 | // We now have enough information to decide whether the result instruction should |
| 1438 | // be communicated via result location pointer or break instructions. | 1458 | // be communicated via result location pointer or break instructions. |
| ... | @@ -1441,42 +1461,42 @@ fn finishThenElseBlock( | ... | @@ -1441,42 +1461,42 @@ fn finishThenElseBlock( |
| 1441 | .break_void => { | 1461 | .break_void => { |
| 1442 | if (!then_result.tag.isNoReturn()) { | 1462 | if (!then_result.tag.isNoReturn()) { |
| 1443 | _ = try addZirInstTag(mod, &then_scope.base, then_src, .break_void, .{ | 1463 | _ = try addZirInstTag(mod, &then_scope.base, then_src, .break_void, .{ |
| 1444 | .block = block, | 1464 | .block = then_break_block, |
| 1445 | }); | 1465 | }); |
| 1446 | } | 1466 | } |
| 1447 | if (else_result) |inst| { | 1467 | if (else_result) |inst| { |
| 1448 | if (!inst.tag.isNoReturn()) { | 1468 | if (!inst.tag.isNoReturn()) { |
| 1449 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ | 1469 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ |
| 1450 | .block = block, | 1470 | .block = main_block, |
| 1451 | }); | 1471 | }); |
| 1452 | } | 1472 | } |
| 1453 | } else { | 1473 | } else { |
| 1454 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ | 1474 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ |
| 1455 | .block = block, | 1475 | .block = main_block, |
| 1456 | }); | 1476 | }); |
| 1457 | } | 1477 | } |
| 1458 | assert(!strat.elide_store_to_block_ptr_instructions); | 1478 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 1459 | try copyBodyNoEliding(then_body, then_scope.*); | 1479 | try copyBodyNoEliding(then_body, then_scope.*); |
| 1460 | try copyBodyNoEliding(else_body, else_scope.*); | 1480 | try copyBodyNoEliding(else_body, else_scope.*); |
| 1461 | return &block.base; | 1481 | return &main_block.base; |
| 1462 | }, | 1482 | }, |
| 1463 | .break_operand => { | 1483 | .break_operand => { |
| 1464 | if (!then_result.tag.isNoReturn()) { | 1484 | if (!then_result.tag.isNoReturn()) { |
| 1465 | _ = try addZirInstTag(mod, &then_scope.base, then_src, .@"break", .{ | 1485 | _ = try addZirInstTag(mod, &then_scope.base, then_src, .@"break", .{ |
| 1466 | .block = block, | 1486 | .block = then_break_block, |
| 1467 | .operand = then_result, | 1487 | .operand = then_result, |
| 1468 | }); | 1488 | }); |
| 1469 | } | 1489 | } |
| 1470 | if (else_result) |inst| { | 1490 | if (else_result) |inst| { |
| 1471 | if (!inst.tag.isNoReturn()) { | 1491 | if (!inst.tag.isNoReturn()) { |
| 1472 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .@"break", .{ | 1492 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .@"break", .{ |
| 1473 | .block = block, | 1493 | .block = main_block, |
| 1474 | .operand = inst, | 1494 | .operand = inst, |
| 1475 | }); | 1495 | }); |
| 1476 | } | 1496 | } |
| 1477 | } else { | 1497 | } else { |
| 1478 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ | 1498 | _ = try addZirInstTag(mod, &else_scope.base, else_src, .break_void, .{ |
| 1479 | .block = block, | 1499 | .block = main_block, |
| 1480 | }); | 1500 | }); |
| 1481 | } | 1501 | } |
| 1482 | if (strat.elide_store_to_block_ptr_instructions) { | 1502 | if (strat.elide_store_to_block_ptr_instructions) { |
| ... | @@ -1487,8 +1507,8 @@ fn finishThenElseBlock( | ... | @@ -1487,8 +1507,8 @@ fn finishThenElseBlock( |
| 1487 | try copyBodyNoEliding(else_body, else_scope.*); | 1507 | try copyBodyNoEliding(else_body, else_scope.*); |
| 1488 | } | 1508 | } |
| 1489 | switch (rl) { | 1509 | switch (rl) { |
| 1490 | .ref => return &block.base, | 1510 | .ref => return &main_block.base, |
| 1491 | else => return rvalue(mod, parent_scope, rl, &block.base), | 1511 | else => return rvalue(mod, parent_scope, rl, &main_block.base), |
| 1492 | } | 1512 | } |
| 1493 | }, | 1513 | }, |
| 1494 | } | 1514 | } |
| ... | @@ -1643,6 +1663,7 @@ fn boolBinOp( | ... | @@ -1643,6 +1663,7 @@ fn boolBinOp( |
| 1643 | .parent = scope, | 1663 | .parent = scope, |
| 1644 | .decl = scope.ownerDecl().?, | 1664 | .decl = scope.ownerDecl().?, |
| 1645 | .arena = scope.arena(), | 1665 | .arena = scope.arena(), |
| | 1666 | .force_comptime = scope.isComptime(), |
| 1646 | .instructions = .{}, | 1667 | .instructions = .{}, |
| 1647 | }; | 1668 | }; |
| 1648 | defer block_scope.instructions.deinit(mod.gpa); | 1669 | defer block_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1662,6 +1683,7 @@ fn boolBinOp( | ... | @@ -1662,6 +1683,7 @@ fn boolBinOp( |
| 1662 | .parent = scope, | 1683 | .parent = scope, |
| 1663 | .decl = block_scope.decl, | 1684 | .decl = block_scope.decl, |
| 1664 | .arena = block_scope.arena, | 1685 | .arena = block_scope.arena, |
| | 1686 | .force_comptime = block_scope.force_comptime, |
| 1665 | .instructions = .{}, | 1687 | .instructions = .{}, |
| 1666 | }; | 1688 | }; |
| 1667 | defer rhs_scope.instructions.deinit(mod.gpa); | 1689 | defer rhs_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1676,6 +1698,7 @@ fn boolBinOp( | ... | @@ -1676,6 +1698,7 @@ fn boolBinOp( |
| 1676 | .parent = scope, | 1698 | .parent = scope, |
| 1677 | .decl = block_scope.decl, | 1699 | .decl = block_scope.decl, |
| 1678 | .arena = block_scope.arena, | 1700 | .arena = block_scope.arena, |
| | 1701 | .force_comptime = block_scope.force_comptime, |
| 1679 | .instructions = .{}, | 1702 | .instructions = .{}, |
| 1680 | }; | 1703 | }; |
| 1681 | defer const_scope.instructions.deinit(mod.gpa); | 1704 | defer const_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1789,6 +1812,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -1789,6 +1812,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 1789 | .parent = scope, | 1812 | .parent = scope, |
| 1790 | .decl = scope.ownerDecl().?, | 1813 | .decl = scope.ownerDecl().?, |
| 1791 | .arena = scope.arena(), | 1814 | .arena = scope.arena(), |
| | 1815 | .force_comptime = scope.isComptime(), |
| 1792 | .instructions = .{}, | 1816 | .instructions = .{}, |
| 1793 | }; | 1817 | }; |
| 1794 | setBlockResultLoc(&block_scope, rl); | 1818 | setBlockResultLoc(&block_scope, rl); |
| ... | @@ -1813,6 +1837,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -1813,6 +1837,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 1813 | .parent = scope, | 1837 | .parent = scope, |
| 1814 | .decl = block_scope.decl, | 1838 | .decl = block_scope.decl, |
| 1815 | .arena = block_scope.arena, | 1839 | .arena = block_scope.arena, |
| | 1840 | .force_comptime = block_scope.force_comptime, |
| 1816 | .instructions = .{}, | 1841 | .instructions = .{}, |
| 1817 | }; | 1842 | }; |
| 1818 | defer then_scope.instructions.deinit(mod.gpa); | 1843 | defer then_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1830,6 +1855,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -1830,6 +1855,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 1830 | .parent = scope, | 1855 | .parent = scope, |
| 1831 | .decl = block_scope.decl, | 1856 | .decl = block_scope.decl, |
| 1832 | .arena = block_scope.arena, | 1857 | .arena = block_scope.arena, |
| | 1858 | .force_comptime = block_scope.force_comptime, |
| 1833 | .instructions = .{}, | 1859 | .instructions = .{}, |
| 1834 | }; | 1860 | }; |
| 1835 | defer else_scope.instructions.deinit(mod.gpa); | 1861 | defer else_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1863,6 +1889,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn | ... | @@ -1863,6 +1889,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn |
| 1863 | then_result, | 1889 | then_result, |
| 1864 | else_result, | 1890 | else_result, |
| 1865 | block, | 1891 | block, |
| | 1892 | block, |
| 1866 | ); | 1893 | ); |
| 1867 | } | 1894 | } |
| 1868 | | 1895 | |
| ... | @@ -1912,6 +1939,7 @@ fn whileExpr( | ... | @@ -1912,6 +1939,7 @@ fn whileExpr( |
| 1912 | .parent = scope, | 1939 | .parent = scope, |
| 1913 | .decl = scope.ownerDecl().?, | 1940 | .decl = scope.ownerDecl().?, |
| 1914 | .arena = scope.arena(), | 1941 | .arena = scope.arena(), |
| | 1942 | .force_comptime = scope.isComptime(), |
| 1915 | .instructions = .{}, | 1943 | .instructions = .{}, |
| 1916 | }; | 1944 | }; |
| 1917 | setBlockResultLoc(&loop_scope, rl); | 1945 | setBlockResultLoc(&loop_scope, rl); |
| ... | @@ -1921,6 +1949,7 @@ fn whileExpr( | ... | @@ -1921,6 +1949,7 @@ fn whileExpr( |
| 1921 | .parent = &loop_scope.base, | 1949 | .parent = &loop_scope.base, |
| 1922 | .decl = loop_scope.decl, | 1950 | .decl = loop_scope.decl, |
| 1923 | .arena = loop_scope.arena, | 1951 | .arena = loop_scope.arena, |
| | 1952 | .force_comptime = loop_scope.force_comptime, |
| 1924 | .instructions = .{}, | 1953 | .instructions = .{}, |
| 1925 | }; | 1954 | }; |
| 1926 | defer continue_scope.instructions.deinit(mod.gpa); | 1955 | defer continue_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1978,6 +2007,7 @@ fn whileExpr( | ... | @@ -1978,6 +2007,7 @@ fn whileExpr( |
| 1978 | .parent = &continue_scope.base, | 2007 | .parent = &continue_scope.base, |
| 1979 | .decl = continue_scope.decl, | 2008 | .decl = continue_scope.decl, |
| 1980 | .arena = continue_scope.arena, | 2009 | .arena = continue_scope.arena, |
| | 2010 | .force_comptime = continue_scope.force_comptime, |
| 1981 | .instructions = .{}, | 2011 | .instructions = .{}, |
| 1982 | }; | 2012 | }; |
| 1983 | defer then_scope.instructions.deinit(mod.gpa); | 2013 | defer then_scope.instructions.deinit(mod.gpa); |
| ... | @@ -1992,6 +2022,7 @@ fn whileExpr( | ... | @@ -1992,6 +2022,7 @@ fn whileExpr( |
| 1992 | .parent = &continue_scope.base, | 2022 | .parent = &continue_scope.base, |
| 1993 | .decl = continue_scope.decl, | 2023 | .decl = continue_scope.decl, |
| 1994 | .arena = continue_scope.arena, | 2024 | .arena = continue_scope.arena, |
| | 2025 | .force_comptime = continue_scope.force_comptime, |
| 1995 | .instructions = .{}, | 2026 | .instructions = .{}, |
| 1996 | }; | 2027 | }; |
| 1997 | defer else_scope.instructions.deinit(mod.gpa); | 2028 | defer else_scope.instructions.deinit(mod.gpa); |
| ... | @@ -2027,6 +2058,7 @@ fn whileExpr( | ... | @@ -2027,6 +2058,7 @@ fn whileExpr( |
| 2027 | then_result, | 2058 | then_result, |
| 2028 | else_result, | 2059 | else_result, |
| 2029 | while_block, | 2060 | while_block, |
| | 2061 | cond_block, |
| 2030 | ); | 2062 | ); |
| 2031 | } | 2063 | } |
| 2032 | | 2064 | |
| ... | @@ -2068,6 +2100,7 @@ fn forExpr( | ... | @@ -2068,6 +2100,7 @@ fn forExpr( |
| 2068 | .parent = scope, | 2100 | .parent = scope, |
| 2069 | .decl = scope.ownerDecl().?, | 2101 | .decl = scope.ownerDecl().?, |
| 2070 | .arena = scope.arena(), | 2102 | .arena = scope.arena(), |
| | 2103 | .force_comptime = scope.isComptime(), |
| 2071 | .instructions = .{}, | 2104 | .instructions = .{}, |
| 2072 | }; | 2105 | }; |
| 2073 | setBlockResultLoc(&loop_scope, rl); | 2106 | setBlockResultLoc(&loop_scope, rl); |
| ... | @@ -2077,6 +2110,7 @@ fn forExpr( | ... | @@ -2077,6 +2110,7 @@ fn forExpr( |
| 2077 | .parent = &loop_scope.base, | 2110 | .parent = &loop_scope.base, |
| 2078 | .decl = loop_scope.decl, | 2111 | .decl = loop_scope.decl, |
| 2079 | .arena = loop_scope.arena, | 2112 | .arena = loop_scope.arena, |
| | 2113 | .force_comptime = loop_scope.force_comptime, |
| 2080 | .instructions = .{}, | 2114 | .instructions = .{}, |
| 2081 | }; | 2115 | }; |
| 2082 | defer cond_scope.instructions.deinit(mod.gpa); | 2116 | defer cond_scope.instructions.deinit(mod.gpa); |
| ... | @@ -2134,6 +2168,7 @@ fn forExpr( | ... | @@ -2134,6 +2168,7 @@ fn forExpr( |
| 2134 | .parent = &cond_scope.base, | 2168 | .parent = &cond_scope.base, |
| 2135 | .decl = cond_scope.decl, | 2169 | .decl = cond_scope.decl, |
| 2136 | .arena = cond_scope.arena, | 2170 | .arena = cond_scope.arena, |
| | 2171 | .force_comptime = cond_scope.force_comptime, |
| 2137 | .instructions = .{}, | 2172 | .instructions = .{}, |
| 2138 | }; | 2173 | }; |
| 2139 | defer then_scope.instructions.deinit(mod.gpa); | 2174 | defer then_scope.instructions.deinit(mod.gpa); |
| ... | @@ -2174,6 +2209,7 @@ fn forExpr( | ... | @@ -2174,6 +2209,7 @@ fn forExpr( |
| 2174 | .parent = &cond_scope.base, | 2209 | .parent = &cond_scope.base, |
| 2175 | .decl = cond_scope.decl, | 2210 | .decl = cond_scope.decl, |
| 2176 | .arena = cond_scope.arena, | 2211 | .arena = cond_scope.arena, |
| | 2212 | .force_comptime = cond_scope.force_comptime, |
| 2177 | .instructions = .{}, | 2213 | .instructions = .{}, |
| 2178 | }; | 2214 | }; |
| 2179 | defer else_scope.instructions.deinit(mod.gpa); | 2215 | defer else_scope.instructions.deinit(mod.gpa); |
| ... | @@ -2206,281 +2242,10 @@ fn forExpr( | ... | @@ -2206,281 +2242,10 @@ fn forExpr( |
| 2206 | then_result, | 2242 | then_result, |
| 2207 | else_result, | 2243 | else_result, |
| 2208 | for_block, | 2244 | for_block, |
| | 2245 | cond_block, |
| 2209 | ); | 2246 | ); |
| 2210 | } | 2247 | } |
| 2211 | | 2248 | |
| 2212 | fn getRangeNode(node: *ast.Node) ?*ast.Node.SimpleInfixOp { | | |
| 2213 | var cur = node; | | |
| 2214 | while (true) { | | |
| 2215 | switch (cur.tag) { | | |
| 2216 | .Range => return @fieldParentPtr(ast.Node.SimpleInfixOp, "base", cur), | | |
| 2217 | .GroupedExpression => cur = @fieldParentPtr(ast.Node.GroupedExpression, "base", cur).expr, | | |
| 2218 | else => return null, | | |
| 2219 | } | | |
| 2220 | } | | |
| 2221 | } | | |
| 2222 | | | |
| 2223 | fn switchExpr(mod: *Module, scope: *Scope, rl: ResultLoc, switch_node: *ast.Node.Switch) InnerError!*zir.Inst { | | |
| 2224 | if (true) { | | |
| 2225 | @panic("TODO reimplement this"); | | |
| 2226 | } | | |
| 2227 | var block_scope: Scope.GenZIR = .{ | | |
| 2228 | .parent = scope, | | |
| 2229 | .decl = scope.ownerDecl().?, | | |
| 2230 | .arena = scope.arena(), | | |
| 2231 | .instructions = .{}, | | |
| 2232 | }; | | |
| 2233 | defer block_scope.instructions.deinit(mod.gpa); | | |
| 2234 | | | |
| 2235 | const tree = scope.tree(); | | |
| 2236 | const switch_src = tree.token_locs[switch_node.switch_token].start; | | |
| 2237 | const target_ptr = try expr(mod, &block_scope.base, .ref, switch_node.expr); | | |
| 2238 | const target = try addZIRUnOp(mod, &block_scope.base, target_ptr.src, .deref, target_ptr); | | |
| 2239 | // Add the switch instruction here so that it comes before any range checks. | | |
| 2240 | const switch_inst = (try addZIRInst(mod, &block_scope.base, switch_src, zir.Inst.SwitchBr, .{ | | |
| 2241 | .target_ptr = target_ptr, | | |
| 2242 | .cases = undefined, // populated below | | |
| 2243 | .items = &[_]*zir.Inst{}, // populated below | | |
| 2244 | .else_body = undefined, // populated below | | |
| 2245 | }, .{})).castTag(.switchbr).?; | | |
| 2246 | | | |
| 2247 | var items = std.ArrayList(*zir.Inst).init(mod.gpa); | | |
| 2248 | defer items.deinit(); | | |
| 2249 | var cases = std.ArrayList(zir.Inst.SwitchBr.Case).init(mod.gpa); | | |
| 2250 | defer cases.deinit(); | | |
| 2251 | | | |
| 2252 | // Add comptime block containing all prong items first, | | |
| 2253 | const item_block = try addZIRInstBlock(mod, scope, switch_src, .block_comptime_flat, .{ | | |
| 2254 | .instructions = undefined, // populated below | | |
| 2255 | }); | | |
| 2256 | // then add block containing the switch. | | |
| 2257 | const block = try addZIRInstBlock(mod, scope, switch_src, .block, .{ | | |
| 2258 | .instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items), | | |
| 2259 | }); | | |
| 2260 | | | |
| 2261 | // Most result location types can be forwarded directly; however | | |
| 2262 | // if we need to write to a pointer which has an inferred type, | | |
| 2263 | // proper type inference requires peer type resolution on the switch case. | | |
| 2264 | const case_rl: ResultLoc = switch (rl) { | | |
| 2265 | .discard, .none, .ty, .ptr, .ref => rl, | | |
| 2266 | .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block }, | | |
| 2267 | }; | | |
| 2268 | | | |
| 2269 | var item_scope: Scope.GenZIR = .{ | | |
| 2270 | .parent = scope, | | |
| 2271 | .decl = scope.ownerDecl().?, | | |
| 2272 | .arena = scope.arena(), | | |
| 2273 | .instructions = .{}, | | |
| 2274 | }; | | |
| 2275 | defer item_scope.instructions.deinit(mod.gpa); | | |
| 2276 | | | |
| 2277 | var case_scope: Scope.GenZIR = .{ | | |
| 2278 | .parent = scope, | | |
| 2279 | .decl = block_scope.decl, | | |
| 2280 | .arena = block_scope.arena, | | |
| 2281 | .instructions = .{}, | | |
| 2282 | }; | | |
| 2283 | defer case_scope.instructions.deinit(mod.gpa); | | |
| 2284 | | | |
| 2285 | var else_scope: Scope.GenZIR = .{ | | |
| 2286 | .parent = scope, | | |
| 2287 | .decl = block_scope.decl, | | |
| 2288 | .arena = block_scope.arena, | | |
| 2289 | .instructions = .{}, | | |
| 2290 | }; | | |
| 2291 | defer else_scope.instructions.deinit(mod.gpa); | | |
| 2292 | | | |
| 2293 | // first we gather all the switch items and check else/'_' prongs | | |
| 2294 | var else_src: ?usize = null; | | |
| 2295 | var underscore_src: ?usize = null; | | |
| 2296 | var first_range: ?*zir.Inst = null; | | |
| 2297 | var special_case: ?*ast.Node.SwitchCase = null; | | |
| 2298 | for (switch_node.cases()) |uncasted_case| { | | |
| 2299 | const case = uncasted_case.castTag(.SwitchCase).?; | | |
| 2300 | const case_src = tree.token_locs[case.firstToken()].start; | | |
| 2301 | // reset without freeing to reduce allocations. | | |
| 2302 | case_scope.instructions.items.len = 0; | | |
| 2303 | assert(case.items_len != 0); | | |
| 2304 | | | |
| 2305 | // Check for else/_ prong, those are handled last. | | |
| 2306 | if (case.items_len == 1 and case.items()[0].tag == .SwitchElse) { | | |
| 2307 | if (else_src) |src| { | | |
| 2308 | const msg = msg: { | | |
| 2309 | const msg = try mod.errMsg( | | |
| 2310 | scope, | | |
| 2311 | case_src, | | |
| 2312 | "multiple else prongs in switch expression", | | |
| 2313 | .{}, | | |
| 2314 | ); | | |
| 2315 | errdefer msg.destroy(mod.gpa); | | |
| 2316 | try mod.errNote(scope, src, msg, "previous else prong is here", .{}); | | |
| 2317 | break :msg msg; | | |
| 2318 | }; | | |
| 2319 | return mod.failWithOwnedErrorMsg(scope, msg); | | |
| 2320 | } | | |
| 2321 | else_src = case_src; | | |
| 2322 | special_case = case; | | |
| 2323 | continue; | | |
| 2324 | } else if (case.items_len == 1 and case.items()[0].tag == .Identifier and | | |
| 2325 | mem.eql(u8, tree.tokenSlice(case.items()[0].firstToken()), "_")) | | |
| 2326 | { | | |
| 2327 | if (underscore_src) |src| { | | |
| 2328 | const msg = msg: { | | |
| 2329 | const msg = try mod.errMsg( | | |
| 2330 | scope, | | |
| 2331 | case_src, | | |
| 2332 | "multiple '_' prongs in switch expression", | | |
| 2333 | .{}, | | |
| 2334 | ); | | |
| 2335 | errdefer msg.destroy(mod.gpa); | | |
| 2336 | try mod.errNote(scope, src, msg, "previous '_' prong is here", .{}); | | |
| 2337 | break :msg msg; | | |
| 2338 | }; | | |
| 2339 | return mod.failWithOwnedErrorMsg(scope, msg); | | |
| 2340 | } | | |
| 2341 | underscore_src = case_src; | | |
| 2342 | special_case = case; | | |
| 2343 | continue; | | |
| 2344 | } | | |
| 2345 | | | |
| 2346 | if (else_src) |some_else| { | | |
| 2347 | if (underscore_src) |some_underscore| { | | |
| 2348 | const msg = msg: { | | |
| 2349 | const msg = try mod.errMsg( | | |
| 2350 | scope, | | |
| 2351 | switch_src, | | |
| 2352 | "else and '_' prong in switch expression", | | |
| 2353 | .{}, | | |
| 2354 | ); | | |
| 2355 | errdefer msg.destroy(mod.gpa); | | |
| 2356 | try mod.errNote(scope, some_else, msg, "else prong is here", .{}); | | |
| 2357 | try mod.errNote(scope, some_underscore, msg, "'_' prong is here", .{}); | | |
| 2358 | break :msg msg; | | |
| 2359 | }; | | |
| 2360 | return mod.failWithOwnedErrorMsg(scope, msg); | | |
| 2361 | } | | |
| 2362 | } | | |
| 2363 | | | |
| 2364 | // If this is a simple one item prong then it is handled by the switchbr. | | |
| 2365 | if (case.items_len == 1 and getRangeNode(case.items()[0]) == null) { | | |
| 2366 | const item = try expr(mod, &item_scope.base, .none, case.items()[0]); | | |
| 2367 | try items.append(item); | | |
| 2368 | try switchCaseExpr(mod, &case_scope.base, case_rl, block, case); | | |
| 2369 | | | |
| 2370 | try cases.append(.{ | | |
| 2371 | .item = item, | | |
| 2372 | .body = .{ .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items) }, | | |
| 2373 | }); | | |
| 2374 | continue; | | |
| 2375 | } | | |
| 2376 | | | |
| 2377 | // TODO if the case has few items and no ranges it might be better | | |
| 2378 | // to just handle them as switch prongs. | | |
| 2379 | | | |
| 2380 | // Check if the target matches any of the items. | | |
| 2381 | // 1, 2, 3..6 will result in | | |
| 2382 | // target == 1 or target == 2 or (target >= 3 and target <= 6) | | |
| 2383 | var any_ok: ?*zir.Inst = null; | | |
| 2384 | for (case.items()) |item| { | | |
| 2385 | if (getRangeNode(item)) |range| { | | |
| 2386 | const start = try expr(mod, &item_scope.base, .none, range.lhs); | | |
| 2387 | const end = try expr(mod, &item_scope.base, .none, range.rhs); | | |
| 2388 | const range_src = tree.token_locs[range.op_token].start; | | |
| 2389 | const range_inst = try addZIRBinOp(mod, &item_scope.base, range_src, .switch_range, start, end); | | |
| 2390 | try items.append(range_inst); | | |
| 2391 | if (first_range == null) first_range = range_inst; | | |
| 2392 | | | |
| 2393 | // target >= start and target <= end | | |
| 2394 | const range_start_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .cmp_gte, target, start); | | |
| 2395 | const range_end_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .cmp_lte, target, end); | | |
| 2396 | const range_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .bool_and, range_start_ok, range_end_ok); | | |
| 2397 | | | |
| 2398 | if (any_ok) |some| { | | |
| 2399 | any_ok = try addZIRBinOp(mod, &else_scope.base, range_src, .bool_or, some, range_ok); | | |
| 2400 | } else { | | |
| 2401 | any_ok = range_ok; | | |
| 2402 | } | | |
| 2403 | continue; | | |
| 2404 | } | | |
| 2405 | | | |
| 2406 | const item_inst = try expr(mod, &item_scope.base, .none, item); | | |
| 2407 | try items.append(item_inst); | | |
| 2408 | const cpm_ok = try addZIRBinOp(mod, &else_scope.base, item_inst.src, .cmp_eq, target, item_inst); | | |
| 2409 | | | |
| 2410 | if (any_ok) |some| { | | |
| 2411 | any_ok = try addZIRBinOp(mod, &else_scope.base, item_inst.src, .bool_or, some, cpm_ok); | | |
| 2412 | } else { | | |
| 2413 | any_ok = cpm_ok; | | |
| 2414 | } | | |
| 2415 | } | | |
| 2416 | | | |
| 2417 | const condbr = try addZIRInstSpecial(mod, &case_scope.base, case_src, zir.Inst.CondBr, .{ | | |
| 2418 | .condition = any_ok.?, | | |
| 2419 | .then_body = undefined, // populated below | | |
| 2420 | .else_body = undefined, // populated below | | |
| 2421 | }, .{}); | | |
| 2422 | const cond_block = try addZIRInstBlock(mod, &else_scope.base, case_src, .block, .{ | | |
| 2423 | .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items), | | |
| 2424 | }); | | |
| 2425 | | | |
| 2426 | // reset cond_scope for then_body | | |
| 2427 | case_scope.instructions.items.len = 0; | | |
| 2428 | try switchCaseExpr(mod, &case_scope.base, case_rl, block, case); | | |
| 2429 | condbr.positionals.then_body = .{ | | |
| 2430 | .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items), | | |
| 2431 | }; | | |
| 2432 | | | |
| 2433 | // reset cond_scope for else_body | | |
| 2434 | case_scope.instructions.items.len = 0; | | |
| 2435 | _ = try addZIRInst(mod, &case_scope.base, case_src, zir.Inst.BreakVoid, .{ | | |
| 2436 | .block = cond_block, | | |
| 2437 | }, .{}); | | |
| 2438 | condbr.positionals.else_body = .{ | | |
| 2439 | .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items), | | |
| 2440 | }; | | |
| 2441 | } | | |
| 2442 | | | |
| 2443 | // Generate else block or a break last to finish the block. | | |
| 2444 | if (special_case) |case| { | | |
| 2445 | try switchCaseExpr(mod, &else_scope.base, case_rl, block, case); | | |
| 2446 | } else { | | |
| 2447 | // Not handling all possible cases is a compile error. | | |
| 2448 | _ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreachable_unsafe); | | |
| 2449 | } | | |
| 2450 | | | |
| 2451 | // All items have been generated, add the instructions to the comptime block. | | |
| 2452 | item_block.positionals.body = .{ | | |
| 2453 | .instructions = try block_scope.arena.dupe(*zir.Inst, item_scope.instructions.items), | | |
| 2454 | }; | | |
| 2455 | | | |
| 2456 | // Actually populate switch instruction values. | | |
| 2457 | if (else_src != null) switch_inst.kw_args.special_prong = .@"else"; | | |
| 2458 | if (underscore_src != null) switch_inst.kw_args.special_prong = .underscore; | | |
| 2459 | switch_inst.positionals.cases = try block_scope.arena.dupe(zir.Inst.SwitchBr.Case, cases.items); | | |
| 2460 | switch_inst.positionals.items = try block_scope.arena.dupe(*zir.Inst, items.items); | | |
| 2461 | switch_inst.kw_args.range = first_range; | | |
| 2462 | switch_inst.positionals.else_body = .{ | | |
| 2463 | .instructions = try block_scope.arena.dupe(*zir.Inst, else_scope.instructions.items), | | |
| 2464 | }; | | |
| 2465 | return &block.base; | | |
| 2466 | } | | |
| 2467 | | | |
| 2468 | fn switchCaseExpr(mod: *Module, scope: *Scope, rl: ResultLoc, block: *zir.Inst.Block, case: *ast.Node.SwitchCase) !void { | | |
| 2469 | const tree = scope.tree(); | | |
| 2470 | const case_src = tree.token_locs[case.firstToken()].start; | | |
| 2471 | if (case.payload != null) { | | |
| 2472 | return mod.fail(scope, case_src, "TODO switch case payload capture", .{}); | | |
| 2473 | } | | |
| 2474 | | | |
| 2475 | const case_body = try expr(mod, scope, rl, case.expr); | | |
| 2476 | if (!case_body.tag.isNoReturn()) { | | |
| 2477 | _ = try addZIRInst(mod, scope, case_src, zir.Inst.Break, .{ | | |
| 2478 | .block = block, | | |
| 2479 | .operand = case_body, | | |
| 2480 | }, .{}); | | |
| 2481 | } | | |
| 2482 | } | | |
| 2483 | | | |
| 2484 | fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst { | 2249 | fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst { |
| 2485 | const tree = scope.tree(); | 2250 | const tree = scope.tree(); |
| 2486 | const src = tree.token_locs[cfe.ltoken].start; | 2251 | const src = tree.token_locs[cfe.ltoken].start; |
| ... | @@ -2859,6 +2624,7 @@ fn asRlPtr( | ... | @@ -2859,6 +2624,7 @@ fn asRlPtr( |
| 2859 | .parent = scope, | 2624 | .parent = scope, |
| 2860 | .decl = scope.ownerDecl().?, | 2625 | .decl = scope.ownerDecl().?, |
| 2861 | .arena = scope.arena(), | 2626 | .arena = scope.arena(), |
| | 2627 | .force_comptime = scope.isComptime(), |
| 2862 | .instructions = .{}, | 2628 | .instructions = .{}, |
| 2863 | }; | 2629 | }; |
| 2864 | defer as_scope.instructions.deinit(mod.gpa); | 2630 | defer as_scope.instructions.deinit(mod.gpa); |