| ... | @@ -36,9 +36,14 @@ branch_count: u32 = 0, | ... | @@ -36,9 +36,14 @@ branch_count: u32 = 0, |
| 36 | /// access to the source location set by the previous instruction which did | 36 | /// access to the source location set by the previous instruction which did |
| 37 | /// contain a mapped source location. | 37 | /// contain a mapped source location. |
| 38 | src: LazySrcLoc = .{ .token_offset = 0 }, | 38 | src: LazySrcLoc = .{ .token_offset = 0 }, |
| 39 | next_arg_index: usize = 0, | | |
| 40 | params: std.ArrayListUnmanaged(Param) = .{}, | | |
| 41 | decl_val_table: std.AutoHashMapUnmanaged(*Decl, Air.Inst.Ref) = .{}, | 39 | decl_val_table: std.AutoHashMapUnmanaged(*Decl, Air.Inst.Ref) = .{}, |
| | 40 | /// `param` instructions are collected here to be used by the `func` instruction. |
| | 41 | params: std.ArrayListUnmanaged(Param) = .{}, |
| | 42 | /// When doing a generic function instantiation, this array collects a `Value` object for |
| | 43 | /// each parameter that is comptime known and thus elided from the generated function. |
| | 44 | /// This memory is allocated by a parent `Sema` and owned by the values arena of the owner_decl. |
| | 45 | comptime_args: []TypedValue = &.{}, |
| | 46 | next_arg_index: usize = 0, |
| 42 | | 47 | |
| 43 | const std = @import("std"); | 48 | const std = @import("std"); |
| 44 | const mem = std.mem; | 49 | const mem = std.mem; |
| ... | @@ -64,8 +69,8 @@ const target_util = @import("target.zig"); | ... | @@ -64,8 +69,8 @@ const target_util = @import("target.zig"); |
| 64 | | 69 | |
| 65 | const Param = struct { | 70 | const Param = struct { |
| 66 | name: [:0]const u8, | 71 | name: [:0]const u8, |
| 67 | /// `none` means `anytype`. | 72 | /// `noreturn` means `anytype`. |
| 68 | ty: Air.Inst.Ref, | 73 | ty: Type, |
| 69 | is_comptime: bool, | 74 | is_comptime: bool, |
| 70 | }; | 75 | }; |
| 71 | | 76 | |
| ... | @@ -366,26 +371,6 @@ pub fn analyzeBody( | ... | @@ -366,26 +371,6 @@ pub fn analyzeBody( |
| 366 | // continue the loop. | 371 | // continue the loop. |
| 367 | // We also know that they cannot be referenced later, so we avoid | 372 | // We also know that they cannot be referenced later, so we avoid |
| 368 | // putting them into the map. | 373 | // putting them into the map. |
| 369 | .param => { | | |
| 370 | try sema.zirParam(inst, false); | | |
| 371 | i += 1; | | |
| 372 | continue; | | |
| 373 | }, | | |
| 374 | .param_comptime => { | | |
| 375 | try sema.zirParam(inst, true); | | |
| 376 | i += 1; | | |
| 377 | continue; | | |
| 378 | }, | | |
| 379 | .param_anytype => { | | |
| 380 | try sema.zirParamAnytype(inst, false); | | |
| 381 | i += 1; | | |
| 382 | continue; | | |
| 383 | }, | | |
| 384 | .param_anytype_comptime => { | | |
| 385 | try sema.zirParamAnytype(inst, true); | | |
| 386 | i += 1; | | |
| 387 | continue; | | |
| 388 | }, | | |
| 389 | .breakpoint => { | 374 | .breakpoint => { |
| 390 | try sema.zirBreakpoint(block, inst); | 375 | try sema.zirBreakpoint(block, inst); |
| 391 | i += 1; | 376 | i += 1; |
| ... | @@ -519,6 +504,88 @@ pub fn analyzeBody( | ... | @@ -519,6 +504,88 @@ pub fn analyzeBody( |
| 519 | return break_inst; | 504 | return break_inst; |
| 520 | } | 505 | } |
| 521 | }, | 506 | }, |
| | 507 | .param => blk: { |
| | 508 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; |
| | 509 | const src = inst_data.src(); |
| | 510 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data; |
| | 511 | const param_name = sema.code.nullTerminatedString(extra.name); |
| | 512 | |
| | 513 | if (sema.nextArgIsComptimeElided()) { |
| | 514 | i += 1; |
| | 515 | continue; |
| | 516 | } |
| | 517 | |
| | 518 | // TODO check if param_name shadows a Decl. This only needs to be done if |
| | 519 | // usingnamespace is implemented. |
| | 520 | |
| | 521 | const param_ty = try sema.resolveType(block, src, extra.ty); |
| | 522 | try sema.params.append(sema.gpa, .{ |
| | 523 | .name = param_name, |
| | 524 | .ty = param_ty, |
| | 525 | .is_comptime = false, |
| | 526 | }); |
| | 527 | break :blk try sema.addConstUndef(param_ty); |
| | 528 | }, |
| | 529 | .param_comptime => blk: { |
| | 530 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; |
| | 531 | const src = inst_data.src(); |
| | 532 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data; |
| | 533 | const param_name = sema.code.nullTerminatedString(extra.name); |
| | 534 | |
| | 535 | if (sema.nextArgIsComptimeElided()) { |
| | 536 | i += 1; |
| | 537 | continue; |
| | 538 | } |
| | 539 | |
| | 540 | // TODO check if param_name shadows a Decl. This only needs to be done if |
| | 541 | // usingnamespace is implemented. |
| | 542 | |
| | 543 | const param_ty = try sema.resolveType(block, src, extra.ty); |
| | 544 | try sema.params.append(sema.gpa, .{ |
| | 545 | .name = param_name, |
| | 546 | .ty = param_ty, |
| | 547 | .is_comptime = true, |
| | 548 | }); |
| | 549 | break :blk try sema.addConstUndef(param_ty); |
| | 550 | }, |
| | 551 | .param_anytype => blk: { |
| | 552 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| | 553 | const param_name = inst_data.get(sema.code); |
| | 554 | |
| | 555 | if (sema.nextArgIsComptimeElided()) { |
| | 556 | i += 1; |
| | 557 | continue; |
| | 558 | } |
| | 559 | |
| | 560 | // TODO check if param_name shadows a Decl. This only needs to be done if |
| | 561 | // usingnamespace is implemented. |
| | 562 | |
| | 563 | try sema.params.append(sema.gpa, .{ |
| | 564 | .name = param_name, |
| | 565 | .ty = Type.initTag(.noreturn), |
| | 566 | .is_comptime = false, |
| | 567 | }); |
| | 568 | break :blk try sema.addConstUndef(Type.initTag(.@"undefined")); |
| | 569 | }, |
| | 570 | .param_anytype_comptime => blk: { |
| | 571 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; |
| | 572 | const param_name = inst_data.get(sema.code); |
| | 573 | |
| | 574 | if (sema.nextArgIsComptimeElided()) { |
| | 575 | i += 1; |
| | 576 | continue; |
| | 577 | } |
| | 578 | |
| | 579 | // TODO check if param_name shadows a Decl. This only needs to be done if |
| | 580 | // usingnamespace is implemented. |
| | 581 | |
| | 582 | try sema.params.append(sema.gpa, .{ |
| | 583 | .name = param_name, |
| | 584 | .ty = Type.initTag(.noreturn), |
| | 585 | .is_comptime = true, |
| | 586 | }); |
| | 587 | break :blk try sema.addConstUndef(Type.initTag(.@"undefined")); |
| | 588 | }, |
| 522 | }; | 589 | }; |
| 523 | if (sema.typeOf(air_inst).isNoReturn()) | 590 | if (sema.typeOf(air_inst).isNoReturn()) |
| 524 | return always_noreturn; | 591 | return always_noreturn; |
| ... | @@ -1339,36 +1406,6 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co | ... | @@ -1339,36 +1406,6 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1339 | return sema.analyzeLoad(block, src, result_ptr, result_ptr_src); | 1406 | return sema.analyzeLoad(block, src, result_ptr, result_ptr_src); |
| 1340 | } | 1407 | } |
| 1341 | | 1408 | |
| 1342 | fn zirParam(sema: *Sema, inst: Zir.Inst.Index, is_comptime: bool) CompileError!void { | | |
| 1343 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; | | |
| 1344 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data; | | |
| 1345 | const param_name = sema.code.nullTerminatedString(extra.name); | | |
| 1346 | | | |
| 1347 | // TODO check if param_name shadows a Decl. This only needs to be done if | | |
| 1348 | // usingnamespace is implemented. | | |
| 1349 | | | |
| 1350 | const param_ty = sema.resolveInst(extra.ty); | | |
| 1351 | try sema.params.append(sema.gpa, .{ | | |
| 1352 | .name = param_name, | | |
| 1353 | .ty = param_ty, | | |
| 1354 | .is_comptime = is_comptime, | | |
| 1355 | }); | | |
| 1356 | } | | |
| 1357 | | | |
| 1358 | fn zirParamAnytype(sema: *Sema, inst: Zir.Inst.Index, is_comptime: bool) CompileError!void { | | |
| 1359 | const inst_data = sema.code.instructions.items(.data)[inst].str_tok; | | |
| 1360 | const param_name = inst_data.get(sema.code); | | |
| 1361 | | | |
| 1362 | // TODO check if param_name shadows a Decl. This only needs to be done if | | |
| 1363 | // usingnamespace is implemented. | | |
| 1364 | | | |
| 1365 | try sema.params.append(sema.gpa, .{ | | |
| 1366 | .name = param_name, | | |
| 1367 | .ty = .none, | | |
| 1368 | .is_comptime = is_comptime, | | |
| 1369 | }); | | |
| 1370 | } | | |
| 1371 | | | |
| 1372 | fn zirAllocExtended( | 1409 | fn zirAllocExtended( |
| 1373 | sema: *Sema, | 1410 | sema: *Sema, |
| 1374 | block: *Scope.Block, | 1411 | block: *Scope.Block, |
| ... | @@ -2497,10 +2534,6 @@ fn analyzeCall( | ... | @@ -2497,10 +2534,6 @@ fn analyzeCall( |
| 2497 | sema.func = module_fn; | 2534 | sema.func = module_fn; |
| 2498 | defer sema.func = parent_func; | 2535 | defer sema.func = parent_func; |
| 2499 | | 2536 | |
| 2500 | const parent_next_arg_index = sema.next_arg_index; | | |
| 2501 | sema.next_arg_index = 0; | | |
| 2502 | defer sema.next_arg_index = parent_next_arg_index; | | |
| 2503 | | | |
| 2504 | var child_block: Scope.Block = .{ | 2537 | var child_block: Scope.Block = .{ |
| 2505 | .parent = null, | 2538 | .parent = null, |
| 2506 | .sema = sema, | 2539 | .sema = sema, |
| ... | @@ -2537,7 +2570,7 @@ fn analyzeCall( | ... | @@ -2537,7 +2570,7 @@ fn analyzeCall( |
| 2537 | } | 2570 | } |
| 2538 | _ = try sema.analyzeBody(&child_block, fn_info.body); | 2571 | _ = try sema.analyzeBody(&child_block, fn_info.body); |
| 2539 | break :res try sema.analyzeBlockBody(block, call_src, &child_block, merges); | 2572 | break :res try sema.analyzeBlockBody(block, call_src, &child_block, merges); |
| 2540 | } else if (func_ty_info.is_generic) { | 2573 | } else if (func_ty_info.is_generic) res: { |
| 2541 | const func_val = try sema.resolveConstValue(block, func_src, func); | 2574 | const func_val = try sema.resolveConstValue(block, func_src, func); |
| 2542 | const module_fn = func_val.castTag(.function).?.data; | 2575 | const module_fn = func_val.castTag(.function).?.data; |
| 2543 | // Check the Module's generic function map with an adapted context, so that we | 2576 | // Check the Module's generic function map with an adapted context, so that we |
| ... | @@ -2545,37 +2578,142 @@ fn analyzeCall( | ... | @@ -2545,37 +2578,142 @@ fn analyzeCall( |
| 2545 | // only to junk it if it matches an existing instantiation. | 2578 | // only to junk it if it matches an existing instantiation. |
| 2546 | // TODO | 2579 | // TODO |
| 2547 | | 2580 | |
| 2548 | // Create a Decl for the new function. | 2581 | const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst); |
| 2549 | const generic_namespace = try sema.arena.create(Module.Scope.Namespace); | 2582 | const zir_tags = sema.code.instructions.items(.tag); |
| 2550 | generic_namespace.* = .{ | 2583 | var non_comptime_args_len: u32 = 0; |
| 2551 | .parent = block.src_decl.namespace, | 2584 | const new_func = new_func: { |
| 2552 | .file_scope = block.src_decl.namespace.file_scope, | 2585 | const namespace = module_fn.owner_decl.namespace; |
| 2553 | .ty = func_ty, | 2586 | try namespace.anon_decls.ensureUnusedCapacity(gpa, 1); |
| | 2587 | |
| | 2588 | // Create a Decl for the new function. |
| | 2589 | const new_decl = try mod.allocateNewDecl(namespace, module_fn.owner_decl.src_node); |
| | 2590 | // TODO better names for generic function instantiations |
| | 2591 | const name_index = mod.getNextAnonNameIndex(); |
| | 2592 | new_decl.name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ |
| | 2593 | module_fn.owner_decl.name, name_index, |
| | 2594 | }); |
| | 2595 | new_decl.src_line = module_fn.owner_decl.src_line; |
| | 2596 | new_decl.is_pub = module_fn.owner_decl.is_pub; |
| | 2597 | new_decl.is_exported = module_fn.owner_decl.is_exported; |
| | 2598 | new_decl.has_align = module_fn.owner_decl.has_align; |
| | 2599 | new_decl.has_linksection = module_fn.owner_decl.has_linksection; |
| | 2600 | new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index; |
| | 2601 | new_decl.alive = true; // This Decl is called at runtime. |
| | 2602 | new_decl.has_tv = true; |
| | 2603 | new_decl.owns_tv = true; |
| | 2604 | new_decl.analysis = .in_progress; |
| | 2605 | new_decl.generation = mod.generation; |
| | 2606 | |
| | 2607 | namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {}); |
| | 2608 | |
| | 2609 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| | 2610 | errdefer new_decl_arena.deinit(); |
| | 2611 | |
| | 2612 | // Re-run the block that creates the function, with the comptime parameters |
| | 2613 | // pre-populated inside `inst_map`. This causes `param_comptime` and |
| | 2614 | // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a |
| | 2615 | // new, monomorphized function, with the comptime parameters elided. |
| | 2616 | var child_sema: Sema = .{ |
| | 2617 | .mod = mod, |
| | 2618 | .gpa = gpa, |
| | 2619 | .arena = sema.arena, |
| | 2620 | .code = sema.code, |
| | 2621 | .owner_decl = new_decl, |
| | 2622 | .namespace = namespace, |
| | 2623 | .func = null, |
| | 2624 | .owner_func = null, |
| | 2625 | .comptime_args = try new_decl_arena.allocator.alloc(TypedValue, args.len), |
| | 2626 | }; |
| | 2627 | defer child_sema.deinit(); |
| | 2628 | |
| | 2629 | var child_block: Scope.Block = .{ |
| | 2630 | .parent = null, |
| | 2631 | .sema = &child_sema, |
| | 2632 | .src_decl = new_decl, |
| | 2633 | .instructions = .{}, |
| | 2634 | .inlining = null, |
| | 2635 | .is_comptime = true, |
| | 2636 | }; |
| | 2637 | defer child_block.instructions.deinit(gpa); |
| | 2638 | |
| | 2639 | try child_sema.inst_map.ensureUnusedCapacity(gpa, @intCast(u32, args.len)); |
| | 2640 | var arg_i: usize = 0; |
| | 2641 | for (fn_info.param_body) |inst| { |
| | 2642 | const is_comptime = switch (zir_tags[inst]) { |
| | 2643 | .param_comptime, .param_anytype_comptime => true, |
| | 2644 | .param, .param_anytype => false, // TODO make true for always comptime types |
| | 2645 | else => continue, |
| | 2646 | }; |
| | 2647 | if (is_comptime) { |
| | 2648 | // TODO: pass .unneeded to resolveConstValue and then if we get |
| | 2649 | // error.NeededSourceLocation resolve the arg source location and |
| | 2650 | // try again. |
| | 2651 | const arg_src = call_src; |
| | 2652 | const arg = args[arg_i]; |
| | 2653 | const arg_val = try sema.resolveConstValue(block, arg_src, arg); |
| | 2654 | child_sema.comptime_args[arg_i] = .{ |
| | 2655 | .ty = try sema.typeOf(arg).copy(&new_decl_arena.allocator), |
| | 2656 | .val = try arg_val.copy(&new_decl_arena.allocator), |
| | 2657 | }; |
| | 2658 | const child_arg = try child_sema.addConstant(sema.typeOf(arg), arg_val); |
| | 2659 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); |
| | 2660 | } else { |
| | 2661 | non_comptime_args_len += 1; |
| | 2662 | child_sema.comptime_args[arg_i] = .{ |
| | 2663 | .ty = Type.initTag(.noreturn), |
| | 2664 | .val = Value.initTag(.unreachable_value), |
| | 2665 | }; |
| | 2666 | } |
| | 2667 | arg_i += 1; |
| | 2668 | } |
| | 2669 | const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body); |
| | 2670 | const new_func_val = try child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst); |
| | 2671 | const new_func = new_func_val.castTag(.function).?.data; |
| | 2672 | |
| | 2673 | // Populate the Decl ty/val with the function and its type. |
| | 2674 | new_decl.ty = try child_sema.typeOf(new_func_inst).copy(&new_decl_arena.allocator); |
| | 2675 | new_decl.val = try Value.Tag.function.create(&new_decl_arena.allocator, new_func); |
| | 2676 | new_decl.analysis = .complete; |
| | 2677 | |
| | 2678 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field |
| | 2679 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR |
| | 2680 | // parameters mapped appropriately. |
| | 2681 | try mod.comp.bin_file.allocateDeclIndexes(new_decl); |
| | 2682 | try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); |
| | 2683 | |
| | 2684 | try new_decl.finalizeNewArena(&new_decl_arena); |
| | 2685 | break :new_func try sema.analyzeDeclVal(block, func_src, new_decl); |
| 2554 | }; | 2686 | }; |
| 2555 | const new_decl = try mod.allocateNewDecl(generic_namespace, module_fn.owner_decl.src_node); | | |
| 2556 | _ = new_decl; | | |
| 2557 | | | |
| 2558 | // Iterate over the parameters that are comptime, evaluating their type expressions | | |
| 2559 | // inside a Scope which contains the previous parameters. | | |
| 2560 | //for (args) |arg, arg_i| { | | |
| 2561 | //} | | |
| 2562 | | | |
| 2563 | // Create a new Fn with only the runtime-known parameters. | | |
| 2564 | // TODO | | |
| 2565 | | | |
| 2566 | // Populate the Decl ty/val with the function and its type. | | |
| 2567 | // TODO | | |
| 2568 | | | |
| 2569 | // Queue up a `codegen_func` work item for the new Fn, making sure it will have | | |
| 2570 | // `analyzeBody` called with the ZIR parameters mapped appropriately. | | |
| 2571 | // TODO | | |
| 2572 | | 2687 | |
| 2573 | // Save it into the Module's generic function map. | 2688 | // Save it into the Module's generic function map. |
| 2574 | // TODO | 2689 | // TODO |
| 2575 | | 2690 | |
| 2576 | // Call it the same as a runtime function. | 2691 | // Make a runtime call to the new function, making sure to omit the comptime args. |
| 2577 | // TODO | 2692 | try sema.requireRuntimeBlock(block, call_src); |
| 2578 | return mod.fail(&block.base, func_src, "TODO implement generic fn call", .{}); | 2693 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + |
| | 2694 | non_comptime_args_len); |
| | 2695 | const func_inst = try block.addInst(.{ |
| | 2696 | .tag = .call, |
| | 2697 | .data = .{ .pl_op = .{ |
| | 2698 | .operand = new_func, |
| | 2699 | .payload = sema.addExtraAssumeCapacity(Air.Call{ |
| | 2700 | .args_len = non_comptime_args_len, |
| | 2701 | }), |
| | 2702 | } }, |
| | 2703 | }); |
| | 2704 | var arg_i: usize = 0; |
| | 2705 | for (fn_info.param_body) |inst| { |
| | 2706 | const is_comptime = switch (zir_tags[inst]) { |
| | 2707 | .param_comptime, .param_anytype_comptime => true, |
| | 2708 | .param, .param_anytype => false, // TODO make true for always comptime types |
| | 2709 | else => continue, |
| | 2710 | }; |
| | 2711 | if (is_comptime) { |
| | 2712 | sema.air_extra.appendAssumeCapacity(@enumToInt(args[arg_i])); |
| | 2713 | } |
| | 2714 | arg_i += 1; |
| | 2715 | } |
| | 2716 | break :res func_inst; |
| 2579 | } else res: { | 2717 | } else res: { |
| 2580 | try sema.requireRuntimeBlock(block, call_src); | 2718 | try sema.requireRuntimeBlock(block, call_src); |
| 2581 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + | 2719 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + |
| ... | @@ -3302,15 +3440,10 @@ fn funcCommon( | ... | @@ -3302,15 +3440,10 @@ fn funcCommon( |
| 3302 | const param_types = try sema.arena.alloc(Type, sema.params.items.len); | 3440 | const param_types = try sema.arena.alloc(Type, sema.params.items.len); |
| 3303 | const comptime_params = try sema.arena.alloc(bool, sema.params.items.len); | 3441 | const comptime_params = try sema.arena.alloc(bool, sema.params.items.len); |
| 3304 | for (sema.params.items) |param, i| { | 3442 | for (sema.params.items) |param, i| { |
| 3305 | if (param.ty == .none) { | 3443 | if (param.ty.tag() == .noreturn) { |
| 3306 | param_types[i] = Type.initTag(.noreturn); // indicates anytype | 3444 | param_types[i] = Type.initTag(.noreturn); // indicates anytype |
| 3307 | } else { | 3445 | } else { |
| 3308 | // TODO make a compile error from `resolveType` report the source location | 3446 | param_types[i] = param.ty; |
| 3309 | // of the specific parameter. Will need to take a similar strategy as | | |
| 3310 | // `resolveSwitchItemVal` to avoid resolving the source location unless | | |
| 3311 | // we actually need to report an error. | | |
| 3312 | const param_src = src; | | |
| 3313 | param_types[i] = try sema.analyzeAsType(block, param_src, param.ty); | | |
| 3314 | } | 3447 | } |
| 3315 | comptime_params[i] = param.is_comptime; | 3448 | comptime_params[i] = param.is_comptime; |
| 3316 | any_are_comptime = any_are_comptime or param.is_comptime; | 3449 | any_are_comptime = any_are_comptime or param.is_comptime; |
| ... | @@ -3402,6 +3535,7 @@ fn funcCommon( | ... | @@ -3402,6 +3535,7 @@ fn funcCommon( |
| 3402 | .state = anal_state, | 3535 | .state = anal_state, |
| 3403 | .zir_body_inst = body_inst, | 3536 | .zir_body_inst = body_inst, |
| 3404 | .owner_decl = sema.owner_decl, | 3537 | .owner_decl = sema.owner_decl, |
| | 3538 | .comptime_args = if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr, |
| 3405 | .lbrace_line = src_locs.lbrace_line, | 3539 | .lbrace_line = src_locs.lbrace_line, |
| 3406 | .rbrace_line = src_locs.rbrace_line, | 3540 | .rbrace_line = src_locs.rbrace_line, |
| 3407 | .lbrace_column = @truncate(u16, src_locs.columns), | 3541 | .lbrace_column = @truncate(u16, src_locs.columns), |
| ... | @@ -6819,19 +6953,12 @@ fn safetyPanic( | ... | @@ -6819,19 +6953,12 @@ fn safetyPanic( |
| 6819 | const msg_inst = msg_inst: { | 6953 | const msg_inst = msg_inst: { |
| 6820 | // TODO instead of making a new decl for every panic in the entire compilation, | 6954 | // TODO instead of making a new decl for every panic in the entire compilation, |
| 6821 | // introduce the concept of a reference-counted decl for these | 6955 | // introduce the concept of a reference-counted decl for these |
| 6822 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | 6956 | var anon_decl = try block.startAnonDecl(); |
| 6823 | errdefer new_decl_arena.deinit(); | 6957 | defer anon_decl.deinit(); |
| 6824 | | 6958 | break :msg_inst try sema.analyzeDeclRef(try anon_decl.finish( |
| 6825 | const decl_ty = try Type.Tag.array_u8.create(&new_decl_arena.allocator, msg.len); | 6959 | try Type.Tag.array_u8.create(anon_decl.arena(), msg.len), |
| 6826 | const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, msg); | 6960 | try Value.Tag.bytes.create(anon_decl.arena(), msg), |
| 6827 | | 6961 | )); |
| 6828 | const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{ | | |
| 6829 | .ty = decl_ty, | | |
| 6830 | .val = decl_val, | | |
| 6831 | }); | | |
| 6832 | errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); | | |
| 6833 | try new_decl.finalizeNewArena(&new_decl_arena); | | |
| 6834 | break :msg_inst try sema.analyzeDeclRef(new_decl); | | |
| 6835 | }; | 6962 | }; |
| 6836 | | 6963 | |
| 6837 | const casted_msg_inst = try sema.coerce(block, Type.initTag(.const_slice_u8), msg_inst, src); | 6964 | const casted_msg_inst = try sema.coerce(block, Type.initTag(.const_slice_u8), msg_inst, src); |
| ... | @@ -8832,7 +8959,7 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref { | ... | @@ -8832,7 +8959,7 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref { |
| 8832 | return sema.addConstant(ty, Value.initTag(.undef)); | 8959 | return sema.addConstant(ty, Value.initTag(.undef)); |
| 8833 | } | 8960 | } |
| 8834 | | 8961 | |
| 8835 | fn addConstant(sema: *Sema, ty: Type, val: Value) CompileError!Air.Inst.Ref { | 8962 | pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref { |
| 8836 | const gpa = sema.gpa; | 8963 | const gpa = sema.gpa; |
| 8837 | const ty_inst = try sema.addType(ty); | 8964 | const ty_inst = try sema.addType(ty); |
| 8838 | try sema.air_values.append(gpa, val); | 8965 | try sema.air_values.append(gpa, val); |
| ... | @@ -8888,3 +9015,10 @@ fn isComptimeKnown( | ... | @@ -8888,3 +9015,10 @@ fn isComptimeKnown( |
| 8888 | ) !bool { | 9015 | ) !bool { |
| 8889 | return (try sema.resolveMaybeUndefVal(block, src, inst)) != null; | 9016 | return (try sema.resolveMaybeUndefVal(block, src, inst)) != null; |
| 8890 | } | 9017 | } |
| | 9018 | |
| | 9019 | fn nextArgIsComptimeElided(sema: *Sema) bool { |
| | 9020 | if (sema.comptime_args.len == 0) return false; |
| | 9021 | const result = sema.comptime_args[sema.next_arg_index].val.tag() != .unreachable_value; |
| | 9022 | sema.next_arg_index += 1; |
| | 9023 | return result; |
| | 9024 | } |