| author | |
| committer | |
| log | b494f6a9dc078c55aea4b27306178084cccb36a8 |
| tree | 8e723d7091f143158e0c63a7c9382328e3d6d589 |
| parent | 7748d2bb44dabbf60bfd7f65b1c5e2ebf0b49207 |
Stage2 bug fixes17 files changed, 329 insertions(+), 65 deletions(-)
src/AstGen.zig+156-34| ... | @@ -339,6 +339,8 @@ pub const ResultInfo = struct { | ... | @@ -339,6 +339,8 @@ pub const ResultInfo = struct { |
| 339 | fn_arg, | 339 | fn_arg, |
| 340 | /// The expression is the right-hand side of an initializer for a `const` variable | 340 | /// The expression is the right-hand side of an initializer for a `const` variable |
| 341 | const_init, | 341 | const_init, |
| 342 | /// The expression is the right-hand side of an assignment expression. | ||
| 343 | assignment, | ||
| 342 | /// No specific operator in particular. | 344 | /// No specific operator in particular. |
| 343 | none, | 345 | none, |
| 344 | }; | 346 | }; |
| ... | @@ -826,7 +828,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -826,7 +828,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 826 | 828 | ||
| 827 | .slice_open => { | 829 | .slice_open => { |
| 828 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | 830 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 831 | |||
| 832 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 833 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 834 | const column = gz.astgen.source_column; | ||
| 835 | |||
| 829 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); | 836 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); |
| 837 | try emitDbgStmt(gz, line, column); | ||
| 830 | const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{ | 838 | const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{ |
| 831 | .lhs = lhs, | 839 | .lhs = lhs, |
| 832 | .start = start, | 840 | .start = start, |
| ... | @@ -835,9 +843,15 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -835,9 +843,15 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 835 | }, | 843 | }, |
| 836 | .slice => { | 844 | .slice => { |
| 837 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | 845 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 846 | |||
| 847 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 848 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 849 | const column = gz.astgen.source_column; | ||
| 850 | |||
| 838 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); | 851 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); |
| 839 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); | 852 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); |
| 840 | const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end); | 853 | const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end); |
| 854 | try emitDbgStmt(gz, line, column); | ||
| 841 | const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{ | 855 | const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{ |
| 842 | .lhs = lhs, | 856 | .lhs = lhs, |
| 843 | .start = start, | 857 | .start = start, |
| ... | @@ -847,10 +861,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -847,10 +861,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 847 | }, | 861 | }, |
| 848 | .slice_sentinel => { | 862 | .slice_sentinel => { |
| 849 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | 863 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 864 | |||
| 865 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 866 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 867 | const column = gz.astgen.source_column; | ||
| 868 | |||
| 850 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); | 869 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); |
| 851 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); | 870 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start); |
| 852 | const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none; | 871 | const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none; |
| 853 | const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel); | 872 | const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel); |
| 873 | try emitDbgStmt(gz, line, column); | ||
| 854 | const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{ | 874 | const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{ |
| 855 | .lhs = lhs, | 875 | .lhs = lhs, |
| 856 | .start = start, | 876 | .start = start, |
| ... | @@ -881,16 +901,26 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE | ... | @@ -881,16 +901,26 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 881 | return rvalue(gz, ri, result, node); | 901 | return rvalue(gz, ri, result, node); |
| 882 | }, | 902 | }, |
| 883 | .unwrap_optional => switch (ri.rl) { | 903 | .unwrap_optional => switch (ri.rl) { |
| 884 | .ref => return gz.addUnNode( | 904 | .ref => { |
| 885 | .optional_payload_safe_ptr, | 905 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 886 | try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs), | 906 | |
| 887 | node, | 907 | maybeAdvanceSourceCursorToMainToken(gz, node); |
| 888 | ), | 908 | const line = gz.astgen.source_line - gz.decl_line; |
| 889 | else => return rvalue(gz, ri, try gz.addUnNode( | 909 | const column = gz.astgen.source_column; |
| 890 | .optional_payload_safe, | 910 | try emitDbgStmt(gz, line, column); |
| 891 | try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), | 911 | |
| 892 | node, | 912 | return gz.addUnNode(.optional_payload_safe_ptr, lhs, node); |
| 893 | ), node), | 913 | }, |
| 914 | else => { | ||
| 915 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | ||
| 916 | |||
| 917 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 918 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 919 | const column = gz.astgen.source_column; | ||
| 920 | try emitDbgStmt(gz, line, column); | ||
| 921 | |||
| 922 | return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node); | ||
| 923 | }, | ||
| 894 | }, | 924 | }, |
| 895 | .block_two, .block_two_semicolon => { | 925 | .block_two, .block_two_semicolon => { |
| 896 | const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; | 926 | const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; |
| ... | @@ -3216,7 +3246,7 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi | ... | @@ -3216,7 +3246,7 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi |
| 3216 | // This intentionally does not support `@"_"` syntax. | 3246 | // This intentionally does not support `@"_"` syntax. |
| 3217 | const ident_name = tree.tokenSlice(main_tokens[lhs]); | 3247 | const ident_name = tree.tokenSlice(main_tokens[lhs]); |
| 3218 | if (mem.eql(u8, ident_name, "_")) { | 3248 | if (mem.eql(u8, ident_name, "_")) { |
| 3219 | _ = try expr(gz, scope, .{ .rl = .discard }, rhs); | 3249 | _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs); |
| 3220 | return; | 3250 | return; |
| 3221 | } | 3251 | } |
| 3222 | } | 3252 | } |
| ... | @@ -3239,10 +3269,27 @@ fn assignOp( | ... | @@ -3239,10 +3269,27 @@ fn assignOp( |
| 3239 | const node_datas = tree.nodes.items(.data); | 3269 | const node_datas = tree.nodes.items(.data); |
| 3240 | 3270 | ||
| 3241 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | 3271 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| 3272 | |||
| 3273 | var line: u32 = undefined; | ||
| 3274 | var column: u32 = undefined; | ||
| 3275 | switch (op_inst_tag) { | ||
| 3276 | .add, .sub, .mul, .div, .mod_rem => { | ||
| 3277 | maybeAdvanceSourceCursorToMainToken(gz, infix_node); | ||
| 3278 | line = gz.astgen.source_line - gz.decl_line; | ||
| 3279 | column = gz.astgen.source_column; | ||
| 3280 | }, | ||
| 3281 | else => {}, | ||
| 3282 | } | ||
| 3242 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); | 3283 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3243 | const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node); | 3284 | const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node); |
| 3244 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs); | 3285 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs); |
| 3245 | 3286 | ||
| 3287 | switch (op_inst_tag) { | ||
| 3288 | .add, .sub, .mul, .div, .mod_rem => { | ||
| 3289 | try emitDbgStmt(gz, line, column); | ||
| 3290 | }, | ||
| 3291 | else => {}, | ||
| 3292 | } | ||
| 3246 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ | 3293 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ |
| 3247 | .lhs = lhs, | 3294 | .lhs = lhs, |
| 3248 | .rhs = rhs, | 3295 | .rhs = rhs, |
| ... | @@ -5294,9 +5341,11 @@ fn orelseCatchExpr( | ... | @@ -5294,9 +5341,11 @@ fn orelseCatchExpr( |
| 5294 | // up for this fact by calling rvalue on the else branch. | 5341 | // up for this fact by calling rvalue on the else branch. |
| 5295 | const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs); | 5342 | const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs); |
| 5296 | const cond = try block_scope.addUnNode(cond_op, operand, node); | 5343 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 5297 | const condbr = try block_scope.addCondBr(.condbr, node); | 5344 | const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr; |
| 5345 | const condbr = try block_scope.addCondBr(condbr_tag, node); | ||
| 5298 | 5346 | ||
| 5299 | const block = try parent_gz.makeBlockInst(.block, node); | 5347 | const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block; |
| 5348 | const block = try parent_gz.makeBlockInst(block_tag, node); | ||
| 5300 | try block_scope.setBlockBody(block); | 5349 | try block_scope.setBlockBody(block); |
| 5301 | // block_scope unstacked now, can add new instructions to parent_gz | 5350 | // block_scope unstacked now, can add new instructions to parent_gz |
| 5302 | try parent_gz.instructions.append(astgen.gpa, block); | 5351 | try parent_gz.instructions.append(astgen.gpa, block); |
| ... | @@ -5471,9 +5520,15 @@ fn addFieldAccess( | ... | @@ -5471,9 +5520,15 @@ fn addFieldAccess( |
| 5471 | const dot_token = main_tokens[node]; | 5520 | const dot_token = main_tokens[node]; |
| 5472 | const field_ident = dot_token + 1; | 5521 | const field_ident = dot_token + 1; |
| 5473 | const str_index = try astgen.identAsString(field_ident); | 5522 | const str_index = try astgen.identAsString(field_ident); |
| 5523 | const lhs = try expr(gz, scope, lhs_ri, object_node); | ||
| 5524 | |||
| 5525 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 5526 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 5527 | const column = gz.astgen.source_column; | ||
| 5528 | try emitDbgStmt(gz, line, column); | ||
| 5474 | 5529 | ||
| 5475 | return gz.addPlNode(tag, node, Zir.Inst.Field{ | 5530 | return gz.addPlNode(tag, node, Zir.Inst.Field{ |
| 5476 | .lhs = try expr(gz, scope, lhs_ri, object_node), | 5531 | .lhs = lhs, |
| 5477 | .field_name_start = str_index, | 5532 | .field_name_start = str_index, |
| 5478 | }); | 5533 | }); |
| 5479 | } | 5534 | } |
| ... | @@ -5484,18 +5539,33 @@ fn arrayAccess( | ... | @@ -5484,18 +5539,33 @@ fn arrayAccess( |
| 5484 | ri: ResultInfo, | 5539 | ri: ResultInfo, |
| 5485 | node: Ast.Node.Index, | 5540 | node: Ast.Node.Index, |
| 5486 | ) InnerError!Zir.Inst.Ref { | 5541 | ) InnerError!Zir.Inst.Ref { |
| 5487 | const astgen = gz.astgen; | 5542 | const tree = gz.astgen.tree; |
| 5488 | const tree = astgen.tree; | ||
| 5489 | const node_datas = tree.nodes.items(.data); | 5543 | const node_datas = tree.nodes.items(.data); |
| 5490 | switch (ri.rl) { | 5544 | switch (ri.rl) { |
| 5491 | .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ | 5545 | .ref => { |
| 5492 | .lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs), | 5546 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 5493 | .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs), | 5547 | |
| 5494 | }), | 5548 | maybeAdvanceSourceCursorToMainToken(gz, node); |
| 5495 | else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ | 5549 | const line = gz.astgen.source_line - gz.decl_line; |
| 5496 | .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), | 5550 | const column = gz.astgen.source_column; |
| 5497 | .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs), | 5551 | |
| 5498 | }), node), | 5552 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs); |
| 5553 | try emitDbgStmt(gz, line, column); | ||
| 5554 | |||
| 5555 | return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); | ||
| 5556 | }, | ||
| 5557 | else => { | ||
| 5558 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | ||
| 5559 | |||
| 5560 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 5561 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 5562 | const column = gz.astgen.source_column; | ||
| 5563 | |||
| 5564 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs); | ||
| 5565 | try emitDbgStmt(gz, line, column); | ||
| 5566 | |||
| 5567 | return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node); | ||
| 5568 | }, | ||
| 5499 | } | 5569 | } |
| 5500 | } | 5570 | } |
| 5501 | 5571 | ||
| ... | @@ -5510,10 +5580,26 @@ fn simpleBinOp( | ... | @@ -5510,10 +5580,26 @@ fn simpleBinOp( |
| 5510 | const tree = astgen.tree; | 5580 | const tree = astgen.tree; |
| 5511 | const node_datas = tree.nodes.items(.data); | 5581 | const node_datas = tree.nodes.items(.data); |
| 5512 | 5582 | ||
| 5513 | const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ | 5583 | const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node); |
| 5514 | .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node), | 5584 | var line: u32 = undefined; |
| 5515 | .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node), | 5585 | var column: u32 = undefined; |
| 5516 | }); | 5586 | switch (op_inst_tag) { |
| 5587 | .add, .sub, .mul, .div, .mod_rem => { | ||
| 5588 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 5589 | line = gz.astgen.source_line - gz.decl_line; | ||
| 5590 | column = gz.astgen.source_column; | ||
| 5591 | }, | ||
| 5592 | else => {}, | ||
| 5593 | } | ||
| 5594 | const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node); | ||
| 5595 | |||
| 5596 | switch (op_inst_tag) { | ||
| 5597 | .add, .sub, .mul, .div, .mod_rem => { | ||
| 5598 | try emitDbgStmt(gz, line, column); | ||
| 5599 | }, | ||
| 5600 | else => {}, | ||
| 5601 | } | ||
| 5602 | const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); | ||
| 5517 | return rvalue(gz, ri, result, node); | 5603 | return rvalue(gz, ri, result, node); |
| 5518 | } | 5604 | } |
| 5519 | 5605 | ||
| ... | @@ -5608,9 +5694,11 @@ fn ifExpr( | ... | @@ -5608,9 +5694,11 @@ fn ifExpr( |
| 5608 | } | 5694 | } |
| 5609 | }; | 5695 | }; |
| 5610 | 5696 | ||
| 5611 | const condbr = try block_scope.addCondBr(.condbr, node); | 5697 | const condbr_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .condbr_inline else .condbr; |
| 5698 | const condbr = try block_scope.addCondBr(condbr_tag, node); | ||
| 5612 | 5699 | ||
| 5613 | const block = try parent_gz.makeBlockInst(.block, node); | 5700 | const block_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .block_inline else .block; |
| 5701 | const block = try parent_gz.makeBlockInst(block_tag, node); | ||
| 5614 | try block_scope.setBlockBody(block); | 5702 | try block_scope.setBlockBody(block); |
| 5615 | // block_scope unstacked now, can add new instructions to parent_gz | 5703 | // block_scope unstacked now, can add new instructions to parent_gz |
| 5616 | try parent_gz.instructions.append(astgen.gpa, block); | 5704 | try parent_gz.instructions.append(astgen.gpa, block); |
| ... | @@ -7084,7 +7172,7 @@ fn localVarRef( | ... | @@ -7084,7 +7172,7 @@ fn localVarRef( |
| 7084 | if (local_val.name == name_str_index) { | 7172 | if (local_val.name == name_str_index) { |
| 7085 | // Locals cannot shadow anything, so we do not need to look for ambiguous | 7173 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 7086 | // references in this case. | 7174 | // references in this case. |
| 7087 | if (ri.rl == .discard) { | 7175 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 7088 | local_val.discarded = ident_token; | 7176 | local_val.discarded = ident_token; |
| 7089 | } else { | 7177 | } else { |
| 7090 | local_val.used = ident_token; | 7178 | local_val.used = ident_token; |
| ... | @@ -7107,7 +7195,7 @@ fn localVarRef( | ... | @@ -7107,7 +7195,7 @@ fn localVarRef( |
| 7107 | .local_ptr => { | 7195 | .local_ptr => { |
| 7108 | const local_ptr = s.cast(Scope.LocalPtr).?; | 7196 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 7109 | if (local_ptr.name == name_str_index) { | 7197 | if (local_ptr.name == name_str_index) { |
| 7110 | if (ri.rl == .discard) { | 7198 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 7111 | local_ptr.discarded = ident_token; | 7199 | local_ptr.discarded = ident_token; |
| 7112 | } else { | 7200 | } else { |
| 7113 | local_ptr.used = ident_token; | 7201 | local_ptr.used = ident_token; |
| ... | @@ -7969,6 +8057,8 @@ fn builtinCall( | ... | @@ -7969,6 +8057,8 @@ fn builtinCall( |
| 7969 | return rvalue(gz, ri, result, node); | 8057 | return rvalue(gz, ri, result, node); |
| 7970 | }, | 8058 | }, |
| 7971 | .err_set_cast => { | 8059 | .err_set_cast => { |
| 8060 | try emitDbgNode(gz, node); | ||
| 8061 | |||
| 7972 | const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ | 8062 | const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ |
| 7973 | .lhs = try typeExpr(gz, scope, params[0]), | 8063 | .lhs = try typeExpr(gz, scope, params[0]), |
| 7974 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), | 8064 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| ... | @@ -8274,6 +8364,8 @@ fn typeCast( | ... | @@ -8274,6 +8364,8 @@ fn typeCast( |
| 8274 | rhs_node: Ast.Node.Index, | 8364 | rhs_node: Ast.Node.Index, |
| 8275 | tag: Zir.Inst.Tag, | 8365 | tag: Zir.Inst.Tag, |
| 8276 | ) InnerError!Zir.Inst.Ref { | 8366 | ) InnerError!Zir.Inst.Ref { |
| 8367 | try emitDbgNode(gz, node); | ||
| 8368 | |||
| 8277 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ | 8369 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8278 | .lhs = try typeExpr(gz, scope, lhs_node), | 8370 | .lhs = try typeExpr(gz, scope, lhs_node), |
| 8279 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), | 8371 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), |
| ... | @@ -8303,6 +8395,10 @@ fn simpleUnOp( | ... | @@ -8303,6 +8395,10 @@ fn simpleUnOp( |
| 8303 | operand_node: Ast.Node.Index, | 8395 | operand_node: Ast.Node.Index, |
| 8304 | tag: Zir.Inst.Tag, | 8396 | tag: Zir.Inst.Tag, |
| 8305 | ) InnerError!Zir.Inst.Ref { | 8397 | ) InnerError!Zir.Inst.Ref { |
| 8398 | switch (tag) { | ||
| 8399 | .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node), | ||
| 8400 | else => {}, | ||
| 8401 | } | ||
| 8306 | const operand = try expr(gz, scope, operand_ri, operand_node); | 8402 | const operand = try expr(gz, scope, operand_ri, operand_node); |
| 8307 | const result = try gz.addUnNode(tag, operand, node); | 8403 | const result = try gz.addUnNode(tag, operand, node); |
| 8308 | return rvalue(gz, ri, result, node); | 8404 | return rvalue(gz, ri, result, node); |
| ... | @@ -8375,6 +8471,8 @@ fn divBuiltin( | ... | @@ -8375,6 +8471,8 @@ fn divBuiltin( |
| 8375 | rhs_node: Ast.Node.Index, | 8471 | rhs_node: Ast.Node.Index, |
| 8376 | tag: Zir.Inst.Tag, | 8472 | tag: Zir.Inst.Tag, |
| 8377 | ) InnerError!Zir.Inst.Ref { | 8473 | ) InnerError!Zir.Inst.Ref { |
| 8474 | try emitDbgNode(gz, node); | ||
| 8475 | |||
| 8378 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ | 8476 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8379 | .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node), | 8477 | .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node), |
| 8380 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), | 8478 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), |
| ... | @@ -8428,8 +8526,15 @@ fn shiftOp( | ... | @@ -8428,8 +8526,15 @@ fn shiftOp( |
| 8428 | tag: Zir.Inst.Tag, | 8526 | tag: Zir.Inst.Tag, |
| 8429 | ) InnerError!Zir.Inst.Ref { | 8527 | ) InnerError!Zir.Inst.Ref { |
| 8430 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); | 8528 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); |
| 8529 | |||
| 8530 | maybeAdvanceSourceCursorToMainToken(gz, node); | ||
| 8531 | const line = gz.astgen.source_line - gz.decl_line; | ||
| 8532 | const column = gz.astgen.source_column; | ||
| 8533 | |||
| 8431 | const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); | 8534 | const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); |
| 8432 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); | 8535 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); |
| 8536 | |||
| 8537 | try emitDbgStmt(gz, line, column); | ||
| 8433 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ | 8538 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8434 | .lhs = lhs, | 8539 | .lhs = lhs, |
| 8435 | .rhs = rhs, | 8540 | .rhs = rhs, |
| ... | @@ -10668,14 +10773,19 @@ const GenZir = struct { | ... | @@ -10668,14 +10773,19 @@ const GenZir = struct { |
| 10668 | gz.break_result_info = parent_ri; | 10773 | gz.break_result_info = parent_ri; |
| 10669 | }, | 10774 | }, |
| 10670 | 10775 | ||
| 10671 | .discard, .none, .ref => { | 10776 | .none, .ref => { |
| 10672 | gz.rl_ty_inst = .none; | 10777 | gz.rl_ty_inst = .none; |
| 10673 | gz.break_result_info = parent_ri; | 10778 | gz.break_result_info = parent_ri; |
| 10674 | }, | 10779 | }, |
| 10675 | 10780 | ||
| 10781 | .discard => { | ||
| 10782 | gz.rl_ty_inst = .none; | ||
| 10783 | gz.break_result_info = .{ .rl = .discard }; | ||
| 10784 | }, | ||
| 10785 | |||
| 10676 | .ptr => |ptr_res| { | 10786 | .ptr => |ptr_res| { |
| 10677 | gz.rl_ty_inst = .none; | 10787 | gz.rl_ty_inst = .none; |
| 10678 | gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } } }; | 10788 | gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } }, .ctx = parent_ri.ctx }; |
| 10679 | }, | 10789 | }, |
| 10680 | 10790 | ||
| 10681 | .inferred_ptr => |ptr| { | 10791 | .inferred_ptr => |ptr| { |
| ... | @@ -12054,6 +12164,18 @@ fn detectLocalShadowing( | ... | @@ -12054,6 +12164,18 @@ fn detectLocalShadowing( |
| 12054 | }; | 12164 | }; |
| 12055 | } | 12165 | } |
| 12056 | 12166 | ||
| 12167 | /// Advances the source cursor to the main token of `node` if not in comptime scope. | ||
| 12168 | /// Usually paired with `emitDbgStmt`. | ||
| 12169 | fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) void { | ||
| 12170 | if (gz.force_comptime) return; | ||
| 12171 | |||
| 12172 | const tree = gz.astgen.tree; | ||
| 12173 | const token_starts = tree.tokens.items(.start); | ||
| 12174 | const main_tokens = tree.nodes.items(.main_token); | ||
| 12175 | const node_start = token_starts[main_tokens[node]]; | ||
| 12176 | gz.astgen.advanceSourceCursor(node_start); | ||
| 12177 | } | ||
| 12178 | |||
| 12057 | /// Advances the source cursor to the beginning of `node`. | 12179 | /// Advances the source cursor to the beginning of `node`. |
| 12058 | fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void { | 12180 | fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void { |
| 12059 | const tree = astgen.tree; | 12181 | const tree = astgen.tree; |
src/Autodoc.zig+12-3| ... | @@ -2129,7 +2129,15 @@ fn walkInstruction( | ... | @@ -2129,7 +2129,15 @@ fn walkInstruction( |
| 2129 | file, | 2129 | file, |
| 2130 | parent_scope, | 2130 | parent_scope, |
| 2131 | parent_src, | 2131 | parent_src, |
| 2132 | getBlockInlineBreak(file.zir, inst_index), | 2132 | getBlockInlineBreak(file.zir, inst_index) orelse { |
| 2133 | const res = DocData.WalkResult{ .expr = .{ | ||
| 2134 | .comptimeExpr = self.comptime_exprs.items.len, | ||
| 2135 | } }; | ||
| 2136 | try self.comptime_exprs.append(self.arena, .{ | ||
| 2137 | .code = "if (...) { ... }", | ||
| 2138 | }); | ||
| 2139 | return res; | ||
| 2140 | }, | ||
| 2133 | need_type, | 2141 | need_type, |
| 2134 | ); | 2142 | ); |
| 2135 | }, | 2143 | }, |
| ... | @@ -3155,7 +3163,7 @@ fn walkDecls( | ... | @@ -3155,7 +3163,7 @@ fn walkDecls( |
| 3155 | 2 => { | 3163 | 2 => { |
| 3156 | // decl test | 3164 | // decl test |
| 3157 | const decl_being_tested = scope.resolveDeclName(doc_comment_index); | 3165 | const decl_being_tested = scope.resolveDeclName(doc_comment_index); |
| 3158 | const func_index = getBlockInlineBreak(file.zir, value_index); | 3166 | const func_index = getBlockInlineBreak(file.zir, value_index).?; |
| 3159 | 3167 | ||
| 3160 | const pl_node = data[Zir.refToIndex(func_index).?].pl_node; | 3168 | const pl_node = data[Zir.refToIndex(func_index).?].pl_node; |
| 3161 | const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src); | 3169 | const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src); |
| ... | @@ -4301,12 +4309,13 @@ fn walkRef( | ... | @@ -4301,12 +4309,13 @@ fn walkRef( |
| 4301 | } | 4309 | } |
| 4302 | } | 4310 | } |
| 4303 | 4311 | ||
| 4304 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) Zir.Inst.Ref { | 4312 | fn getBlockInlineBreak(zir: Zir, inst_index: usize) ?Zir.Inst.Ref { |
| 4305 | const tags = zir.instructions.items(.tag); | 4313 | const tags = zir.instructions.items(.tag); |
| 4306 | const data = zir.instructions.items(.data); | 4314 | const data = zir.instructions.items(.data); |
| 4307 | const pl_node = data[inst_index].pl_node; | 4315 | const pl_node = data[inst_index].pl_node; |
| 4308 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); | 4316 | const extra = zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 4309 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; | 4317 | const break_index = zir.extra[extra.end..][extra.data.body_len - 1]; |
| 4318 | if (tags[break_index] == .condbr_inline) return null; | ||
| 4310 | std.debug.assert(tags[break_index] == .break_inline); | 4319 | std.debug.assert(tags[break_index] == .break_inline); |
| 4311 | return data[break_index].@"break".operand; | 4320 | return data[break_index].@"break".operand; |
| 4312 | } | 4321 | } |
src/Sema.zig+9-12| ... | @@ -1491,6 +1491,8 @@ fn analyzeBodyInner( | ... | @@ -1491,6 +1491,8 @@ fn analyzeBodyInner( |
| 1491 | return err; | 1491 | return err; |
| 1492 | }; | 1492 | }; |
| 1493 | const inline_body = if (cond.val.toBool()) then_body else else_body; | 1493 | const inline_body = if (cond.val.toBool()) then_body else else_body; |
| 1494 | |||
| 1495 | try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); | ||
| 1494 | const old_runtime_index = block.runtime_index; | 1496 | const old_runtime_index = block.runtime_index; |
| 1495 | defer block.runtime_index = old_runtime_index; | 1497 | defer block.runtime_index = old_runtime_index; |
| 1496 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse | 1498 | const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse |
| ... | @@ -5658,14 +5660,14 @@ fn lookupInNamespace( | ... | @@ -5658,14 +5660,14 @@ fn lookupInNamespace( |
| 5658 | const src_file = block.namespace.file_scope; | 5660 | const src_file = block.namespace.file_scope; |
| 5659 | 5661 | ||
| 5660 | const gpa = sema.gpa; | 5662 | const gpa = sema.gpa; |
| 5661 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{}; | 5663 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{}; |
| 5662 | defer checked_namespaces.deinit(gpa); | 5664 | defer checked_namespaces.deinit(gpa); |
| 5663 | 5665 | ||
| 5664 | // Keep track of name conflicts for error notes. | 5666 | // Keep track of name conflicts for error notes. |
| 5665 | var candidates: std.ArrayListUnmanaged(Decl.Index) = .{}; | 5667 | var candidates: std.ArrayListUnmanaged(Decl.Index) = .{}; |
| 5666 | defer candidates.deinit(gpa); | 5668 | defer candidates.deinit(gpa); |
| 5667 | 5669 | ||
| 5668 | try checked_namespaces.put(gpa, namespace, {}); | 5670 | try checked_namespaces.put(gpa, namespace, namespace.file_scope == src_file); |
| 5669 | var check_i: usize = 0; | 5671 | var check_i: usize = 0; |
| 5670 | 5672 | ||
| 5671 | while (check_i < checked_namespaces.count()) : (check_i += 1) { | 5673 | while (check_i < checked_namespaces.count()) : (check_i += 1) { |
| ... | @@ -5674,7 +5676,7 @@ fn lookupInNamespace( | ... | @@ -5674,7 +5676,7 @@ fn lookupInNamespace( |
| 5674 | // Skip decls which are not marked pub, which are in a different | 5676 | // Skip decls which are not marked pub, which are in a different |
| 5675 | // file than the `a.b`/`@hasDecl` syntax. | 5677 | // file than the `a.b`/`@hasDecl` syntax. |
| 5676 | const decl = mod.declPtr(decl_index); | 5678 | const decl = mod.declPtr(decl_index); |
| 5677 | if (decl.is_pub or src_file == decl.getFileScope()) { | 5679 | if (decl.is_pub or (src_file == decl.getFileScope() and checked_namespaces.values()[check_i])) { |
| 5678 | try candidates.append(gpa, decl_index); | 5680 | try candidates.append(gpa, decl_index); |
| 5679 | } | 5681 | } |
| 5680 | } | 5682 | } |
| ... | @@ -5693,7 +5695,7 @@ fn lookupInNamespace( | ... | @@ -5693,7 +5695,7 @@ fn lookupInNamespace( |
| 5693 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index); | 5695 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index); |
| 5694 | const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data; | 5696 | const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data; |
| 5695 | const sub_ns = ns_ty.getNamespace().?; | 5697 | const sub_ns = ns_ty.getNamespace().?; |
| 5696 | try checked_namespaces.put(gpa, sub_ns, {}); | 5698 | try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope()); |
| 5697 | } | 5699 | } |
| 5698 | } | 5700 | } |
| 5699 | 5701 | ||
| ... | @@ -6331,6 +6333,7 @@ fn analyzeCall( | ... | @@ -6331,6 +6333,7 @@ fn analyzeCall( |
| 6331 | .instructions = .{}, | 6333 | .instructions = .{}, |
| 6332 | .label = null, | 6334 | .label = null, |
| 6333 | .inlining = &inlining, | 6335 | .inlining = &inlining, |
| 6336 | .is_typeof = block.is_typeof, | ||
| 6334 | .is_comptime = is_comptime_call, | 6337 | .is_comptime = is_comptime_call, |
| 6335 | .comptime_reason = comptime_reason, | 6338 | .comptime_reason = comptime_reason, |
| 6336 | .error_return_trace_index = block.error_return_trace_index, | 6339 | .error_return_trace_index = block.error_return_trace_index, |
| ... | @@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -16530,9 +16533,6 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 16530 | // This is only relevant at runtime. | 16533 | // This is only relevant at runtime. |
| 16531 | if (block.is_comptime or block.is_typeof) return; | 16534 | if (block.is_comptime or block.is_typeof) return; |
| 16532 | 16535 | ||
| 16533 | // This is only relevant within functions. | ||
| 16534 | if (sema.func == null) return; | ||
| 16535 | |||
| 16536 | const save_index = inst_data.operand == .none or b: { | 16536 | const save_index = inst_data.operand == .none or b: { |
| 16537 | const operand = try sema.resolveInst(inst_data.operand); | 16537 | const operand = try sema.resolveInst(inst_data.operand); |
| 16538 | const operand_ty = sema.typeOf(operand); | 16538 | const operand_ty = sema.typeOf(operand); |
| ... | @@ -20179,8 +20179,8 @@ fn analyzeShuffle( | ... | @@ -20179,8 +20179,8 @@ fn analyzeShuffle( |
| 20179 | .elem_type = elem_ty, | 20179 | .elem_type = elem_ty, |
| 20180 | }); | 20180 | }); |
| 20181 | 20181 | ||
| 20182 | if (maybe_a_len == null) a = try sema.addConstUndef(a_ty); | 20182 | if (maybe_a_len == null) a = try sema.addConstUndef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src); |
| 20183 | if (maybe_b_len == null) b = try sema.addConstUndef(b_ty); | 20183 | if (maybe_b_len == null) b = try sema.addConstUndef(b_ty) else b = try sema.coerce(block, b_ty, b, b_src); |
| 20184 | 20184 | ||
| 20185 | const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){ | 20185 | const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){ |
| 20186 | .{ a_len, a_src, a_ty }, | 20186 | .{ a_len, a_src, a_ty }, |
| ... | @@ -27503,9 +27503,6 @@ fn analyzeLoad( | ... | @@ -27503,9 +27503,6 @@ fn analyzeLoad( |
| 27503 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { | 27503 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { |
| 27504 | return sema.addConstant(elem_ty, elem_val); | 27504 | return sema.addConstant(elem_ty, elem_val); |
| 27505 | } | 27505 | } |
| 27506 | if (block.is_typeof) { | ||
| 27507 | return sema.addConstUndef(elem_ty); | ||
| 27508 | } | ||
| 27509 | } | 27506 | } |
| 27510 | 27507 | ||
| 27511 | return block.addTyOp(.load, elem_ty, ptr); | 27508 | return block.addTyOp(.load, elem_ty, ptr); |
src/codegen/llvm.zig+17-14| ... | @@ -1966,7 +1966,7 @@ pub const Object = struct { | ... | @@ -1966,7 +1966,7 @@ pub const Object = struct { |
| 1966 | 1966 | ||
| 1967 | for (tuple.types) |field_ty, i| { | 1967 | for (tuple.types) |field_ty, i| { |
| 1968 | const field_val = tuple.values[i]; | 1968 | const field_val = tuple.values[i]; |
| 1969 | if (field_val.tag() != .unreachable_value) continue; | 1969 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; |
| 1970 | 1970 | ||
| 1971 | const field_size = field_ty.abiSize(target); | 1971 | const field_size = field_ty.abiSize(target); |
| 1972 | const field_align = field_ty.abiAlignment(target); | 1972 | const field_align = field_ty.abiAlignment(target); |
| ... | @@ -2901,7 +2901,7 @@ pub const DeclGen = struct { | ... | @@ -2901,7 +2901,7 @@ pub const DeclGen = struct { |
| 2901 | 2901 | ||
| 2902 | for (tuple.types) |field_ty, i| { | 2902 | for (tuple.types) |field_ty, i| { |
| 2903 | const field_val = tuple.values[i]; | 2903 | const field_val = tuple.values[i]; |
| 2904 | if (field_val.tag() != .unreachable_value) continue; | 2904 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; |
| 2905 | 2905 | ||
| 2906 | const field_align = field_ty.abiAlignment(target); | 2906 | const field_align = field_ty.abiAlignment(target); |
| 2907 | big_align = @max(big_align, field_align); | 2907 | big_align = @max(big_align, field_align); |
| ... | @@ -3198,7 +3198,8 @@ pub const DeclGen = struct { | ... | @@ -3198,7 +3198,8 @@ pub const DeclGen = struct { |
| 3198 | /// There are other similar cases handled here as well. | 3198 | /// There are other similar cases handled here as well. |
| 3199 | fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type { | 3199 | fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type { |
| 3200 | const lower_elem_ty = switch (elem_ty.zigTypeTag()) { | 3200 | const lower_elem_ty = switch (elem_ty.zigTypeTag()) { |
| 3201 | .Opaque, .Fn => true, | 3201 | .Opaque => true, |
| 3202 | .Fn => !elem_ty.fnInfo().is_generic, | ||
| 3202 | .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), | 3203 | .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), |
| 3203 | else => elem_ty.hasRuntimeBitsIgnoreComptime(), | 3204 | else => elem_ty.hasRuntimeBitsIgnoreComptime(), |
| 3204 | }; | 3205 | }; |
| ... | @@ -4145,7 +4146,9 @@ pub const DeclGen = struct { | ... | @@ -4145,7 +4146,9 @@ pub const DeclGen = struct { |
| 4145 | } | 4146 | } |
| 4146 | 4147 | ||
| 4147 | const is_fn_body = decl.ty.zigTypeTag() == .Fn; | 4148 | const is_fn_body = decl.ty.zigTypeTag() == .Fn; |
| 4148 | if (!is_fn_body and !decl.ty.hasRuntimeBits()) { | 4149 | if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or |
| 4150 | (is_fn_body and decl.ty.fnInfo().is_generic)) | ||
| 4151 | { | ||
| 4149 | return self.lowerPtrToVoid(tv.ty); | 4152 | return self.lowerPtrToVoid(tv.ty); |
| 4150 | } | 4153 | } |
| 4151 | 4154 | ||
| ... | @@ -8671,9 +8674,9 @@ pub const FuncGen = struct { | ... | @@ -8671,9 +8674,9 @@ pub const FuncGen = struct { |
| 8671 | const arena = arena_allocator.allocator(); | 8674 | const arena = arena_allocator.allocator(); |
| 8672 | 8675 | ||
| 8673 | const mod = self.dg.module; | 8676 | const mod = self.dg.module; |
| 8674 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{ | 8677 | const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod); |
| 8675 | try mod.declPtr(enum_decl).getFullyQualifiedName(mod), | 8678 | defer self.gpa.free(fqn); |
| 8676 | }); | 8679 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn}); |
| 8677 | 8680 | ||
| 8678 | var int_tag_type_buffer: Type.Payload.Bits = undefined; | 8681 | var int_tag_type_buffer: Type.Payload.Bits = undefined; |
| 8679 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); | 8682 | const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer); |
| ... | @@ -8752,9 +8755,9 @@ pub const FuncGen = struct { | ... | @@ -8752,9 +8755,9 @@ pub const FuncGen = struct { |
| 8752 | const arena = arena_allocator.allocator(); | 8755 | const arena = arena_allocator.allocator(); |
| 8753 | 8756 | ||
| 8754 | const mod = self.dg.module; | 8757 | const mod = self.dg.module; |
| 8755 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{ | 8758 | const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod); |
| 8756 | try mod.declPtr(enum_decl).getFullyQualifiedName(mod), | 8759 | defer self.gpa.free(fqn); |
| 8757 | }); | 8760 | const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn}); |
| 8758 | 8761 | ||
| 8759 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); | 8762 | const slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 8760 | const llvm_ret_ty = try self.dg.lowerType(slice_ty); | 8763 | const llvm_ret_ty = try self.dg.lowerType(slice_ty); |
| ... | @@ -10204,7 +10207,7 @@ fn llvmFieldIndex( | ... | @@ -10204,7 +10207,7 @@ fn llvmFieldIndex( |
| 10204 | const tuple = ty.tupleFields(); | 10207 | const tuple = ty.tupleFields(); |
| 10205 | var llvm_field_index: c_uint = 0; | 10208 | var llvm_field_index: c_uint = 0; |
| 10206 | for (tuple.types) |field_ty, i| { | 10209 | for (tuple.types) |field_ty, i| { |
| 10207 | if (tuple.values[i].tag() != .unreachable_value) continue; | 10210 | if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; |
| 10208 | 10211 | ||
| 10209 | const field_align = field_ty.abiAlignment(target); | 10212 | const field_align = field_ty.abiAlignment(target); |
| 10210 | big_align = @max(big_align, field_align); | 10213 | big_align = @max(big_align, field_align); |
| ... | @@ -10216,7 +10219,7 @@ fn llvmFieldIndex( | ... | @@ -10216,7 +10219,7 @@ fn llvmFieldIndex( |
| 10216 | llvm_field_index += 1; | 10219 | llvm_field_index += 1; |
| 10217 | } | 10220 | } |
| 10218 | 10221 | ||
| 10219 | if (field_index == i) { | 10222 | if (field_index <= i) { |
| 10220 | ptr_pl_buf.* = .{ | 10223 | ptr_pl_buf.* = .{ |
| 10221 | .data = .{ | 10224 | .data = .{ |
| 10222 | .pointee_type = field_ty, | 10225 | .pointee_type = field_ty, |
| ... | @@ -10249,7 +10252,7 @@ fn llvmFieldIndex( | ... | @@ -10249,7 +10252,7 @@ fn llvmFieldIndex( |
| 10249 | llvm_field_index += 1; | 10252 | llvm_field_index += 1; |
| 10250 | } | 10253 | } |
| 10251 | 10254 | ||
| 10252 | if (field_index == i) { | 10255 | if (field_index <= i) { |
| 10253 | ptr_pl_buf.* = .{ | 10256 | ptr_pl_buf.* = .{ |
| 10254 | .data = .{ | 10257 | .data = .{ |
| 10255 | .pointee_type = field.ty, | 10258 | .pointee_type = field.ty, |
| ... | @@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool { | ... | @@ -10768,7 +10771,7 @@ fn isByRef(ty: Type) bool { |
| 10768 | const tuple = ty.tupleFields(); | 10771 | const tuple = ty.tupleFields(); |
| 10769 | var count: usize = 0; | 10772 | var count: usize = 0; |
| 10770 | for (tuple.values) |field_val, i| { | 10773 | for (tuple.values) |field_val, i| { |
| 10771 | if (field_val.tag() != .unreachable_value) continue; | 10774 | if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue; |
| 10772 | 10775 | ||
| 10773 | count += 1; | 10776 | count += 1; |
| 10774 | if (count > max_fields_byval) return true; | 10777 | if (count > max_fields_byval) return true; |
src/type.zig+4-2| ... | @@ -640,7 +640,9 @@ pub const Type = extern union { | ... | @@ -640,7 +640,9 @@ pub const Type = extern union { |
| 640 | const a_info = a.fnInfo(); | 640 | const a_info = a.fnInfo(); |
| 641 | const b_info = b.fnInfo(); | 641 | const b_info = b.fnInfo(); |
| 642 | 642 | ||
| 643 | if (!eql(a_info.return_type, b_info.return_type, mod)) | 643 | if (a_info.return_type.tag() != .generic_poison and |
| 644 | b_info.return_type.tag() != .generic_poison and | ||
| 645 | !eql(a_info.return_type, b_info.return_type, mod)) | ||
| 644 | return false; | 646 | return false; |
| 645 | 647 | ||
| 646 | if (a_info.is_var_args != b_info.is_var_args) | 648 | if (a_info.is_var_args != b_info.is_var_args) |
| ... | @@ -5757,7 +5759,7 @@ pub const Type = extern union { | ... | @@ -5757,7 +5759,7 @@ pub const Type = extern union { |
| 5757 | 5759 | ||
| 5758 | for (tuple.types) |field_ty, i| { | 5760 | for (tuple.types) |field_ty, i| { |
| 5759 | const field_val = tuple.values[i]; | 5761 | const field_val = tuple.values[i]; |
| 5760 | if (field_val.tag() != .unreachable_value) { | 5762 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) { |
| 5761 | // comptime field | 5763 | // comptime field |
| 5762 | if (i == index) return offset; | 5764 | if (i == index) return offset; |
| 5763 | continue; | 5765 | continue; |
test/behavior/eval.zig+8| ... | @@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" { | ... | @@ -1499,3 +1499,11 @@ test "non-optional and optional array elements concatenated" { |
| 1499 | var index: usize = 0; | 1499 | var index: usize = 0; |
| 1500 | try expect(array[index].? == 'A'); | 1500 | try expect(array[index].? == 'A'); |
| 1501 | } | 1501 | } |
| 1502 | |||
| 1503 | test "inline call in @TypeOf inherits is_inline property" { | ||
| 1504 | const S = struct { | ||
| 1505 | inline fn doNothing() void {} | ||
| 1506 | const T = @TypeOf(doNothing()); | ||
| 1507 | }; | ||
| 1508 | try expect(S.T == void); | ||
| 1509 | } |
test/behavior/generics.zig+12| ... | @@ -405,3 +405,15 @@ test "null sentinel pointer passed as generic argument" { | ... | @@ -405,3 +405,15 @@ test "null sentinel pointer passed as generic argument" { |
| 405 | }; | 405 | }; |
| 406 | try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8))); | 406 | try S.doTheTest((@intToPtr([*:null]const [*c]const u8, 8))); |
| 407 | } | 407 | } |
| 408 | |||
| 409 | test "generic function passed as comptime argument" { | ||
| 410 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 411 | |||
| 412 | const S = struct { | ||
| 413 | fn doMath(comptime f: fn (type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void { | ||
| 414 | const result = try f(i32, a, b); | ||
| 415 | try expect(result == 11); | ||
| 416 | } | ||
| 417 | }; | ||
| 418 | try S.doMath(std.math.add, 5, 6); | ||
| 419 | } |
test/behavior/pointers.zig+17| ... | @@ -489,3 +489,20 @@ test "ptrCast comptime known slice to C pointer" { | ... | @@ -489,3 +489,20 @@ test "ptrCast comptime known slice to C pointer" { |
| 489 | var p = @ptrCast([*c]const u8, s); | 489 | var p = @ptrCast([*c]const u8, s); |
| 490 | try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0)); | 490 | try std.testing.expectEqualStrings(s, std.mem.sliceTo(p, 0)); |
| 491 | } | 491 | } |
| 492 | |||
| 493 | test "ptrToInt on a generic function" { | ||
| 494 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 495 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 496 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO | ||
| 497 | if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .linux) return error.SkipZigTest; // TODO | ||
| 498 | |||
| 499 | const S = struct { | ||
| 500 | fn generic(i: anytype) @TypeOf(i) { | ||
| 501 | return i; | ||
| 502 | } | ||
| 503 | fn doTheTest(a: anytype) !void { | ||
| 504 | try expect(@ptrToInt(a) != 0); | ||
| 505 | } | ||
| 506 | }; | ||
| 507 | try S.doTheTest(&S.generic); | ||
| 508 | } |
test/behavior/struct.zig+20| ... | @@ -1398,3 +1398,23 @@ test "under-aligned struct field" { | ... | @@ -1398,3 +1398,23 @@ test "under-aligned struct field" { |
| 1398 | const result = std.mem.readIntNative(u64, array[4..12]); | 1398 | const result = std.mem.readIntNative(u64, array[4..12]); |
| 1399 | try expect(result == 1234); | 1399 | try expect(result == 1234); |
| 1400 | } | 1400 | } |
| 1401 | |||
| 1402 | test "address of zero-bit field is equal to address of only field" { | ||
| 1403 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1404 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1405 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1406 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 1407 | |||
| 1408 | { | ||
| 1409 | const A = struct { b: void = {}, u: u8 }; | ||
| 1410 | var a = A{ .u = 0 }; | ||
| 1411 | const a_ptr = @fieldParentPtr(A, "b", &a.b); | ||
| 1412 | try std.testing.expectEqual(&a, a_ptr); | ||
| 1413 | } | ||
| 1414 | { | ||
| 1415 | const A = struct { u: u8, b: void = {} }; | ||
| 1416 | var a = A{ .u = 0 }; | ||
| 1417 | const a_ptr = @fieldParentPtr(A, "b", &a.b); | ||
| 1418 | try std.testing.expectEqual(&a, a_ptr); | ||
| 1419 | } | ||
| 1420 | } |
test/behavior/tuple.zig+10| ... | @@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" { | ... | @@ -323,3 +323,13 @@ test "zero sized struct in tuple handled correctly" { |
| 323 | var s: State = undefined; | 323 | var s: State = undefined; |
| 324 | try expect(s.do() == 0); | 324 | try expect(s.do() == 0); |
| 325 | } | 325 | } |
| 326 | |||
| 327 | test "tuple type with void field and a runtime field" { | ||
| 328 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 329 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 330 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 331 | |||
| 332 | const T = std.meta.Tuple(&[_]type{ usize, void }); | ||
| 333 | var t: T = .{ 5, {} }; | ||
| 334 | try expect(t[0] == 5); | ||
| 335 | } |
test/behavior/usingnamespace.zig+4| ... | @@ -75,3 +75,7 @@ test { | ... | @@ -75,3 +75,7 @@ test { |
| 75 | const a = AA.b(42); | 75 | const a = AA.b(42); |
| 76 | try expect(a.x == AA.c().expected); | 76 | try expect(a.x == AA.c().expected); |
| 77 | } | 77 | } |
| 78 | |||
| 79 | comptime { | ||
| 80 | _ = @import("usingnamespace/file_1.zig"); | ||
| 81 | } |
test/behavior/usingnamespace/file_0.zig created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | pub const A = 123; | ||
test/behavior/usingnamespace/file_1.zig created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const imports = @import("imports.zig"); | ||
| 4 | |||
| 5 | const A = 456; | ||
| 6 | |||
| 7 | test { | ||
| 8 | try expect(imports.A == 123); | ||
| 9 | } | ||
test/behavior/usingnamespace/imports.zig created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | const file_0 = @import("file_0.zig"); | ||
| 2 | const file_1 = @import("file_1.zig"); | ||
| 3 | |||
| 4 | pub usingnamespace file_0; | ||
| 5 | pub usingnamespace file_1; | ||
test/behavior/vector.zig+15| ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,7 @@ const builtin = @import("builtin"); |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const math = std.math; | 4 | const math = std.math; |
| 5 | const expect = std.testing.expect; | 5 | const expect = std.testing.expect; |
| 6 | const expectEqual = std.testing.expectEqual; | ||
| 6 | 7 | ||
| 7 | test "implicit cast vector to array - bool" { | 8 | test "implicit cast vector to array - bool" { |
| 8 | if (builtin.zig_backend == .stage1) { | 9 | if (builtin.zig_backend == .stage1) { |
| ... | @@ -1231,3 +1232,17 @@ test "modRem with zero divisor" { | ... | @@ -1231,3 +1232,17 @@ test "modRem with zero divisor" { |
| 1231 | _ = zeros[0]; | 1232 | _ = zeros[0]; |
| 1232 | } | 1233 | } |
| 1233 | } | 1234 | } |
| 1235 | |||
| 1236 | test "array operands to shuffle are coerced to vectors" { | ||
| 1237 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1238 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 1239 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1240 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1241 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1242 | |||
| 1243 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; | ||
| 1244 | |||
| 1245 | var a = [5]u32{ 3, 5, 7, 9, 0 }; | ||
| 1246 | var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask); | ||
| 1247 | try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b); | ||
| 1248 | } |
test/cases/compile_errors/branch_in_comptime_only_scope_uses_condbr_inline.zig created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | pub export fn entry1() void { | ||
| 2 | var x: u32 = 3; | ||
| 3 | _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{ | ||
| 4 | if (x > 1) 1 else -1, | ||
| 5 | }); | ||
| 6 | } | ||
| 7 | |||
| 8 | pub export fn entry2() void { | ||
| 9 | var y: ?i8 = -1; | ||
| 10 | _ = @shuffle(u32, [_]u32{0}, @splat(1, @as(u32, 0)), [_]i8{ | ||
| 11 | y orelse 1, | ||
| 12 | }); | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=stage2 | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // :4:15: error: unable to resolve comptime value | ||
| 20 | // :4:15: note: condition in comptime branch must be comptime-known | ||
| 21 | // :11:11: error: unable to resolve comptime value | ||
| 22 | // :11:11: note: condition in comptime branch must be comptime-known | ||
test/cases/compile_errors/pointless discard.zig	+8| ... | @@ -3,6 +3,14 @@ export fn foo() void { | ... | @@ -3,6 +3,14 @@ export fn foo() void { |
| 3 | x += 1; | 3 | x += 1; |
| 4 | _ = x; | 4 | _ = x; |
| 5 | } | 5 | } |
| 6 | export fn bar() void { | ||
| 7 | var b: u32 = 1; | ||
| 8 | _ = blk: { | ||
| 9 | const a = 1; | ||
| 10 | b = a; | ||
| 11 | break :blk a; | ||
| 12 | }; | ||
| 13 | } | ||
| 6 | 14 | ||
| 7 | // error | 15 | // error |
| 8 | // backend=stage2 | 16 | // backend=stage2 |