| ... | ... | @@ -213,123 +213,149 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void { |
| 213 | 213 | astgen.ref_table.deinit(gpa); |
| 214 | 214 | } |
| 215 | 215 | |
| 216 | | pub const ResultLoc = union(enum) { |
| 217 | | /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the |
| 218 | | /// expression should be generated. The result instruction from the expression must |
| 219 | | /// be ignored. |
| 220 | | discard, |
| 221 | | /// The expression has an inferred type, and it will be evaluated as an rvalue. |
| 222 | | none, |
| 223 | | /// The expression must generate a pointer rather than a value. For example, the left hand side |
| 224 | | /// of an assignment uses this kind of result location. |
| 225 | | ref, |
| 226 | | /// The expression will be coerced into this type, but it will be evaluated as an rvalue. |
| 227 | | ty: Zir.Inst.Ref, |
| 228 | | /// Same as `ty` but for shift operands. |
| 229 | | ty_shift_operand: Zir.Inst.Ref, |
| 230 | | /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion, |
| 231 | | /// so no `as` instruction needs to be emitted. |
| 232 | | coerced_ty: Zir.Inst.Ref, |
| 233 | | /// The expression must store its result into this typed pointer. The result instruction |
| 234 | | /// from the expression must be ignored. |
| 235 | | ptr: PtrResultLoc, |
| 236 | | /// The expression must store its result into this allocation, which has an inferred type. |
| 237 | | /// The result instruction from the expression must be ignored. |
| 238 | | /// Always an instruction with tag `alloc_inferred`. |
| 239 | | inferred_ptr: Zir.Inst.Ref, |
| 240 | | /// There is a pointer for the expression to store its result into, however, its type |
| 241 | | /// is inferred based on peer type resolution for a `Zir.Inst.Block`. |
| 242 | | /// The result instruction from the expression must be ignored. |
| 243 | | block_ptr: *GenZir, |
| 244 | | |
| 245 | | const PtrResultLoc = struct { |
| 246 | | inst: Zir.Inst.Ref, |
| 247 | | src_node: ?Ast.Node.Index = null, |
| 248 | | }; |
| 216 | pub const ResultInfo = struct { |
| 217 | /// The semantics requested for the result location |
| 218 | rl: Loc, |
| 249 | 219 | |
| 250 | | pub const Strategy = struct { |
| 251 | | elide_store_to_block_ptr_instructions: bool, |
| 252 | | tag: Tag, |
| 253 | | |
| 254 | | pub const Tag = enum { |
| 255 | | /// Both branches will use break_void; result location is used to communicate the |
| 256 | | /// result instruction. |
| 257 | | break_void, |
| 258 | | /// Use break statements to pass the block result value, and call rvalue() at |
| 259 | | /// the end depending on rl. Also elide the store_to_block_ptr instructions |
| 260 | | /// depending on rl. |
| 261 | | break_operand, |
| 262 | | }; |
| 263 | | }; |
| 220 | /// The "operator" consuming the result location |
| 221 | ctx: Context = .none, |
| 264 | 222 | |
| 265 | | fn strategy(rl: ResultLoc, block_scope: *GenZir) Strategy { |
| 266 | | switch (rl) { |
| 267 | | // In this branch there will not be any store_to_block_ptr instructions. |
| 268 | | .none, .ty, .ty_shift_operand, .coerced_ty, .ref => return .{ |
| 269 | | .tag = .break_operand, |
| 270 | | .elide_store_to_block_ptr_instructions = false, |
| 271 | | }, |
| 272 | | .discard => return .{ |
| 273 | | .tag = .break_void, |
| 274 | | .elide_store_to_block_ptr_instructions = false, |
| 275 | | }, |
| 276 | | // The pointer got passed through to the sub-expressions, so we will use |
| 277 | | // break_void here. |
| 278 | | // In this branch there will not be any store_to_block_ptr instructions. |
| 279 | | .ptr => return .{ |
| 280 | | .tag = .break_void, |
| 281 | | .elide_store_to_block_ptr_instructions = false, |
| 223 | /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points |
| 224 | /// such as if and switch expressions. |
| 225 | fn br(ri: ResultInfo) ResultInfo { |
| 226 | return switch (ri.rl) { |
| 227 | .coerced_ty => |ty| .{ |
| 228 | .rl = .{ .ty = ty }, |
| 229 | .ctx = ri.ctx, |
| 282 | 230 | }, |
| 283 | | .inferred_ptr, .block_ptr => { |
| 284 | | if (block_scope.rvalue_rl_count == block_scope.break_count) { |
| 285 | | // Neither prong of the if consumed the result location, so we can |
| 286 | | // use break instructions to create an rvalue. |
| 287 | | return .{ |
| 288 | | .tag = .break_operand, |
| 289 | | .elide_store_to_block_ptr_instructions = true, |
| 290 | | }; |
| 291 | | } else { |
| 292 | | // Allow the store_to_block_ptr instructions to remain so that |
| 293 | | // semantic analysis can turn them into bitcasts. |
| 294 | | return .{ |
| 295 | | .tag = .break_void, |
| 296 | | .elide_store_to_block_ptr_instructions = false, |
| 297 | | }; |
| 298 | | } |
| 231 | else => ri, |
| 232 | }; |
| 233 | } |
| 234 | |
| 235 | fn zirTag(ri: ResultInfo) Zir.Inst.Tag { |
| 236 | switch (ri.rl) { |
| 237 | .ty => return switch (ri.ctx) { |
| 238 | .shift_op => .as_shift_operand, |
| 239 | else => .as_node, |
| 299 | 240 | }, |
| 241 | else => unreachable, |
| 300 | 242 | } |
| 301 | 243 | } |
| 302 | 244 | |
| 303 | | /// Turns a `coerced_ty` back into a `ty`. Should be called at branch points |
| 304 | | /// such as if and switch expressions. |
| 305 | | fn br(rl: ResultLoc) ResultLoc { |
| 306 | | return switch (rl) { |
| 307 | | .coerced_ty => |ty| .{ .ty = ty }, |
| 308 | | else => rl, |
| 245 | pub const Loc = union(enum) { |
| 246 | /// The expression is the right-hand side of assignment to `_`. Only the side-effects of the |
| 247 | /// expression should be generated. The result instruction from the expression must |
| 248 | /// be ignored. |
| 249 | discard, |
| 250 | /// The expression has an inferred type, and it will be evaluated as an rvalue. |
| 251 | none, |
| 252 | /// The expression must generate a pointer rather than a value. For example, the left hand side |
| 253 | /// of an assignment uses this kind of result location. |
| 254 | ref, |
| 255 | /// The expression will be coerced into this type, but it will be evaluated as an rvalue. |
| 256 | ty: Zir.Inst.Ref, |
| 257 | /// Same as `ty` but it is guaranteed that Sema will additionally perform the coercion, |
| 258 | /// so no `as` instruction needs to be emitted. |
| 259 | coerced_ty: Zir.Inst.Ref, |
| 260 | /// The expression must store its result into this typed pointer. The result instruction |
| 261 | /// from the expression must be ignored. |
| 262 | ptr: PtrResultLoc, |
| 263 | /// The expression must store its result into this allocation, which has an inferred type. |
| 264 | /// The result instruction from the expression must be ignored. |
| 265 | /// Always an instruction with tag `alloc_inferred`. |
| 266 | inferred_ptr: Zir.Inst.Ref, |
| 267 | /// There is a pointer for the expression to store its result into, however, its type |
| 268 | /// is inferred based on peer type resolution for a `Zir.Inst.Block`. |
| 269 | /// The result instruction from the expression must be ignored. |
| 270 | block_ptr: *GenZir, |
| 271 | |
| 272 | const PtrResultLoc = struct { |
| 273 | inst: Zir.Inst.Ref, |
| 274 | src_node: ?Ast.Node.Index = null, |
| 309 | 275 | }; |
| 310 | | } |
| 311 | 276 | |
| 312 | | fn zirTag(rl: ResultLoc) Zir.Inst.Tag { |
| 313 | | return switch (rl) { |
| 314 | | .ty => .as_node, |
| 315 | | .ty_shift_operand => .as_shift_operand, |
| 316 | | else => unreachable, |
| 277 | pub const Strategy = struct { |
| 278 | elide_store_to_block_ptr_instructions: bool, |
| 279 | tag: Tag, |
| 280 | |
| 281 | pub const Tag = enum { |
| 282 | /// Both branches will use break_void; result location is used to communicate the |
| 283 | /// result instruction. |
| 284 | break_void, |
| 285 | /// Use break statements to pass the block result value, and call rvalue() at |
| 286 | /// the end depending on rl. Also elide the store_to_block_ptr instructions |
| 287 | /// depending on rl. |
| 288 | break_operand, |
| 289 | }; |
| 317 | 290 | }; |
| 318 | | } |
| 291 | |
| 292 | fn strategy(rl: Loc, block_scope: *GenZir) Strategy { |
| 293 | switch (rl) { |
| 294 | // In this branch there will not be any store_to_block_ptr instructions. |
| 295 | .none, .ty, .coerced_ty, .ref => return .{ |
| 296 | .tag = .break_operand, |
| 297 | .elide_store_to_block_ptr_instructions = false, |
| 298 | }, |
| 299 | .discard => return .{ |
| 300 | .tag = .break_void, |
| 301 | .elide_store_to_block_ptr_instructions = false, |
| 302 | }, |
| 303 | // The pointer got passed through to the sub-expressions, so we will use |
| 304 | // break_void here. |
| 305 | // In this branch there will not be any store_to_block_ptr instructions. |
| 306 | .ptr => return .{ |
| 307 | .tag = .break_void, |
| 308 | .elide_store_to_block_ptr_instructions = false, |
| 309 | }, |
| 310 | .inferred_ptr, .block_ptr => { |
| 311 | if (block_scope.rvalue_rl_count == block_scope.break_count) { |
| 312 | // Neither prong of the if consumed the result location, so we can |
| 313 | // use break instructions to create an rvalue. |
| 314 | return .{ |
| 315 | .tag = .break_operand, |
| 316 | .elide_store_to_block_ptr_instructions = true, |
| 317 | }; |
| 318 | } else { |
| 319 | // Allow the store_to_block_ptr instructions to remain so that |
| 320 | // semantic analysis can turn them into bitcasts. |
| 321 | return .{ |
| 322 | .tag = .break_void, |
| 323 | .elide_store_to_block_ptr_instructions = false, |
| 324 | }; |
| 325 | } |
| 326 | }, |
| 327 | } |
| 328 | } |
| 329 | }; |
| 330 | |
| 331 | pub const Context = enum { |
| 332 | /// The expression is the operand to a return expression. |
| 333 | @"return", |
| 334 | /// The expression is the input to an error-handling operator (if-else, try, or catch). |
| 335 | error_handling_expr, |
| 336 | /// The expression is the right-hand side of a shift operation. |
| 337 | shift_op, |
| 338 | /// The expression is an argument in a function call. |
| 339 | fn_arg, |
| 340 | /// The expression is the right-hand side of an initializer for a `const` variable |
| 341 | const_init, |
| 342 | /// No specific operator in particular. |
| 343 | none, |
| 344 | }; |
| 319 | 345 | }; |
| 320 | 346 | |
| 321 | | pub const align_rl: ResultLoc = .{ .ty = .u29_type }; |
| 322 | | pub const coerced_align_rl: ResultLoc = .{ .coerced_ty = .u29_type }; |
| 323 | | pub const bool_rl: ResultLoc = .{ .ty = .bool_type }; |
| 324 | | pub const type_rl: ResultLoc = .{ .ty = .type_type }; |
| 325 | | pub const coerced_type_rl: ResultLoc = .{ .coerced_ty = .type_type }; |
| 347 | pub const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } }; |
| 348 | pub const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } }; |
| 349 | pub const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } }; |
| 350 | pub const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } }; |
| 351 | pub const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } }; |
| 326 | 352 | |
| 327 | 353 | fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 328 | 354 | const prev_force_comptime = gz.force_comptime; |
| 329 | 355 | gz.force_comptime = true; |
| 330 | 356 | defer gz.force_comptime = prev_force_comptime; |
| 331 | 357 | |
| 332 | | return expr(gz, scope, coerced_type_rl, type_node); |
| 358 | return expr(gz, scope, coerced_type_ri, type_node); |
| 333 | 359 | } |
| 334 | 360 | |
| 335 | 361 | fn reachableTypeExpr( |
| ... | ... | @@ -342,24 +368,24 @@ fn reachableTypeExpr( |
| 342 | 368 | gz.force_comptime = true; |
| 343 | 369 | defer gz.force_comptime = prev_force_comptime; |
| 344 | 370 | |
| 345 | | return reachableExpr(gz, scope, coerced_type_rl, type_node, reachable_node); |
| 371 | return reachableExpr(gz, scope, coerced_type_ri, type_node, reachable_node); |
| 346 | 372 | } |
| 347 | 373 | |
| 348 | 374 | /// Same as `expr` but fails with a compile error if the result type is `noreturn`. |
| 349 | 375 | fn reachableExpr( |
| 350 | 376 | gz: *GenZir, |
| 351 | 377 | scope: *Scope, |
| 352 | | rl: ResultLoc, |
| 378 | ri: ResultInfo, |
| 353 | 379 | node: Ast.Node.Index, |
| 354 | 380 | reachable_node: Ast.Node.Index, |
| 355 | 381 | ) InnerError!Zir.Inst.Ref { |
| 356 | | return reachableExprComptime(gz, scope, rl, node, reachable_node, false); |
| 382 | return reachableExprComptime(gz, scope, ri, node, reachable_node, false); |
| 357 | 383 | } |
| 358 | 384 | |
| 359 | 385 | fn reachableExprComptime( |
| 360 | 386 | gz: *GenZir, |
| 361 | 387 | scope: *Scope, |
| 362 | | rl: ResultLoc, |
| 388 | ri: ResultInfo, |
| 363 | 389 | node: Ast.Node.Index, |
| 364 | 390 | reachable_node: Ast.Node.Index, |
| 365 | 391 | force_comptime: bool, |
| ... | ... | @@ -368,7 +394,7 @@ fn reachableExprComptime( |
| 368 | 394 | gz.force_comptime = prev_force_comptime or force_comptime; |
| 369 | 395 | defer gz.force_comptime = prev_force_comptime; |
| 370 | 396 | |
| 371 | | const result_inst = try expr(gz, scope, rl, node); |
| 397 | const result_inst = try expr(gz, scope, ri, node); |
| 372 | 398 | if (gz.refIsNoReturn(result_inst)) { |
| 373 | 399 | try gz.astgen.appendErrorNodeNotes(reachable_node, "unreachable code", .{}, &[_]u32{ |
| 374 | 400 | try gz.astgen.errNoteNode(node, "control flow is diverted here", .{}), |
| ... | ... | @@ -569,14 +595,14 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins |
| 569 | 595 | .@"orelse", |
| 570 | 596 | => {}, |
| 571 | 597 | } |
| 572 | | return expr(gz, scope, .ref, node); |
| 598 | return expr(gz, scope, .{ .rl = .ref }, node); |
| 573 | 599 | } |
| 574 | 600 | |
| 575 | 601 | /// Turn Zig AST into untyped ZIR instructions. |
| 576 | 602 | /// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the |
| 577 | 603 | /// result instruction can be used to inspect whether it is isNoReturn() but that is it, |
| 578 | 604 | /// it must otherwise not be used. |
| 579 | | fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 605 | fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 580 | 606 | const astgen = gz.astgen; |
| 581 | 607 | const tree = astgen.tree; |
| 582 | 608 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -617,161 +643,161 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 617 | 643 | |
| 618 | 644 | .assign => { |
| 619 | 645 | try assign(gz, scope, node); |
| 620 | | return rvalue(gz, rl, .void_value, node); |
| 646 | return rvalue(gz, ri, .void_value, node); |
| 621 | 647 | }, |
| 622 | 648 | |
| 623 | 649 | .assign_shl => { |
| 624 | 650 | try assignShift(gz, scope, node, .shl); |
| 625 | | return rvalue(gz, rl, .void_value, node); |
| 651 | return rvalue(gz, ri, .void_value, node); |
| 626 | 652 | }, |
| 627 | 653 | .assign_shl_sat => { |
| 628 | 654 | try assignShiftSat(gz, scope, node); |
| 629 | | return rvalue(gz, rl, .void_value, node); |
| 655 | return rvalue(gz, ri, .void_value, node); |
| 630 | 656 | }, |
| 631 | 657 | .assign_shr => { |
| 632 | 658 | try assignShift(gz, scope, node, .shr); |
| 633 | | return rvalue(gz, rl, .void_value, node); |
| 659 | return rvalue(gz, ri, .void_value, node); |
| 634 | 660 | }, |
| 635 | 661 | |
| 636 | 662 | .assign_bit_and => { |
| 637 | 663 | try assignOp(gz, scope, node, .bit_and); |
| 638 | | return rvalue(gz, rl, .void_value, node); |
| 664 | return rvalue(gz, ri, .void_value, node); |
| 639 | 665 | }, |
| 640 | 666 | .assign_bit_or => { |
| 641 | 667 | try assignOp(gz, scope, node, .bit_or); |
| 642 | | return rvalue(gz, rl, .void_value, node); |
| 668 | return rvalue(gz, ri, .void_value, node); |
| 643 | 669 | }, |
| 644 | 670 | .assign_bit_xor => { |
| 645 | 671 | try assignOp(gz, scope, node, .xor); |
| 646 | | return rvalue(gz, rl, .void_value, node); |
| 672 | return rvalue(gz, ri, .void_value, node); |
| 647 | 673 | }, |
| 648 | 674 | .assign_div => { |
| 649 | 675 | try assignOp(gz, scope, node, .div); |
| 650 | | return rvalue(gz, rl, .void_value, node); |
| 676 | return rvalue(gz, ri, .void_value, node); |
| 651 | 677 | }, |
| 652 | 678 | .assign_sub => { |
| 653 | 679 | try assignOp(gz, scope, node, .sub); |
| 654 | | return rvalue(gz, rl, .void_value, node); |
| 680 | return rvalue(gz, ri, .void_value, node); |
| 655 | 681 | }, |
| 656 | 682 | .assign_sub_wrap => { |
| 657 | 683 | try assignOp(gz, scope, node, .subwrap); |
| 658 | | return rvalue(gz, rl, .void_value, node); |
| 684 | return rvalue(gz, ri, .void_value, node); |
| 659 | 685 | }, |
| 660 | 686 | .assign_sub_sat => { |
| 661 | 687 | try assignOp(gz, scope, node, .sub_sat); |
| 662 | | return rvalue(gz, rl, .void_value, node); |
| 688 | return rvalue(gz, ri, .void_value, node); |
| 663 | 689 | }, |
| 664 | 690 | .assign_mod => { |
| 665 | 691 | try assignOp(gz, scope, node, .mod_rem); |
| 666 | | return rvalue(gz, rl, .void_value, node); |
| 692 | return rvalue(gz, ri, .void_value, node); |
| 667 | 693 | }, |
| 668 | 694 | .assign_add => { |
| 669 | 695 | try assignOp(gz, scope, node, .add); |
| 670 | | return rvalue(gz, rl, .void_value, node); |
| 696 | return rvalue(gz, ri, .void_value, node); |
| 671 | 697 | }, |
| 672 | 698 | .assign_add_wrap => { |
| 673 | 699 | try assignOp(gz, scope, node, .addwrap); |
| 674 | | return rvalue(gz, rl, .void_value, node); |
| 700 | return rvalue(gz, ri, .void_value, node); |
| 675 | 701 | }, |
| 676 | 702 | .assign_add_sat => { |
| 677 | 703 | try assignOp(gz, scope, node, .add_sat); |
| 678 | | return rvalue(gz, rl, .void_value, node); |
| 704 | return rvalue(gz, ri, .void_value, node); |
| 679 | 705 | }, |
| 680 | 706 | .assign_mul => { |
| 681 | 707 | try assignOp(gz, scope, node, .mul); |
| 682 | | return rvalue(gz, rl, .void_value, node); |
| 708 | return rvalue(gz, ri, .void_value, node); |
| 683 | 709 | }, |
| 684 | 710 | .assign_mul_wrap => { |
| 685 | 711 | try assignOp(gz, scope, node, .mulwrap); |
| 686 | | return rvalue(gz, rl, .void_value, node); |
| 712 | return rvalue(gz, ri, .void_value, node); |
| 687 | 713 | }, |
| 688 | 714 | .assign_mul_sat => { |
| 689 | 715 | try assignOp(gz, scope, node, .mul_sat); |
| 690 | | return rvalue(gz, rl, .void_value, node); |
| 716 | return rvalue(gz, ri, .void_value, node); |
| 691 | 717 | }, |
| 692 | 718 | |
| 693 | 719 | // zig fmt: off |
| 694 | | .shl => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shl), |
| 695 | | .shr => return shiftOp(gz, scope, rl, node, node_datas[node].lhs, node_datas[node].rhs, .shr), |
| 696 | | |
| 697 | | .add => return simpleBinOp(gz, scope, rl, node, .add), |
| 698 | | .add_wrap => return simpleBinOp(gz, scope, rl, node, .addwrap), |
| 699 | | .add_sat => return simpleBinOp(gz, scope, rl, node, .add_sat), |
| 700 | | .sub => return simpleBinOp(gz, scope, rl, node, .sub), |
| 701 | | .sub_wrap => return simpleBinOp(gz, scope, rl, node, .subwrap), |
| 702 | | .sub_sat => return simpleBinOp(gz, scope, rl, node, .sub_sat), |
| 703 | | .mul => return simpleBinOp(gz, scope, rl, node, .mul), |
| 704 | | .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap), |
| 705 | | .mul_sat => return simpleBinOp(gz, scope, rl, node, .mul_sat), |
| 706 | | .div => return simpleBinOp(gz, scope, rl, node, .div), |
| 707 | | .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem), |
| 708 | | .shl_sat => return simpleBinOp(gz, scope, rl, node, .shl_sat), |
| 709 | | |
| 710 | | .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and), |
| 711 | | .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or), |
| 712 | | .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor), |
| 713 | | .bang_equal => return simpleBinOp(gz, scope, rl, node, .cmp_neq), |
| 714 | | .equal_equal => return simpleBinOp(gz, scope, rl, node, .cmp_eq), |
| 715 | | .greater_than => return simpleBinOp(gz, scope, rl, node, .cmp_gt), |
| 716 | | .greater_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_gte), |
| 717 | | .less_than => return simpleBinOp(gz, scope, rl, node, .cmp_lt), |
| 718 | | .less_or_equal => return simpleBinOp(gz, scope, rl, node, .cmp_lte), |
| 719 | | .array_cat => return simpleBinOp(gz, scope, rl, node, .array_cat), |
| 720 | .shl => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shl), |
| 721 | .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr), |
| 722 | |
| 723 | .add => return simpleBinOp(gz, scope, ri, node, .add), |
| 724 | .add_wrap => return simpleBinOp(gz, scope, ri, node, .addwrap), |
| 725 | .add_sat => return simpleBinOp(gz, scope, ri, node, .add_sat), |
| 726 | .sub => return simpleBinOp(gz, scope, ri, node, .sub), |
| 727 | .sub_wrap => return simpleBinOp(gz, scope, ri, node, .subwrap), |
| 728 | .sub_sat => return simpleBinOp(gz, scope, ri, node, .sub_sat), |
| 729 | .mul => return simpleBinOp(gz, scope, ri, node, .mul), |
| 730 | .mul_wrap => return simpleBinOp(gz, scope, ri, node, .mulwrap), |
| 731 | .mul_sat => return simpleBinOp(gz, scope, ri, node, .mul_sat), |
| 732 | .div => return simpleBinOp(gz, scope, ri, node, .div), |
| 733 | .mod => return simpleBinOp(gz, scope, ri, node, .mod_rem), |
| 734 | .shl_sat => return simpleBinOp(gz, scope, ri, node, .shl_sat), |
| 735 | |
| 736 | .bit_and => return simpleBinOp(gz, scope, ri, node, .bit_and), |
| 737 | .bit_or => return simpleBinOp(gz, scope, ri, node, .bit_or), |
| 738 | .bit_xor => return simpleBinOp(gz, scope, ri, node, .xor), |
| 739 | .bang_equal => return simpleBinOp(gz, scope, ri, node, .cmp_neq), |
| 740 | .equal_equal => return simpleBinOp(gz, scope, ri, node, .cmp_eq), |
| 741 | .greater_than => return simpleBinOp(gz, scope, ri, node, .cmp_gt), |
| 742 | .greater_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_gte), |
| 743 | .less_than => return simpleBinOp(gz, scope, ri, node, .cmp_lt), |
| 744 | .less_or_equal => return simpleBinOp(gz, scope, ri, node, .cmp_lte), |
| 745 | .array_cat => return simpleBinOp(gz, scope, ri, node, .array_cat), |
| 720 | 746 | |
| 721 | 747 | .array_mult => { |
| 722 | 748 | const result = try gz.addPlNode(.array_mul, node, Zir.Inst.Bin{ |
| 723 | | .lhs = try expr(gz, scope, .none, node_datas[node].lhs), |
| 724 | | .rhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs), |
| 749 | .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), |
| 750 | .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs), |
| 725 | 751 | }); |
| 726 | | return rvalue(gz, rl, result, node); |
| 752 | return rvalue(gz, ri, result, node); |
| 727 | 753 | }, |
| 728 | 754 | |
| 729 | | .error_union => return simpleBinOp(gz, scope, rl, node, .error_union_type), |
| 730 | | .merge_error_sets => return simpleBinOp(gz, scope, rl, node, .merge_error_sets), |
| 755 | .error_union => return simpleBinOp(gz, scope, ri, node, .error_union_type), |
| 756 | .merge_error_sets => return simpleBinOp(gz, scope, ri, node, .merge_error_sets), |
| 731 | 757 | |
| 732 | | .bool_and => return boolBinOp(gz, scope, rl, node, .bool_br_and), |
| 733 | | .bool_or => return boolBinOp(gz, scope, rl, node, .bool_br_or), |
| 758 | .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and), |
| 759 | .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or), |
| 734 | 760 | |
| 735 | | .bool_not => return simpleUnOp(gz, scope, rl, node, bool_rl, node_datas[node].lhs, .bool_not), |
| 736 | | .bit_not => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .bit_not), |
| 761 | .bool_not => return simpleUnOp(gz, scope, ri, node, bool_ri, node_datas[node].lhs, .bool_not), |
| 762 | .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not), |
| 737 | 763 | |
| 738 | | .negation => return negation(gz, scope, rl, node), |
| 739 | | .negation_wrap => return simpleUnOp(gz, scope, rl, node, .none, node_datas[node].lhs, .negate_wrap), |
| 764 | .negation => return negation(gz, scope, ri, node), |
| 765 | .negation_wrap => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .negate_wrap), |
| 740 | 766 | |
| 741 | | .identifier => return identifier(gz, scope, rl, node), |
| 767 | .identifier => return identifier(gz, scope, ri, node), |
| 742 | 768 | |
| 743 | | .asm_simple => return asmExpr(gz, scope, rl, node, tree.asmSimple(node)), |
| 744 | | .@"asm" => return asmExpr(gz, scope, rl, node, tree.asmFull(node)), |
| 769 | .asm_simple => return asmExpr(gz, scope, ri, node, tree.asmSimple(node)), |
| 770 | .@"asm" => return asmExpr(gz, scope, ri, node, tree.asmFull(node)), |
| 745 | 771 | |
| 746 | | .string_literal => return stringLiteral(gz, rl, node), |
| 747 | | .multiline_string_literal => return multilineStringLiteral(gz, rl, node), |
| 772 | .string_literal => return stringLiteral(gz, ri, node), |
| 773 | .multiline_string_literal => return multilineStringLiteral(gz, ri, node), |
| 748 | 774 | |
| 749 | | .number_literal => return numberLiteral(gz, rl, node, node, .positive), |
| 775 | .number_literal => return numberLiteral(gz, ri, node, node, .positive), |
| 750 | 776 | // zig fmt: on |
| 751 | 777 | |
| 752 | 778 | .builtin_call_two, .builtin_call_two_comma => { |
| 753 | 779 | if (node_datas[node].lhs == 0) { |
| 754 | 780 | const params = [_]Ast.Node.Index{}; |
| 755 | | return builtinCall(gz, scope, rl, node, &params); |
| 781 | return builtinCall(gz, scope, ri, node, &params); |
| 756 | 782 | } else if (node_datas[node].rhs == 0) { |
| 757 | 783 | const params = [_]Ast.Node.Index{node_datas[node].lhs}; |
| 758 | | return builtinCall(gz, scope, rl, node, &params); |
| 784 | return builtinCall(gz, scope, ri, node, &params); |
| 759 | 785 | } else { |
| 760 | 786 | const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; |
| 761 | | return builtinCall(gz, scope, rl, node, &params); |
| 787 | return builtinCall(gz, scope, ri, node, &params); |
| 762 | 788 | } |
| 763 | 789 | }, |
| 764 | 790 | .builtin_call, .builtin_call_comma => { |
| 765 | 791 | const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; |
| 766 | | return builtinCall(gz, scope, rl, node, params); |
| 792 | return builtinCall(gz, scope, ri, node, params); |
| 767 | 793 | }, |
| 768 | 794 | |
| 769 | 795 | .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => { |
| 770 | 796 | var params: [1]Ast.Node.Index = undefined; |
| 771 | | return callExpr(gz, scope, rl, node, tree.callOne(&params, node)); |
| 797 | return callExpr(gz, scope, ri, node, tree.callOne(&params, node)); |
| 772 | 798 | }, |
| 773 | 799 | .call, .call_comma, .async_call, .async_call_comma => { |
| 774 | | return callExpr(gz, scope, rl, node, tree.callFull(node)); |
| 800 | return callExpr(gz, scope, ri, node, tree.callFull(node)); |
| 775 | 801 | }, |
| 776 | 802 | |
| 777 | 803 | .unreachable_literal => { |
| ... | ... | @@ -786,112 +812,112 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 786 | 812 | return Zir.Inst.Ref.unreachable_value; |
| 787 | 813 | }, |
| 788 | 814 | .@"return" => return ret(gz, scope, node), |
| 789 | | .field_access => return fieldAccess(gz, scope, rl, node), |
| 815 | .field_access => return fieldAccess(gz, scope, ri, node), |
| 790 | 816 | |
| 791 | | .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)), |
| 792 | | .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)), |
| 817 | .if_simple => return ifExpr(gz, scope, ri.br(), node, tree.ifSimple(node)), |
| 818 | .@"if" => return ifExpr(gz, scope, ri.br(), node, tree.ifFull(node)), |
| 793 | 819 | |
| 794 | | .while_simple => return whileExpr(gz, scope, rl.br(), node, tree.whileSimple(node), false), |
| 795 | | .while_cont => return whileExpr(gz, scope, rl.br(), node, tree.whileCont(node), false), |
| 796 | | .@"while" => return whileExpr(gz, scope, rl.br(), node, tree.whileFull(node), false), |
| 820 | .while_simple => return whileExpr(gz, scope, ri.br(), node, tree.whileSimple(node), false), |
| 821 | .while_cont => return whileExpr(gz, scope, ri.br(), node, tree.whileCont(node), false), |
| 822 | .@"while" => return whileExpr(gz, scope, ri.br(), node, tree.whileFull(node), false), |
| 797 | 823 | |
| 798 | | .for_simple => return forExpr(gz, scope, rl.br(), node, tree.forSimple(node), false), |
| 799 | | .@"for" => return forExpr(gz, scope, rl.br(), node, tree.forFull(node), false), |
| 824 | .for_simple => return forExpr(gz, scope, ri.br(), node, tree.forSimple(node), false), |
| 825 | .@"for" => return forExpr(gz, scope, ri.br(), node, tree.forFull(node), false), |
| 800 | 826 | |
| 801 | 827 | .slice_open => { |
| 802 | | const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); |
| 803 | | const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, node_datas[node].rhs); |
| 828 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 829 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); |
| 804 | 830 | const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{ |
| 805 | 831 | .lhs = lhs, |
| 806 | 832 | .start = start, |
| 807 | 833 | }); |
| 808 | | return rvalue(gz, rl, result, node); |
| 834 | return rvalue(gz, ri, result, node); |
| 809 | 835 | }, |
| 810 | 836 | .slice => { |
| 811 | | const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); |
| 837 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 812 | 838 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); |
| 813 | | const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start); |
| 814 | | const end = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end); |
| 839 | 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); |
| 815 | 841 | const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{ |
| 816 | 842 | .lhs = lhs, |
| 817 | 843 | .start = start, |
| 818 | 844 | .end = end, |
| 819 | 845 | }); |
| 820 | | return rvalue(gz, rl, result, node); |
| 846 | return rvalue(gz, ri, result, node); |
| 821 | 847 | }, |
| 822 | 848 | .slice_sentinel => { |
| 823 | | const lhs = try expr(gz, scope, .ref, node_datas[node].lhs); |
| 849 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 824 | 850 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); |
| 825 | | const start = try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.start); |
| 826 | | const end = if (extra.end != 0) try expr(gz, scope, .{ .coerced_ty = .usize_type }, extra.end) else .none; |
| 827 | | const sentinel = try expr(gz, scope, .none, extra.sentinel); |
| 851 | 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; |
| 853 | const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel); |
| 828 | 854 | const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{ |
| 829 | 855 | .lhs = lhs, |
| 830 | 856 | .start = start, |
| 831 | 857 | .end = end, |
| 832 | 858 | .sentinel = sentinel, |
| 833 | 859 | }); |
| 834 | | return rvalue(gz, rl, result, node); |
| 860 | return rvalue(gz, ri, result, node); |
| 835 | 861 | }, |
| 836 | 862 | |
| 837 | 863 | .deref => { |
| 838 | | const lhs = try expr(gz, scope, .none, node_datas[node].lhs); |
| 864 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); |
| 839 | 865 | _ = try gz.addUnNode(.validate_deref, lhs, node); |
| 840 | | switch (rl) { |
| 866 | switch (ri.rl) { |
| 841 | 867 | .ref => return lhs, |
| 842 | 868 | else => { |
| 843 | 869 | const result = try gz.addUnNode(.load, lhs, node); |
| 844 | | return rvalue(gz, rl, result, node); |
| 870 | return rvalue(gz, ri, result, node); |
| 845 | 871 | }, |
| 846 | 872 | } |
| 847 | 873 | }, |
| 848 | 874 | .address_of => { |
| 849 | | const result = try expr(gz, scope, .ref, node_datas[node].lhs); |
| 850 | | return rvalue(gz, rl, result, node); |
| 875 | const result = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); |
| 876 | return rvalue(gz, ri, result, node); |
| 851 | 877 | }, |
| 852 | 878 | .optional_type => { |
| 853 | 879 | const operand = try typeExpr(gz, scope, node_datas[node].lhs); |
| 854 | 880 | const result = try gz.addUnNode(.optional_type, operand, node); |
| 855 | | return rvalue(gz, rl, result, node); |
| 881 | return rvalue(gz, ri, result, node); |
| 856 | 882 | }, |
| 857 | | .unwrap_optional => switch (rl) { |
| 883 | .unwrap_optional => switch (ri.rl) { |
| 858 | 884 | .ref => return gz.addUnNode( |
| 859 | 885 | .optional_payload_safe_ptr, |
| 860 | | try expr(gz, scope, .ref, node_datas[node].lhs), |
| 886 | try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs), |
| 861 | 887 | node, |
| 862 | 888 | ), |
| 863 | | else => return rvalue(gz, rl, try gz.addUnNode( |
| 889 | else => return rvalue(gz, ri, try gz.addUnNode( |
| 864 | 890 | .optional_payload_safe, |
| 865 | | try expr(gz, scope, .none, node_datas[node].lhs), |
| 891 | try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), |
| 866 | 892 | node, |
| 867 | 893 | ), node), |
| 868 | 894 | }, |
| 869 | 895 | .block_two, .block_two_semicolon => { |
| 870 | 896 | const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; |
| 871 | 897 | if (node_datas[node].lhs == 0) { |
| 872 | | return blockExpr(gz, scope, rl, node, statements[0..0]); |
| 898 | return blockExpr(gz, scope, ri, node, statements[0..0]); |
| 873 | 899 | } else if (node_datas[node].rhs == 0) { |
| 874 | | return blockExpr(gz, scope, rl, node, statements[0..1]); |
| 900 | return blockExpr(gz, scope, ri, node, statements[0..1]); |
| 875 | 901 | } else { |
| 876 | | return blockExpr(gz, scope, rl, node, statements[0..2]); |
| 902 | return blockExpr(gz, scope, ri, node, statements[0..2]); |
| 877 | 903 | } |
| 878 | 904 | }, |
| 879 | 905 | .block, .block_semicolon => { |
| 880 | 906 | const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; |
| 881 | | return blockExpr(gz, scope, rl, node, statements); |
| 907 | return blockExpr(gz, scope, ri, node, statements); |
| 882 | 908 | }, |
| 883 | | .enum_literal => return simpleStrTok(gz, rl, main_tokens[node], node, .enum_literal), |
| 884 | | .error_value => return simpleStrTok(gz, rl, node_datas[node].rhs, node, .error_value), |
| 909 | .enum_literal => return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal), |
| 910 | .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value), |
| 885 | 911 | // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025 |
| 886 | | // .anyframe_literal => return rvalue(gz, rl, .anyframe_type, node), |
| 912 | // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node), |
| 887 | 913 | .anyframe_literal => { |
| 888 | 914 | const result = try gz.addUnNode(.anyframe_type, .void_type, node); |
| 889 | | return rvalue(gz, rl, result, node); |
| 915 | return rvalue(gz, ri, result, node); |
| 890 | 916 | }, |
| 891 | 917 | .anyframe_type => { |
| 892 | 918 | const return_type = try typeExpr(gz, scope, node_datas[node].rhs); |
| 893 | 919 | const result = try gz.addUnNode(.anyframe_type, return_type, node); |
| 894 | | return rvalue(gz, rl, result, node); |
| 920 | return rvalue(gz, ri, result, node); |
| 895 | 921 | }, |
| 896 | 922 | .@"catch" => { |
| 897 | 923 | const catch_token = main_tokens[node]; |
| ... | ... | @@ -899,11 +925,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 899 | 925 | catch_token + 2 |
| 900 | 926 | else |
| 901 | 927 | null; |
| 902 | | switch (rl) { |
| 928 | switch (ri.rl) { |
| 903 | 929 | .ref => return orelseCatchExpr( |
| 904 | 930 | gz, |
| 905 | 931 | scope, |
| 906 | | rl, |
| 932 | ri, |
| 907 | 933 | node, |
| 908 | 934 | node_datas[node].lhs, |
| 909 | 935 | .is_non_err_ptr, |
| ... | ... | @@ -915,7 +941,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 915 | 941 | else => return orelseCatchExpr( |
| 916 | 942 | gz, |
| 917 | 943 | scope, |
| 918 | | rl, |
| 944 | ri, |
| 919 | 945 | node, |
| 920 | 946 | node_datas[node].lhs, |
| 921 | 947 | .is_non_err, |
| ... | ... | @@ -926,11 +952,11 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 926 | 952 | ), |
| 927 | 953 | } |
| 928 | 954 | }, |
| 929 | | .@"orelse" => switch (rl) { |
| 955 | .@"orelse" => switch (ri.rl) { |
| 930 | 956 | .ref => return orelseCatchExpr( |
| 931 | 957 | gz, |
| 932 | 958 | scope, |
| 933 | | rl, |
| 959 | ri, |
| 934 | 960 | node, |
| 935 | 961 | node_datas[node].lhs, |
| 936 | 962 | .is_non_null_ptr, |
| ... | ... | @@ -942,7 +968,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 942 | 968 | else => return orelseCatchExpr( |
| 943 | 969 | gz, |
| 944 | 970 | scope, |
| 945 | | rl, |
| 971 | ri, |
| 946 | 972 | node, |
| 947 | 973 | node_datas[node].lhs, |
| 948 | 974 | .is_non_null, |
| ... | ... | @@ -953,94 +979,94 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 953 | 979 | ), |
| 954 | 980 | }, |
| 955 | 981 | |
| 956 | | .ptr_type_aligned => return ptrType(gz, scope, rl, node, tree.ptrTypeAligned(node)), |
| 957 | | .ptr_type_sentinel => return ptrType(gz, scope, rl, node, tree.ptrTypeSentinel(node)), |
| 958 | | .ptr_type => return ptrType(gz, scope, rl, node, tree.ptrType(node)), |
| 959 | | .ptr_type_bit_range => return ptrType(gz, scope, rl, node, tree.ptrTypeBitRange(node)), |
| 982 | .ptr_type_aligned => return ptrType(gz, scope, ri, node, tree.ptrTypeAligned(node)), |
| 983 | .ptr_type_sentinel => return ptrType(gz, scope, ri, node, tree.ptrTypeSentinel(node)), |
| 984 | .ptr_type => return ptrType(gz, scope, ri, node, tree.ptrType(node)), |
| 985 | .ptr_type_bit_range => return ptrType(gz, scope, ri, node, tree.ptrTypeBitRange(node)), |
| 960 | 986 | |
| 961 | 987 | .container_decl, |
| 962 | 988 | .container_decl_trailing, |
| 963 | | => return containerDecl(gz, scope, rl, node, tree.containerDecl(node)), |
| 989 | => return containerDecl(gz, scope, ri, node, tree.containerDecl(node)), |
| 964 | 990 | .container_decl_two, .container_decl_two_trailing => { |
| 965 | 991 | var buffer: [2]Ast.Node.Index = undefined; |
| 966 | | return containerDecl(gz, scope, rl, node, tree.containerDeclTwo(&buffer, node)); |
| 992 | return containerDecl(gz, scope, ri, node, tree.containerDeclTwo(&buffer, node)); |
| 967 | 993 | }, |
| 968 | 994 | .container_decl_arg, |
| 969 | 995 | .container_decl_arg_trailing, |
| 970 | | => return containerDecl(gz, scope, rl, node, tree.containerDeclArg(node)), |
| 996 | => return containerDecl(gz, scope, ri, node, tree.containerDeclArg(node)), |
| 971 | 997 | |
| 972 | 998 | .tagged_union, |
| 973 | 999 | .tagged_union_trailing, |
| 974 | | => return containerDecl(gz, scope, rl, node, tree.taggedUnion(node)), |
| 1000 | => return containerDecl(gz, scope, ri, node, tree.taggedUnion(node)), |
| 975 | 1001 | .tagged_union_two, .tagged_union_two_trailing => { |
| 976 | 1002 | var buffer: [2]Ast.Node.Index = undefined; |
| 977 | | return containerDecl(gz, scope, rl, node, tree.taggedUnionTwo(&buffer, node)); |
| 1003 | return containerDecl(gz, scope, ri, node, tree.taggedUnionTwo(&buffer, node)); |
| 978 | 1004 | }, |
| 979 | 1005 | .tagged_union_enum_tag, |
| 980 | 1006 | .tagged_union_enum_tag_trailing, |
| 981 | | => return containerDecl(gz, scope, rl, node, tree.taggedUnionEnumTag(node)), |
| 1007 | => return containerDecl(gz, scope, ri, node, tree.taggedUnionEnumTag(node)), |
| 982 | 1008 | |
| 983 | 1009 | .@"break" => return breakExpr(gz, scope, node), |
| 984 | 1010 | .@"continue" => return continueExpr(gz, scope, node), |
| 985 | | .grouped_expression => return expr(gz, scope, rl, node_datas[node].lhs), |
| 986 | | .array_type => return arrayType(gz, scope, rl, node), |
| 987 | | .array_type_sentinel => return arrayTypeSentinel(gz, scope, rl, node), |
| 988 | | .char_literal => return charLiteral(gz, rl, node), |
| 989 | | .error_set_decl => return errorSetDecl(gz, rl, node), |
| 990 | | .array_access => return arrayAccess(gz, scope, rl, node), |
| 991 | | .@"comptime" => return comptimeExprAst(gz, scope, rl, node), |
| 992 | | .@"switch", .switch_comma => return switchExpr(gz, scope, rl.br(), node), |
| 993 | | |
| 994 | | .@"nosuspend" => return nosuspendExpr(gz, scope, rl, node), |
| 1011 | .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs), |
| 1012 | .array_type => return arrayType(gz, scope, ri, node), |
| 1013 | .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node), |
| 1014 | .char_literal => return charLiteral(gz, ri, node), |
| 1015 | .error_set_decl => return errorSetDecl(gz, ri, node), |
| 1016 | .array_access => return arrayAccess(gz, scope, ri, node), |
| 1017 | .@"comptime" => return comptimeExprAst(gz, scope, ri, node), |
| 1018 | .@"switch", .switch_comma => return switchExpr(gz, scope, ri.br(), node), |
| 1019 | |
| 1020 | .@"nosuspend" => return nosuspendExpr(gz, scope, ri, node), |
| 995 | 1021 | .@"suspend" => return suspendExpr(gz, scope, node), |
| 996 | | .@"await" => return awaitExpr(gz, scope, rl, node), |
| 997 | | .@"resume" => return resumeExpr(gz, scope, rl, node), |
| 1022 | .@"await" => return awaitExpr(gz, scope, ri, node), |
| 1023 | .@"resume" => return resumeExpr(gz, scope, ri, node), |
| 998 | 1024 | |
| 999 | | .@"try" => return tryExpr(gz, scope, rl, node, node_datas[node].lhs), |
| 1025 | .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs), |
| 1000 | 1026 | |
| 1001 | 1027 | .array_init_one, .array_init_one_comma => { |
| 1002 | 1028 | var elements: [1]Ast.Node.Index = undefined; |
| 1003 | | return arrayInitExpr(gz, scope, rl, node, tree.arrayInitOne(&elements, node)); |
| 1029 | return arrayInitExpr(gz, scope, ri, node, tree.arrayInitOne(&elements, node)); |
| 1004 | 1030 | }, |
| 1005 | 1031 | .array_init_dot_two, .array_init_dot_two_comma => { |
| 1006 | 1032 | var elements: [2]Ast.Node.Index = undefined; |
| 1007 | | return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDotTwo(&elements, node)); |
| 1033 | return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDotTwo(&elements, node)); |
| 1008 | 1034 | }, |
| 1009 | 1035 | .array_init_dot, |
| 1010 | 1036 | .array_init_dot_comma, |
| 1011 | | => return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDot(node)), |
| 1037 | => return arrayInitExpr(gz, scope, ri, node, tree.arrayInitDot(node)), |
| 1012 | 1038 | .array_init, |
| 1013 | 1039 | .array_init_comma, |
| 1014 | | => return arrayInitExpr(gz, scope, rl, node, tree.arrayInit(node)), |
| 1040 | => return arrayInitExpr(gz, scope, ri, node, tree.arrayInit(node)), |
| 1015 | 1041 | |
| 1016 | 1042 | .struct_init_one, .struct_init_one_comma => { |
| 1017 | 1043 | var fields: [1]Ast.Node.Index = undefined; |
| 1018 | | return structInitExpr(gz, scope, rl, node, tree.structInitOne(&fields, node)); |
| 1044 | return structInitExpr(gz, scope, ri, node, tree.structInitOne(&fields, node)); |
| 1019 | 1045 | }, |
| 1020 | 1046 | .struct_init_dot_two, .struct_init_dot_two_comma => { |
| 1021 | 1047 | var fields: [2]Ast.Node.Index = undefined; |
| 1022 | | return structInitExpr(gz, scope, rl, node, tree.structInitDotTwo(&fields, node)); |
| 1048 | return structInitExpr(gz, scope, ri, node, tree.structInitDotTwo(&fields, node)); |
| 1023 | 1049 | }, |
| 1024 | 1050 | .struct_init_dot, |
| 1025 | 1051 | .struct_init_dot_comma, |
| 1026 | | => return structInitExpr(gz, scope, rl, node, tree.structInitDot(node)), |
| 1052 | => return structInitExpr(gz, scope, ri, node, tree.structInitDot(node)), |
| 1027 | 1053 | .struct_init, |
| 1028 | 1054 | .struct_init_comma, |
| 1029 | | => return structInitExpr(gz, scope, rl, node, tree.structInit(node)), |
| 1055 | => return structInitExpr(gz, scope, ri, node, tree.structInit(node)), |
| 1030 | 1056 | |
| 1031 | 1057 | .fn_proto_simple => { |
| 1032 | 1058 | var params: [1]Ast.Node.Index = undefined; |
| 1033 | | return fnProtoExpr(gz, scope, rl, node, tree.fnProtoSimple(&params, node)); |
| 1059 | return fnProtoExpr(gz, scope, ri, node, tree.fnProtoSimple(&params, node)); |
| 1034 | 1060 | }, |
| 1035 | 1061 | .fn_proto_multi => { |
| 1036 | | return fnProtoExpr(gz, scope, rl, node, tree.fnProtoMulti(node)); |
| 1062 | return fnProtoExpr(gz, scope, ri, node, tree.fnProtoMulti(node)); |
| 1037 | 1063 | }, |
| 1038 | 1064 | .fn_proto_one => { |
| 1039 | 1065 | var params: [1]Ast.Node.Index = undefined; |
| 1040 | | return fnProtoExpr(gz, scope, rl, node, tree.fnProtoOne(&params, node)); |
| 1066 | return fnProtoExpr(gz, scope, ri, node, tree.fnProtoOne(&params, node)); |
| 1041 | 1067 | }, |
| 1042 | 1068 | .fn_proto => { |
| 1043 | | return fnProtoExpr(gz, scope, rl, node, tree.fnProto(node)); |
| 1069 | return fnProtoExpr(gz, scope, ri, node, tree.fnProto(node)); |
| 1044 | 1070 | }, |
| 1045 | 1071 | } |
| 1046 | 1072 | } |
| ... | ... | @@ -1048,7 +1074,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 1048 | 1074 | fn nosuspendExpr( |
| 1049 | 1075 | gz: *GenZir, |
| 1050 | 1076 | scope: *Scope, |
| 1051 | | rl: ResultLoc, |
| 1077 | ri: ResultInfo, |
| 1052 | 1078 | node: Ast.Node.Index, |
| 1053 | 1079 | ) InnerError!Zir.Inst.Ref { |
| 1054 | 1080 | const astgen = gz.astgen; |
| ... | ... | @@ -1063,7 +1089,7 @@ fn nosuspendExpr( |
| 1063 | 1089 | } |
| 1064 | 1090 | gz.nosuspend_node = node; |
| 1065 | 1091 | defer gz.nosuspend_node = 0; |
| 1066 | | return expr(gz, scope, rl, body_node); |
| 1092 | return expr(gz, scope, ri, body_node); |
| 1067 | 1093 | } |
| 1068 | 1094 | |
| 1069 | 1095 | fn suspendExpr( |
| ... | ... | @@ -1096,7 +1122,7 @@ fn suspendExpr( |
| 1096 | 1122 | suspend_scope.suspend_node = node; |
| 1097 | 1123 | defer suspend_scope.unstack(); |
| 1098 | 1124 | |
| 1099 | | const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); |
| 1125 | const body_result = try expr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node); |
| 1100 | 1126 | if (!gz.refIsNoReturn(body_result)) { |
| 1101 | 1127 | _ = try suspend_scope.addBreak(.break_inline, suspend_inst, .void_value); |
| 1102 | 1128 | } |
| ... | ... | @@ -1108,7 +1134,7 @@ fn suspendExpr( |
| 1108 | 1134 | fn awaitExpr( |
| 1109 | 1135 | gz: *GenZir, |
| 1110 | 1136 | scope: *Scope, |
| 1111 | | rl: ResultLoc, |
| 1137 | ri: ResultInfo, |
| 1112 | 1138 | node: Ast.Node.Index, |
| 1113 | 1139 | ) InnerError!Zir.Inst.Ref { |
| 1114 | 1140 | const astgen = gz.astgen; |
| ... | ... | @@ -1121,7 +1147,7 @@ fn awaitExpr( |
| 1121 | 1147 | try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}), |
| 1122 | 1148 | }); |
| 1123 | 1149 | } |
| 1124 | | const operand = try expr(gz, scope, .none, rhs_node); |
| 1150 | const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node); |
| 1125 | 1151 | const result = if (gz.nosuspend_node != 0) |
| 1126 | 1152 | try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{ |
| 1127 | 1153 | .node = gz.nodeIndexToRelative(node), |
| ... | ... | @@ -1130,28 +1156,28 @@ fn awaitExpr( |
| 1130 | 1156 | else |
| 1131 | 1157 | try gz.addUnNode(.@"await", operand, node); |
| 1132 | 1158 | |
| 1133 | | return rvalue(gz, rl, result, node); |
| 1159 | return rvalue(gz, ri, result, node); |
| 1134 | 1160 | } |
| 1135 | 1161 | |
| 1136 | 1162 | fn resumeExpr( |
| 1137 | 1163 | gz: *GenZir, |
| 1138 | 1164 | scope: *Scope, |
| 1139 | | rl: ResultLoc, |
| 1165 | ri: ResultInfo, |
| 1140 | 1166 | node: Ast.Node.Index, |
| 1141 | 1167 | ) InnerError!Zir.Inst.Ref { |
| 1142 | 1168 | const astgen = gz.astgen; |
| 1143 | 1169 | const tree = astgen.tree; |
| 1144 | 1170 | const node_datas = tree.nodes.items(.data); |
| 1145 | 1171 | const rhs_node = node_datas[node].lhs; |
| 1146 | | const operand = try expr(gz, scope, .none, rhs_node); |
| 1172 | const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node); |
| 1147 | 1173 | const result = try gz.addUnNode(.@"resume", operand, node); |
| 1148 | | return rvalue(gz, rl, result, node); |
| 1174 | return rvalue(gz, ri, result, node); |
| 1149 | 1175 | } |
| 1150 | 1176 | |
| 1151 | 1177 | fn fnProtoExpr( |
| 1152 | 1178 | gz: *GenZir, |
| 1153 | 1179 | scope: *Scope, |
| 1154 | | rl: ResultLoc, |
| 1180 | ri: ResultInfo, |
| 1155 | 1181 | node: Ast.Node.Index, |
| 1156 | 1182 | fn_proto: Ast.full.FnProto, |
| 1157 | 1183 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -1217,7 +1243,7 @@ fn fnProtoExpr( |
| 1217 | 1243 | assert(param_type_node != 0); |
| 1218 | 1244 | var param_gz = block_scope.makeSubBlock(scope); |
| 1219 | 1245 | defer param_gz.unstack(); |
| 1220 | | const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node); |
| 1246 | const param_type = try expr(&param_gz, scope, coerced_type_ri, param_type_node); |
| 1221 | 1247 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 1222 | 1248 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| 1223 | 1249 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -1231,7 +1257,7 @@ fn fnProtoExpr( |
| 1231 | 1257 | }; |
| 1232 | 1258 | |
| 1233 | 1259 | const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 1234 | | break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr); |
| 1260 | break :inst try expr(&block_scope, scope, align_ri, fn_proto.ast.align_expr); |
| 1235 | 1261 | }; |
| 1236 | 1262 | |
| 1237 | 1263 | if (fn_proto.ast.addrspace_expr != 0) { |
| ... | ... | @@ -1246,7 +1272,7 @@ fn fnProtoExpr( |
| 1246 | 1272 | try expr( |
| 1247 | 1273 | &block_scope, |
| 1248 | 1274 | scope, |
| 1249 | | .{ .ty = .calling_convention_type }, |
| 1275 | .{ .rl = .{ .ty = .calling_convention_type } }, |
| 1250 | 1276 | fn_proto.ast.callconv_expr, |
| 1251 | 1277 | ) |
| 1252 | 1278 | else |
| ... | ... | @@ -1257,7 +1283,7 @@ fn fnProtoExpr( |
| 1257 | 1283 | if (is_inferred_error) { |
| 1258 | 1284 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| 1259 | 1285 | } |
| 1260 | | const ret_ty = try expr(&block_scope, scope, coerced_type_rl, fn_proto.ast.return_type); |
| 1286 | const ret_ty = try expr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type); |
| 1261 | 1287 | |
| 1262 | 1288 | const result = try block_scope.addFunc(.{ |
| 1263 | 1289 | .src_node = fn_proto.ast.proto_node, |
| ... | ... | @@ -1288,13 +1314,13 @@ fn fnProtoExpr( |
| 1288 | 1314 | try block_scope.setBlockBody(block_inst); |
| 1289 | 1315 | try gz.instructions.append(astgen.gpa, block_inst); |
| 1290 | 1316 | |
| 1291 | | return rvalue(gz, rl, indexToRef(block_inst), fn_proto.ast.proto_node); |
| 1317 | return rvalue(gz, ri, indexToRef(block_inst), fn_proto.ast.proto_node); |
| 1292 | 1318 | } |
| 1293 | 1319 | |
| 1294 | 1320 | fn arrayInitExpr( |
| 1295 | 1321 | gz: *GenZir, |
| 1296 | 1322 | scope: *Scope, |
| 1297 | | rl: ResultLoc, |
| 1323 | ri: ResultInfo, |
| 1298 | 1324 | node: Ast.Node.Index, |
| 1299 | 1325 | array_init: Ast.full.ArrayInit, |
| 1300 | 1326 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -1336,7 +1362,7 @@ fn arrayInitExpr( |
| 1336 | 1362 | .elem = elem_type, |
| 1337 | 1363 | }; |
| 1338 | 1364 | } else { |
| 1339 | | const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel); |
| 1365 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel); |
| 1340 | 1366 | const array_type_inst = try gz.addPlNode( |
| 1341 | 1367 | .array_type_sentinel, |
| 1342 | 1368 | array_init.ast.type_expr, |
| ... | ... | @@ -1364,11 +1390,11 @@ fn arrayInitExpr( |
| 1364 | 1390 | }; |
| 1365 | 1391 | }; |
| 1366 | 1392 | |
| 1367 | | switch (rl) { |
| 1393 | switch (ri.rl) { |
| 1368 | 1394 | .discard => { |
| 1369 | 1395 | // TODO elements should still be coerced if type is provided |
| 1370 | 1396 | for (array_init.ast.elements) |elem_init| { |
| 1371 | | _ = try expr(gz, scope, .discard, elem_init); |
| 1397 | _ = try expr(gz, scope, .{ .rl = .discard }, elem_init); |
| 1372 | 1398 | } |
| 1373 | 1399 | return Zir.Inst.Ref.void_value; |
| 1374 | 1400 | }, |
| ... | ... | @@ -1380,13 +1406,13 @@ fn arrayInitExpr( |
| 1380 | 1406 | const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon; |
| 1381 | 1407 | return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); |
| 1382 | 1408 | }, |
| 1383 | | .ty, .ty_shift_operand, .coerced_ty => { |
| 1409 | .ty, .coerced_ty => { |
| 1384 | 1410 | const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon; |
| 1385 | 1411 | const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); |
| 1386 | | return rvalue(gz, rl, result, node); |
| 1412 | return rvalue(gz, ri, result, node); |
| 1387 | 1413 | }, |
| 1388 | 1414 | .ptr => |ptr_res| { |
| 1389 | | return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array); |
| 1415 | return arrayInitExprRlPtr(gz, scope, ri, node, ptr_res.inst, array_init.ast.elements, types.array); |
| 1390 | 1416 | }, |
| 1391 | 1417 | .inferred_ptr => |ptr_inst| { |
| 1392 | 1418 | if (types.array == .none) { |
| ... | ... | @@ -1394,9 +1420,9 @@ fn arrayInitExpr( |
| 1394 | 1420 | // analyzing array_base_ptr against an alloc_inferred_mut. |
| 1395 | 1421 | // See corresponding logic in structInitExpr. |
| 1396 | 1422 | const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); |
| 1397 | | return rvalue(gz, rl, result, node); |
| 1423 | return rvalue(gz, ri, result, node); |
| 1398 | 1424 | } else { |
| 1399 | | return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array); |
| 1425 | return arrayInitExprRlPtr(gz, scope, ri, node, ptr_inst, array_init.ast.elements, types.array); |
| 1400 | 1426 | } |
| 1401 | 1427 | }, |
| 1402 | 1428 | .block_ptr => |block_gz| { |
| ... | ... | @@ -1404,9 +1430,9 @@ fn arrayInitExpr( |
| 1404 | 1430 | // See corresponding logic in structInitExpr. |
| 1405 | 1431 | if (types.array == .none and astgen.isInferred(block_gz.rl_ptr)) { |
| 1406 | 1432 | const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon); |
| 1407 | | return rvalue(gz, rl, result, node); |
| 1433 | return rvalue(gz, ri, result, node); |
| 1408 | 1434 | } |
| 1409 | | return arrayInitExprRlPtr(gz, scope, rl, node, block_gz.rl_ptr, array_init.ast.elements, types.array); |
| 1435 | return arrayInitExprRlPtr(gz, scope, ri, node, block_gz.rl_ptr, array_init.ast.elements, types.array); |
| 1410 | 1436 | }, |
| 1411 | 1437 | } |
| 1412 | 1438 | } |
| ... | ... | @@ -1426,7 +1452,7 @@ fn arrayInitExprRlNone( |
| 1426 | 1452 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1427 | 1453 | |
| 1428 | 1454 | for (elements) |elem_init| { |
| 1429 | | const elem_ref = try expr(gz, scope, .none, elem_init); |
| 1455 | const elem_ref = try expr(gz, scope, .{ .rl = .none }, elem_init); |
| 1430 | 1456 | astgen.extra.items[extra_index] = @enumToInt(elem_ref); |
| 1431 | 1457 | extra_index += 1; |
| 1432 | 1458 | } |
| ... | ... | @@ -1455,9 +1481,9 @@ fn arrayInitExprInner( |
| 1455 | 1481 | } |
| 1456 | 1482 | |
| 1457 | 1483 | for (elements) |elem_init, i| { |
| 1458 | | const rl = if (elem_ty != .none) |
| 1459 | | ResultLoc{ .coerced_ty = elem_ty } |
| 1460 | | else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: { |
| 1484 | const ri = if (elem_ty != .none) |
| 1485 | ResultInfo{ .rl = .{ .coerced_ty = elem_ty } } |
| 1486 | else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) ri: { |
| 1461 | 1487 | const ty_expr = try gz.add(.{ |
| 1462 | 1488 | .tag = .elem_type_index, |
| 1463 | 1489 | .data = .{ .bin = .{ |
| ... | ... | @@ -1465,10 +1491,10 @@ fn arrayInitExprInner( |
| 1465 | 1491 | .rhs = @intToEnum(Zir.Inst.Ref, i), |
| 1466 | 1492 | } }, |
| 1467 | 1493 | }); |
| 1468 | | break :rl ResultLoc{ .coerced_ty = ty_expr }; |
| 1469 | | } else ResultLoc{ .none = {} }; |
| 1494 | break :ri ResultInfo{ .rl = .{ .coerced_ty = ty_expr } }; |
| 1495 | } else ResultInfo{ .rl = .{ .none = {} } }; |
| 1470 | 1496 | |
| 1471 | | const elem_ref = try expr(gz, scope, rl, elem_init); |
| 1497 | const elem_ref = try expr(gz, scope, ri, elem_init); |
| 1472 | 1498 | astgen.extra.items[extra_index] = @enumToInt(elem_ref); |
| 1473 | 1499 | extra_index += 1; |
| 1474 | 1500 | } |
| ... | ... | @@ -1479,7 +1505,7 @@ fn arrayInitExprInner( |
| 1479 | 1505 | fn arrayInitExprRlPtr( |
| 1480 | 1506 | gz: *GenZir, |
| 1481 | 1507 | scope: *Scope, |
| 1482 | | rl: ResultLoc, |
| 1508 | ri: ResultInfo, |
| 1483 | 1509 | node: Ast.Node.Index, |
| 1484 | 1510 | result_ptr: Zir.Inst.Ref, |
| 1485 | 1511 | elements: []const Ast.Node.Index, |
| ... | ... | @@ -1494,7 +1520,7 @@ fn arrayInitExprRlPtr( |
| 1494 | 1520 | defer as_scope.unstack(); |
| 1495 | 1521 | |
| 1496 | 1522 | const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); |
| 1497 | | return as_scope.finishCoercion(gz, rl, node, result, array_ty); |
| 1523 | return as_scope.finishCoercion(gz, ri, node, result, array_ty); |
| 1498 | 1524 | } |
| 1499 | 1525 | |
| 1500 | 1526 | fn arrayInitExprRlPtrInner( |
| ... | ... | @@ -1518,7 +1544,7 @@ fn arrayInitExprRlPtrInner( |
| 1518 | 1544 | }); |
| 1519 | 1545 | astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; |
| 1520 | 1546 | extra_index += 1; |
| 1521 | | _ = try expr(gz, scope, .{ .ptr = .{ .inst = elem_ptr } }, elem_init); |
| 1547 | _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = elem_ptr } } }, elem_init); |
| 1522 | 1548 | } |
| 1523 | 1549 | |
| 1524 | 1550 | const tag: Zir.Inst.Tag = if (gz.force_comptime) |
| ... | ... | @@ -1533,7 +1559,7 @@ fn arrayInitExprRlPtrInner( |
| 1533 | 1559 | fn structInitExpr( |
| 1534 | 1560 | gz: *GenZir, |
| 1535 | 1561 | scope: *Scope, |
| 1536 | | rl: ResultLoc, |
| 1562 | ri: ResultInfo, |
| 1537 | 1563 | node: Ast.Node.Index, |
| 1538 | 1564 | struct_init: Ast.full.StructInit, |
| 1539 | 1565 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -1542,7 +1568,7 @@ fn structInitExpr( |
| 1542 | 1568 | |
| 1543 | 1569 | if (struct_init.ast.type_expr == 0) { |
| 1544 | 1570 | if (struct_init.ast.fields.len == 0) { |
| 1545 | | return rvalue(gz, rl, .empty_struct, node); |
| 1571 | return rvalue(gz, ri, .empty_struct, node); |
| 1546 | 1572 | } |
| 1547 | 1573 | } else array: { |
| 1548 | 1574 | const node_tags = tree.nodes.items(.tag); |
| ... | ... | @@ -1554,7 +1580,7 @@ fn structInitExpr( |
| 1554 | 1580 | if (struct_init.ast.fields.len == 0) { |
| 1555 | 1581 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1556 | 1582 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); |
| 1557 | | return rvalue(gz, rl, result, node); |
| 1583 | return rvalue(gz, ri, result, node); |
| 1558 | 1584 | } |
| 1559 | 1585 | break :array; |
| 1560 | 1586 | }, |
| ... | ... | @@ -1571,7 +1597,7 @@ fn structInitExpr( |
| 1571 | 1597 | .rhs = elem_type, |
| 1572 | 1598 | }); |
| 1573 | 1599 | } else blk: { |
| 1574 | | const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel); |
| 1600 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel); |
| 1575 | 1601 | break :blk try gz.addPlNode( |
| 1576 | 1602 | .array_type_sentinel, |
| 1577 | 1603 | struct_init.ast.type_expr, |
| ... | ... | @@ -1583,11 +1609,11 @@ fn structInitExpr( |
| 1583 | 1609 | ); |
| 1584 | 1610 | }; |
| 1585 | 1611 | const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node); |
| 1586 | | return rvalue(gz, rl, result, node); |
| 1612 | return rvalue(gz, ri, result, node); |
| 1587 | 1613 | } |
| 1588 | 1614 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1589 | 1615 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); |
| 1590 | | return rvalue(gz, rl, result, node); |
| 1616 | return rvalue(gz, ri, result, node); |
| 1591 | 1617 | } else { |
| 1592 | 1618 | return astgen.failNode( |
| 1593 | 1619 | struct_init.ast.type_expr, |
| ... | ... | @@ -1597,7 +1623,7 @@ fn structInitExpr( |
| 1597 | 1623 | } |
| 1598 | 1624 | } |
| 1599 | 1625 | |
| 1600 | | switch (rl) { |
| 1626 | switch (ri.rl) { |
| 1601 | 1627 | .discard => { |
| 1602 | 1628 | if (struct_init.ast.type_expr != 0) { |
| 1603 | 1629 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| ... | ... | @@ -1626,26 +1652,26 @@ fn structInitExpr( |
| 1626 | 1652 | return structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon); |
| 1627 | 1653 | } |
| 1628 | 1654 | }, |
| 1629 | | .ty, .ty_shift_operand, .coerced_ty => |ty_inst| { |
| 1655 | .ty, .coerced_ty => |ty_inst| { |
| 1630 | 1656 | if (struct_init.ast.type_expr == 0) { |
| 1631 | 1657 | const result = try structInitExprRlNone(gz, scope, node, struct_init, ty_inst, .struct_init_anon); |
| 1632 | | return rvalue(gz, rl, result, node); |
| 1658 | return rvalue(gz, ri, result, node); |
| 1633 | 1659 | } |
| 1634 | 1660 | const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1635 | 1661 | _ = try gz.addUnNode(.validate_struct_init_ty, inner_ty_inst, node); |
| 1636 | 1662 | const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init); |
| 1637 | | return rvalue(gz, rl, result, node); |
| 1663 | return rvalue(gz, ri, result, node); |
| 1638 | 1664 | }, |
| 1639 | | .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_res.inst), |
| 1665 | .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_res.inst), |
| 1640 | 1666 | .inferred_ptr => |ptr_inst| { |
| 1641 | 1667 | if (struct_init.ast.type_expr == 0) { |
| 1642 | 1668 | // We treat this case differently so that we don't get a crash when |
| 1643 | 1669 | // analyzing field_base_ptr against an alloc_inferred_mut. |
| 1644 | 1670 | // See corresponding logic in arrayInitExpr. |
| 1645 | 1671 | const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon); |
| 1646 | | return rvalue(gz, rl, result, node); |
| 1672 | return rvalue(gz, ri, result, node); |
| 1647 | 1673 | } else { |
| 1648 | | return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst); |
| 1674 | return structInitExprRlPtr(gz, scope, ri, node, struct_init, ptr_inst); |
| 1649 | 1675 | } |
| 1650 | 1676 | }, |
| 1651 | 1677 | .block_ptr => |block_gz| { |
| ... | ... | @@ -1653,10 +1679,10 @@ fn structInitExpr( |
| 1653 | 1679 | // See corresponding logic in arrayInitExpr. |
| 1654 | 1680 | if (struct_init.ast.type_expr == 0 and astgen.isInferred(block_gz.rl_ptr)) { |
| 1655 | 1681 | const result = try structInitExprRlNone(gz, scope, node, struct_init, .none, .struct_init_anon); |
| 1656 | | return rvalue(gz, rl, result, node); |
| 1682 | return rvalue(gz, ri, result, node); |
| 1657 | 1683 | } |
| 1658 | 1684 | |
| 1659 | | return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr); |
| 1685 | return structInitExprRlPtr(gz, scope, ri, node, struct_init, block_gz.rl_ptr); |
| 1660 | 1686 | }, |
| 1661 | 1687 | } |
| 1662 | 1688 | } |
| ... | ... | @@ -1681,16 +1707,15 @@ fn structInitExprRlNone( |
| 1681 | 1707 | for (struct_init.ast.fields) |field_init| { |
| 1682 | 1708 | const name_token = tree.firstToken(field_init) - 2; |
| 1683 | 1709 | const str_index = try astgen.identAsString(name_token); |
| 1684 | | const sub_rl: ResultLoc = if (ty_inst != .none) |
| 1685 | | ResultLoc{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ |
| 1710 | const sub_ri: ResultInfo = if (ty_inst != .none) |
| 1711 | ResultInfo{ .rl = .{ .ty = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ |
| 1686 | 1712 | .container_type = ty_inst, |
| 1687 | 1713 | .name_start = str_index, |
| 1688 | | }) } |
| 1689 | | else |
| 1690 | | .none; |
| 1714 | }) } } |
| 1715 | else .{ .rl = .none }; |
| 1691 | 1716 | setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{ |
| 1692 | 1717 | .field_name = str_index, |
| 1693 | | .init = try expr(gz, scope, sub_rl, field_init), |
| 1718 | .init = try expr(gz, scope, sub_ri, field_init), |
| 1694 | 1719 | }); |
| 1695 | 1720 | extra_index += field_size; |
| 1696 | 1721 | } |
| ... | ... | @@ -1701,7 +1726,7 @@ fn structInitExprRlNone( |
| 1701 | 1726 | fn structInitExprRlPtr( |
| 1702 | 1727 | gz: *GenZir, |
| 1703 | 1728 | scope: *Scope, |
| 1704 | | rl: ResultLoc, |
| 1729 | ri: ResultInfo, |
| 1705 | 1730 | node: Ast.Node.Index, |
| 1706 | 1731 | struct_init: Ast.full.StructInit, |
| 1707 | 1732 | result_ptr: Zir.Inst.Ref, |
| ... | ... | @@ -1717,7 +1742,7 @@ fn structInitExprRlPtr( |
| 1717 | 1742 | defer as_scope.unstack(); |
| 1718 | 1743 | |
| 1719 | 1744 | const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); |
| 1720 | | return as_scope.finishCoercion(gz, rl, node, result, ty_inst); |
| 1745 | return as_scope.finishCoercion(gz, ri, node, result, ty_inst); |
| 1721 | 1746 | } |
| 1722 | 1747 | |
| 1723 | 1748 | fn structInitExprRlPtrInner( |
| ... | ... | @@ -1744,7 +1769,7 @@ fn structInitExprRlPtrInner( |
| 1744 | 1769 | }); |
| 1745 | 1770 | astgen.extra.items[extra_index] = refToIndex(field_ptr).?; |
| 1746 | 1771 | extra_index += 1; |
| 1747 | | _ = try expr(gz, scope, .{ .ptr = .{ .inst = field_ptr } }, field_init); |
| 1772 | _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ .inst = field_ptr } } }, field_init); |
| 1748 | 1773 | } |
| 1749 | 1774 | |
| 1750 | 1775 | const tag: Zir.Inst.Tag = if (gz.force_comptime) |
| ... | ... | @@ -1782,7 +1807,7 @@ fn structInitExprRlTy( |
| 1782 | 1807 | }); |
| 1783 | 1808 | setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{ |
| 1784 | 1809 | .field_type = refToIndex(field_ty_inst).?, |
| 1785 | | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), |
| 1810 | .init = try expr(gz, scope, .{ .rl = .{ .ty = field_ty_inst } }, field_init), |
| 1786 | 1811 | }); |
| 1787 | 1812 | extra_index += field_size; |
| 1788 | 1813 | } |
| ... | ... | @@ -1795,14 +1820,14 @@ fn structInitExprRlTy( |
| 1795 | 1820 | fn comptimeExpr( |
| 1796 | 1821 | gz: *GenZir, |
| 1797 | 1822 | scope: *Scope, |
| 1798 | | rl: ResultLoc, |
| 1823 | ri: ResultInfo, |
| 1799 | 1824 | node: Ast.Node.Index, |
| 1800 | 1825 | ) InnerError!Zir.Inst.Ref { |
| 1801 | 1826 | const prev_force_comptime = gz.force_comptime; |
| 1802 | 1827 | gz.force_comptime = true; |
| 1803 | 1828 | defer gz.force_comptime = prev_force_comptime; |
| 1804 | 1829 | |
| 1805 | | return expr(gz, scope, rl, node); |
| 1830 | return expr(gz, scope, ri, node); |
| 1806 | 1831 | } |
| 1807 | 1832 | |
| 1808 | 1833 | /// This one is for an actual `comptime` syntax, and will emit a compile error if |
| ... | ... | @@ -1811,7 +1836,7 @@ fn comptimeExpr( |
| 1811 | 1836 | fn comptimeExprAst( |
| 1812 | 1837 | gz: *GenZir, |
| 1813 | 1838 | scope: *Scope, |
| 1814 | | rl: ResultLoc, |
| 1839 | ri: ResultInfo, |
| 1815 | 1840 | node: Ast.Node.Index, |
| 1816 | 1841 | ) InnerError!Zir.Inst.Ref { |
| 1817 | 1842 | const astgen = gz.astgen; |
| ... | ... | @@ -1822,11 +1847,50 @@ fn comptimeExprAst( |
| 1822 | 1847 | const node_datas = tree.nodes.items(.data); |
| 1823 | 1848 | const body_node = node_datas[node].lhs; |
| 1824 | 1849 | gz.force_comptime = true; |
| 1825 | | const result = try expr(gz, scope, rl, body_node); |
| 1850 | const result = try expr(gz, scope, ri, body_node); |
| 1826 | 1851 | gz.force_comptime = false; |
| 1827 | 1852 | return result; |
| 1828 | 1853 | } |
| 1829 | 1854 | |
| 1855 | /// Restore the error return trace index. Performs the restore only if the result is a non-error or |
| 1856 | /// if the result location is a non-error-handling expression. |
| 1857 | fn restoreErrRetIndex( |
| 1858 | gz: *GenZir, |
| 1859 | bt: GenZir.BranchTarget, |
| 1860 | ri: ResultInfo, |
| 1861 | node: Ast.Node.Index, |
| 1862 | result: Zir.Inst.Ref, |
| 1863 | ) !void { |
| 1864 | const op = switch (nodeMayEvalToError(gz.astgen.tree, node)) { |
| 1865 | .always => return, // never restore/pop |
| 1866 | .never => .none, // always restore/pop |
| 1867 | .maybe => switch (ri.ctx) { |
| 1868 | .error_handling_expr, .@"return", .fn_arg, .const_init => switch (ri.rl) { |
| 1869 | .ptr => |ptr_res| try gz.addUnNode(.load, ptr_res.inst, node), |
| 1870 | .inferred_ptr => |ptr| try gz.addUnNode(.load, ptr, node), |
| 1871 | .block_ptr => |block_scope| if (block_scope.rvalue_rl_count != block_scope.break_count) b: { |
| 1872 | // The result location may have been used by this expression, in which case |
| 1873 | // the operand is not the result and we need to load the rl ptr. |
| 1874 | switch (gz.astgen.instructions.items(.tag)[Zir.refToIndex(block_scope.rl_ptr).?]) { |
| 1875 | .alloc_inferred, .alloc_inferred_mut => { |
| 1876 | // This is a terrible workaround for Sema's inability to load from a .alloc_inferred ptr |
| 1877 | // before its type has been resolved. The operand we use here instead is not guaranteed |
| 1878 | // to be valid, and when it's not, we will pop error traces prematurely. |
| 1879 | // |
| 1880 | // TODO: Update this to do a proper load from the rl_ptr, once Sema can support it. |
| 1881 | break :b result; |
| 1882 | }, |
| 1883 | else => break :b try gz.addUnNode(.load, block_scope.rl_ptr, node), |
| 1884 | } |
| 1885 | } else result, |
| 1886 | else => result, |
| 1887 | }, |
| 1888 | else => .none, // always restore/pop |
| 1889 | }, |
| 1890 | }; |
| 1891 | _ = try gz.addRestoreErrRetIndex(bt, .{ .if_non_error = op }); |
| 1892 | } |
| 1893 | |
| 1830 | 1894 | fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 1831 | 1895 | const astgen = parent_gz.astgen; |
| 1832 | 1896 | const tree = astgen.tree; |
| ... | ... | @@ -1842,6 +1906,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1842 | 1906 | const block_gz = scope.cast(GenZir).?; |
| 1843 | 1907 | |
| 1844 | 1908 | if (block_gz.cur_defer_node != 0) { |
| 1909 | // We are breaking out of a `defer` block. |
| 1845 | 1910 | return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{ |
| 1846 | 1911 | try astgen.errNoteNode( |
| 1847 | 1912 | block_gz.cur_defer_node, |
| ... | ... | @@ -1862,9 +1927,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1862 | 1927 | } else if (block_gz.break_block != 0) { |
| 1863 | 1928 | break :blk block_gz.break_block; |
| 1864 | 1929 | } |
| 1930 | // If not the target, start over with the parent |
| 1865 | 1931 | scope = block_gz.parent; |
| 1866 | 1932 | continue; |
| 1867 | 1933 | }; |
| 1934 | // If we made it here, this block is the target of the break expr |
| 1868 | 1935 | |
| 1869 | 1936 | const break_tag: Zir.Inst.Tag = if (block_gz.is_inline or block_gz.force_comptime) |
| 1870 | 1937 | .break_inline |
| ... | ... | @@ -1874,17 +1941,25 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1874 | 1941 | if (rhs == 0) { |
| 1875 | 1942 | try genDefers(parent_gz, scope, parent_scope, .normal_only); |
| 1876 | 1943 | |
| 1944 | // As our last action before the break, "pop" the error trace if needed |
| 1945 | if (!block_gz.force_comptime) |
| 1946 | _ = try parent_gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always); |
| 1947 | |
| 1877 | 1948 | _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); |
| 1878 | 1949 | return Zir.Inst.Ref.unreachable_value; |
| 1879 | 1950 | } |
| 1880 | 1951 | block_gz.break_count += 1; |
| 1881 | 1952 | |
| 1882 | | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node); |
| 1953 | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node); |
| 1883 | 1954 | const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 1884 | 1955 | |
| 1885 | 1956 | try genDefers(parent_gz, scope, parent_scope, .normal_only); |
| 1886 | 1957 | |
| 1887 | | switch (block_gz.break_result_loc) { |
| 1958 | // As our last action before the break, "pop" the error trace if needed |
| 1959 | if (!block_gz.force_comptime) |
| 1960 | try restoreErrRetIndex(parent_gz, .{ .block = block_inst }, block_gz.break_result_info, rhs, operand); |
| 1961 | |
| 1962 | switch (block_gz.break_result_info.rl) { |
| 1888 | 1963 | .block_ptr => { |
| 1889 | 1964 | const br = try parent_gz.addBreak(break_tag, block_inst, operand); |
| 1890 | 1965 | try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index }); |
| ... | ... | @@ -1990,7 +2065,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 1990 | 2065 | fn blockExpr( |
| 1991 | 2066 | gz: *GenZir, |
| 1992 | 2067 | scope: *Scope, |
| 1993 | | rl: ResultLoc, |
| 2068 | ri: ResultInfo, |
| 1994 | 2069 | block_node: Ast.Node.Index, |
| 1995 | 2070 | statements: []const Ast.Node.Index, |
| 1996 | 2071 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -2006,12 +2081,38 @@ fn blockExpr( |
| 2006 | 2081 | if (token_tags[lbrace - 1] == .colon and |
| 2007 | 2082 | token_tags[lbrace - 2] == .identifier) |
| 2008 | 2083 | { |
| 2009 | | return labeledBlockExpr(gz, scope, rl, block_node, statements); |
| 2084 | return labeledBlockExpr(gz, scope, ri, block_node, statements); |
| 2085 | } |
| 2086 | |
| 2087 | if (!gz.force_comptime) { |
| 2088 | // Since this block is unlabeled, its control flow is effectively linear and we |
| 2089 | // can *almost* get away with inlining the block here. However, we actually need |
| 2090 | // to preserve the .block for Sema, to properly pop the error return trace. |
| 2091 | |
| 2092 | const block_tag: Zir.Inst.Tag = .block; |
| 2093 | const block_inst = try gz.makeBlockInst(block_tag, block_node); |
| 2094 | try gz.instructions.append(astgen.gpa, block_inst); |
| 2095 | |
| 2096 | var block_scope = gz.makeSubBlock(scope); |
| 2097 | defer block_scope.unstack(); |
| 2098 | |
| 2099 | try blockExprStmts(&block_scope, &block_scope.base, statements); |
| 2100 | |
| 2101 | if (!block_scope.endsWithNoReturn()) { |
| 2102 | // As our last action before the break, "pop" the error trace if needed |
| 2103 | _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always); |
| 2104 | |
| 2105 | const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break"; |
| 2106 | _ = try block_scope.addBreak(break_tag, block_inst, .void_value); |
| 2107 | } |
| 2108 | |
| 2109 | try block_scope.setBlockBody(block_inst); |
| 2110 | } else { |
| 2111 | var sub_gz = gz.makeSubBlock(scope); |
| 2112 | try blockExprStmts(&sub_gz, &sub_gz.base, statements); |
| 2010 | 2113 | } |
| 2011 | 2114 | |
| 2012 | | var sub_gz = gz.makeSubBlock(scope); |
| 2013 | | try blockExprStmts(&sub_gz, &sub_gz.base, statements); |
| 2014 | | return rvalue(gz, rl, .void_value, block_node); |
| 2115 | return rvalue(gz, ri, .void_value, block_node); |
| 2015 | 2116 | } |
| 2016 | 2117 | |
| 2017 | 2118 | fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.TokenIndex) !void { |
| ... | ... | @@ -2049,7 +2150,7 @@ fn checkLabelRedefinition(astgen: *AstGen, parent_scope: *Scope, label: Ast.Toke |
| 2049 | 2150 | fn labeledBlockExpr( |
| 2050 | 2151 | gz: *GenZir, |
| 2051 | 2152 | parent_scope: *Scope, |
| 2052 | | rl: ResultLoc, |
| 2153 | ri: ResultInfo, |
| 2053 | 2154 | block_node: Ast.Node.Index, |
| 2054 | 2155 | statements: []const Ast.Node.Index, |
| 2055 | 2156 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -2078,12 +2179,15 @@ fn labeledBlockExpr( |
| 2078 | 2179 | .token = label_token, |
| 2079 | 2180 | .block_inst = block_inst, |
| 2080 | 2181 | }; |
| 2081 | | block_scope.setBreakResultLoc(rl); |
| 2182 | block_scope.setBreakResultInfo(ri); |
| 2082 | 2183 | defer block_scope.unstack(); |
| 2083 | 2184 | defer block_scope.labeled_breaks.deinit(astgen.gpa); |
| 2084 | 2185 | |
| 2085 | 2186 | try blockExprStmts(&block_scope, &block_scope.base, statements); |
| 2086 | 2187 | if (!block_scope.endsWithNoReturn()) { |
| 2188 | // As our last action before the return, "pop" the error trace if needed |
| 2189 | _ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always); |
| 2190 | |
| 2087 | 2191 | const break_tag: Zir.Inst.Tag = if (block_scope.force_comptime) .break_inline else .@"break"; |
| 2088 | 2192 | _ = try block_scope.addBreak(break_tag, block_inst, .void_value); |
| 2089 | 2193 | } |
| ... | ... | @@ -2094,7 +2198,7 @@ fn labeledBlockExpr( |
| 2094 | 2198 | |
| 2095 | 2199 | const zir_datas = gz.astgen.instructions.items(.data); |
| 2096 | 2200 | const zir_tags = gz.astgen.instructions.items(.tag); |
| 2097 | | const strat = rl.strategy(&block_scope); |
| 2201 | const strat = ri.rl.strategy(&block_scope); |
| 2098 | 2202 | switch (strat.tag) { |
| 2099 | 2203 | .break_void => { |
| 2100 | 2204 | // The code took advantage of the result location as a pointer. |
| ... | ... | @@ -2107,7 +2211,8 @@ fn labeledBlockExpr( |
| 2107 | 2211 | return indexToRef(block_inst); |
| 2108 | 2212 | }, |
| 2109 | 2213 | .break_operand => { |
| 2110 | | // All break operands are values that did not use the result location pointer. |
| 2214 | // All break operands are values that did not use the result location pointer |
| 2215 | // (except for a single .store_to_block_ptr inst which we re-write here). |
| 2111 | 2216 | // The break instructions need to have their operands coerced if the |
| 2112 | 2217 | // block's result location is a `ty`. In this case we overwrite the |
| 2113 | 2218 | // `store_to_block_ptr` instruction with an `as` instruction and repurpose |
| ... | ... | @@ -2135,9 +2240,9 @@ fn labeledBlockExpr( |
| 2135 | 2240 | } |
| 2136 | 2241 | try block_scope.setBlockBody(block_inst); |
| 2137 | 2242 | const block_ref = indexToRef(block_inst); |
| 2138 | | switch (rl) { |
| 2243 | switch (ri.rl) { |
| 2139 | 2244 | .ref => return block_ref, |
| 2140 | | else => return rvalue(gz, rl, block_ref, block_node), |
| 2245 | else => return rvalue(gz, ri, block_ref, block_node), |
| 2141 | 2246 | } |
| 2142 | 2247 | }, |
| 2143 | 2248 | } |
| ... | ... | @@ -2208,12 +2313,12 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2208 | 2313 | continue; |
| 2209 | 2314 | }, |
| 2210 | 2315 | |
| 2211 | | .while_simple => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileSimple(inner_node), true), |
| 2212 | | .while_cont => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileCont(inner_node), true), |
| 2213 | | .@"while" => _ = try whileExpr(gz, scope, .discard, inner_node, tree.whileFull(inner_node), true), |
| 2316 | .while_simple => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileSimple(inner_node), true), |
| 2317 | .while_cont => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileCont(inner_node), true), |
| 2318 | .@"while" => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.whileFull(inner_node), true), |
| 2214 | 2319 | |
| 2215 | | .for_simple => _ = try forExpr(gz, scope, .discard, inner_node, tree.forSimple(inner_node), true), |
| 2216 | | .@"for" => _ = try forExpr(gz, scope, .discard, inner_node, tree.forFull(inner_node), true), |
| 2320 | .for_simple => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forSimple(inner_node), true), |
| 2321 | .@"for" => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.forFull(inner_node), true), |
| 2217 | 2322 | |
| 2218 | 2323 | else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node), |
| 2219 | 2324 | // zig fmt: on |
| ... | ... | @@ -2234,7 +2339,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2234 | 2339 | try emitDbgNode(gz, statement); |
| 2235 | 2340 | // We need to emit an error if the result is not `noreturn` or `void`, but |
| 2236 | 2341 | // we want to avoid adding the ZIR instruction if possible for performance. |
| 2237 | | const maybe_unused_result = try expr(gz, scope, .none, statement); |
| 2342 | const maybe_unused_result = try expr(gz, scope, .{ .rl = .none }, statement); |
| 2238 | 2343 | return addEnsureResult(gz, maybe_unused_result, statement); |
| 2239 | 2344 | } |
| 2240 | 2345 | |
| ... | ... | @@ -2533,6 +2638,8 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2533 | 2638 | .validate_array_init_ty, |
| 2534 | 2639 | .validate_struct_init_ty, |
| 2535 | 2640 | .validate_deref, |
| 2641 | .save_err_ret_index, |
| 2642 | .restore_err_ret_index, |
| 2536 | 2643 | => break :b true, |
| 2537 | 2644 | |
| 2538 | 2645 | .@"defer" => unreachable, |
| ... | ... | @@ -2799,7 +2906,7 @@ fn varDecl( |
| 2799 | 2906 | } |
| 2800 | 2907 | |
| 2801 | 2908 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) |
| 2802 | | try expr(gz, scope, align_rl, var_decl.ast.align_node) |
| 2909 | try expr(gz, scope, align_ri, var_decl.ast.align_node) |
| 2803 | 2910 | else |
| 2804 | 2911 | .none; |
| 2805 | 2912 | |
| ... | ... | @@ -2816,16 +2923,22 @@ fn varDecl( |
| 2816 | 2923 | if (align_inst == .none and |
| 2817 | 2924 | !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node, type_node != 0)) |
| 2818 | 2925 | { |
| 2819 | | const result_loc: ResultLoc = if (type_node != 0) .{ |
| 2820 | | .ty = try typeExpr(gz, scope, type_node), |
| 2821 | | } else .none; |
| 2926 | const result_info: ResultInfo = if (type_node != 0) .{ |
| 2927 | .rl = .{ .ty = try typeExpr(gz, scope, type_node) }, |
| 2928 | .ctx = .const_init, |
| 2929 | } else .{ .rl = .none, .ctx = .const_init }; |
| 2822 | 2930 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 2823 | 2931 | gz.anon_name_strategy = .dbg_var; |
| 2824 | | const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node); |
| 2932 | const init_inst = try reachableExpr(gz, scope, result_info, var_decl.ast.init_node, node); |
| 2825 | 2933 | gz.anon_name_strategy = prev_anon_name_strategy; |
| 2826 | 2934 | |
| 2827 | 2935 | try gz.addDbgVar(.dbg_var_val, ident_name, init_inst); |
| 2828 | 2936 | |
| 2937 | // The const init expression may have modified the error return trace, so signal |
| 2938 | // to Sema that it should save the new index for restoring later. |
| 2939 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) |
| 2940 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 2941 | |
| 2829 | 2942 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 2830 | 2943 | sub_scope.* = .{ |
| 2831 | 2944 | .parent = scope, |
| ... | ... | @@ -2891,8 +3004,13 @@ fn varDecl( |
| 2891 | 3004 | init_scope.rl_ptr = alloc; |
| 2892 | 3005 | init_scope.rl_ty_inst = .none; |
| 2893 | 3006 | } |
| 2894 | | const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; |
| 2895 | | const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_loc, var_decl.ast.init_node, node); |
| 3007 | const init_result_info: ResultInfo = .{ .rl = .{ .block_ptr = &init_scope }, .ctx = .const_init }; |
| 3008 | const init_inst = try reachableExpr(&init_scope, &init_scope.base, init_result_info, var_decl.ast.init_node, node); |
| 3009 | |
| 3010 | // The const init expression may have modified the error return trace, so signal |
| 3011 | // to Sema that it should save the new index for restoring later. |
| 3012 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) |
| 3013 | _ = try init_scope.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 2896 | 3014 | |
| 2897 | 3015 | const zir_tags = astgen.instructions.items(.tag); |
| 2898 | 3016 | const zir_datas = astgen.instructions.items(.data); |
| ... | ... | @@ -2981,7 +3099,7 @@ fn varDecl( |
| 2981 | 3099 | const is_comptime = var_decl.comptime_token != null or gz.force_comptime; |
| 2982 | 3100 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| 2983 | 3101 | const var_data: struct { |
| 2984 | | result_loc: ResultLoc, |
| 3102 | result_info: ResultInfo, |
| 2985 | 3103 | alloc: Zir.Inst.Ref, |
| 2986 | 3104 | } = if (var_decl.ast.type_node != 0) a: { |
| 2987 | 3105 | const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); |
| ... | ... | @@ -3003,7 +3121,7 @@ fn varDecl( |
| 3003 | 3121 | } |
| 3004 | 3122 | }; |
| 3005 | 3123 | gz.rl_ty_inst = type_inst; |
| 3006 | | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = .{ .inst = alloc } } }; |
| 3124 | break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .ptr = .{ .inst = alloc } } } }; |
| 3007 | 3125 | } else a: { |
| 3008 | 3126 | const alloc = alloc: { |
| 3009 | 3127 | if (align_inst == .none) { |
| ... | ... | @@ -3024,11 +3142,11 @@ fn varDecl( |
| 3024 | 3142 | }; |
| 3025 | 3143 | gz.rl_ty_inst = .none; |
| 3026 | 3144 | resolve_inferred_alloc = alloc; |
| 3027 | | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; |
| 3145 | break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .inferred_ptr = alloc } } }; |
| 3028 | 3146 | }; |
| 3029 | 3147 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 3030 | 3148 | gz.anon_name_strategy = .dbg_var; |
| 3031 | | _ = try reachableExprComptime(gz, scope, var_data.result_loc, var_decl.ast.init_node, node, is_comptime); |
| 3149 | _ = try reachableExprComptime(gz, scope, var_data.result_info, var_decl.ast.init_node, node, is_comptime); |
| 3032 | 3150 | gz.anon_name_strategy = prev_anon_name_strategy; |
| 3033 | 3151 | if (resolve_inferred_alloc != .none) { |
| 3034 | 3152 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| ... | ... | @@ -3098,15 +3216,15 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi |
| 3098 | 3216 | // This intentionally does not support `@"_"` syntax. |
| 3099 | 3217 | const ident_name = tree.tokenSlice(main_tokens[lhs]); |
| 3100 | 3218 | if (mem.eql(u8, ident_name, "_")) { |
| 3101 | | _ = try expr(gz, scope, .discard, rhs); |
| 3219 | _ = try expr(gz, scope, .{ .rl = .discard }, rhs); |
| 3102 | 3220 | return; |
| 3103 | 3221 | } |
| 3104 | 3222 | } |
| 3105 | 3223 | const lvalue = try lvalExpr(gz, scope, lhs); |
| 3106 | | _ = try expr(gz, scope, .{ .ptr = .{ |
| 3224 | _ = try expr(gz, scope, .{ .rl = .{ .ptr = .{ |
| 3107 | 3225 | .inst = lvalue, |
| 3108 | 3226 | .src_node = infix_node, |
| 3109 | | } }, rhs); |
| 3227 | } } }, rhs); |
| 3110 | 3228 | } |
| 3111 | 3229 | |
| 3112 | 3230 | fn assignOp( |
| ... | ... | @@ -3123,7 +3241,7 @@ fn assignOp( |
| 3123 | 3241 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| 3124 | 3242 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3125 | 3243 | const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node); |
| 3126 | | const rhs = try expr(gz, scope, .{ .coerced_ty = lhs_type }, node_datas[infix_node].rhs); |
| 3244 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs); |
| 3127 | 3245 | |
| 3128 | 3246 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ |
| 3129 | 3247 | .lhs = lhs, |
| ... | ... | @@ -3146,7 +3264,7 @@ fn assignShift( |
| 3146 | 3264 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| 3147 | 3265 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3148 | 3266 | const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node); |
| 3149 | | const rhs = try expr(gz, scope, .{ .ty = rhs_type }, node_datas[infix_node].rhs); |
| 3267 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs); |
| 3150 | 3268 | |
| 3151 | 3269 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ |
| 3152 | 3270 | .lhs = lhs, |
| ... | ... | @@ -3164,7 +3282,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE |
| 3164 | 3282 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); |
| 3165 | 3283 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3166 | 3284 | // Saturating shift-left allows any integer type for both the LHS and RHS. |
| 3167 | | const rhs = try expr(gz, scope, .none, node_datas[infix_node].rhs); |
| 3285 | const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs); |
| 3168 | 3286 | |
| 3169 | 3287 | const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{ |
| 3170 | 3288 | .lhs = lhs, |
| ... | ... | @@ -3176,7 +3294,7 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE |
| 3176 | 3294 | fn ptrType( |
| 3177 | 3295 | gz: *GenZir, |
| 3178 | 3296 | scope: *Scope, |
| 3179 | | rl: ResultLoc, |
| 3297 | ri: ResultInfo, |
| 3180 | 3298 | node: Ast.Node.Index, |
| 3181 | 3299 | ptr_info: Ast.full.PtrType, |
| 3182 | 3300 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -3194,21 +3312,21 @@ fn ptrType( |
| 3194 | 3312 | var trailing_count: u32 = 0; |
| 3195 | 3313 | |
| 3196 | 3314 | if (ptr_info.ast.sentinel != 0) { |
| 3197 | | sentinel_ref = try expr(gz, scope, .{ .ty = elem_type }, ptr_info.ast.sentinel); |
| 3315 | sentinel_ref = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel); |
| 3198 | 3316 | trailing_count += 1; |
| 3199 | 3317 | } |
| 3200 | 3318 | if (ptr_info.ast.align_node != 0) { |
| 3201 | | align_ref = try expr(gz, scope, coerced_align_rl, ptr_info.ast.align_node); |
| 3319 | align_ref = try expr(gz, scope, coerced_align_ri, ptr_info.ast.align_node); |
| 3202 | 3320 | trailing_count += 1; |
| 3203 | 3321 | } |
| 3204 | 3322 | if (ptr_info.ast.addrspace_node != 0) { |
| 3205 | | addrspace_ref = try expr(gz, scope, .{ .ty = .address_space_type }, ptr_info.ast.addrspace_node); |
| 3323 | addrspace_ref = try expr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, ptr_info.ast.addrspace_node); |
| 3206 | 3324 | trailing_count += 1; |
| 3207 | 3325 | } |
| 3208 | 3326 | if (ptr_info.ast.bit_range_start != 0) { |
| 3209 | 3327 | assert(ptr_info.ast.bit_range_end != 0); |
| 3210 | | bit_start_ref = try expr(gz, scope, .{ .coerced_ty = .u16_type }, ptr_info.ast.bit_range_start); |
| 3211 | | bit_end_ref = try expr(gz, scope, .{ .coerced_ty = .u16_type }, ptr_info.ast.bit_range_end); |
| 3328 | bit_start_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start); |
| 3329 | bit_end_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end); |
| 3212 | 3330 | trailing_count += 2; |
| 3213 | 3331 | } |
| 3214 | 3332 | |
| ... | ... | @@ -3255,10 +3373,10 @@ fn ptrType( |
| 3255 | 3373 | } }); |
| 3256 | 3374 | gz.instructions.appendAssumeCapacity(new_index); |
| 3257 | 3375 | |
| 3258 | | return rvalue(gz, rl, result, node); |
| 3376 | return rvalue(gz, ri, result, node); |
| 3259 | 3377 | } |
| 3260 | 3378 | |
| 3261 | | fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 3379 | fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 3262 | 3380 | const astgen = gz.astgen; |
| 3263 | 3381 | const tree = astgen.tree; |
| 3264 | 3382 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -3271,17 +3389,17 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Z |
| 3271 | 3389 | { |
| 3272 | 3390 | return astgen.failNode(len_node, "unable to infer array size", .{}); |
| 3273 | 3391 | } |
| 3274 | | const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node); |
| 3392 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node); |
| 3275 | 3393 | const elem_type = try typeExpr(gz, scope, node_datas[node].rhs); |
| 3276 | 3394 | |
| 3277 | 3395 | const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{ |
| 3278 | 3396 | .lhs = len, |
| 3279 | 3397 | .rhs = elem_type, |
| 3280 | 3398 | }); |
| 3281 | | return rvalue(gz, rl, result, node); |
| 3399 | return rvalue(gz, ri, result, node); |
| 3282 | 3400 | } |
| 3283 | 3401 | |
| 3284 | | fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 3402 | fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 3285 | 3403 | const astgen = gz.astgen; |
| 3286 | 3404 | const tree = astgen.tree; |
| 3287 | 3405 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -3295,16 +3413,16 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I |
| 3295 | 3413 | { |
| 3296 | 3414 | return astgen.failNode(len_node, "unable to infer array size", .{}); |
| 3297 | 3415 | } |
| 3298 | | const len = try reachableExpr(gz, scope, .{ .coerced_ty = .usize_type }, len_node, node); |
| 3416 | const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node); |
| 3299 | 3417 | const elem_type = try typeExpr(gz, scope, extra.elem_type); |
| 3300 | | const sentinel = try reachableExpr(gz, scope, .{ .coerced_ty = elem_type }, extra.sentinel, node); |
| 3418 | const sentinel = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node); |
| 3301 | 3419 | |
| 3302 | 3420 | const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{ |
| 3303 | 3421 | .len = len, |
| 3304 | 3422 | .elem_type = elem_type, |
| 3305 | 3423 | .sentinel = sentinel, |
| 3306 | 3424 | }); |
| 3307 | | return rvalue(gz, rl, result, node); |
| 3425 | return rvalue(gz, ri, result, node); |
| 3308 | 3426 | } |
| 3309 | 3427 | |
| 3310 | 3428 | const WipMembers = struct { |
| ... | ... | @@ -3540,7 +3658,7 @@ fn fnDecl( |
| 3540 | 3658 | assert(param_type_node != 0); |
| 3541 | 3659 | var param_gz = decl_gz.makeSubBlock(scope); |
| 3542 | 3660 | defer param_gz.unstack(); |
| 3543 | | const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node); |
| 3661 | const param_type = try expr(&param_gz, params_scope, coerced_type_ri, param_type_node); |
| 3544 | 3662 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 3545 | 3663 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| 3546 | 3664 | |
| ... | ... | @@ -3589,7 +3707,7 @@ fn fnDecl( |
| 3589 | 3707 | var align_gz = decl_gz.makeSubBlock(params_scope); |
| 3590 | 3708 | defer align_gz.unstack(); |
| 3591 | 3709 | const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 3592 | | const inst = try expr(&decl_gz, params_scope, coerced_align_rl, fn_proto.ast.align_expr); |
| 3710 | const inst = try expr(&decl_gz, params_scope, coerced_align_ri, fn_proto.ast.align_expr); |
| 3593 | 3711 | if (align_gz.instructionsSlice().len == 0) { |
| 3594 | 3712 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 3595 | 3713 | break :inst inst; |
| ... | ... | @@ -3601,7 +3719,7 @@ fn fnDecl( |
| 3601 | 3719 | var addrspace_gz = decl_gz.makeSubBlock(params_scope); |
| 3602 | 3720 | defer addrspace_gz.unstack(); |
| 3603 | 3721 | const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { |
| 3604 | | const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .address_space_type }, fn_proto.ast.addrspace_expr); |
| 3722 | const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .address_space_type } }, fn_proto.ast.addrspace_expr); |
| 3605 | 3723 | if (addrspace_gz.instructionsSlice().len == 0) { |
| 3606 | 3724 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 3607 | 3725 | break :inst inst; |
| ... | ... | @@ -3613,7 +3731,7 @@ fn fnDecl( |
| 3613 | 3731 | var section_gz = decl_gz.makeSubBlock(params_scope); |
| 3614 | 3732 | defer section_gz.unstack(); |
| 3615 | 3733 | const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: { |
| 3616 | | const inst = try expr(&decl_gz, params_scope, .{ .coerced_ty = .const_slice_u8_type }, fn_proto.ast.section_expr); |
| 3734 | const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .const_slice_u8_type } }, fn_proto.ast.section_expr); |
| 3617 | 3735 | if (section_gz.instructionsSlice().len == 0) { |
| 3618 | 3736 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 3619 | 3737 | break :inst inst; |
| ... | ... | @@ -3636,7 +3754,7 @@ fn fnDecl( |
| 3636 | 3754 | const inst = try expr( |
| 3637 | 3755 | &decl_gz, |
| 3638 | 3756 | params_scope, |
| 3639 | | .{ .coerced_ty = .calling_convention_type }, |
| 3757 | .{ .rl = .{ .coerced_ty = .calling_convention_type } }, |
| 3640 | 3758 | fn_proto.ast.callconv_expr, |
| 3641 | 3759 | ); |
| 3642 | 3760 | if (cc_gz.instructionsSlice().len == 0) { |
| ... | ... | @@ -3658,7 +3776,7 @@ fn fnDecl( |
| 3658 | 3776 | var ret_gz = decl_gz.makeSubBlock(params_scope); |
| 3659 | 3777 | defer ret_gz.unstack(); |
| 3660 | 3778 | const ret_ref: Zir.Inst.Ref = inst: { |
| 3661 | | const inst = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); |
| 3779 | const inst = try expr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type); |
| 3662 | 3780 | if (ret_gz.instructionsSlice().len == 0) { |
| 3663 | 3781 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 3664 | 3782 | break :inst inst; |
| ... | ... | @@ -3712,10 +3830,13 @@ fn fnDecl( |
| 3712 | 3830 | const lbrace_line = astgen.source_line - decl_gz.decl_line; |
| 3713 | 3831 | const lbrace_column = astgen.source_column; |
| 3714 | 3832 | |
| 3715 | | _ = try expr(&fn_gz, params_scope, .none, body_node); |
| 3833 | _ = try expr(&fn_gz, params_scope, .{ .rl = .none }, body_node); |
| 3716 | 3834 | try checkUsed(gz, &fn_gz.base, params_scope); |
| 3717 | 3835 | |
| 3718 | 3836 | if (!fn_gz.endsWithNoReturn()) { |
| 3837 | // As our last action before the return, "pop" the error trace if needed |
| 3838 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 3839 | |
| 3719 | 3840 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3720 | 3841 | // We do this by using the `ret_tok` instruction. |
| 3721 | 3842 | _ = try fn_gz.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node)); |
| ... | ... | @@ -3808,13 +3929,13 @@ fn globalVarDecl( |
| 3808 | 3929 | break :blk token_tags[maybe_extern_token] == .keyword_extern; |
| 3809 | 3930 | }; |
| 3810 | 3931 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: { |
| 3811 | | break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node); |
| 3932 | break :inst try expr(&block_scope, &block_scope.base, align_ri, var_decl.ast.align_node); |
| 3812 | 3933 | }; |
| 3813 | 3934 | const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: { |
| 3814 | | break :inst try expr(&block_scope, &block_scope.base, .{ .ty = .address_space_type }, var_decl.ast.addrspace_node); |
| 3935 | break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node); |
| 3815 | 3936 | }; |
| 3816 | 3937 | const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: { |
| 3817 | | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); |
| 3938 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .const_slice_u8_type } }, var_decl.ast.section_node); |
| 3818 | 3939 | }; |
| 3819 | 3940 | const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; |
| 3820 | 3941 | wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace); |
| ... | ... | @@ -3854,7 +3975,7 @@ fn globalVarDecl( |
| 3854 | 3975 | try expr( |
| 3855 | 3976 | &block_scope, |
| 3856 | 3977 | &block_scope.base, |
| 3857 | | .{ .ty = .type_type }, |
| 3978 | .{ .rl = .{ .ty = .type_type } }, |
| 3858 | 3979 | var_decl.ast.type_node, |
| 3859 | 3980 | ) |
| 3860 | 3981 | else |
| ... | ... | @@ -3863,7 +3984,7 @@ fn globalVarDecl( |
| 3863 | 3984 | const init_inst = try expr( |
| 3864 | 3985 | &block_scope, |
| 3865 | 3986 | &block_scope.base, |
| 3866 | | if (type_inst != .none) .{ .ty = type_inst } else .none, |
| 3987 | if (type_inst != .none) .{ .rl = .{ .ty = type_inst } } else .{ .rl = .none }, |
| 3867 | 3988 | var_decl.ast.init_node, |
| 3868 | 3989 | ); |
| 3869 | 3990 | |
| ... | ... | @@ -3952,7 +4073,7 @@ fn comptimeDecl( |
| 3952 | 4073 | }; |
| 3953 | 4074 | defer decl_block.unstack(); |
| 3954 | 4075 | |
| 3955 | | const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); |
| 4076 | const block_result = try expr(&decl_block, &decl_block.base, .{ .rl = .none }, body_node); |
| 3956 | 4077 | if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { |
| 3957 | 4078 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); |
| 3958 | 4079 | } |
| ... | ... | @@ -4156,8 +4277,12 @@ fn testDecl( |
| 4156 | 4277 | const lbrace_line = astgen.source_line - decl_block.decl_line; |
| 4157 | 4278 | const lbrace_column = astgen.source_column; |
| 4158 | 4279 | |
| 4159 | | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); |
| 4280 | const block_result = try expr(&fn_block, &fn_block.base, .{ .rl = .none }, body_node); |
| 4160 | 4281 | if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) { |
| 4282 | |
| 4283 | // As our last action before the return, "pop" the error trace if needed |
| 4284 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 4285 | |
| 4161 | 4286 | // Since we are adding the return instruction here, we must handle the coercion. |
| 4162 | 4287 | // We do this by using the `ret_tok` instruction. |
| 4163 | 4288 | _ = try fn_block.addUnTok(.ret_tok, .void_value, tree.lastToken(body_node)); |
| ... | ... | @@ -4370,7 +4495,7 @@ fn structDeclInner( |
| 4370 | 4495 | if (layout == .Packed) { |
| 4371 | 4496 | try astgen.appendErrorNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{}); |
| 4372 | 4497 | } |
| 4373 | | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_rl, member.ast.align_expr); |
| 4498 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr); |
| 4374 | 4499 | if (!block_scope.endsWithNoReturn()) { |
| 4375 | 4500 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 4376 | 4501 | } |
| ... | ... | @@ -4383,9 +4508,9 @@ fn structDeclInner( |
| 4383 | 4508 | } |
| 4384 | 4509 | |
| 4385 | 4510 | if (have_value) { |
| 4386 | | const rl: ResultLoc = if (field_type == .none) .none else .{ .coerced_ty = field_type }; |
| 4511 | const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = field_type } }; |
| 4387 | 4512 | |
| 4388 | | const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr); |
| 4513 | const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr); |
| 4389 | 4514 | if (!block_scope.endsWithNoReturn()) { |
| 4390 | 4515 | _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); |
| 4391 | 4516 | } |
| ... | ... | @@ -4514,7 +4639,7 @@ fn unionDeclInner( |
| 4514 | 4639 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 4515 | 4640 | } |
| 4516 | 4641 | if (have_align) { |
| 4517 | | const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr); |
| 4642 | const align_inst = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .u32_type } }, member.ast.align_expr); |
| 4518 | 4643 | wip_members.appendToField(@enumToInt(align_inst)); |
| 4519 | 4644 | } |
| 4520 | 4645 | if (have_value) { |
| ... | ... | @@ -4546,7 +4671,7 @@ fn unionDeclInner( |
| 4546 | 4671 | }, |
| 4547 | 4672 | ); |
| 4548 | 4673 | } |
| 4549 | | const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4674 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); |
| 4550 | 4675 | wip_members.appendToField(@enumToInt(tag_value)); |
| 4551 | 4676 | } |
| 4552 | 4677 | } |
| ... | ... | @@ -4584,7 +4709,7 @@ fn unionDeclInner( |
| 4584 | 4709 | fn containerDecl( |
| 4585 | 4710 | gz: *GenZir, |
| 4586 | 4711 | scope: *Scope, |
| 4587 | | rl: ResultLoc, |
| 4712 | ri: ResultInfo, |
| 4588 | 4713 | node: Ast.Node.Index, |
| 4589 | 4714 | container_decl: Ast.full.ContainerDecl, |
| 4590 | 4715 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -4610,7 +4735,7 @@ fn containerDecl( |
| 4610 | 4735 | } else std.builtin.Type.ContainerLayout.Auto; |
| 4611 | 4736 | |
| 4612 | 4737 | const result = try structDeclInner(gz, scope, node, container_decl, layout, container_decl.ast.arg); |
| 4613 | | return rvalue(gz, rl, result, node); |
| 4738 | return rvalue(gz, ri, result, node); |
| 4614 | 4739 | }, |
| 4615 | 4740 | .keyword_union => { |
| 4616 | 4741 | const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) { |
| ... | ... | @@ -4620,7 +4745,7 @@ fn containerDecl( |
| 4620 | 4745 | } else std.builtin.Type.ContainerLayout.Auto; |
| 4621 | 4746 | |
| 4622 | 4747 | const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, container_decl.ast.enum_token); |
| 4623 | | return rvalue(gz, rl, result, node); |
| 4748 | return rvalue(gz, ri, result, node); |
| 4624 | 4749 | }, |
| 4625 | 4750 | .keyword_enum => { |
| 4626 | 4751 | if (container_decl.layout_token) |t| { |
| ... | ... | @@ -4750,7 +4875,7 @@ fn containerDecl( |
| 4750 | 4875 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4751 | 4876 | |
| 4752 | 4877 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) |
| 4753 | | try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg) |
| 4878 | try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg) |
| 4754 | 4879 | else |
| 4755 | 4880 | .none; |
| 4756 | 4881 | |
| ... | ... | @@ -4794,7 +4919,7 @@ fn containerDecl( |
| 4794 | 4919 | }, |
| 4795 | 4920 | ); |
| 4796 | 4921 | } |
| 4797 | | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4922 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); |
| 4798 | 4923 | wip_members.appendToField(@enumToInt(tag_value_inst)); |
| 4799 | 4924 | } |
| 4800 | 4925 | } |
| ... | ... | @@ -4825,7 +4950,7 @@ fn containerDecl( |
| 4825 | 4950 | |
| 4826 | 4951 | block_scope.unstack(); |
| 4827 | 4952 | try gz.addNamespaceCaptures(&namespace); |
| 4828 | | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4953 | return rvalue(gz, ri, indexToRef(decl_inst), node); |
| 4829 | 4954 | }, |
| 4830 | 4955 | .keyword_opaque => { |
| 4831 | 4956 | assert(container_decl.ast.arg == 0); |
| ... | ... | @@ -4875,7 +5000,7 @@ fn containerDecl( |
| 4875 | 5000 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4876 | 5001 | |
| 4877 | 5002 | try gz.addNamespaceCaptures(&namespace); |
| 4878 | | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 5003 | return rvalue(gz, ri, indexToRef(decl_inst), node); |
| 4879 | 5004 | }, |
| 4880 | 5005 | else => unreachable, |
| 4881 | 5006 | } |
| ... | ... | @@ -5006,7 +5131,7 @@ fn containerMember( |
| 5006 | 5131 | return .decl; |
| 5007 | 5132 | } |
| 5008 | 5133 | |
| 5009 | | fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 5134 | fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 5010 | 5135 | const astgen = gz.astgen; |
| 5011 | 5136 | const gpa = astgen.gpa; |
| 5012 | 5137 | const tree = astgen.tree; |
| ... | ... | @@ -5061,13 +5186,13 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir |
| 5061 | 5186 | .fields_len = @intCast(u32, fields_len), |
| 5062 | 5187 | }); |
| 5063 | 5188 | const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index); |
| 5064 | | return rvalue(gz, rl, result, node); |
| 5189 | return rvalue(gz, ri, result, node); |
| 5065 | 5190 | } |
| 5066 | 5191 | |
| 5067 | 5192 | fn tryExpr( |
| 5068 | 5193 | parent_gz: *GenZir, |
| 5069 | 5194 | scope: *Scope, |
| 5070 | | rl: ResultLoc, |
| 5195 | ri: ResultInfo, |
| 5071 | 5196 | node: Ast.Node.Index, |
| 5072 | 5197 | operand_node: Ast.Node.Index, |
| 5073 | 5198 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -5097,15 +5222,15 @@ fn tryExpr( |
| 5097 | 5222 | const try_line = astgen.source_line - parent_gz.decl_line; |
| 5098 | 5223 | const try_column = astgen.source_column; |
| 5099 | 5224 | |
| 5100 | | const operand_rl: ResultLoc = switch (rl) { |
| 5101 | | .ref => .ref, |
| 5102 | | else => .none, |
| 5225 | const operand_ri: ResultInfo = switch (ri.rl) { |
| 5226 | .ref => .{ .rl = .ref, .ctx = .error_handling_expr }, |
| 5227 | else => .{ .rl = .none, .ctx = .error_handling_expr }, |
| 5103 | 5228 | }; |
| 5104 | | // This could be a pointer or value depending on the `rl` parameter. |
| 5105 | | const operand = try reachableExpr(parent_gz, scope, operand_rl, operand_node, node); |
| 5229 | // This could be a pointer or value depending on the `ri` parameter. |
| 5230 | const operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, node); |
| 5106 | 5231 | const is_inline = parent_gz.force_comptime; |
| 5107 | 5232 | const is_inline_bit = @as(u2, @boolToInt(is_inline)); |
| 5108 | | const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1; |
| 5233 | const is_ptr_bit = @as(u2, @boolToInt(operand_ri.rl == .ref)) << 1; |
| 5109 | 5234 | const block_tag: Zir.Inst.Tag = switch (is_inline_bit | is_ptr_bit) { |
| 5110 | 5235 | 0b00 => .@"try", |
| 5111 | 5236 | 0b01 => .@"try", |
| ... | ... | @@ -5120,7 +5245,7 @@ fn tryExpr( |
| 5120 | 5245 | var else_scope = parent_gz.makeSubBlock(scope); |
| 5121 | 5246 | defer else_scope.unstack(); |
| 5122 | 5247 | |
| 5123 | | const err_tag = switch (rl) { |
| 5248 | const err_tag = switch (ri.rl) { |
| 5124 | 5249 | .ref => Zir.Inst.Tag.err_union_code_ptr, |
| 5125 | 5250 | else => Zir.Inst.Tag.err_union_code, |
| 5126 | 5251 | }; |
| ... | ... | @@ -5131,16 +5256,16 @@ fn tryExpr( |
| 5131 | 5256 | |
| 5132 | 5257 | try else_scope.setTryBody(try_inst, operand); |
| 5133 | 5258 | const result = indexToRef(try_inst); |
| 5134 | | switch (rl) { |
| 5259 | switch (ri.rl) { |
| 5135 | 5260 | .ref => return result, |
| 5136 | | else => return rvalue(parent_gz, rl, result, node), |
| 5261 | else => return rvalue(parent_gz, ri, result, node), |
| 5137 | 5262 | } |
| 5138 | 5263 | } |
| 5139 | 5264 | |
| 5140 | 5265 | fn orelseCatchExpr( |
| 5141 | 5266 | parent_gz: *GenZir, |
| 5142 | 5267 | scope: *Scope, |
| 5143 | | rl: ResultLoc, |
| 5268 | ri: ResultInfo, |
| 5144 | 5269 | node: Ast.Node.Index, |
| 5145 | 5270 | lhs: Ast.Node.Index, |
| 5146 | 5271 | cond_op: Zir.Inst.Tag, |
| ... | ... | @@ -5152,20 +5277,22 @@ fn orelseCatchExpr( |
| 5152 | 5277 | const astgen = parent_gz.astgen; |
| 5153 | 5278 | const tree = astgen.tree; |
| 5154 | 5279 | |
| 5280 | const do_err_trace = astgen.fn_block != null and (cond_op == .is_non_err or cond_op == .is_non_err_ptr); |
| 5281 | |
| 5155 | 5282 | var block_scope = parent_gz.makeSubBlock(scope); |
| 5156 | | block_scope.setBreakResultLoc(rl); |
| 5283 | block_scope.setBreakResultInfo(ri); |
| 5157 | 5284 | defer block_scope.unstack(); |
| 5158 | 5285 | |
| 5159 | | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 5160 | | .ref => .ref, |
| 5161 | | else => .none, |
| 5286 | const operand_ri: ResultInfo = switch (block_scope.break_result_info.rl) { |
| 5287 | .ref => .{ .rl = .ref, .ctx = if (do_err_trace) .error_handling_expr else .none }, |
| 5288 | else => .{ .rl = .none, .ctx = if (do_err_trace) .error_handling_expr else .none }, |
| 5162 | 5289 | }; |
| 5163 | 5290 | block_scope.break_count += 1; |
| 5164 | | // This could be a pointer or value depending on the `operand_rl` parameter. |
| 5165 | | // We cannot use `block_scope.break_result_loc` because that has the bare |
| 5291 | // This could be a pointer or value depending on the `operand_ri` parameter. |
| 5292 | // We cannot use `block_scope.break_result_info` because that has the bare |
| 5166 | 5293 | // type, whereas this expression has the optional type. Later we make |
| 5167 | 5294 | // up for this fact by calling rvalue on the else branch. |
| 5168 | | const operand = try reachableExpr(&block_scope, &block_scope.base, operand_rl, lhs, rhs); |
| 5295 | const operand = try reachableExpr(&block_scope, &block_scope.base, operand_ri, lhs, rhs); |
| 5169 | 5296 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 5170 | 5297 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 5171 | 5298 | |
| ... | ... | @@ -5179,14 +5306,19 @@ fn orelseCatchExpr( |
| 5179 | 5306 | |
| 5180 | 5307 | // This could be a pointer or value depending on `unwrap_op`. |
| 5181 | 5308 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); |
| 5182 | | const then_result = switch (rl) { |
| 5309 | const then_result = switch (ri.rl) { |
| 5183 | 5310 | .ref => unwrapped_payload, |
| 5184 | | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), |
| 5311 | else => try rvalue(&then_scope, block_scope.break_result_info, unwrapped_payload, node), |
| 5185 | 5312 | }; |
| 5186 | 5313 | |
| 5187 | 5314 | var else_scope = block_scope.makeSubBlock(scope); |
| 5188 | 5315 | defer else_scope.unstack(); |
| 5189 | 5316 | |
| 5317 | // We know that the operand (almost certainly) modified the error return trace, |
| 5318 | // so signal to Sema that it should save the new index for restoring later. |
| 5319 | if (do_err_trace and nodeMayAppendToErrorTrace(tree, lhs)) |
| 5320 | _ = try else_scope.addSaveErrRetIndex(.always); |
| 5321 | |
| 5190 | 5322 | var err_val_scope: Scope.LocalVal = undefined; |
| 5191 | 5323 | const else_sub_scope = blk: { |
| 5192 | 5324 | const payload = payload_token orelse break :blk &else_scope.base; |
| ... | ... | @@ -5209,9 +5341,13 @@ fn orelseCatchExpr( |
| 5209 | 5341 | break :blk &err_val_scope.base; |
| 5210 | 5342 | }; |
| 5211 | 5343 | |
| 5212 | | const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_loc, rhs); |
| 5344 | const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_info, rhs); |
| 5213 | 5345 | if (!else_scope.endsWithNoReturn()) { |
| 5214 | 5346 | block_scope.break_count += 1; |
| 5347 | |
| 5348 | // As our last action before the break, "pop" the error trace if needed |
| 5349 | if (do_err_trace) |
| 5350 | try restoreErrRetIndex(&else_scope, .{ .block = block }, block_scope.break_result_info, rhs, else_result); |
| 5215 | 5351 | } |
| 5216 | 5352 | try checkUsed(parent_gz, &else_scope.base, else_sub_scope); |
| 5217 | 5353 | |
| ... | ... | @@ -5220,9 +5356,9 @@ fn orelseCatchExpr( |
| 5220 | 5356 | // instructions or not. |
| 5221 | 5357 | |
| 5222 | 5358 | const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break"; |
| 5223 | | return finishThenElseBlock( |
| 5359 | const result = try finishThenElseBlock( |
| 5224 | 5360 | parent_gz, |
| 5225 | | rl, |
| 5361 | ri, |
| 5226 | 5362 | node, |
| 5227 | 5363 | &block_scope, |
| 5228 | 5364 | &then_scope, |
| ... | ... | @@ -5235,12 +5371,13 @@ fn orelseCatchExpr( |
| 5235 | 5371 | block, |
| 5236 | 5372 | break_tag, |
| 5237 | 5373 | ); |
| 5374 | return result; |
| 5238 | 5375 | } |
| 5239 | 5376 | |
| 5240 | 5377 | /// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`. |
| 5241 | 5378 | fn finishThenElseBlock( |
| 5242 | 5379 | parent_gz: *GenZir, |
| 5243 | | rl: ResultLoc, |
| 5380 | ri: ResultInfo, |
| 5244 | 5381 | node: Ast.Node.Index, |
| 5245 | 5382 | block_scope: *GenZir, |
| 5246 | 5383 | then_scope: *GenZir, |
| ... | ... | @@ -5255,7 +5392,7 @@ fn finishThenElseBlock( |
| 5255 | 5392 | ) InnerError!Zir.Inst.Ref { |
| 5256 | 5393 | // We now have enough information to decide whether the result instruction should |
| 5257 | 5394 | // be communicated via result location pointer or break instructions. |
| 5258 | | const strat = rl.strategy(block_scope); |
| 5395 | const strat = ri.rl.strategy(block_scope); |
| 5259 | 5396 | // else_scope may be stacked on then_scope, so check for no-return on then_scope manually |
| 5260 | 5397 | const tags = parent_gz.astgen.instructions.items(.tag); |
| 5261 | 5398 | const then_slice = then_scope.instructionsSliceUpto(else_scope); |
| ... | ... | @@ -5285,9 +5422,9 @@ fn finishThenElseBlock( |
| 5285 | 5422 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 5286 | 5423 | } |
| 5287 | 5424 | const block_ref = indexToRef(main_block); |
| 5288 | | switch (rl) { |
| 5425 | switch (ri.rl) { |
| 5289 | 5426 | .ref => return block_ref, |
| 5290 | | else => return rvalue(parent_gz, rl, block_ref, node), |
| 5427 | else => return rvalue(parent_gz, ri, block_ref, node), |
| 5291 | 5428 | } |
| 5292 | 5429 | }, |
| 5293 | 5430 | } |
| ... | ... | @@ -5306,14 +5443,14 @@ fn tokenIdentEql(astgen: *AstGen, token1: Ast.TokenIndex, token2: Ast.TokenIndex |
| 5306 | 5443 | fn fieldAccess( |
| 5307 | 5444 | gz: *GenZir, |
| 5308 | 5445 | scope: *Scope, |
| 5309 | | rl: ResultLoc, |
| 5446 | ri: ResultInfo, |
| 5310 | 5447 | node: Ast.Node.Index, |
| 5311 | 5448 | ) InnerError!Zir.Inst.Ref { |
| 5312 | | switch (rl) { |
| 5313 | | .ref => return addFieldAccess(.field_ptr, gz, scope, .ref, node), |
| 5449 | switch (ri.rl) { |
| 5450 | .ref => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node), |
| 5314 | 5451 | else => { |
| 5315 | | const access = try addFieldAccess(.field_val, gz, scope, .none, node); |
| 5316 | | return rvalue(gz, rl, access, node); |
| 5452 | const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node); |
| 5453 | return rvalue(gz, ri, access, node); |
| 5317 | 5454 | }, |
| 5318 | 5455 | } |
| 5319 | 5456 | } |
| ... | ... | @@ -5322,7 +5459,7 @@ fn addFieldAccess( |
| 5322 | 5459 | tag: Zir.Inst.Tag, |
| 5323 | 5460 | gz: *GenZir, |
| 5324 | 5461 | scope: *Scope, |
| 5325 | | lhs_rl: ResultLoc, |
| 5462 | lhs_ri: ResultInfo, |
| 5326 | 5463 | node: Ast.Node.Index, |
| 5327 | 5464 | ) InnerError!Zir.Inst.Ref { |
| 5328 | 5465 | const astgen = gz.astgen; |
| ... | ... | @@ -5336,7 +5473,7 @@ fn addFieldAccess( |
| 5336 | 5473 | const str_index = try astgen.identAsString(field_ident); |
| 5337 | 5474 | |
| 5338 | 5475 | return gz.addPlNode(tag, node, Zir.Inst.Field{ |
| 5339 | | .lhs = try expr(gz, scope, lhs_rl, object_node), |
| 5476 | .lhs = try expr(gz, scope, lhs_ri, object_node), |
| 5340 | 5477 | .field_name_start = str_index, |
| 5341 | 5478 | }); |
| 5342 | 5479 | } |
| ... | ... | @@ -5344,20 +5481,20 @@ fn addFieldAccess( |
| 5344 | 5481 | fn arrayAccess( |
| 5345 | 5482 | gz: *GenZir, |
| 5346 | 5483 | scope: *Scope, |
| 5347 | | rl: ResultLoc, |
| 5484 | ri: ResultInfo, |
| 5348 | 5485 | node: Ast.Node.Index, |
| 5349 | 5486 | ) InnerError!Zir.Inst.Ref { |
| 5350 | 5487 | const astgen = gz.astgen; |
| 5351 | 5488 | const tree = astgen.tree; |
| 5352 | 5489 | const node_datas = tree.nodes.items(.data); |
| 5353 | | switch (rl) { |
| 5490 | switch (ri.rl) { |
| 5354 | 5491 | .ref => return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ |
| 5355 | | .lhs = try expr(gz, scope, .ref, node_datas[node].lhs), |
| 5356 | | .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), |
| 5492 | .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), |
| 5357 | 5494 | }), |
| 5358 | | else => return rvalue(gz, rl, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ |
| 5359 | | .lhs = try expr(gz, scope, .none, node_datas[node].lhs), |
| 5360 | | .rhs = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), |
| 5495 | else => return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ |
| 5496 | .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs), |
| 5497 | .rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs), |
| 5361 | 5498 | }), node), |
| 5362 | 5499 | } |
| 5363 | 5500 | } |
| ... | ... | @@ -5365,7 +5502,7 @@ fn arrayAccess( |
| 5365 | 5502 | fn simpleBinOp( |
| 5366 | 5503 | gz: *GenZir, |
| 5367 | 5504 | scope: *Scope, |
| 5368 | | rl: ResultLoc, |
| 5505 | ri: ResultInfo, |
| 5369 | 5506 | node: Ast.Node.Index, |
| 5370 | 5507 | op_inst_tag: Zir.Inst.Tag, |
| 5371 | 5508 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -5374,15 +5511,15 @@ fn simpleBinOp( |
| 5374 | 5511 | const node_datas = tree.nodes.items(.data); |
| 5375 | 5512 | |
| 5376 | 5513 | const result = try gz.addPlNode(op_inst_tag, node, Zir.Inst.Bin{ |
| 5377 | | .lhs = try reachableExpr(gz, scope, .none, node_datas[node].lhs, node), |
| 5378 | | .rhs = try reachableExpr(gz, scope, .none, node_datas[node].rhs, node), |
| 5514 | .lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node), |
| 5515 | .rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node), |
| 5379 | 5516 | }); |
| 5380 | | return rvalue(gz, rl, result, node); |
| 5517 | return rvalue(gz, ri, result, node); |
| 5381 | 5518 | } |
| 5382 | 5519 | |
| 5383 | 5520 | fn simpleStrTok( |
| 5384 | 5521 | gz: *GenZir, |
| 5385 | | rl: ResultLoc, |
| 5522 | ri: ResultInfo, |
| 5386 | 5523 | ident_token: Ast.TokenIndex, |
| 5387 | 5524 | node: Ast.Node.Index, |
| 5388 | 5525 | op_inst_tag: Zir.Inst.Tag, |
| ... | ... | @@ -5390,13 +5527,13 @@ fn simpleStrTok( |
| 5390 | 5527 | const astgen = gz.astgen; |
| 5391 | 5528 | const str_index = try astgen.identAsString(ident_token); |
| 5392 | 5529 | const result = try gz.addStrTok(op_inst_tag, str_index, ident_token); |
| 5393 | | return rvalue(gz, rl, result, node); |
| 5530 | return rvalue(gz, ri, result, node); |
| 5394 | 5531 | } |
| 5395 | 5532 | |
| 5396 | 5533 | fn boolBinOp( |
| 5397 | 5534 | gz: *GenZir, |
| 5398 | 5535 | scope: *Scope, |
| 5399 | | rl: ResultLoc, |
| 5536 | ri: ResultInfo, |
| 5400 | 5537 | node: Ast.Node.Index, |
| 5401 | 5538 | zir_tag: Zir.Inst.Tag, |
| 5402 | 5539 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -5404,25 +5541,25 @@ fn boolBinOp( |
| 5404 | 5541 | const tree = astgen.tree; |
| 5405 | 5542 | const node_datas = tree.nodes.items(.data); |
| 5406 | 5543 | |
| 5407 | | const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs); |
| 5544 | const lhs = try expr(gz, scope, bool_ri, node_datas[node].lhs); |
| 5408 | 5545 | const bool_br = try gz.addBoolBr(zir_tag, lhs); |
| 5409 | 5546 | |
| 5410 | 5547 | var rhs_scope = gz.makeSubBlock(scope); |
| 5411 | 5548 | defer rhs_scope.unstack(); |
| 5412 | | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); |
| 5549 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_ri, node_datas[node].rhs); |
| 5413 | 5550 | if (!gz.refIsNoReturn(rhs)) { |
| 5414 | 5551 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); |
| 5415 | 5552 | } |
| 5416 | 5553 | try rhs_scope.setBoolBrBody(bool_br); |
| 5417 | 5554 | |
| 5418 | 5555 | const block_ref = indexToRef(bool_br); |
| 5419 | | return rvalue(gz, rl, block_ref, node); |
| 5556 | return rvalue(gz, ri, block_ref, node); |
| 5420 | 5557 | } |
| 5421 | 5558 | |
| 5422 | 5559 | fn ifExpr( |
| 5423 | 5560 | parent_gz: *GenZir, |
| 5424 | 5561 | scope: *Scope, |
| 5425 | | rl: ResultLoc, |
| 5562 | ri: ResultInfo, |
| 5426 | 5563 | node: Ast.Node.Index, |
| 5427 | 5564 | if_full: Ast.full.If, |
| 5428 | 5565 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -5430,8 +5567,10 @@ fn ifExpr( |
| 5430 | 5567 | const tree = astgen.tree; |
| 5431 | 5568 | const token_tags = tree.tokens.items(.tag); |
| 5432 | 5569 | |
| 5570 | const do_err_trace = astgen.fn_block != null and if_full.error_token != null; |
| 5571 | |
| 5433 | 5572 | var block_scope = parent_gz.makeSubBlock(scope); |
| 5434 | | block_scope.setBreakResultLoc(rl); |
| 5573 | block_scope.setBreakResultInfo(ri); |
| 5435 | 5574 | defer block_scope.unstack(); |
| 5436 | 5575 | |
| 5437 | 5576 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| ... | ... | @@ -5445,23 +5584,23 @@ fn ifExpr( |
| 5445 | 5584 | bool_bit: Zir.Inst.Ref, |
| 5446 | 5585 | } = c: { |
| 5447 | 5586 | if (if_full.error_token) |_| { |
| 5448 | | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| 5449 | | const err_union = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr); |
| 5587 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none, .ctx = .error_handling_expr }; |
| 5588 | const err_union = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr); |
| 5450 | 5589 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; |
| 5451 | 5590 | break :c .{ |
| 5452 | 5591 | .inst = err_union, |
| 5453 | 5592 | .bool_bit = try block_scope.addUnNode(tag, err_union, if_full.ast.cond_expr), |
| 5454 | 5593 | }; |
| 5455 | 5594 | } else if (if_full.payload_token) |_| { |
| 5456 | | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| 5457 | | const optional = try expr(&block_scope, &block_scope.base, cond_rl, if_full.ast.cond_expr); |
| 5595 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; |
| 5596 | const optional = try expr(&block_scope, &block_scope.base, cond_ri, if_full.ast.cond_expr); |
| 5458 | 5597 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; |
| 5459 | 5598 | break :c .{ |
| 5460 | 5599 | .inst = optional, |
| 5461 | 5600 | .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr), |
| 5462 | 5601 | }; |
| 5463 | 5602 | } else { |
| 5464 | | const cond = try expr(&block_scope, &block_scope.base, bool_rl, if_full.ast.cond_expr); |
| 5603 | const cond = try expr(&block_scope, &block_scope.base, bool_ri, if_full.ast.cond_expr); |
| 5465 | 5604 | break :c .{ |
| 5466 | 5605 | .inst = cond, |
| 5467 | 5606 | .bool_bit = cond, |
| ... | ... | @@ -5537,7 +5676,7 @@ fn ifExpr( |
| 5537 | 5676 | } |
| 5538 | 5677 | }; |
| 5539 | 5678 | |
| 5540 | | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr); |
| 5679 | const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_info, if_full.ast.then_expr); |
| 5541 | 5680 | if (!then_scope.endsWithNoReturn()) { |
| 5542 | 5681 | block_scope.break_count += 1; |
| 5543 | 5682 | } |
| ... | ... | @@ -5550,6 +5689,11 @@ fn ifExpr( |
| 5550 | 5689 | var else_scope = parent_gz.makeSubBlock(scope); |
| 5551 | 5690 | defer else_scope.unstack(); |
| 5552 | 5691 | |
| 5692 | // We know that the operand (almost certainly) modified the error return trace, |
| 5693 | // so signal to Sema that it should save the new index for restoring later. |
| 5694 | if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr)) |
| 5695 | _ = try else_scope.addSaveErrRetIndex(.always); |
| 5696 | |
| 5553 | 5697 | const else_node = if_full.ast.else_expr; |
| 5554 | 5698 | const else_info: struct { |
| 5555 | 5699 | src: Ast.Node.Index, |
| ... | ... | @@ -5582,9 +5726,13 @@ fn ifExpr( |
| 5582 | 5726 | break :s &else_scope.base; |
| 5583 | 5727 | } |
| 5584 | 5728 | }; |
| 5585 | | const e = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node); |
| 5729 | const e = try expr(&else_scope, sub_scope, block_scope.break_result_info, else_node); |
| 5586 | 5730 | if (!else_scope.endsWithNoReturn()) { |
| 5587 | 5731 | block_scope.break_count += 1; |
| 5732 | |
| 5733 | // As our last action before the break, "pop" the error trace if needed |
| 5734 | if (do_err_trace) |
| 5735 | try restoreErrRetIndex(&else_scope, .{ .block = block }, block_scope.break_result_info, else_node, e); |
| 5588 | 5736 | } |
| 5589 | 5737 | try checkUsed(parent_gz, &else_scope.base, sub_scope); |
| 5590 | 5738 | try else_scope.addDbgBlockEnd(); |
| ... | ... | @@ -5594,17 +5742,17 @@ fn ifExpr( |
| 5594 | 5742 | }; |
| 5595 | 5743 | } else .{ |
| 5596 | 5744 | .src = if_full.ast.then_expr, |
| 5597 | | .result = switch (rl) { |
| 5745 | .result = switch (ri.rl) { |
| 5598 | 5746 | // Explicitly store void to ptr result loc if there is no else branch |
| 5599 | | .ptr, .block_ptr => try rvalue(&else_scope, rl, .void_value, node), |
| 5747 | .ptr, .block_ptr => try rvalue(&else_scope, ri, .void_value, node), |
| 5600 | 5748 | else => .none, |
| 5601 | 5749 | }, |
| 5602 | 5750 | }; |
| 5603 | 5751 | |
| 5604 | 5752 | const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break"; |
| 5605 | | return finishThenElseBlock( |
| 5753 | const result = try finishThenElseBlock( |
| 5606 | 5754 | parent_gz, |
| 5607 | | rl, |
| 5755 | ri, |
| 5608 | 5756 | node, |
| 5609 | 5757 | &block_scope, |
| 5610 | 5758 | &then_scope, |
| ... | ... | @@ -5617,6 +5765,7 @@ fn ifExpr( |
| 5617 | 5765 | block, |
| 5618 | 5766 | break_tag, |
| 5619 | 5767 | ); |
| 5768 | return result; |
| 5620 | 5769 | } |
| 5621 | 5770 | |
| 5622 | 5771 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| ... | ... | @@ -5737,7 +5886,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5737 | 5886 | fn whileExpr( |
| 5738 | 5887 | parent_gz: *GenZir, |
| 5739 | 5888 | scope: *Scope, |
| 5740 | | rl: ResultLoc, |
| 5889 | ri: ResultInfo, |
| 5741 | 5890 | node: Ast.Node.Index, |
| 5742 | 5891 | while_full: Ast.full.While, |
| 5743 | 5892 | is_statement: bool, |
| ... | ... | @@ -5757,7 +5906,7 @@ fn whileExpr( |
| 5757 | 5906 | |
| 5758 | 5907 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5759 | 5908 | loop_scope.is_inline = is_inline; |
| 5760 | | loop_scope.setBreakResultLoc(rl); |
| 5909 | loop_scope.setBreakResultInfo(ri); |
| 5761 | 5910 | defer loop_scope.unstack(); |
| 5762 | 5911 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5763 | 5912 | |
| ... | ... | @@ -5775,23 +5924,23 @@ fn whileExpr( |
| 5775 | 5924 | bool_bit: Zir.Inst.Ref, |
| 5776 | 5925 | } = c: { |
| 5777 | 5926 | if (while_full.error_token) |_| { |
| 5778 | | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| 5779 | | const err_union = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr); |
| 5927 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; |
| 5928 | const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); |
| 5780 | 5929 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err; |
| 5781 | 5930 | break :c .{ |
| 5782 | 5931 | .inst = err_union, |
| 5783 | 5932 | .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr), |
| 5784 | 5933 | }; |
| 5785 | 5934 | } else if (while_full.payload_token) |_| { |
| 5786 | | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| 5787 | | const optional = try expr(&continue_scope, &continue_scope.base, cond_rl, while_full.ast.cond_expr); |
| 5935 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; |
| 5936 | const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr); |
| 5788 | 5937 | const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null; |
| 5789 | 5938 | break :c .{ |
| 5790 | 5939 | .inst = optional, |
| 5791 | 5940 | .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr), |
| 5792 | 5941 | }; |
| 5793 | 5942 | } else { |
| 5794 | | const cond = try expr(&continue_scope, &continue_scope.base, bool_rl, while_full.ast.cond_expr); |
| 5943 | const cond = try expr(&continue_scope, &continue_scope.base, bool_ri, while_full.ast.cond_expr); |
| 5795 | 5944 | break :c .{ |
| 5796 | 5945 | .inst = cond, |
| 5797 | 5946 | .bool_bit = cond, |
| ... | ... | @@ -5910,7 +6059,7 @@ fn whileExpr( |
| 5910 | 6059 | if (dbg_var_name) |some| { |
| 5911 | 6060 | try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst); |
| 5912 | 6061 | } |
| 5913 | | const then_result = try expr(&then_scope, then_sub_scope, .none, while_full.ast.then_expr); |
| 6062 | const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, while_full.ast.then_expr); |
| 5914 | 6063 | _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr); |
| 5915 | 6064 | |
| 5916 | 6065 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| ... | ... | @@ -5955,7 +6104,7 @@ fn whileExpr( |
| 5955 | 6104 | // control flow apply to outer loops; not this one. |
| 5956 | 6105 | loop_scope.continue_block = 0; |
| 5957 | 6106 | loop_scope.break_block = 0; |
| 5958 | | const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); |
| 6107 | const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node); |
| 5959 | 6108 | if (is_statement) { |
| 5960 | 6109 | _ = try addEnsureResult(&else_scope, else_result, else_node); |
| 5961 | 6110 | } |
| ... | ... | @@ -5982,7 +6131,7 @@ fn whileExpr( |
| 5982 | 6131 | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 5983 | 6132 | const result = try finishThenElseBlock( |
| 5984 | 6133 | parent_gz, |
| 5985 | | rl, |
| 6134 | ri, |
| 5986 | 6135 | node, |
| 5987 | 6136 | &loop_scope, |
| 5988 | 6137 | &then_scope, |
| ... | ... | @@ -6004,7 +6153,7 @@ fn whileExpr( |
| 6004 | 6153 | fn forExpr( |
| 6005 | 6154 | parent_gz: *GenZir, |
| 6006 | 6155 | scope: *Scope, |
| 6007 | | rl: ResultLoc, |
| 6156 | ri: ResultInfo, |
| 6008 | 6157 | node: Ast.Node.Index, |
| 6009 | 6158 | for_full: Ast.full.While, |
| 6010 | 6159 | is_statement: bool, |
| ... | ... | @@ -6027,8 +6176,8 @@ fn forExpr( |
| 6027 | 6176 | |
| 6028 | 6177 | try emitDbgNode(parent_gz, for_full.ast.cond_expr); |
| 6029 | 6178 | |
| 6030 | | const cond_rl: ResultLoc = if (payload_is_ref) .ref else .none; |
| 6031 | | const array_ptr = try expr(parent_gz, scope, cond_rl, for_full.ast.cond_expr); |
| 6179 | const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none }; |
| 6180 | const array_ptr = try expr(parent_gz, scope, cond_ri, for_full.ast.cond_expr); |
| 6032 | 6181 | const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr); |
| 6033 | 6182 | |
| 6034 | 6183 | const index_ptr = blk: { |
| ... | ... | @@ -6045,7 +6194,7 @@ fn forExpr( |
| 6045 | 6194 | |
| 6046 | 6195 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 6047 | 6196 | loop_scope.is_inline = is_inline; |
| 6048 | | loop_scope.setBreakResultLoc(rl); |
| 6197 | loop_scope.setBreakResultInfo(ri); |
| 6049 | 6198 | defer loop_scope.unstack(); |
| 6050 | 6199 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 6051 | 6200 | |
| ... | ... | @@ -6149,7 +6298,7 @@ fn forExpr( |
| 6149 | 6298 | break :blk &index_scope.base; |
| 6150 | 6299 | }; |
| 6151 | 6300 | |
| 6152 | | const then_result = try expr(&then_scope, then_sub_scope, .none, for_full.ast.then_expr); |
| 6301 | const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr); |
| 6153 | 6302 | _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr); |
| 6154 | 6303 | |
| 6155 | 6304 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| ... | ... | @@ -6168,7 +6317,7 @@ fn forExpr( |
| 6168 | 6317 | // control flow apply to outer loops; not this one. |
| 6169 | 6318 | loop_scope.continue_block = 0; |
| 6170 | 6319 | loop_scope.break_block = 0; |
| 6171 | | const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node); |
| 6320 | const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_info, else_node); |
| 6172 | 6321 | if (is_statement) { |
| 6173 | 6322 | _ = try addEnsureResult(&else_scope, else_result, else_node); |
| 6174 | 6323 | } |
| ... | ... | @@ -6193,7 +6342,7 @@ fn forExpr( |
| 6193 | 6342 | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 6194 | 6343 | const result = try finishThenElseBlock( |
| 6195 | 6344 | parent_gz, |
| 6196 | | rl, |
| 6345 | ri, |
| 6197 | 6346 | node, |
| 6198 | 6347 | &loop_scope, |
| 6199 | 6348 | &then_scope, |
| ... | ... | @@ -6215,7 +6364,7 @@ fn forExpr( |
| 6215 | 6364 | fn switchExpr( |
| 6216 | 6365 | parent_gz: *GenZir, |
| 6217 | 6366 | scope: *Scope, |
| 6218 | | rl: ResultLoc, |
| 6367 | ri: ResultInfo, |
| 6219 | 6368 | switch_node: Ast.Node.Index, |
| 6220 | 6369 | ) InnerError!Zir.Inst.Ref { |
| 6221 | 6370 | const astgen = parent_gz.astgen; |
| ... | ... | @@ -6346,13 +6495,13 @@ fn switchExpr( |
| 6346 | 6495 | } |
| 6347 | 6496 | } |
| 6348 | 6497 | |
| 6349 | | const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none; |
| 6350 | | const raw_operand = try expr(parent_gz, scope, operand_rl, operand_node); |
| 6498 | const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none }; |
| 6499 | const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node); |
| 6351 | 6500 | const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond; |
| 6352 | 6501 | const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node); |
| 6353 | 6502 | // We need the type of the operand to use as the result location for all the prong items. |
| 6354 | 6503 | const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node); |
| 6355 | | const item_rl: ResultLoc = .{ .ty = cond_ty_inst }; |
| 6504 | const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } }; |
| 6356 | 6505 | |
| 6357 | 6506 | // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti, |
| 6358 | 6507 | // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with |
| ... | ... | @@ -6369,7 +6518,7 @@ fn switchExpr( |
| 6369 | 6518 | var block_scope = parent_gz.makeSubBlock(scope); |
| 6370 | 6519 | // block_scope not used for collecting instructions |
| 6371 | 6520 | block_scope.instructions_top = GenZir.unstacked_top; |
| 6372 | | block_scope.setBreakResultLoc(rl); |
| 6521 | block_scope.setBreakResultInfo(ri); |
| 6373 | 6522 | |
| 6374 | 6523 | // This gets added to the parent block later, after the item expressions. |
| 6375 | 6524 | const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node); |
| ... | ... | @@ -6510,7 +6659,7 @@ fn switchExpr( |
| 6510 | 6659 | if (node_tags[item_node] == .switch_range) continue; |
| 6511 | 6660 | items_len += 1; |
| 6512 | 6661 | |
| 6513 | | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 6662 | const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node); |
| 6514 | 6663 | try payloads.append(gpa, @enumToInt(item_inst)); |
| 6515 | 6664 | } |
| 6516 | 6665 | |
| ... | ... | @@ -6520,8 +6669,8 @@ fn switchExpr( |
| 6520 | 6669 | if (node_tags[range] != .switch_range) continue; |
| 6521 | 6670 | ranges_len += 1; |
| 6522 | 6671 | |
| 6523 | | const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs); |
| 6524 | | const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs); |
| 6672 | const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs); |
| 6673 | const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs); |
| 6525 | 6674 | try payloads.appendSlice(gpa, &[_]u32{ |
| 6526 | 6675 | @enumToInt(first), @enumToInt(last), |
| 6527 | 6676 | }); |
| ... | ... | @@ -6539,7 +6688,7 @@ fn switchExpr( |
| 6539 | 6688 | scalar_case_index += 1; |
| 6540 | 6689 | try payloads.resize(gpa, header_index + 2); // item, body_len |
| 6541 | 6690 | const item_node = case.ast.values[0]; |
| 6542 | | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 6691 | const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node); |
| 6543 | 6692 | payloads.items[header_index] = @enumToInt(item_inst); |
| 6544 | 6693 | break :blk header_index + 1; |
| 6545 | 6694 | }; |
| ... | ... | @@ -6558,7 +6707,7 @@ fn switchExpr( |
| 6558 | 6707 | if (dbg_var_tag_name) |some| { |
| 6559 | 6708 | try case_scope.addDbgVar(.dbg_var_val, some, dbg_var_tag_inst); |
| 6560 | 6709 | } |
| 6561 | | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6710 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_info, case.ast.target_expr); |
| 6562 | 6711 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6563 | 6712 | try case_scope.addDbgBlockEnd(); |
| 6564 | 6713 | if (!parent_gz.refIsNoReturn(case_result)) { |
| ... | ... | @@ -6600,7 +6749,7 @@ fn switchExpr( |
| 6600 | 6749 | |
| 6601 | 6750 | zir_datas[switch_block].pl_node.payload_index = payload_index; |
| 6602 | 6751 | |
| 6603 | | const strat = rl.strategy(&block_scope); |
| 6752 | const strat = ri.rl.strategy(&block_scope); |
| 6604 | 6753 | for (payloads.items[case_table_start..case_table_end]) |start_index, i| { |
| 6605 | 6754 | var body_len_index = start_index; |
| 6606 | 6755 | var end_index = start_index; |
| ... | ... | @@ -6672,8 +6821,8 @@ fn switchExpr( |
| 6672 | 6821 | } |
| 6673 | 6822 | |
| 6674 | 6823 | const block_ref = indexToRef(switch_block); |
| 6675 | | if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref) |
| 6676 | | return rvalue(parent_gz, rl, block_ref, switch_node); |
| 6824 | if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and ri.rl != .ref) |
| 6825 | return rvalue(parent_gz, ri, block_ref, switch_node); |
| 6677 | 6826 | return block_ref; |
| 6678 | 6827 | } |
| 6679 | 6828 | |
| ... | ... | @@ -6713,6 +6862,10 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6713 | 6862 | if (operand_node == 0) { |
| 6714 | 6863 | // Returning a void value; skip error defers. |
| 6715 | 6864 | try genDefers(gz, defer_outer, scope, .normal_only); |
| 6865 | |
| 6866 | // As our last action before the return, "pop" the error trace if needed |
| 6867 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 6868 | |
| 6716 | 6869 | _ = try gz.addUnNode(.ret_node, .void_value, node); |
| 6717 | 6870 | return Zir.Inst.Ref.unreachable_value; |
| 6718 | 6871 | } |
| ... | ... | @@ -6736,30 +6889,36 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6736 | 6889 | return Zir.Inst.Ref.unreachable_value; |
| 6737 | 6890 | } |
| 6738 | 6891 | |
| 6739 | | const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{ |
| 6740 | | .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) }, |
| 6892 | const ri: ResultInfo = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{ |
| 6893 | .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } }, |
| 6894 | .ctx = .@"return", |
| 6741 | 6895 | } else .{ |
| 6742 | | .ty = try gz.addNode(.ret_type, node), |
| 6896 | .rl = .{ .ty = try gz.addNode(.ret_type, node) }, |
| 6897 | .ctx = .@"return", |
| 6743 | 6898 | }; |
| 6744 | 6899 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 6745 | 6900 | gz.anon_name_strategy = .func; |
| 6746 | | const operand = try reachableExpr(gz, scope, rl, operand_node, node); |
| 6901 | const operand = try reachableExpr(gz, scope, ri, operand_node, node); |
| 6747 | 6902 | gz.anon_name_strategy = prev_anon_name_strategy; |
| 6748 | 6903 | |
| 6749 | 6904 | switch (nodeMayEvalToError(tree, operand_node)) { |
| 6750 | 6905 | .never => { |
| 6751 | 6906 | // Returning a value that cannot be an error; skip error defers. |
| 6752 | 6907 | try genDefers(gz, defer_outer, scope, .normal_only); |
| 6908 | |
| 6909 | // As our last action before the return, "pop" the error trace if needed |
| 6910 | _ = try gz.addRestoreErrRetIndex(.ret, .always); |
| 6911 | |
| 6753 | 6912 | try emitDbgStmt(gz, ret_line, ret_column); |
| 6754 | | try gz.addRet(rl, operand, node); |
| 6913 | try gz.addRet(ri, operand, node); |
| 6755 | 6914 | return Zir.Inst.Ref.unreachable_value; |
| 6756 | 6915 | }, |
| 6757 | 6916 | .always => { |
| 6758 | 6917 | // Value is always an error. Emit both error defers and regular defers. |
| 6759 | | const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; |
| 6918 | const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand; |
| 6760 | 6919 | try genDefers(gz, defer_outer, scope, .{ .both = err_code }); |
| 6761 | 6920 | try emitDbgStmt(gz, ret_line, ret_column); |
| 6762 | | try gz.addRet(rl, operand, node); |
| 6921 | try gz.addRet(ri, operand, node); |
| 6763 | 6922 | return Zir.Inst.Ref.unreachable_value; |
| 6764 | 6923 | }, |
| 6765 | 6924 | .maybe => { |
| ... | ... | @@ -6768,12 +6927,17 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6768 | 6927 | // Only regular defers; no branch needed. |
| 6769 | 6928 | try genDefers(gz, defer_outer, scope, .normal_only); |
| 6770 | 6929 | try emitDbgStmt(gz, ret_line, ret_column); |
| 6771 | | try gz.addRet(rl, operand, node); |
| 6930 | |
| 6931 | // As our last action before the return, "pop" the error trace if needed |
| 6932 | const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand; |
| 6933 | _ = try gz.addRestoreErrRetIndex(.ret, .{ .if_non_error = result }); |
| 6934 | |
| 6935 | try gz.addRet(ri, operand, node); |
| 6772 | 6936 | return Zir.Inst.Ref.unreachable_value; |
| 6773 | 6937 | } |
| 6774 | 6938 | |
| 6775 | 6939 | // Emit conditional branch for generating errdefers. |
| 6776 | | const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand; |
| 6940 | const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand; |
| 6777 | 6941 | const is_non_err = try gz.addUnNode(.is_non_err, result, node); |
| 6778 | 6942 | const condbr = try gz.addCondBr(.condbr, node); |
| 6779 | 6943 | |
| ... | ... | @@ -6781,8 +6945,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6781 | 6945 | defer then_scope.unstack(); |
| 6782 | 6946 | |
| 6783 | 6947 | try genDefers(&then_scope, defer_outer, scope, .normal_only); |
| 6948 | |
| 6949 | // As our last action before the return, "pop" the error trace if needed |
| 6950 | _ = try then_scope.addRestoreErrRetIndex(.ret, .always); |
| 6951 | |
| 6784 | 6952 | try emitDbgStmt(&then_scope, ret_line, ret_column); |
| 6785 | | try then_scope.addRet(rl, operand, node); |
| 6953 | try then_scope.addRet(ri, operand, node); |
| 6786 | 6954 | |
| 6787 | 6955 | var else_scope = gz.makeSubBlock(scope); |
| 6788 | 6956 | defer else_scope.unstack(); |
| ... | ... | @@ -6792,7 +6960,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6792 | 6960 | }; |
| 6793 | 6961 | try genDefers(&else_scope, defer_outer, scope, which_ones); |
| 6794 | 6962 | try emitDbgStmt(&else_scope, ret_line, ret_column); |
| 6795 | | try else_scope.addRet(rl, operand, node); |
| 6963 | try else_scope.addRet(ri, operand, node); |
| 6796 | 6964 | |
| 6797 | 6965 | try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0); |
| 6798 | 6966 | |
| ... | ... | @@ -6825,7 +6993,7 @@ fn parseBitCount(buf: []const u8) std.fmt.ParseIntError!u16 { |
| 6825 | 6993 | fn identifier( |
| 6826 | 6994 | gz: *GenZir, |
| 6827 | 6995 | scope: *Scope, |
| 6828 | | rl: ResultLoc, |
| 6996 | ri: ResultInfo, |
| 6829 | 6997 | ident: Ast.Node.Index, |
| 6830 | 6998 | ) InnerError!Zir.Inst.Ref { |
| 6831 | 6999 | const tracy = trace(@src()); |
| ... | ... | @@ -6844,7 +7012,7 @@ fn identifier( |
| 6844 | 7012 | // if not @"" syntax, just use raw token slice |
| 6845 | 7013 | if (ident_name_raw[0] != '@') { |
| 6846 | 7014 | if (primitives.get(ident_name_raw)) |zir_const_ref| { |
| 6847 | | return rvalue(gz, rl, zir_const_ref, ident); |
| 7015 | return rvalue(gz, ri, zir_const_ref, ident); |
| 6848 | 7016 | } |
| 6849 | 7017 | |
| 6850 | 7018 | if (ident_name_raw.len >= 2) integer: { |
| ... | ... | @@ -6877,19 +7045,19 @@ fn identifier( |
| 6877 | 7045 | .bit_count = bit_count, |
| 6878 | 7046 | } }, |
| 6879 | 7047 | }); |
| 6880 | | return rvalue(gz, rl, result, ident); |
| 7048 | return rvalue(gz, ri, result, ident); |
| 6881 | 7049 | } |
| 6882 | 7050 | } |
| 6883 | 7051 | } |
| 6884 | 7052 | |
| 6885 | 7053 | // Local variables, including function parameters. |
| 6886 | | return localVarRef(gz, scope, rl, ident, ident_token); |
| 7054 | return localVarRef(gz, scope, ri, ident, ident_token); |
| 6887 | 7055 | } |
| 6888 | 7056 | |
| 6889 | 7057 | fn localVarRef( |
| 6890 | 7058 | gz: *GenZir, |
| 6891 | 7059 | scope: *Scope, |
| 6892 | | rl: ResultLoc, |
| 7060 | ri: ResultInfo, |
| 6893 | 7061 | ident: Ast.Node.Index, |
| 6894 | 7062 | ident_token: Ast.TokenIndex, |
| 6895 | 7063 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -6907,7 +7075,7 @@ fn localVarRef( |
| 6907 | 7075 | if (local_val.name == name_str_index) { |
| 6908 | 7076 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 6909 | 7077 | // references in this case. |
| 6910 | | if (rl == .discard) { |
| 7078 | if (ri.rl == .discard) { |
| 6911 | 7079 | local_val.discarded = ident_token; |
| 6912 | 7080 | } else { |
| 6913 | 7081 | local_val.used = ident_token; |
| ... | ... | @@ -6923,14 +7091,14 @@ fn localVarRef( |
| 6923 | 7091 | gpa, |
| 6924 | 7092 | ); |
| 6925 | 7093 | |
| 6926 | | return rvalue(gz, rl, value_inst, ident); |
| 7094 | return rvalue(gz, ri, value_inst, ident); |
| 6927 | 7095 | } |
| 6928 | 7096 | s = local_val.parent; |
| 6929 | 7097 | }, |
| 6930 | 7098 | .local_ptr => { |
| 6931 | 7099 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6932 | 7100 | if (local_ptr.name == name_str_index) { |
| 6933 | | if (rl == .discard) { |
| 7101 | if (ri.rl == .discard) { |
| 6934 | 7102 | local_ptr.discarded = ident_token; |
| 6935 | 7103 | } else { |
| 6936 | 7104 | local_ptr.used = ident_token; |
| ... | ... | @@ -6955,11 +7123,11 @@ fn localVarRef( |
| 6955 | 7123 | gpa, |
| 6956 | 7124 | ); |
| 6957 | 7125 | |
| 6958 | | switch (rl) { |
| 7126 | switch (ri.rl) { |
| 6959 | 7127 | .ref => return ptr_inst, |
| 6960 | 7128 | else => { |
| 6961 | 7129 | const loaded = try gz.addUnNode(.load, ptr_inst, ident); |
| 6962 | | return rvalue(gz, rl, loaded, ident); |
| 7130 | return rvalue(gz, ri, loaded, ident); |
| 6963 | 7131 | }, |
| 6964 | 7132 | } |
| 6965 | 7133 | } |
| ... | ... | @@ -6992,11 +7160,11 @@ fn localVarRef( |
| 6992 | 7160 | |
| 6993 | 7161 | // Decl references happen by name rather than ZIR index so that when unrelated |
| 6994 | 7162 | // decls are modified, ZIR code containing references to them can be unmodified. |
| 6995 | | switch (rl) { |
| 7163 | switch (ri.rl) { |
| 6996 | 7164 | .ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token), |
| 6997 | 7165 | else => { |
| 6998 | 7166 | const result = try gz.addStrTok(.decl_val, name_str_index, ident_token); |
| 6999 | | return rvalue(gz, rl, result, ident); |
| 7167 | return rvalue(gz, ri, result, ident); |
| 7000 | 7168 | }, |
| 7001 | 7169 | } |
| 7002 | 7170 | } |
| ... | ... | @@ -7040,7 +7208,7 @@ fn tunnelThroughClosure( |
| 7040 | 7208 | |
| 7041 | 7209 | fn stringLiteral( |
| 7042 | 7210 | gz: *GenZir, |
| 7043 | | rl: ResultLoc, |
| 7211 | ri: ResultInfo, |
| 7044 | 7212 | node: Ast.Node.Index, |
| 7045 | 7213 | ) InnerError!Zir.Inst.Ref { |
| 7046 | 7214 | const astgen = gz.astgen; |
| ... | ... | @@ -7055,12 +7223,12 @@ fn stringLiteral( |
| 7055 | 7223 | .len = str.len, |
| 7056 | 7224 | } }, |
| 7057 | 7225 | }); |
| 7058 | | return rvalue(gz, rl, result, node); |
| 7226 | return rvalue(gz, ri, result, node); |
| 7059 | 7227 | } |
| 7060 | 7228 | |
| 7061 | 7229 | fn multilineStringLiteral( |
| 7062 | 7230 | gz: *GenZir, |
| 7063 | | rl: ResultLoc, |
| 7231 | ri: ResultInfo, |
| 7064 | 7232 | node: Ast.Node.Index, |
| 7065 | 7233 | ) InnerError!Zir.Inst.Ref { |
| 7066 | 7234 | const astgen = gz.astgen; |
| ... | ... | @@ -7072,10 +7240,10 @@ fn multilineStringLiteral( |
| 7072 | 7240 | .len = str.len, |
| 7073 | 7241 | } }, |
| 7074 | 7242 | }); |
| 7075 | | return rvalue(gz, rl, result, node); |
| 7243 | return rvalue(gz, ri, result, node); |
| 7076 | 7244 | } |
| 7077 | 7245 | |
| 7078 | | fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 7246 | fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 7079 | 7247 | const astgen = gz.astgen; |
| 7080 | 7248 | const tree = astgen.tree; |
| 7081 | 7249 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -7085,7 +7253,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir. |
| 7085 | 7253 | switch (std.zig.parseCharLiteral(slice)) { |
| 7086 | 7254 | .success => |codepoint| { |
| 7087 | 7255 | const result = try gz.addInt(codepoint); |
| 7088 | | return rvalue(gz, rl, result, node); |
| 7256 | return rvalue(gz, ri, result, node); |
| 7089 | 7257 | }, |
| 7090 | 7258 | .failure => |err| return astgen.failWithStrLitError(err, main_token, slice, 0), |
| 7091 | 7259 | } |
| ... | ... | @@ -7093,7 +7261,7 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir. |
| 7093 | 7261 | |
| 7094 | 7262 | const Sign = enum { negative, positive }; |
| 7095 | 7263 | |
| 7096 | | fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { |
| 7264 | fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { |
| 7097 | 7265 | const astgen = gz.astgen; |
| 7098 | 7266 | const tree = astgen.tree; |
| 7099 | 7267 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -7135,7 +7303,7 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: |
| 7135 | 7303 | const bigger_again: f128 = smaller_float; |
| 7136 | 7304 | if (bigger_again == float_number) { |
| 7137 | 7305 | const result = try gz.addFloat(smaller_float); |
| 7138 | | return rvalue(gz, rl, result, source_node); |
| 7306 | return rvalue(gz, ri, result, source_node); |
| 7139 | 7307 | } |
| 7140 | 7308 | // We need to use 128 bits. Break the float into 4 u32 values so we can |
| 7141 | 7309 | // put it into the `extra` array. |
| ... | ... | @@ -7146,16 +7314,16 @@ fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: |
| 7146 | 7314 | .piece2 = @truncate(u32, int_bits >> 64), |
| 7147 | 7315 | .piece3 = @truncate(u32, int_bits >> 96), |
| 7148 | 7316 | }); |
| 7149 | | return rvalue(gz, rl, result, source_node); |
| 7317 | return rvalue(gz, ri, result, source_node); |
| 7150 | 7318 | }, |
| 7151 | 7319 | .failure => |err| return astgen.failWithNumberError(err, num_token, bytes), |
| 7152 | 7320 | }; |
| 7153 | 7321 | |
| 7154 | 7322 | if (sign == .positive) { |
| 7155 | | return rvalue(gz, rl, result, source_node); |
| 7323 | return rvalue(gz, ri, result, source_node); |
| 7156 | 7324 | } else { |
| 7157 | 7325 | const negated = try gz.addUnNode(.negate, result, source_node); |
| 7158 | | return rvalue(gz, rl, negated, source_node); |
| 7326 | return rvalue(gz, ri, negated, source_node); |
| 7159 | 7327 | } |
| 7160 | 7328 | } |
| 7161 | 7329 | |
| ... | ... | @@ -7191,7 +7359,7 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token |
| 7191 | 7359 | fn asmExpr( |
| 7192 | 7360 | gz: *GenZir, |
| 7193 | 7361 | scope: *Scope, |
| 7194 | | rl: ResultLoc, |
| 7362 | ri: ResultInfo, |
| 7195 | 7363 | node: Ast.Node.Index, |
| 7196 | 7364 | full: Ast.full.Asm, |
| 7197 | 7365 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -7214,7 +7382,7 @@ fn asmExpr( |
| 7214 | 7382 | }, |
| 7215 | 7383 | else => .{ |
| 7216 | 7384 | .tag = .asm_expr, |
| 7217 | | .tmpl = @enumToInt(try comptimeExpr(gz, scope, .none, full.ast.template)), |
| 7385 | .tmpl = @enumToInt(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template)), |
| 7218 | 7386 | }, |
| 7219 | 7387 | }; |
| 7220 | 7388 | |
| ... | ... | @@ -7266,7 +7434,7 @@ fn asmExpr( |
| 7266 | 7434 | outputs[i] = .{ |
| 7267 | 7435 | .name = name, |
| 7268 | 7436 | .constraint = constraint, |
| 7269 | | .operand = try localVarRef(gz, scope, .ref, node, ident_token), |
| 7437 | .operand = try localVarRef(gz, scope, .{ .rl = .ref }, node, ident_token), |
| 7270 | 7438 | }; |
| 7271 | 7439 | } |
| 7272 | 7440 | } |
| ... | ... | @@ -7282,7 +7450,7 @@ fn asmExpr( |
| 7282 | 7450 | const name = try astgen.identAsString(symbolic_name); |
| 7283 | 7451 | const constraint_token = symbolic_name + 2; |
| 7284 | 7452 | const constraint = (try astgen.strLitAsString(constraint_token)).index; |
| 7285 | | const operand = try expr(gz, scope, .none, node_datas[input_node].lhs); |
| 7453 | const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs); |
| 7286 | 7454 | inputs[i] = .{ |
| 7287 | 7455 | .name = name, |
| 7288 | 7456 | .constraint = constraint, |
| ... | ... | @@ -7327,31 +7495,31 @@ fn asmExpr( |
| 7327 | 7495 | .inputs = inputs, |
| 7328 | 7496 | .clobbers = clobbers_buffer[0..clobber_i], |
| 7329 | 7497 | }); |
| 7330 | | return rvalue(gz, rl, result, node); |
| 7498 | return rvalue(gz, ri, result, node); |
| 7331 | 7499 | } |
| 7332 | 7500 | |
| 7333 | 7501 | fn as( |
| 7334 | 7502 | gz: *GenZir, |
| 7335 | 7503 | scope: *Scope, |
| 7336 | | rl: ResultLoc, |
| 7504 | ri: ResultInfo, |
| 7337 | 7505 | node: Ast.Node.Index, |
| 7338 | 7506 | lhs: Ast.Node.Index, |
| 7339 | 7507 | rhs: Ast.Node.Index, |
| 7340 | 7508 | ) InnerError!Zir.Inst.Ref { |
| 7341 | 7509 | const dest_type = try typeExpr(gz, scope, lhs); |
| 7342 | | switch (rl) { |
| 7343 | | .none, .discard, .ref, .ty, .ty_shift_operand, .coerced_ty => { |
| 7344 | | const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node); |
| 7345 | | return rvalue(gz, rl, result, node); |
| 7510 | switch (ri.rl) { |
| 7511 | .none, .discard, .ref, .ty, .coerced_ty => { |
| 7512 | const result = try reachableExpr(gz, scope, .{ .rl = .{ .ty = dest_type } }, rhs, node); |
| 7513 | return rvalue(gz, ri, result, node); |
| 7346 | 7514 | }, |
| 7347 | 7515 | .ptr => |result_ptr| { |
| 7348 | | return asRlPtr(gz, scope, rl, node, result_ptr.inst, rhs, dest_type); |
| 7516 | return asRlPtr(gz, scope, ri, node, result_ptr.inst, rhs, dest_type); |
| 7349 | 7517 | }, |
| 7350 | 7518 | .inferred_ptr => |result_ptr| { |
| 7351 | | return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type); |
| 7519 | return asRlPtr(gz, scope, ri, node, result_ptr, rhs, dest_type); |
| 7352 | 7520 | }, |
| 7353 | 7521 | .block_ptr => |block_scope| { |
| 7354 | | return asRlPtr(gz, scope, rl, node, block_scope.rl_ptr, rhs, dest_type); |
| 7522 | return asRlPtr(gz, scope, ri, node, block_scope.rl_ptr, rhs, dest_type); |
| 7355 | 7523 | }, |
| 7356 | 7524 | } |
| 7357 | 7525 | } |
| ... | ... | @@ -7359,29 +7527,29 @@ fn as( |
| 7359 | 7527 | fn unionInit( |
| 7360 | 7528 | gz: *GenZir, |
| 7361 | 7529 | scope: *Scope, |
| 7362 | | rl: ResultLoc, |
| 7530 | ri: ResultInfo, |
| 7363 | 7531 | node: Ast.Node.Index, |
| 7364 | 7532 | params: []const Ast.Node.Index, |
| 7365 | 7533 | ) InnerError!Zir.Inst.Ref { |
| 7366 | 7534 | const union_type = try typeExpr(gz, scope, params[0]); |
| 7367 | | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); |
| 7535 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]); |
| 7368 | 7536 | const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{ |
| 7369 | 7537 | .container_type = union_type, |
| 7370 | 7538 | .field_name = field_name, |
| 7371 | 7539 | }); |
| 7372 | | const init = try reachableExpr(gz, scope, .{ .ty = field_type }, params[2], node); |
| 7540 | const init = try reachableExpr(gz, scope, .{ .rl = .{ .ty = field_type } }, params[2], node); |
| 7373 | 7541 | const result = try gz.addPlNode(.union_init, node, Zir.Inst.UnionInit{ |
| 7374 | 7542 | .union_type = union_type, |
| 7375 | 7543 | .init = init, |
| 7376 | 7544 | .field_name = field_name, |
| 7377 | 7545 | }); |
| 7378 | | return rvalue(gz, rl, result, node); |
| 7546 | return rvalue(gz, ri, result, node); |
| 7379 | 7547 | } |
| 7380 | 7548 | |
| 7381 | 7549 | fn asRlPtr( |
| 7382 | 7550 | parent_gz: *GenZir, |
| 7383 | 7551 | scope: *Scope, |
| 7384 | | rl: ResultLoc, |
| 7552 | ri: ResultInfo, |
| 7385 | 7553 | src_node: Ast.Node.Index, |
| 7386 | 7554 | result_ptr: Zir.Inst.Ref, |
| 7387 | 7555 | operand_node: Ast.Node.Index, |
| ... | ... | @@ -7390,31 +7558,31 @@ fn asRlPtr( |
| 7390 | 7558 | var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr, src_node); |
| 7391 | 7559 | defer as_scope.unstack(); |
| 7392 | 7560 | |
| 7393 | | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); |
| 7394 | | return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); |
| 7561 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .rl = .{ .block_ptr = &as_scope } }, operand_node, src_node); |
| 7562 | return as_scope.finishCoercion(parent_gz, ri, operand_node, result, dest_type); |
| 7395 | 7563 | } |
| 7396 | 7564 | |
| 7397 | 7565 | fn bitCast( |
| 7398 | 7566 | gz: *GenZir, |
| 7399 | 7567 | scope: *Scope, |
| 7400 | | rl: ResultLoc, |
| 7568 | ri: ResultInfo, |
| 7401 | 7569 | node: Ast.Node.Index, |
| 7402 | 7570 | lhs: Ast.Node.Index, |
| 7403 | 7571 | rhs: Ast.Node.Index, |
| 7404 | 7572 | ) InnerError!Zir.Inst.Ref { |
| 7405 | 7573 | const dest_type = try reachableTypeExpr(gz, scope, lhs, node); |
| 7406 | | const operand = try reachableExpr(gz, scope, .none, rhs, node); |
| 7574 | const operand = try reachableExpr(gz, scope, .{ .rl = .none }, rhs, node); |
| 7407 | 7575 | const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{ |
| 7408 | 7576 | .lhs = dest_type, |
| 7409 | 7577 | .rhs = operand, |
| 7410 | 7578 | }); |
| 7411 | | return rvalue(gz, rl, result, node); |
| 7579 | return rvalue(gz, ri, result, node); |
| 7412 | 7580 | } |
| 7413 | 7581 | |
| 7414 | 7582 | fn typeOf( |
| 7415 | 7583 | gz: *GenZir, |
| 7416 | 7584 | scope: *Scope, |
| 7417 | | rl: ResultLoc, |
| 7585 | ri: ResultInfo, |
| 7418 | 7586 | node: Ast.Node.Index, |
| 7419 | 7587 | args: []const Ast.Node.Index, |
| 7420 | 7588 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -7430,7 +7598,7 @@ fn typeOf( |
| 7430 | 7598 | typeof_scope.force_comptime = false; |
| 7431 | 7599 | defer typeof_scope.unstack(); |
| 7432 | 7600 | |
| 7433 | | const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, args[0], node); |
| 7601 | const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, args[0], node); |
| 7434 | 7602 | if (!gz.refIsNoReturn(ty_expr)) { |
| 7435 | 7603 | _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr); |
| 7436 | 7604 | } |
| ... | ... | @@ -7438,7 +7606,7 @@ fn typeOf( |
| 7438 | 7606 | |
| 7439 | 7607 | // typeof_scope unstacked now, can add new instructions to gz |
| 7440 | 7608 | try gz.instructions.append(gpa, typeof_inst); |
| 7441 | | return rvalue(gz, rl, indexToRef(typeof_inst), node); |
| 7609 | return rvalue(gz, ri, indexToRef(typeof_inst), node); |
| 7442 | 7610 | } |
| 7443 | 7611 | const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len; |
| 7444 | 7612 | const payload_index = try reserveExtra(astgen, payload_size + args.len); |
| ... | ... | @@ -7450,7 +7618,7 @@ fn typeOf( |
| 7450 | 7618 | typeof_scope.force_comptime = false; |
| 7451 | 7619 | |
| 7452 | 7620 | for (args) |arg, i| { |
| 7453 | | const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node); |
| 7621 | const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .{ .rl = .none }, arg, node); |
| 7454 | 7622 | astgen.extra.items[args_index + i] = @enumToInt(param_ref); |
| 7455 | 7623 | } |
| 7456 | 7624 | _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value); |
| ... | ... | @@ -7466,13 +7634,13 @@ fn typeOf( |
| 7466 | 7634 | astgen.appendBodyWithFixups(body); |
| 7467 | 7635 | typeof_scope.unstack(); |
| 7468 | 7636 | |
| 7469 | | return rvalue(gz, rl, typeof_inst, node); |
| 7637 | return rvalue(gz, ri, typeof_inst, node); |
| 7470 | 7638 | } |
| 7471 | 7639 | |
| 7472 | 7640 | fn builtinCall( |
| 7473 | 7641 | gz: *GenZir, |
| 7474 | 7642 | scope: *Scope, |
| 7475 | | rl: ResultLoc, |
| 7643 | ri: ResultInfo, |
| 7476 | 7644 | node: Ast.Node.Index, |
| 7477 | 7645 | params: []const Ast.Node.Index, |
| 7478 | 7646 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -7524,7 +7692,7 @@ fn builtinCall( |
| 7524 | 7692 | if (!gop.found_existing) { |
| 7525 | 7693 | gop.value_ptr.* = str_lit_token; |
| 7526 | 7694 | } |
| 7527 | | return rvalue(gz, rl, result, node); |
| 7695 | return rvalue(gz, ri, result, node); |
| 7528 | 7696 | }, |
| 7529 | 7697 | .compile_log => { |
| 7530 | 7698 | const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ |
| ... | ... | @@ -7532,32 +7700,32 @@ fn builtinCall( |
| 7532 | 7700 | }); |
| 7533 | 7701 | var extra_index = try reserveExtra(gz.astgen, params.len); |
| 7534 | 7702 | for (params) |param| { |
| 7535 | | const param_ref = try expr(gz, scope, .none, param); |
| 7703 | const param_ref = try expr(gz, scope, .{ .rl = .none }, param); |
| 7536 | 7704 | astgen.extra.items[extra_index] = @enumToInt(param_ref); |
| 7537 | 7705 | extra_index += 1; |
| 7538 | 7706 | } |
| 7539 | 7707 | const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len); |
| 7540 | | return rvalue(gz, rl, result, node); |
| 7708 | return rvalue(gz, ri, result, node); |
| 7541 | 7709 | }, |
| 7542 | 7710 | .field => { |
| 7543 | | if (rl == .ref) { |
| 7711 | if (ri.rl == .ref) { |
| 7544 | 7712 | return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{ |
| 7545 | | .lhs = try expr(gz, scope, .ref, params[0]), |
| 7546 | | .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]), |
| 7713 | .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), |
| 7714 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]), |
| 7547 | 7715 | }); |
| 7548 | 7716 | } |
| 7549 | 7717 | const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{ |
| 7550 | | .lhs = try expr(gz, scope, .none, params[0]), |
| 7551 | | .field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]), |
| 7718 | .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]), |
| 7719 | .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]), |
| 7552 | 7720 | }); |
| 7553 | | return rvalue(gz, rl, result, node); |
| 7721 | return rvalue(gz, ri, result, node); |
| 7554 | 7722 | }, |
| 7555 | 7723 | |
| 7556 | 7724 | // zig fmt: off |
| 7557 | | .as => return as( gz, scope, rl, node, params[0], params[1]), |
| 7558 | | .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]), |
| 7559 | | .TypeOf => return typeOf( gz, scope, rl, node, params), |
| 7560 | | .union_init => return unionInit(gz, scope, rl, node, params), |
| 7725 | .as => return as( gz, scope, ri, node, params[0], params[1]), |
| 7726 | .bit_cast => return bitCast( gz, scope, ri, node, params[0], params[1]), |
| 7727 | .TypeOf => return typeOf( gz, scope, ri, node, params), |
| 7728 | .union_init => return unionInit(gz, scope, ri, node, params), |
| 7561 | 7729 | .c_import => return cImport( gz, scope, node, params[0]), |
| 7562 | 7730 | // zig fmt: on |
| 7563 | 7731 | |
| ... | ... | @@ -7582,9 +7750,9 @@ fn builtinCall( |
| 7582 | 7750 | local_val.used = ident_token; |
| 7583 | 7751 | _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ |
| 7584 | 7752 | .operand = local_val.inst, |
| 7585 | | .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), |
| 7753 | .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]), |
| 7586 | 7754 | }); |
| 7587 | | return rvalue(gz, rl, .void_value, node); |
| 7755 | return rvalue(gz, ri, .void_value, node); |
| 7588 | 7756 | } |
| 7589 | 7757 | s = local_val.parent; |
| 7590 | 7758 | }, |
| ... | ... | @@ -7597,9 +7765,9 @@ fn builtinCall( |
| 7597 | 7765 | const loaded = try gz.addUnNode(.load, local_ptr.ptr, node); |
| 7598 | 7766 | _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ |
| 7599 | 7767 | .operand = loaded, |
| 7600 | | .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), |
| 7768 | .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]), |
| 7601 | 7769 | }); |
| 7602 | | return rvalue(gz, rl, .void_value, node); |
| 7770 | return rvalue(gz, ri, .void_value, node); |
| 7603 | 7771 | } |
| 7604 | 7772 | s = local_ptr.parent; |
| 7605 | 7773 | }, |
| ... | ... | @@ -7631,47 +7799,47 @@ fn builtinCall( |
| 7631 | 7799 | }, |
| 7632 | 7800 | else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}), |
| 7633 | 7801 | } |
| 7634 | | const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]); |
| 7802 | const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .export_options_type } }, params[1]); |
| 7635 | 7803 | _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{ |
| 7636 | 7804 | .namespace = namespace, |
| 7637 | 7805 | .decl_name = decl_name, |
| 7638 | 7806 | .options = options, |
| 7639 | 7807 | }); |
| 7640 | | return rvalue(gz, rl, .void_value, node); |
| 7808 | return rvalue(gz, ri, .void_value, node); |
| 7641 | 7809 | }, |
| 7642 | 7810 | .@"extern" => { |
| 7643 | 7811 | const type_inst = try typeExpr(gz, scope, params[0]); |
| 7644 | | const options = try comptimeExpr(gz, scope, .{ .ty = .extern_options_type }, params[1]); |
| 7812 | const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .extern_options_type } }, params[1]); |
| 7645 | 7813 | const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{ |
| 7646 | 7814 | .node = gz.nodeIndexToRelative(node), |
| 7647 | 7815 | .lhs = type_inst, |
| 7648 | 7816 | .rhs = options, |
| 7649 | 7817 | }); |
| 7650 | | return rvalue(gz, rl, result, node); |
| 7818 | return rvalue(gz, ri, result, node); |
| 7651 | 7819 | }, |
| 7652 | 7820 | .fence => { |
| 7653 | | const order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[0]); |
| 7821 | const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[0]); |
| 7654 | 7822 | const result = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{ |
| 7655 | 7823 | .node = gz.nodeIndexToRelative(node), |
| 7656 | 7824 | .operand = order, |
| 7657 | 7825 | }); |
| 7658 | | return rvalue(gz, rl, result, node); |
| 7826 | return rvalue(gz, ri, result, node); |
| 7659 | 7827 | }, |
| 7660 | 7828 | .set_float_mode => { |
| 7661 | | const order = try expr(gz, scope, .{ .coerced_ty = .float_mode_type }, params[0]); |
| 7829 | const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .float_mode_type } }, params[0]); |
| 7662 | 7830 | const result = try gz.addExtendedPayload(.set_float_mode, Zir.Inst.UnNode{ |
| 7663 | 7831 | .node = gz.nodeIndexToRelative(node), |
| 7664 | 7832 | .operand = order, |
| 7665 | 7833 | }); |
| 7666 | | return rvalue(gz, rl, result, node); |
| 7834 | return rvalue(gz, ri, result, node); |
| 7667 | 7835 | }, |
| 7668 | 7836 | .set_align_stack => { |
| 7669 | | const order = try expr(gz, scope, align_rl, params[0]); |
| 7837 | const order = try expr(gz, scope, align_ri, params[0]); |
| 7670 | 7838 | const result = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{ |
| 7671 | 7839 | .node = gz.nodeIndexToRelative(node), |
| 7672 | 7840 | .operand = order, |
| 7673 | 7841 | }); |
| 7674 | | return rvalue(gz, rl, result, node); |
| 7842 | return rvalue(gz, ri, result, node); |
| 7675 | 7843 | }, |
| 7676 | 7844 | |
| 7677 | 7845 | .src => { |
| ... | ... | @@ -7683,62 +7851,62 @@ fn builtinCall( |
| 7683 | 7851 | .line = astgen.source_line, |
| 7684 | 7852 | .column = astgen.source_column, |
| 7685 | 7853 | }); |
| 7686 | | return rvalue(gz, rl, result, node); |
| 7854 | return rvalue(gz, ri, result, node); |
| 7687 | 7855 | }, |
| 7688 | 7856 | |
| 7689 | 7857 | // zig fmt: off |
| 7690 | | .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node), |
| 7691 | | .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node), |
| 7692 | | .error_return_trace => return rvalue(gz, rl, try gz.addNodeExtended(.error_return_trace, node), node), |
| 7693 | | .frame => return rvalue(gz, rl, try gz.addNodeExtended(.frame, node), node), |
| 7694 | | .frame_address => return rvalue(gz, rl, try gz.addNodeExtended(.frame_address, node), node), |
| 7695 | | .breakpoint => return rvalue(gz, rl, try gz.addNodeExtended(.breakpoint, node), node), |
| 7696 | | |
| 7697 | | .type_info => return simpleUnOpType(gz, scope, rl, node, params[0], .type_info), |
| 7698 | | .size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .size_of), |
| 7699 | | .bit_size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .bit_size_of), |
| 7700 | | .align_of => return simpleUnOpType(gz, scope, rl, node, params[0], .align_of), |
| 7701 | | |
| 7702 | | .ptr_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ptr_to_int), |
| 7703 | | .compile_error => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .compile_error), |
| 7704 | | .set_eval_branch_quota => return simpleUnOp(gz, scope, rl, node, .{ .coerced_ty = .u32_type }, params[0], .set_eval_branch_quota), |
| 7705 | | .enum_to_int => return simpleUnOp(gz, scope, rl, node, .none, params[0], .enum_to_int), |
| 7706 | | .bool_to_int => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .bool_to_int), |
| 7707 | | .embed_file => return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], .embed_file), |
| 7708 | | .error_name => return simpleUnOp(gz, scope, rl, node, .{ .ty = .anyerror_type }, params[0], .error_name), |
| 7709 | | .set_cold => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_cold), |
| 7710 | | .set_runtime_safety => return simpleUnOp(gz, scope, rl, node, bool_rl, params[0], .set_runtime_safety), |
| 7711 | | .sqrt => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sqrt), |
| 7712 | | .sin => return simpleUnOp(gz, scope, rl, node, .none, params[0], .sin), |
| 7713 | | .cos => return simpleUnOp(gz, scope, rl, node, .none, params[0], .cos), |
| 7714 | | .tan => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tan), |
| 7715 | | .exp => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp), |
| 7716 | | .exp2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .exp2), |
| 7717 | | .log => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log), |
| 7718 | | .log2 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log2), |
| 7719 | | .log10 => return simpleUnOp(gz, scope, rl, node, .none, params[0], .log10), |
| 7720 | | .fabs => return simpleUnOp(gz, scope, rl, node, .none, params[0], .fabs), |
| 7721 | | .floor => return simpleUnOp(gz, scope, rl, node, .none, params[0], .floor), |
| 7722 | | .ceil => return simpleUnOp(gz, scope, rl, node, .none, params[0], .ceil), |
| 7723 | | .trunc => return simpleUnOp(gz, scope, rl, node, .none, params[0], .trunc), |
| 7724 | | .round => return simpleUnOp(gz, scope, rl, node, .none, params[0], .round), |
| 7725 | | .tag_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .tag_name), |
| 7726 | | .type_name => return simpleUnOp(gz, scope, rl, node, .none, params[0], .type_name), |
| 7727 | | .Frame => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_type), |
| 7728 | | .frame_size => return simpleUnOp(gz, scope, rl, node, .none, params[0], .frame_size), |
| 7729 | | |
| 7730 | | .float_to_int => return typeCast(gz, scope, rl, node, params[0], params[1], .float_to_int), |
| 7731 | | .int_to_float => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_float), |
| 7732 | | .int_to_ptr => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_ptr), |
| 7733 | | .int_to_enum => return typeCast(gz, scope, rl, node, params[0], params[1], .int_to_enum), |
| 7734 | | .float_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .float_cast), |
| 7735 | | .int_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .int_cast), |
| 7736 | | .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast), |
| 7737 | | .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate), |
| 7858 | .This => return rvalue(gz, ri, try gz.addNodeExtended(.this, node), node), |
| 7859 | .return_address => return rvalue(gz, ri, try gz.addNodeExtended(.ret_addr, node), node), |
| 7860 | .error_return_trace => return rvalue(gz, ri, try gz.addNodeExtended(.error_return_trace, node), node), |
| 7861 | .frame => return rvalue(gz, ri, try gz.addNodeExtended(.frame, node), node), |
| 7862 | .frame_address => return rvalue(gz, ri, try gz.addNodeExtended(.frame_address, node), node), |
| 7863 | .breakpoint => return rvalue(gz, ri, try gz.addNodeExtended(.breakpoint, node), node), |
| 7864 | |
| 7865 | .type_info => return simpleUnOpType(gz, scope, ri, node, params[0], .type_info), |
| 7866 | .size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .size_of), |
| 7867 | .bit_size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .bit_size_of), |
| 7868 | .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of), |
| 7869 | |
| 7870 | .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int), |
| 7871 | .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .compile_error), |
| 7872 | .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota), |
| 7873 | .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int), |
| 7874 | .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int), |
| 7875 | .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file), |
| 7876 | .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name), |
| 7877 | .set_cold => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_cold), |
| 7878 | .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety), |
| 7879 | .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), |
| 7880 | .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), |
| 7881 | .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos), |
| 7882 | .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan), |
| 7883 | .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp), |
| 7884 | .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2), |
| 7885 | .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), |
| 7886 | .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), |
| 7887 | .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), |
| 7888 | .fabs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .fabs), |
| 7889 | .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), |
| 7890 | .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), |
| 7891 | .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), |
| 7892 | .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round), |
| 7893 | .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name), |
| 7894 | .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name), |
| 7895 | .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type), |
| 7896 | .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size), |
| 7897 | |
| 7898 | .float_to_int => return typeCast(gz, scope, ri, node, params[0], params[1], .float_to_int), |
| 7899 | .int_to_float => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_float), |
| 7900 | .int_to_ptr => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_ptr), |
| 7901 | .int_to_enum => return typeCast(gz, scope, ri, node, params[0], params[1], .int_to_enum), |
| 7902 | .float_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .float_cast), |
| 7903 | .int_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .int_cast), |
| 7904 | .ptr_cast => return typeCast(gz, scope, ri, node, params[0], params[1], .ptr_cast), |
| 7905 | .truncate => return typeCast(gz, scope, ri, node, params[0], params[1], .truncate), |
| 7738 | 7906 | // zig fmt: on |
| 7739 | 7907 | |
| 7740 | 7908 | .Type => { |
| 7741 | | const operand = try expr(gz, scope, .{ .coerced_ty = .type_info_type }, params[0]); |
| 7909 | const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .type_info_type } }, params[0]); |
| 7742 | 7910 | |
| 7743 | 7911 | const gpa = gz.astgen.gpa; |
| 7744 | 7912 | |
| ... | ... | @@ -7760,219 +7928,219 @@ fn builtinCall( |
| 7760 | 7928 | }); |
| 7761 | 7929 | gz.instructions.appendAssumeCapacity(new_index); |
| 7762 | 7930 | const result = indexToRef(new_index); |
| 7763 | | return rvalue(gz, rl, result, node); |
| 7931 | return rvalue(gz, ri, result, node); |
| 7764 | 7932 | }, |
| 7765 | 7933 | .panic => { |
| 7766 | 7934 | try emitDbgNode(gz, node); |
| 7767 | | return simpleUnOp(gz, scope, rl, node, .{ .ty = .const_slice_u8_type }, params[0], if (gz.force_comptime) .panic_comptime else .panic); |
| 7935 | return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], if (gz.force_comptime) .panic_comptime else .panic); |
| 7768 | 7936 | }, |
| 7769 | 7937 | .error_to_int => { |
| 7770 | | const operand = try expr(gz, scope, .none, params[0]); |
| 7938 | const operand = try expr(gz, scope, .{ .rl = .none }, params[0]); |
| 7771 | 7939 | const result = try gz.addExtendedPayload(.error_to_int, Zir.Inst.UnNode{ |
| 7772 | 7940 | .node = gz.nodeIndexToRelative(node), |
| 7773 | 7941 | .operand = operand, |
| 7774 | 7942 | }); |
| 7775 | | return rvalue(gz, rl, result, node); |
| 7943 | return rvalue(gz, ri, result, node); |
| 7776 | 7944 | }, |
| 7777 | 7945 | .int_to_error => { |
| 7778 | | const operand = try expr(gz, scope, .{ .coerced_ty = .u16_type }, params[0]); |
| 7946 | const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[0]); |
| 7779 | 7947 | const result = try gz.addExtendedPayload(.int_to_error, Zir.Inst.UnNode{ |
| 7780 | 7948 | .node = gz.nodeIndexToRelative(node), |
| 7781 | 7949 | .operand = operand, |
| 7782 | 7950 | }); |
| 7783 | | return rvalue(gz, rl, result, node); |
| 7951 | return rvalue(gz, ri, result, node); |
| 7784 | 7952 | }, |
| 7785 | 7953 | .align_cast => { |
| 7786 | | const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]); |
| 7787 | | const rhs = try expr(gz, scope, .none, params[1]); |
| 7954 | const dest_align = try comptimeExpr(gz, scope, align_ri, params[0]); |
| 7955 | const rhs = try expr(gz, scope, .{ .rl = .none }, params[1]); |
| 7788 | 7956 | const result = try gz.addPlNode(.align_cast, node, Zir.Inst.Bin{ |
| 7789 | 7957 | .lhs = dest_align, |
| 7790 | 7958 | .rhs = rhs, |
| 7791 | 7959 | }); |
| 7792 | | return rvalue(gz, rl, result, node); |
| 7960 | return rvalue(gz, ri, result, node); |
| 7793 | 7961 | }, |
| 7794 | 7962 | .err_set_cast => { |
| 7795 | 7963 | const result = try gz.addExtendedPayload(.err_set_cast, Zir.Inst.BinNode{ |
| 7796 | 7964 | .lhs = try typeExpr(gz, scope, params[0]), |
| 7797 | | .rhs = try expr(gz, scope, .none, params[1]), |
| 7965 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 7798 | 7966 | .node = gz.nodeIndexToRelative(node), |
| 7799 | 7967 | }); |
| 7800 | | return rvalue(gz, rl, result, node); |
| 7968 | return rvalue(gz, ri, result, node); |
| 7801 | 7969 | }, |
| 7802 | 7970 | .addrspace_cast => { |
| 7803 | 7971 | const result = try gz.addExtendedPayload(.addrspace_cast, Zir.Inst.BinNode{ |
| 7804 | | .lhs = try comptimeExpr(gz, scope, .{ .ty = .address_space_type }, params[0]), |
| 7805 | | .rhs = try expr(gz, scope, .none, params[1]), |
| 7972 | .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .address_space_type } }, params[0]), |
| 7973 | .rhs = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 7806 | 7974 | .node = gz.nodeIndexToRelative(node), |
| 7807 | 7975 | }); |
| 7808 | | return rvalue(gz, rl, result, node); |
| 7976 | return rvalue(gz, ri, result, node); |
| 7809 | 7977 | }, |
| 7810 | 7978 | |
| 7811 | 7979 | // zig fmt: off |
| 7812 | | .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl), |
| 7813 | | .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field), |
| 7980 | .has_decl => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_decl), |
| 7981 | .has_field => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_field), |
| 7814 | 7982 | |
| 7815 | | .clz => return bitBuiltin(gz, scope, rl, node, params[0], .clz), |
| 7816 | | .ctz => return bitBuiltin(gz, scope, rl, node, params[0], .ctz), |
| 7817 | | .pop_count => return bitBuiltin(gz, scope, rl, node, params[0], .pop_count), |
| 7818 | | .byte_swap => return bitBuiltin(gz, scope, rl, node, params[0], .byte_swap), |
| 7819 | | .bit_reverse => return bitBuiltin(gz, scope, rl, node, params[0], .bit_reverse), |
| 7983 | .clz => return bitBuiltin(gz, scope, ri, node, params[0], .clz), |
| 7984 | .ctz => return bitBuiltin(gz, scope, ri, node, params[0], .ctz), |
| 7985 | .pop_count => return bitBuiltin(gz, scope, ri, node, params[0], .pop_count), |
| 7986 | .byte_swap => return bitBuiltin(gz, scope, ri, node, params[0], .byte_swap), |
| 7987 | .bit_reverse => return bitBuiltin(gz, scope, ri, node, params[0], .bit_reverse), |
| 7820 | 7988 | |
| 7821 | | .div_exact => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_exact), |
| 7822 | | .div_floor => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_floor), |
| 7823 | | .div_trunc => return divBuiltin(gz, scope, rl, node, params[0], params[1], .div_trunc), |
| 7824 | | .mod => return divBuiltin(gz, scope, rl, node, params[0], params[1], .mod), |
| 7825 | | .rem => return divBuiltin(gz, scope, rl, node, params[0], params[1], .rem), |
| 7989 | .div_exact => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_exact), |
| 7990 | .div_floor => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_floor), |
| 7991 | .div_trunc => return divBuiltin(gz, scope, ri, node, params[0], params[1], .div_trunc), |
| 7992 | .mod => return divBuiltin(gz, scope, ri, node, params[0], params[1], .mod), |
| 7993 | .rem => return divBuiltin(gz, scope, ri, node, params[0], params[1], .rem), |
| 7826 | 7994 | |
| 7827 | | .shl_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shl_exact), |
| 7828 | | .shr_exact => return shiftOp(gz, scope, rl, node, params[0], params[1], .shr_exact), |
| 7995 | .shl_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shl_exact), |
| 7996 | .shr_exact => return shiftOp(gz, scope, ri, node, params[0], params[1], .shr_exact), |
| 7829 | 7997 | |
| 7830 | | .bit_offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .bit_offset_of), |
| 7831 | | .offset_of => return offsetOf(gz, scope, rl, node, params[0], params[1], .offset_of), |
| 7998 | .bit_offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .bit_offset_of), |
| 7999 | .offset_of => return offsetOf(gz, scope, ri, node, params[0], params[1], .offset_of), |
| 7832 | 8000 | |
| 7833 | | .c_undef => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_undef), |
| 7834 | | .c_include => return simpleCBuiltin(gz, scope, rl, node, params[0], .c_include), |
| 8001 | .c_undef => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_undef), |
| 8002 | .c_include => return simpleCBuiltin(gz, scope, ri, node, params[0], .c_include), |
| 7835 | 8003 | |
| 7836 | | .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, 1), |
| 7837 | | .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, 0), |
| 8004 | .cmpxchg_strong => return cmpxchg(gz, scope, ri, node, params, 1), |
| 8005 | .cmpxchg_weak => return cmpxchg(gz, scope, ri, node, params, 0), |
| 7838 | 8006 | // zig fmt: on |
| 7839 | 8007 | |
| 7840 | 8008 | .wasm_memory_size => { |
| 7841 | | const operand = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]); |
| 8009 | const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); |
| 7842 | 8010 | const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{ |
| 7843 | 8011 | .node = gz.nodeIndexToRelative(node), |
| 7844 | 8012 | .operand = operand, |
| 7845 | 8013 | }); |
| 7846 | | return rvalue(gz, rl, result, node); |
| 8014 | return rvalue(gz, ri, result, node); |
| 7847 | 8015 | }, |
| 7848 | 8016 | .wasm_memory_grow => { |
| 7849 | | const index_arg = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]); |
| 7850 | | const delta_arg = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[1]); |
| 8017 | const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); |
| 8018 | const delta_arg = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[1]); |
| 7851 | 8019 | const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{ |
| 7852 | 8020 | .node = gz.nodeIndexToRelative(node), |
| 7853 | 8021 | .lhs = index_arg, |
| 7854 | 8022 | .rhs = delta_arg, |
| 7855 | 8023 | }); |
| 7856 | | return rvalue(gz, rl, result, node); |
| 8024 | return rvalue(gz, ri, result, node); |
| 7857 | 8025 | }, |
| 7858 | 8026 | .c_define => { |
| 7859 | 8027 | if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{}); |
| 7860 | | const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[0]); |
| 7861 | | const value = try comptimeExpr(gz, scope, .none, params[1]); |
| 8028 | const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0]); |
| 8029 | const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]); |
| 7862 | 8030 | const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{ |
| 7863 | 8031 | .node = gz.nodeIndexToRelative(node), |
| 7864 | 8032 | .lhs = name, |
| 7865 | 8033 | .rhs = value, |
| 7866 | 8034 | }); |
| 7867 | | return rvalue(gz, rl, result, node); |
| 8035 | return rvalue(gz, ri, result, node); |
| 7868 | 8036 | }, |
| 7869 | 8037 | |
| 7870 | 8038 | .splat => { |
| 7871 | | const len = try expr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]); |
| 7872 | | const scalar = try expr(gz, scope, .none, params[1]); |
| 8039 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]); |
| 8040 | const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); |
| 7873 | 8041 | const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ |
| 7874 | 8042 | .lhs = len, |
| 7875 | 8043 | .rhs = scalar, |
| 7876 | 8044 | }); |
| 7877 | | return rvalue(gz, rl, result, node); |
| 8045 | return rvalue(gz, ri, result, node); |
| 7878 | 8046 | }, |
| 7879 | 8047 | .reduce => { |
| 7880 | | const op = try expr(gz, scope, .{ .ty = .reduce_op_type }, params[0]); |
| 7881 | | const scalar = try expr(gz, scope, .none, params[1]); |
| 8048 | const op = try expr(gz, scope, .{ .rl = .{ .ty = .reduce_op_type } }, params[0]); |
| 8049 | const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); |
| 7882 | 8050 | const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{ |
| 7883 | 8051 | .lhs = op, |
| 7884 | 8052 | .rhs = scalar, |
| 7885 | 8053 | }); |
| 7886 | | return rvalue(gz, rl, result, node); |
| 8054 | return rvalue(gz, ri, result, node); |
| 7887 | 8055 | }, |
| 7888 | 8056 | |
| 7889 | 8057 | .max => { |
| 7890 | | const a = try expr(gz, scope, .none, params[0]); |
| 7891 | | const b = try expr(gz, scope, .none, params[1]); |
| 8058 | const a = try expr(gz, scope, .{ .rl = .none }, params[0]); |
| 8059 | const b = try expr(gz, scope, .{ .rl = .none }, params[1]); |
| 7892 | 8060 | const result = try gz.addPlNode(.max, node, Zir.Inst.Bin{ |
| 7893 | 8061 | .lhs = a, |
| 7894 | 8062 | .rhs = b, |
| 7895 | 8063 | }); |
| 7896 | | return rvalue(gz, rl, result, node); |
| 8064 | return rvalue(gz, ri, result, node); |
| 7897 | 8065 | }, |
| 7898 | 8066 | .min => { |
| 7899 | | const a = try expr(gz, scope, .none, params[0]); |
| 7900 | | const b = try expr(gz, scope, .none, params[1]); |
| 8067 | const a = try expr(gz, scope, .{ .rl = .none }, params[0]); |
| 8068 | const b = try expr(gz, scope, .{ .rl = .none }, params[1]); |
| 7901 | 8069 | const result = try gz.addPlNode(.min, node, Zir.Inst.Bin{ |
| 7902 | 8070 | .lhs = a, |
| 7903 | 8071 | .rhs = b, |
| 7904 | 8072 | }); |
| 7905 | | return rvalue(gz, rl, result, node); |
| 8073 | return rvalue(gz, ri, result, node); |
| 7906 | 8074 | }, |
| 7907 | 8075 | |
| 7908 | | .add_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .add_with_overflow), |
| 7909 | | .sub_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .sub_with_overflow), |
| 7910 | | .mul_with_overflow => return overflowArithmetic(gz, scope, rl, node, params, .mul_with_overflow), |
| 8076 | .add_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .add_with_overflow), |
| 8077 | .sub_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .sub_with_overflow), |
| 8078 | .mul_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .mul_with_overflow), |
| 7911 | 8079 | .shl_with_overflow => { |
| 7912 | 8080 | const int_type = try typeExpr(gz, scope, params[0]); |
| 7913 | 8081 | const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]); |
| 7914 | 8082 | const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]); |
| 7915 | | const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]); |
| 7916 | | const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]); |
| 7917 | | const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]); |
| 8083 | const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]); |
| 8084 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type } }, params[2]); |
| 8085 | const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]); |
| 7918 | 8086 | const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{ |
| 7919 | 8087 | .node = gz.nodeIndexToRelative(node), |
| 7920 | 8088 | .lhs = lhs, |
| 7921 | 8089 | .rhs = rhs, |
| 7922 | 8090 | .ptr = ptr, |
| 7923 | 8091 | }); |
| 7924 | | return rvalue(gz, rl, result, node); |
| 8092 | return rvalue(gz, ri, result, node); |
| 7925 | 8093 | }, |
| 7926 | 8094 | |
| 7927 | 8095 | .atomic_load => { |
| 7928 | 8096 | const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{ |
| 7929 | 8097 | // zig fmt: off |
| 7930 | | .elem_type = try typeExpr(gz, scope, params[0]), |
| 7931 | | .ptr = try expr (gz, scope, .none, params[1]), |
| 7932 | | .ordering = try expr (gz, scope, .{ .coerced_ty = .atomic_order_type }, params[2]), |
| 8098 | .elem_type = try typeExpr(gz, scope, params[0]), |
| 8099 | .ptr = try expr (gz, scope, .{ .rl = .none }, params[1]), |
| 8100 | .ordering = try expr (gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[2]), |
| 7933 | 8101 | // zig fmt: on |
| 7934 | 8102 | }); |
| 7935 | | return rvalue(gz, rl, result, node); |
| 8103 | return rvalue(gz, ri, result, node); |
| 7936 | 8104 | }, |
| 7937 | 8105 | .atomic_rmw => { |
| 7938 | 8106 | const int_type = try typeExpr(gz, scope, params[0]); |
| 7939 | 8107 | const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{ |
| 7940 | 8108 | // zig fmt: off |
| 7941 | | .ptr = try expr(gz, scope, .none, params[1]), |
| 7942 | | .operation = try expr(gz, scope, .{ .coerced_ty = .atomic_rmw_op_type }, params[2]), |
| 7943 | | .operand = try expr(gz, scope, .{ .ty = int_type }, params[3]), |
| 7944 | | .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]), |
| 8109 | .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 8110 | .operation = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_rmw_op_type } }, params[2]), |
| 8111 | .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[3]), |
| 8112 | .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]), |
| 7945 | 8113 | // zig fmt: on |
| 7946 | 8114 | }); |
| 7947 | | return rvalue(gz, rl, result, node); |
| 8115 | return rvalue(gz, ri, result, node); |
| 7948 | 8116 | }, |
| 7949 | 8117 | .atomic_store => { |
| 7950 | 8118 | const int_type = try typeExpr(gz, scope, params[0]); |
| 7951 | 8119 | const result = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{ |
| 7952 | 8120 | // zig fmt: off |
| 7953 | | .ptr = try expr(gz, scope, .none, params[1]), |
| 7954 | | .operand = try expr(gz, scope, .{ .ty = int_type }, params[2]), |
| 7955 | | .ordering = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[3]), |
| 8121 | .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 8122 | .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), |
| 8123 | .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[3]), |
| 7956 | 8124 | // zig fmt: on |
| 7957 | 8125 | }); |
| 7958 | | return rvalue(gz, rl, result, node); |
| 8126 | return rvalue(gz, ri, result, node); |
| 7959 | 8127 | }, |
| 7960 | 8128 | .mul_add => { |
| 7961 | 8129 | const float_type = try typeExpr(gz, scope, params[0]); |
| 7962 | | const mulend1 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[1]); |
| 7963 | | const mulend2 = try expr(gz, scope, .{ .coerced_ty = float_type }, params[2]); |
| 7964 | | const addend = try expr(gz, scope, .{ .ty = float_type }, params[3]); |
| 8130 | const mulend1 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[1]); |
| 8131 | const mulend2 = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_type } }, params[2]); |
| 8132 | const addend = try expr(gz, scope, .{ .rl = .{ .ty = float_type } }, params[3]); |
| 7965 | 8133 | const result = try gz.addPlNode(.mul_add, node, Zir.Inst.MulAdd{ |
| 7966 | 8134 | .mulend1 = mulend1, |
| 7967 | 8135 | .mulend2 = mulend2, |
| 7968 | 8136 | .addend = addend, |
| 7969 | 8137 | }); |
| 7970 | | return rvalue(gz, rl, result, node); |
| 8138 | return rvalue(gz, ri, result, node); |
| 7971 | 8139 | }, |
| 7972 | 8140 | .call => { |
| 7973 | | const options = try comptimeExpr(gz, scope, .{ .ty = .call_options_type }, params[0]); |
| 8141 | const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .call_options_type } }, params[0]); |
| 7974 | 8142 | const callee = try calleeExpr(gz, scope, params[1]); |
| 7975 | | const args = try expr(gz, scope, .none, params[2]); |
| 8143 | const args = try expr(gz, scope, .{ .rl = .none }, params[2]); |
| 7976 | 8144 | const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{ |
| 7977 | 8145 | .options = options, |
| 7978 | 8146 | .callee = callee, |
| ... | ... | @@ -7983,115 +8151,115 @@ fn builtinCall( |
| 7983 | 8151 | .ensure_result_used = false, |
| 7984 | 8152 | }, |
| 7985 | 8153 | }); |
| 7986 | | return rvalue(gz, rl, result, node); |
| 8154 | return rvalue(gz, ri, result, node); |
| 7987 | 8155 | }, |
| 7988 | 8156 | .field_parent_ptr => { |
| 7989 | 8157 | const parent_type = try typeExpr(gz, scope, params[0]); |
| 7990 | | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); |
| 8158 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]); |
| 7991 | 8159 | const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{ |
| 7992 | 8160 | .parent_type = parent_type, |
| 7993 | 8161 | .field_name = field_name, |
| 7994 | | .field_ptr = try expr(gz, scope, .none, params[2]), |
| 8162 | .field_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]), |
| 7995 | 8163 | }); |
| 7996 | | return rvalue(gz, rl, result, node); |
| 8164 | return rvalue(gz, ri, result, node); |
| 7997 | 8165 | }, |
| 7998 | 8166 | .memcpy => { |
| 7999 | 8167 | const result = try gz.addPlNode(.memcpy, node, Zir.Inst.Memcpy{ |
| 8000 | | .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]), |
| 8001 | | .source = try expr(gz, scope, .{ .coerced_ty = .manyptr_const_u8_type }, params[1]), |
| 8002 | | .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]), |
| 8168 | .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]), |
| 8169 | .source = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_const_u8_type } }, params[1]), |
| 8170 | .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]), |
| 8003 | 8171 | }); |
| 8004 | | return rvalue(gz, rl, result, node); |
| 8172 | return rvalue(gz, ri, result, node); |
| 8005 | 8173 | }, |
| 8006 | 8174 | .memset => { |
| 8007 | 8175 | const result = try gz.addPlNode(.memset, node, Zir.Inst.Memset{ |
| 8008 | | .dest = try expr(gz, scope, .{ .coerced_ty = .manyptr_u8_type }, params[0]), |
| 8009 | | .byte = try expr(gz, scope, .{ .coerced_ty = .u8_type }, params[1]), |
| 8010 | | .byte_count = try expr(gz, scope, .{ .coerced_ty = .usize_type }, params[2]), |
| 8176 | .dest = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .manyptr_u8_type } }, params[0]), |
| 8177 | .byte = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u8_type } }, params[1]), |
| 8178 | .byte_count = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[2]), |
| 8011 | 8179 | }); |
| 8012 | | return rvalue(gz, rl, result, node); |
| 8180 | return rvalue(gz, ri, result, node); |
| 8013 | 8181 | }, |
| 8014 | 8182 | .shuffle => { |
| 8015 | 8183 | const result = try gz.addPlNode(.shuffle, node, Zir.Inst.Shuffle{ |
| 8016 | 8184 | .elem_type = try typeExpr(gz, scope, params[0]), |
| 8017 | | .a = try expr(gz, scope, .none, params[1]), |
| 8018 | | .b = try expr(gz, scope, .none, params[2]), |
| 8019 | | .mask = try comptimeExpr(gz, scope, .none, params[3]), |
| 8185 | .a = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 8186 | .b = try expr(gz, scope, .{ .rl = .none }, params[2]), |
| 8187 | .mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3]), |
| 8020 | 8188 | }); |
| 8021 | | return rvalue(gz, rl, result, node); |
| 8189 | return rvalue(gz, ri, result, node); |
| 8022 | 8190 | }, |
| 8023 | 8191 | .select => { |
| 8024 | 8192 | const result = try gz.addExtendedPayload(.select, Zir.Inst.Select{ |
| 8025 | 8193 | .node = gz.nodeIndexToRelative(node), |
| 8026 | 8194 | .elem_type = try typeExpr(gz, scope, params[0]), |
| 8027 | | .pred = try expr(gz, scope, .none, params[1]), |
| 8028 | | .a = try expr(gz, scope, .none, params[2]), |
| 8029 | | .b = try expr(gz, scope, .none, params[3]), |
| 8195 | .pred = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 8196 | .a = try expr(gz, scope, .{ .rl = .none }, params[2]), |
| 8197 | .b = try expr(gz, scope, .{ .rl = .none }, params[3]), |
| 8030 | 8198 | }); |
| 8031 | | return rvalue(gz, rl, result, node); |
| 8199 | return rvalue(gz, ri, result, node); |
| 8032 | 8200 | }, |
| 8033 | 8201 | .async_call => { |
| 8034 | 8202 | const result = try gz.addExtendedPayload(.builtin_async_call, Zir.Inst.AsyncCall{ |
| 8035 | 8203 | .node = gz.nodeIndexToRelative(node), |
| 8036 | | .frame_buffer = try expr(gz, scope, .none, params[0]), |
| 8037 | | .result_ptr = try expr(gz, scope, .none, params[1]), |
| 8038 | | .fn_ptr = try expr(gz, scope, .none, params[2]), |
| 8039 | | .args = try expr(gz, scope, .none, params[3]), |
| 8204 | .frame_buffer = try expr(gz, scope, .{ .rl = .none }, params[0]), |
| 8205 | .result_ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 8206 | .fn_ptr = try expr(gz, scope, .{ .rl = .none }, params[2]), |
| 8207 | .args = try expr(gz, scope, .{ .rl = .none }, params[3]), |
| 8040 | 8208 | }); |
| 8041 | | return rvalue(gz, rl, result, node); |
| 8209 | return rvalue(gz, ri, result, node); |
| 8042 | 8210 | }, |
| 8043 | 8211 | .Vector => { |
| 8044 | 8212 | const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{ |
| 8045 | | .lhs = try comptimeExpr(gz, scope, .{ .coerced_ty = .u32_type }, params[0]), |
| 8213 | .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]), |
| 8046 | 8214 | .rhs = try typeExpr(gz, scope, params[1]), |
| 8047 | 8215 | }); |
| 8048 | | return rvalue(gz, rl, result, node); |
| 8216 | return rvalue(gz, ri, result, node); |
| 8049 | 8217 | }, |
| 8050 | 8218 | .prefetch => { |
| 8051 | | const ptr = try expr(gz, scope, .none, params[0]); |
| 8052 | | const options = try comptimeExpr(gz, scope, .{ .ty = .prefetch_options_type }, params[1]); |
| 8219 | const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]); |
| 8220 | const options = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .prefetch_options_type } }, params[1]); |
| 8053 | 8221 | const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{ |
| 8054 | 8222 | .node = gz.nodeIndexToRelative(node), |
| 8055 | 8223 | .lhs = ptr, |
| 8056 | 8224 | .rhs = options, |
| 8057 | 8225 | }); |
| 8058 | | return rvalue(gz, rl, result, node); |
| 8226 | return rvalue(gz, ri, result, node); |
| 8059 | 8227 | }, |
| 8060 | 8228 | } |
| 8061 | 8229 | } |
| 8062 | 8230 | |
| 8063 | 8231 | fn simpleNoOpVoid( |
| 8064 | 8232 | gz: *GenZir, |
| 8065 | | rl: ResultLoc, |
| 8233 | ri: ResultInfo, |
| 8066 | 8234 | node: Ast.Node.Index, |
| 8067 | 8235 | tag: Zir.Inst.Tag, |
| 8068 | 8236 | ) InnerError!Zir.Inst.Ref { |
| 8069 | 8237 | _ = try gz.addNode(tag, node); |
| 8070 | | return rvalue(gz, rl, .void_value, node); |
| 8238 | return rvalue(gz, ri, .void_value, node); |
| 8071 | 8239 | } |
| 8072 | 8240 | |
| 8073 | 8241 | fn hasDeclOrField( |
| 8074 | 8242 | gz: *GenZir, |
| 8075 | 8243 | scope: *Scope, |
| 8076 | | rl: ResultLoc, |
| 8244 | ri: ResultInfo, |
| 8077 | 8245 | node: Ast.Node.Index, |
| 8078 | 8246 | lhs_node: Ast.Node.Index, |
| 8079 | 8247 | rhs_node: Ast.Node.Index, |
| 8080 | 8248 | tag: Zir.Inst.Tag, |
| 8081 | 8249 | ) InnerError!Zir.Inst.Ref { |
| 8082 | 8250 | const container_type = try typeExpr(gz, scope, lhs_node); |
| 8083 | | const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node); |
| 8251 | const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node); |
| 8084 | 8252 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8085 | 8253 | .lhs = container_type, |
| 8086 | 8254 | .rhs = name, |
| 8087 | 8255 | }); |
| 8088 | | return rvalue(gz, rl, result, node); |
| 8256 | return rvalue(gz, ri, result, node); |
| 8089 | 8257 | } |
| 8090 | 8258 | |
| 8091 | 8259 | fn typeCast( |
| 8092 | 8260 | gz: *GenZir, |
| 8093 | 8261 | scope: *Scope, |
| 8094 | | rl: ResultLoc, |
| 8262 | ri: ResultInfo, |
| 8095 | 8263 | node: Ast.Node.Index, |
| 8096 | 8264 | lhs_node: Ast.Node.Index, |
| 8097 | 8265 | rhs_node: Ast.Node.Index, |
| ... | ... | @@ -8099,42 +8267,42 @@ fn typeCast( |
| 8099 | 8267 | ) InnerError!Zir.Inst.Ref { |
| 8100 | 8268 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8101 | 8269 | .lhs = try typeExpr(gz, scope, lhs_node), |
| 8102 | | .rhs = try expr(gz, scope, .none, rhs_node), |
| 8270 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), |
| 8103 | 8271 | }); |
| 8104 | | return rvalue(gz, rl, result, node); |
| 8272 | return rvalue(gz, ri, result, node); |
| 8105 | 8273 | } |
| 8106 | 8274 | |
| 8107 | 8275 | fn simpleUnOpType( |
| 8108 | 8276 | gz: *GenZir, |
| 8109 | 8277 | scope: *Scope, |
| 8110 | | rl: ResultLoc, |
| 8278 | ri: ResultInfo, |
| 8111 | 8279 | node: Ast.Node.Index, |
| 8112 | 8280 | operand_node: Ast.Node.Index, |
| 8113 | 8281 | tag: Zir.Inst.Tag, |
| 8114 | 8282 | ) InnerError!Zir.Inst.Ref { |
| 8115 | 8283 | const operand = try typeExpr(gz, scope, operand_node); |
| 8116 | 8284 | const result = try gz.addUnNode(tag, operand, node); |
| 8117 | | return rvalue(gz, rl, result, node); |
| 8285 | return rvalue(gz, ri, result, node); |
| 8118 | 8286 | } |
| 8119 | 8287 | |
| 8120 | 8288 | fn simpleUnOp( |
| 8121 | 8289 | gz: *GenZir, |
| 8122 | 8290 | scope: *Scope, |
| 8123 | | rl: ResultLoc, |
| 8291 | ri: ResultInfo, |
| 8124 | 8292 | node: Ast.Node.Index, |
| 8125 | | operand_rl: ResultLoc, |
| 8293 | operand_ri: ResultInfo, |
| 8126 | 8294 | operand_node: Ast.Node.Index, |
| 8127 | 8295 | tag: Zir.Inst.Tag, |
| 8128 | 8296 | ) InnerError!Zir.Inst.Ref { |
| 8129 | | const operand = try expr(gz, scope, operand_rl, operand_node); |
| 8297 | const operand = try expr(gz, scope, operand_ri, operand_node); |
| 8130 | 8298 | const result = try gz.addUnNode(tag, operand, node); |
| 8131 | | return rvalue(gz, rl, result, node); |
| 8299 | return rvalue(gz, ri, result, node); |
| 8132 | 8300 | } |
| 8133 | 8301 | |
| 8134 | 8302 | fn negation( |
| 8135 | 8303 | gz: *GenZir, |
| 8136 | 8304 | scope: *Scope, |
| 8137 | | rl: ResultLoc, |
| 8305 | ri: ResultInfo, |
| 8138 | 8306 | node: Ast.Node.Index, |
| 8139 | 8307 | ) InnerError!Zir.Inst.Ref { |
| 8140 | 8308 | const astgen = gz.astgen; |
| ... | ... | @@ -8146,18 +8314,18 @@ fn negation( |
| 8146 | 8314 | // its negativity rather than having it go through comptime subtraction. |
| 8147 | 8315 | const operand_node = node_datas[node].lhs; |
| 8148 | 8316 | if (node_tags[operand_node] == .number_literal) { |
| 8149 | | return numberLiteral(gz, rl, operand_node, node, .negative); |
| 8317 | return numberLiteral(gz, ri, operand_node, node, .negative); |
| 8150 | 8318 | } |
| 8151 | 8319 | |
| 8152 | | const operand = try expr(gz, scope, .none, operand_node); |
| 8320 | const operand = try expr(gz, scope, .{ .rl = .none }, operand_node); |
| 8153 | 8321 | const result = try gz.addUnNode(.negate, operand, node); |
| 8154 | | return rvalue(gz, rl, result, node); |
| 8322 | return rvalue(gz, ri, result, node); |
| 8155 | 8323 | } |
| 8156 | 8324 | |
| 8157 | 8325 | fn cmpxchg( |
| 8158 | 8326 | gz: *GenZir, |
| 8159 | 8327 | scope: *Scope, |
| 8160 | | rl: ResultLoc, |
| 8328 | ri: ResultInfo, |
| 8161 | 8329 | node: Ast.Node.Index, |
| 8162 | 8330 | params: []const Ast.Node.Index, |
| 8163 | 8331 | small: u16, |
| ... | ... | @@ -8166,98 +8334,98 @@ fn cmpxchg( |
| 8166 | 8334 | const result = try gz.addExtendedPayloadSmall(.cmpxchg, small, Zir.Inst.Cmpxchg{ |
| 8167 | 8335 | // zig fmt: off |
| 8168 | 8336 | .node = gz.nodeIndexToRelative(node), |
| 8169 | | .ptr = try expr(gz, scope, .none, params[1]), |
| 8170 | | .expected_value = try expr(gz, scope, .{ .ty = int_type }, params[2]), |
| 8171 | | .new_value = try expr(gz, scope, .{ .coerced_ty = int_type }, params[3]), |
| 8172 | | .success_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[4]), |
| 8173 | | .failure_order = try expr(gz, scope, .{ .coerced_ty = .atomic_order_type }, params[5]), |
| 8337 | .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), |
| 8338 | .expected_value = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), |
| 8339 | .new_value = try expr(gz, scope, .{ .rl = .{ .coerced_ty = int_type } }, params[3]), |
| 8340 | .success_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]), |
| 8341 | .failure_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[5]), |
| 8174 | 8342 | // zig fmt: on |
| 8175 | 8343 | }); |
| 8176 | | return rvalue(gz, rl, result, node); |
| 8344 | return rvalue(gz, ri, result, node); |
| 8177 | 8345 | } |
| 8178 | 8346 | |
| 8179 | 8347 | fn bitBuiltin( |
| 8180 | 8348 | gz: *GenZir, |
| 8181 | 8349 | scope: *Scope, |
| 8182 | | rl: ResultLoc, |
| 8350 | ri: ResultInfo, |
| 8183 | 8351 | node: Ast.Node.Index, |
| 8184 | 8352 | operand_node: Ast.Node.Index, |
| 8185 | 8353 | tag: Zir.Inst.Tag, |
| 8186 | 8354 | ) InnerError!Zir.Inst.Ref { |
| 8187 | | const operand = try expr(gz, scope, .none, operand_node); |
| 8355 | const operand = try expr(gz, scope, .{ .rl = .none }, operand_node); |
| 8188 | 8356 | const result = try gz.addUnNode(tag, operand, node); |
| 8189 | | return rvalue(gz, rl, result, node); |
| 8357 | return rvalue(gz, ri, result, node); |
| 8190 | 8358 | } |
| 8191 | 8359 | |
| 8192 | 8360 | fn divBuiltin( |
| 8193 | 8361 | gz: *GenZir, |
| 8194 | 8362 | scope: *Scope, |
| 8195 | | rl: ResultLoc, |
| 8363 | ri: ResultInfo, |
| 8196 | 8364 | node: Ast.Node.Index, |
| 8197 | 8365 | lhs_node: Ast.Node.Index, |
| 8198 | 8366 | rhs_node: Ast.Node.Index, |
| 8199 | 8367 | tag: Zir.Inst.Tag, |
| 8200 | 8368 | ) InnerError!Zir.Inst.Ref { |
| 8201 | 8369 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8202 | | .lhs = try expr(gz, scope, .none, lhs_node), |
| 8203 | | .rhs = try expr(gz, scope, .none, rhs_node), |
| 8370 | .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node), |
| 8371 | .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node), |
| 8204 | 8372 | }); |
| 8205 | | return rvalue(gz, rl, result, node); |
| 8373 | return rvalue(gz, ri, result, node); |
| 8206 | 8374 | } |
| 8207 | 8375 | |
| 8208 | 8376 | fn simpleCBuiltin( |
| 8209 | 8377 | gz: *GenZir, |
| 8210 | 8378 | scope: *Scope, |
| 8211 | | rl: ResultLoc, |
| 8379 | ri: ResultInfo, |
| 8212 | 8380 | node: Ast.Node.Index, |
| 8213 | 8381 | operand_node: Ast.Node.Index, |
| 8214 | 8382 | tag: Zir.Inst.Extended, |
| 8215 | 8383 | ) InnerError!Zir.Inst.Ref { |
| 8216 | 8384 | const name: []const u8 = if (tag == .c_undef) "C undef" else "C include"; |
| 8217 | 8385 | if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name}); |
| 8218 | | const operand = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, operand_node); |
| 8386 | const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, operand_node); |
| 8219 | 8387 | _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{ |
| 8220 | 8388 | .node = gz.nodeIndexToRelative(node), |
| 8221 | 8389 | .operand = operand, |
| 8222 | 8390 | }); |
| 8223 | | return rvalue(gz, rl, .void_value, node); |
| 8391 | return rvalue(gz, ri, .void_value, node); |
| 8224 | 8392 | } |
| 8225 | 8393 | |
| 8226 | 8394 | fn offsetOf( |
| 8227 | 8395 | gz: *GenZir, |
| 8228 | 8396 | scope: *Scope, |
| 8229 | | rl: ResultLoc, |
| 8397 | ri: ResultInfo, |
| 8230 | 8398 | node: Ast.Node.Index, |
| 8231 | 8399 | lhs_node: Ast.Node.Index, |
| 8232 | 8400 | rhs_node: Ast.Node.Index, |
| 8233 | 8401 | tag: Zir.Inst.Tag, |
| 8234 | 8402 | ) InnerError!Zir.Inst.Ref { |
| 8235 | 8403 | const type_inst = try typeExpr(gz, scope, lhs_node); |
| 8236 | | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, rhs_node); |
| 8404 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node); |
| 8237 | 8405 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8238 | 8406 | .lhs = type_inst, |
| 8239 | 8407 | .rhs = field_name, |
| 8240 | 8408 | }); |
| 8241 | | return rvalue(gz, rl, result, node); |
| 8409 | return rvalue(gz, ri, result, node); |
| 8242 | 8410 | } |
| 8243 | 8411 | |
| 8244 | 8412 | fn shiftOp( |
| 8245 | 8413 | gz: *GenZir, |
| 8246 | 8414 | scope: *Scope, |
| 8247 | | rl: ResultLoc, |
| 8415 | ri: ResultInfo, |
| 8248 | 8416 | node: Ast.Node.Index, |
| 8249 | 8417 | lhs_node: Ast.Node.Index, |
| 8250 | 8418 | rhs_node: Ast.Node.Index, |
| 8251 | 8419 | tag: Zir.Inst.Tag, |
| 8252 | 8420 | ) InnerError!Zir.Inst.Ref { |
| 8253 | | const lhs = try expr(gz, scope, .none, lhs_node); |
| 8421 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); |
| 8254 | 8422 | const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); |
| 8255 | | const rhs = try expr(gz, scope, .{ .ty_shift_operand = log2_int_type }, rhs_node); |
| 8423 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); |
| 8256 | 8424 | const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ |
| 8257 | 8425 | .lhs = lhs, |
| 8258 | 8426 | .rhs = rhs, |
| 8259 | 8427 | }); |
| 8260 | | return rvalue(gz, rl, result, node); |
| 8428 | return rvalue(gz, ri, result, node); |
| 8261 | 8429 | } |
| 8262 | 8430 | |
| 8263 | 8431 | fn cImport( |
| ... | ... | @@ -8275,7 +8443,7 @@ fn cImport( |
| 8275 | 8443 | defer block_scope.unstack(); |
| 8276 | 8444 | |
| 8277 | 8445 | const block_inst = try gz.makeBlockInst(.c_import, node); |
| 8278 | | const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); |
| 8446 | const block_result = try expr(&block_scope, &block_scope.base, .{ .rl = .none }, body_node); |
| 8279 | 8447 | _ = try gz.addUnNode(.ensure_result_used, block_result, node); |
| 8280 | 8448 | if (!gz.refIsNoReturn(block_result)) { |
| 8281 | 8449 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); |
| ... | ... | @@ -8290,29 +8458,29 @@ fn cImport( |
| 8290 | 8458 | fn overflowArithmetic( |
| 8291 | 8459 | gz: *GenZir, |
| 8292 | 8460 | scope: *Scope, |
| 8293 | | rl: ResultLoc, |
| 8461 | ri: ResultInfo, |
| 8294 | 8462 | node: Ast.Node.Index, |
| 8295 | 8463 | params: []const Ast.Node.Index, |
| 8296 | 8464 | tag: Zir.Inst.Extended, |
| 8297 | 8465 | ) InnerError!Zir.Inst.Ref { |
| 8298 | 8466 | const int_type = try typeExpr(gz, scope, params[0]); |
| 8299 | 8467 | const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]); |
| 8300 | | const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]); |
| 8301 | | const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]); |
| 8302 | | const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]); |
| 8468 | const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]); |
| 8469 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]); |
| 8470 | const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]); |
| 8303 | 8471 | const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{ |
| 8304 | 8472 | .node = gz.nodeIndexToRelative(node), |
| 8305 | 8473 | .lhs = lhs, |
| 8306 | 8474 | .rhs = rhs, |
| 8307 | 8475 | .ptr = ptr, |
| 8308 | 8476 | }); |
| 8309 | | return rvalue(gz, rl, result, node); |
| 8477 | return rvalue(gz, ri, result, node); |
| 8310 | 8478 | } |
| 8311 | 8479 | |
| 8312 | 8480 | fn callExpr( |
| 8313 | 8481 | gz: *GenZir, |
| 8314 | 8482 | scope: *Scope, |
| 8315 | | rl: ResultLoc, |
| 8483 | ri: ResultInfo, |
| 8316 | 8484 | node: Ast.Node.Index, |
| 8317 | 8485 | call: Ast.full.Call, |
| 8318 | 8486 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -8364,7 +8532,7 @@ fn callExpr( |
| 8364 | 8532 | defer arg_block.unstack(); |
| 8365 | 8533 | |
| 8366 | 8534 | // `call_inst` is reused to provide the param type. |
| 8367 | | const arg_ref = try expr(&arg_block, &arg_block.base, .{ .coerced_ty = call_inst }, param_node); |
| 8535 | const arg_ref = try expr(&arg_block, &arg_block.base, .{ .rl = .{ .coerced_ty = call_inst }, .ctx = .fn_arg }, param_node); |
| 8368 | 8536 | _ = try arg_block.addBreak(.break_inline, call_index, arg_ref); |
| 8369 | 8537 | |
| 8370 | 8538 | const body = arg_block.instructionsSlice(); |
| ... | ... | @@ -8375,9 +8543,18 @@ fn callExpr( |
| 8375 | 8543 | scratch_index += 1; |
| 8376 | 8544 | } |
| 8377 | 8545 | |
| 8546 | // If our result location is a try/catch/error-union-if/return, a function argument, |
| 8547 | // or an initializer for a `const` variable, the error trace propagates. |
| 8548 | // Otherwise, it should always be popped (handled in Sema). |
| 8549 | const propagate_error_trace = switch (ri.ctx) { |
| 8550 | .error_handling_expr, .@"return", .fn_arg, .const_init => true, |
| 8551 | else => false, |
| 8552 | }; |
| 8553 | |
| 8378 | 8554 | const payload_index = try addExtra(astgen, Zir.Inst.Call{ |
| 8379 | 8555 | .callee = callee, |
| 8380 | 8556 | .flags = .{ |
| 8557 | .pop_error_return_trace = !propagate_error_trace, |
| 8381 | 8558 | .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)), |
| 8382 | 8559 | .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len), |
| 8383 | 8560 | }, |
| ... | ... | @@ -8392,7 +8569,7 @@ fn callExpr( |
| 8392 | 8569 | .payload_index = payload_index, |
| 8393 | 8570 | } }, |
| 8394 | 8571 | }); |
| 8395 | | return rvalue(gz, rl, call_inst, node); // TODO function call with result location |
| 8572 | return rvalue(gz, ri, call_inst, node); // TODO function call with result location |
| 8396 | 8573 | } |
| 8397 | 8574 | |
| 8398 | 8575 | /// calleeExpr generates the function part of a call expression (f in f(x)), or the |
| ... | ... | @@ -8413,7 +8590,7 @@ fn calleeExpr( |
| 8413 | 8590 | |
| 8414 | 8591 | const tag = tree.nodes.items(.tag)[node]; |
| 8415 | 8592 | switch (tag) { |
| 8416 | | .field_access => return addFieldAccess(.field_call_bind, gz, scope, .ref, node), |
| 8593 | .field_access => return addFieldAccess(.field_call_bind, gz, scope, .{ .rl = .ref }, node), |
| 8417 | 8594 | |
| 8418 | 8595 | .builtin_call_two, |
| 8419 | 8596 | .builtin_call_two_comma, |
| ... | ... | @@ -8445,8 +8622,8 @@ fn calleeExpr( |
| 8445 | 8622 | // If anything is wrong, fall back to builtinCall. |
| 8446 | 8623 | // It will emit any necessary compile errors and notes. |
| 8447 | 8624 | if (std.mem.eql(u8, builtin_name, "@field") and params.len == 2) { |
| 8448 | | const lhs = try expr(gz, scope, .ref, params[0]); |
| 8449 | | const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); |
| 8625 | const lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]); |
| 8626 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]); |
| 8450 | 8627 | return gz.addExtendedPayload(.field_call_bind_named, Zir.Inst.FieldNamedNode{ |
| 8451 | 8628 | .node = gz.nodeIndexToRelative(node), |
| 8452 | 8629 | .lhs = lhs, |
| ... | ... | @@ -8454,9 +8631,9 @@ fn calleeExpr( |
| 8454 | 8631 | }); |
| 8455 | 8632 | } |
| 8456 | 8633 | |
| 8457 | | return builtinCall(gz, scope, .none, node, params); |
| 8634 | return builtinCall(gz, scope, .{ .rl = .none }, node, params); |
| 8458 | 8635 | }, |
| 8459 | | else => return expr(gz, scope, .none, node), |
| 8636 | else => return expr(gz, scope, .{ .rl = .none }, node), |
| 8460 | 8637 | } |
| 8461 | 8638 | } |
| 8462 | 8639 | |
| ... | ... | @@ -8738,6 +8915,33 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_ |
| 8738 | 8915 | } |
| 8739 | 8916 | } |
| 8740 | 8917 | |
| 8918 | fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 8919 | const node_tags = tree.nodes.items(.tag); |
| 8920 | const node_datas = tree.nodes.items(.data); |
| 8921 | |
| 8922 | var node = start_node; |
| 8923 | while (true) { |
| 8924 | switch (node_tags[node]) { |
| 8925 | // These don't have the opportunity to call any runtime functions. |
| 8926 | .error_value, |
| 8927 | .identifier, |
| 8928 | .@"comptime", |
| 8929 | => return false, |
| 8930 | |
| 8931 | // Forward the question to the LHS sub-expression. |
| 8932 | .grouped_expression, |
| 8933 | .@"try", |
| 8934 | .@"nosuspend", |
| 8935 | .unwrap_optional, |
| 8936 | => node = node_datas[node].lhs, |
| 8937 | |
| 8938 | // Anything that does not eval to an error is guaranteed to pop any |
| 8939 | // additions to the error trace, so it effectively does not append. |
| 8940 | else => return nodeMayEvalToError(tree, start_node) != .never, |
| 8941 | } |
| 8942 | } |
| 8943 | } |
| 8944 | |
| 8741 | 8945 | fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError { |
| 8742 | 8946 | const node_tags = tree.nodes.items(.tag); |
| 8743 | 8947 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -9472,7 +9676,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { |
| 9472 | 9676 | /// Assumes nothing stacked on `gz`. |
| 9473 | 9677 | fn rvalue( |
| 9474 | 9678 | gz: *GenZir, |
| 9475 | | rl: ResultLoc, |
| 9679 | ri: ResultInfo, |
| 9476 | 9680 | raw_result: Zir.Inst.Ref, |
| 9477 | 9681 | src_node: Ast.Node.Index, |
| 9478 | 9682 | ) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -9487,7 +9691,7 @@ fn rvalue( |
| 9487 | 9691 | break :r raw_result; |
| 9488 | 9692 | }; |
| 9489 | 9693 | if (gz.endsWithNoReturn()) return result; |
| 9490 | | switch (rl) { |
| 9694 | switch (ri.rl) { |
| 9491 | 9695 | .none, .coerced_ty => return result, |
| 9492 | 9696 | .discard => { |
| 9493 | 9697 | // Emit a compile error for discarding error values. |
| ... | ... | @@ -9513,7 +9717,7 @@ fn rvalue( |
| 9513 | 9717 | } |
| 9514 | 9718 | return indexToRef(gop.value_ptr.*); |
| 9515 | 9719 | }, |
| 9516 | | .ty, .ty_shift_operand => |ty_inst| { |
| 9720 | .ty => |ty_inst| { |
| 9517 | 9721 | // Quickly eliminate some common, unnecessary type coercion. |
| 9518 | 9722 | const as_ty = @as(u64, @enumToInt(Zir.Inst.Ref.type_type)) << 32; |
| 9519 | 9723 | const as_comptime_int = @as(u64, @enumToInt(Zir.Inst.Ref.comptime_int_type)) << 32; |
| ... | ... | @@ -9574,7 +9778,7 @@ fn rvalue( |
| 9574 | 9778 | => return result, // type of result is already correct |
| 9575 | 9779 | |
| 9576 | 9780 | // Need an explicit type coercion instruction. |
| 9577 | | else => return gz.addPlNode(rl.zirTag(), src_node, Zir.Inst.As{ |
| 9781 | else => return gz.addPlNode(ri.zirTag(), src_node, Zir.Inst.As{ |
| 9578 | 9782 | .dest_type = ty_inst, |
| 9579 | 9783 | .operand = result, |
| 9580 | 9784 | }), |
| ... | ... | @@ -10268,8 +10472,8 @@ const GenZir = struct { |
| 10268 | 10472 | label: ?Label = null, |
| 10269 | 10473 | break_block: Zir.Inst.Index = 0, |
| 10270 | 10474 | continue_block: Zir.Inst.Index = 0, |
| 10271 | | /// Only valid when setBreakResultLoc is called. |
| 10272 | | break_result_loc: AstGen.ResultLoc = undefined, |
| 10475 | /// Only valid when setBreakResultInfo is called. |
| 10476 | break_result_info: AstGen.ResultInfo = undefined, |
| 10273 | 10477 | /// When a block has a pointer result location, here it is. |
| 10274 | 10478 | rl_ptr: Zir.Inst.Ref = .none, |
| 10275 | 10479 | /// When a block has a type result location, here it is. |
| ... | ... | @@ -10371,7 +10575,7 @@ const GenZir = struct { |
| 10371 | 10575 | fn finishCoercion( |
| 10372 | 10576 | as_scope: *GenZir, |
| 10373 | 10577 | parent_gz: *GenZir, |
| 10374 | | rl: ResultLoc, |
| 10578 | ri: ResultInfo, |
| 10375 | 10579 | src_node: Ast.Node.Index, |
| 10376 | 10580 | result: Zir.Inst.Ref, |
| 10377 | 10581 | dest_type: Zir.Inst.Ref, |
| ... | ... | @@ -10397,7 +10601,7 @@ const GenZir = struct { |
| 10397 | 10601 | as_scope.instructions_top = GenZir.unstacked_top; |
| 10398 | 10602 | // as_scope now unstacked, can add new instructions to parent_gz |
| 10399 | 10603 | const casted_result = try parent_gz.addBin(.as, dest_type, result); |
| 10400 | | return rvalue(parent_gz, rl, casted_result, src_node); |
| 10604 | return rvalue(parent_gz, ri, casted_result, src_node); |
| 10401 | 10605 | } else { |
| 10402 | 10606 | // implicitly move all as_scope instructions to parent_gz |
| 10403 | 10607 | as_scope.instructions_top = GenZir.unstacked_top; |
| ... | ... | @@ -10440,7 +10644,7 @@ const GenZir = struct { |
| 10440 | 10644 | return gz.astgen.tree.firstToken(gz.decl_node_index); |
| 10441 | 10645 | } |
| 10442 | 10646 | |
| 10443 | | fn setBreakResultLoc(gz: *GenZir, parent_rl: AstGen.ResultLoc) void { |
| 10647 | fn setBreakResultInfo(gz: *GenZir, parent_ri: AstGen.ResultInfo) void { |
| 10444 | 10648 | // Depending on whether the result location is a pointer or value, different |
| 10445 | 10649 | // ZIR needs to be generated. In the former case we rely on storing to the |
| 10446 | 10650 | // pointer to communicate the result, and use breakvoid; in the latter case |
| ... | ... | @@ -10449,32 +10653,32 @@ const GenZir = struct { |
| 10449 | 10653 | // the scenario where the result location is not consumed. In this case |
| 10450 | 10654 | // we emit ZIR for the block break instructions to have the result values, |
| 10451 | 10655 | // and then rvalue() on that to pass the value to the result location. |
| 10452 | | switch (parent_rl) { |
| 10453 | | .ty, .ty_shift_operand, .coerced_ty => |ty_inst| { |
| 10656 | switch (parent_ri.rl) { |
| 10657 | .ty, .coerced_ty => |ty_inst| { |
| 10454 | 10658 | gz.rl_ty_inst = ty_inst; |
| 10455 | | gz.break_result_loc = parent_rl; |
| 10659 | gz.break_result_info = parent_ri; |
| 10456 | 10660 | }, |
| 10457 | 10661 | |
| 10458 | 10662 | .discard, .none, .ref => { |
| 10459 | 10663 | gz.rl_ty_inst = .none; |
| 10460 | | gz.break_result_loc = parent_rl; |
| 10664 | gz.break_result_info = parent_ri; |
| 10461 | 10665 | }, |
| 10462 | 10666 | |
| 10463 | 10667 | .ptr => |ptr_res| { |
| 10464 | 10668 | gz.rl_ty_inst = .none; |
| 10465 | | gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } }; |
| 10669 | gz.break_result_info = .{ .rl = .{ .ptr = .{ .inst = ptr_res.inst } } }; |
| 10466 | 10670 | }, |
| 10467 | 10671 | |
| 10468 | 10672 | .inferred_ptr => |ptr| { |
| 10469 | 10673 | gz.rl_ty_inst = .none; |
| 10470 | 10674 | gz.rl_ptr = ptr; |
| 10471 | | gz.break_result_loc = .{ .block_ptr = gz }; |
| 10675 | gz.break_result_info = .{ .rl = .{ .block_ptr = gz }, .ctx = parent_ri.ctx }; |
| 10472 | 10676 | }, |
| 10473 | 10677 | |
| 10474 | 10678 | .block_ptr => |parent_block_scope| { |
| 10475 | 10679 | gz.rl_ty_inst = parent_block_scope.rl_ty_inst; |
| 10476 | 10680 | gz.rl_ptr = parent_block_scope.rl_ptr; |
| 10477 | | gz.break_result_loc = .{ .block_ptr = gz }; |
| 10681 | gz.break_result_info = .{ .rl = .{ .block_ptr = gz }, .ctx = parent_ri.ctx }; |
| 10478 | 10682 | }, |
| 10479 | 10683 | } |
| 10480 | 10684 | } |
| ... | ... | @@ -11157,6 +11361,46 @@ const GenZir = struct { |
| 11157 | 11361 | }); |
| 11158 | 11362 | } |
| 11159 | 11363 | |
| 11364 | fn addSaveErrRetIndex( |
| 11365 | gz: *GenZir, |
| 11366 | cond: union(enum) { |
| 11367 | always: void, |
| 11368 | if_of_error_type: Zir.Inst.Ref, |
| 11369 | }, |
| 11370 | ) !Zir.Inst.Index { |
| 11371 | return gz.addAsIndex(.{ |
| 11372 | .tag = .save_err_ret_index, |
| 11373 | .data = .{ .save_err_ret_index = .{ |
| 11374 | .operand = if (cond == .if_of_error_type) cond.if_of_error_type else .none, |
| 11375 | } }, |
| 11376 | }); |
| 11377 | } |
| 11378 | |
| 11379 | const BranchTarget = union(enum) { |
| 11380 | ret, |
| 11381 | block: Zir.Inst.Index, |
| 11382 | }; |
| 11383 | |
| 11384 | fn addRestoreErrRetIndex( |
| 11385 | gz: *GenZir, |
| 11386 | bt: BranchTarget, |
| 11387 | cond: union(enum) { |
| 11388 | always: void, |
| 11389 | if_non_error: Zir.Inst.Ref, |
| 11390 | }, |
| 11391 | ) !Zir.Inst.Index { |
| 11392 | return gz.addAsIndex(.{ |
| 11393 | .tag = .restore_err_ret_index, |
| 11394 | .data = .{ .restore_err_ret_index = .{ |
| 11395 | .block = switch (bt) { |
| 11396 | .ret => .none, |
| 11397 | .block => |b| Zir.indexToRef(b), |
| 11398 | }, |
| 11399 | .operand = if (cond == .if_non_error) cond.if_non_error else .none, |
| 11400 | } }, |
| 11401 | }); |
| 11402 | } |
| 11403 | |
| 11160 | 11404 | fn addBreak( |
| 11161 | 11405 | gz: *GenZir, |
| 11162 | 11406 | tag: Zir.Inst.Tag, |
| ... | ... | @@ -11624,10 +11868,10 @@ const GenZir = struct { |
| 11624 | 11868 | return new_index; |
| 11625 | 11869 | } |
| 11626 | 11870 | |
| 11627 | | fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { |
| 11628 | | switch (rl) { |
| 11871 | fn addRet(gz: *GenZir, ri: ResultInfo, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { |
| 11872 | switch (ri.rl) { |
| 11629 | 11873 | .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node), |
| 11630 | | .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node), |
| 11874 | .ty => _ = try gz.addUnNode(.ret_node, operand, node), |
| 11631 | 11875 | else => unreachable, |
| 11632 | 11876 | } |
| 11633 | 11877 | } |