| author | |
| committer | |
| log | 609b84611dcde382af5d9fbc2345ede468d31a6f |
| tree | 9dab23600c4fd136b10ccd65eb3d908dfe6bb206 |
| parent | 1472dc3ddb6fd7932ff530e7a2fd3f0185c7353f |
* ZIR function instructions encode the index of the block that
contains the function instruction. This allows Zig to later scan the
block and find the parameter instructions, which is needed for
semantically analyzing function bodies.
* Runtime function calls insert AIR arg instructions and then inserts
Sema inst_map entries mapping the ZIR param instructions to them.
* comptime/inline function call inserts Sema inst_map entries mapping
the ZIR param instructions to the AIR callsite arguments.
With this commit we are back to the tests passing.5 files changed, 117 insertions(+), 78 deletions(-)
BRANCH_TODO-2| ... | @@ -1,6 +1,4 @@ | ... | @@ -1,6 +1,4 @@ |
| 1 | * update arg instructions: | 1 | * update arg instructions: |
| 2 | - runtime function call inserts AIR arg instructions and Sema map items for them | ||
| 3 | - comptime/inline function call inserts Sema map items for the args | ||
| 4 | - generic instantiation inserts Sema map items for the comptime args only, re-runs the | 2 | - generic instantiation inserts Sema map items for the comptime args only, re-runs the |
| 5 | Decl ZIR to get the new Fn. | 3 | Decl ZIR to get the new Fn. |
| 6 | * generic function call where it makes a new function | 4 | * generic function call where it makes a new function |
src/AstGen.zig+7| ... | @@ -1125,6 +1125,7 @@ fn fnProtoExpr( | ... | @@ -1125,6 +1125,7 @@ fn fnProtoExpr( |
| 1125 | 1125 | ||
| 1126 | const result = try gz.addFunc(.{ | 1126 | const result = try gz.addFunc(.{ |
| 1127 | .src_node = fn_proto.ast.proto_node, | 1127 | .src_node = fn_proto.ast.proto_node, |
| 1128 | .param_block = 0, | ||
| 1128 | .ret_ty = return_type_inst, | 1129 | .ret_ty = return_type_inst, |
| 1129 | .body = &[0]Zir.Inst.Index{}, | 1130 | .body = &[0]Zir.Inst.Index{}, |
| 1130 | .cc = cc, | 1131 | .cc = cc, |
| ... | @@ -3035,6 +3036,7 @@ fn fnDecl( | ... | @@ -3035,6 +3036,7 @@ fn fnDecl( |
| 3035 | break :func try decl_gz.addFunc(.{ | 3036 | break :func try decl_gz.addFunc(.{ |
| 3036 | .src_node = decl_node, | 3037 | .src_node = decl_node, |
| 3037 | .ret_ty = return_type_inst, | 3038 | .ret_ty = return_type_inst, |
| 3039 | .param_block = block_inst, | ||
| 3038 | .body = &[0]Zir.Inst.Index{}, | 3040 | .body = &[0]Zir.Inst.Index{}, |
| 3039 | .cc = cc, | 3041 | .cc = cc, |
| 3040 | .align_inst = .none, // passed in the per-decl data | 3042 | .align_inst = .none, // passed in the per-decl data |
| ... | @@ -3071,6 +3073,7 @@ fn fnDecl( | ... | @@ -3071,6 +3073,7 @@ fn fnDecl( |
| 3071 | 3073 | ||
| 3072 | break :func try decl_gz.addFunc(.{ | 3074 | break :func try decl_gz.addFunc(.{ |
| 3073 | .src_node = decl_node, | 3075 | .src_node = decl_node, |
| 3076 | .param_block = block_inst, | ||
| 3074 | .ret_ty = return_type_inst, | 3077 | .ret_ty = return_type_inst, |
| 3075 | .body = fn_gz.instructions.items, | 3078 | .body = fn_gz.instructions.items, |
| 3076 | .cc = cc, | 3079 | .cc = cc, |
| ... | @@ -3415,6 +3418,7 @@ fn testDecl( | ... | @@ -3415,6 +3418,7 @@ fn testDecl( |
| 3415 | 3418 | ||
| 3416 | const func_inst = try decl_block.addFunc(.{ | 3419 | const func_inst = try decl_block.addFunc(.{ |
| 3417 | .src_node = node, | 3420 | .src_node = node, |
| 3421 | .param_block = block_inst, | ||
| 3418 | .ret_ty = .void_type, | 3422 | .ret_ty = .void_type, |
| 3419 | .body = fn_block.instructions.items, | 3423 | .body = fn_block.instructions.items, |
| 3420 | .cc = .none, | 3424 | .cc = .none, |
| ... | @@ -9111,6 +9115,7 @@ const GenZir = struct { | ... | @@ -9111,6 +9115,7 @@ const GenZir = struct { |
| 9111 | fn addFunc(gz: *GenZir, args: struct { | 9115 | fn addFunc(gz: *GenZir, args: struct { |
| 9112 | src_node: ast.Node.Index, | 9116 | src_node: ast.Node.Index, |
| 9113 | body: []const Zir.Inst.Index, | 9117 | body: []const Zir.Inst.Index, |
| 9118 | param_block: Zir.Inst.Index, | ||
| 9114 | ret_ty: Zir.Inst.Ref, | 9119 | ret_ty: Zir.Inst.Ref, |
| 9115 | cc: Zir.Inst.Ref, | 9120 | cc: Zir.Inst.Ref, |
| 9116 | align_inst: Zir.Inst.Ref, | 9121 | align_inst: Zir.Inst.Ref, |
| ... | @@ -9170,6 +9175,7 @@ const GenZir = struct { | ... | @@ -9170,6 +9175,7 @@ const GenZir = struct { |
| 9170 | ); | 9175 | ); |
| 9171 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ | 9176 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ |
| 9172 | .src_node = gz.nodeIndexToRelative(args.src_node), | 9177 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 9178 | .param_block = args.param_block, | ||
| 9173 | .return_type = args.ret_ty, | 9179 | .return_type = args.ret_ty, |
| 9174 | .body_len = @intCast(u32, args.body.len), | 9180 | .body_len = @intCast(u32, args.body.len), |
| 9175 | }); | 9181 | }); |
| ... | @@ -9212,6 +9218,7 @@ const GenZir = struct { | ... | @@ -9212,6 +9218,7 @@ const GenZir = struct { |
| 9212 | ); | 9218 | ); |
| 9213 | 9219 | ||
| 9214 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{ | 9220 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{ |
| 9221 | .param_block = args.param_block, | ||
| 9215 | .return_type = args.ret_ty, | 9222 | .return_type = args.ret_ty, |
| 9216 | .body_len = @intCast(u32, args.body.len), | 9223 | .body_len = @intCast(u32, args.body.len), |
| 9217 | }); | 9224 | }); |
src/Module.zig+38-19| ... | @@ -2899,7 +2899,6 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { | ... | @@ -2899,7 +2899,6 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { |
| 2899 | .namespace = &struct_obj.namespace, | 2899 | .namespace = &struct_obj.namespace, |
| 2900 | .func = null, | 2900 | .func = null, |
| 2901 | .owner_func = null, | 2901 | .owner_func = null, |
| 2902 | .param_inst_list = &.{}, | ||
| 2903 | }; | 2902 | }; |
| 2904 | defer sema.deinit(); | 2903 | defer sema.deinit(); |
| 2905 | var block_scope: Scope.Block = .{ | 2904 | var block_scope: Scope.Block = .{ |
| ... | @@ -2954,7 +2953,6 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2954,7 +2953,6 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 2954 | .namespace = decl.namespace, | 2953 | .namespace = decl.namespace, |
| 2955 | .func = null, | 2954 | .func = null, |
| 2956 | .owner_func = null, | 2955 | .owner_func = null, |
| 2957 | .param_inst_list = &.{}, | ||
| 2958 | }; | 2956 | }; |
| 2959 | defer sema.deinit(); | 2957 | defer sema.deinit(); |
| 2960 | 2958 | ||
| ... | @@ -3625,8 +3623,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { | ... | @@ -3625,8 +3623,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { |
| 3625 | defer decl.value_arena.?.* = arena.state; | 3623 | defer decl.value_arena.?.* = arena.state; |
| 3626 | 3624 | ||
| 3627 | const fn_ty = decl.ty; | 3625 | const fn_ty = decl.ty; |
| 3628 | const param_inst_list = try gpa.alloc(Air.Inst.Ref, fn_ty.fnParamLen()); | ||
| 3629 | defer gpa.free(param_inst_list); | ||
| 3630 | 3626 | ||
| 3631 | var sema: Sema = .{ | 3627 | var sema: Sema = .{ |
| 3632 | .mod = mod, | 3628 | .mod = mod, |
| ... | @@ -3637,7 +3633,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { | ... | @@ -3637,7 +3633,6 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { |
| 3637 | .namespace = decl.namespace, | 3633 | .namespace = decl.namespace, |
| 3638 | .func = func, | 3634 | .func = func, |
| 3639 | .owner_func = func, | 3635 | .owner_func = func, |
| 3640 | .param_inst_list = param_inst_list, | ||
| 3641 | }; | 3636 | }; |
| 3642 | defer sema.deinit(); | 3637 | defer sema.deinit(); |
| 3643 | 3638 | ||
| ... | @@ -3656,29 +3651,55 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { | ... | @@ -3656,29 +3651,55 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { |
| 3656 | }; | 3651 | }; |
| 3657 | defer inner_block.instructions.deinit(gpa); | 3652 | defer inner_block.instructions.deinit(gpa); |
| 3658 | 3653 | ||
| 3659 | // AIR requires the arg parameters to be the first N instructions. | 3654 | const fn_info = sema.code.getFnInfo(func.zir_body_inst); |
| 3660 | try inner_block.instructions.ensureTotalCapacity(gpa, param_inst_list.len); | 3655 | const zir_tags = sema.code.instructions.items(.tag); |
| 3661 | for (param_inst_list) |*param_inst, param_index| { | 3656 | |
| 3657 | // Here we are performing "runtime semantic analysis" for a function body, which means | ||
| 3658 | // we must map the parameter ZIR instructions to `arg` AIR instructions. | ||
| 3659 | // AIR requires the `arg` parameters to be the first N instructions. | ||
| 3660 | const params_len = @intCast(u32, fn_ty.fnParamLen()); | ||
| 3661 | try inner_block.instructions.ensureTotalCapacity(gpa, params_len); | ||
| 3662 | try sema.air_instructions.ensureUnusedCapacity(gpa, params_len * 2); // * 2 for the `addType` | ||
| 3663 | try sema.inst_map.ensureUnusedCapacity(gpa, params_len); | ||
| 3664 | |||
| 3665 | var param_index: usize = 0; | ||
| 3666 | for (fn_info.param_body) |inst| { | ||
| 3667 | const name = switch (zir_tags[inst]) { | ||
| 3668 | .param, .param_comptime => blk: { | ||
| 3669 | const inst_data = sema.code.instructions.items(.data)[inst].pl_tok; | ||
| 3670 | const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index).data; | ||
| 3671 | break :blk extra.name; | ||
| 3672 | }, | ||
| 3673 | |||
| 3674 | .param_anytype, .param_anytype_comptime => blk: { | ||
| 3675 | const str_tok = sema.code.instructions.items(.data)[inst].str_tok; | ||
| 3676 | break :blk str_tok.start; | ||
| 3677 | }, | ||
| 3678 | |||
| 3679 | else => continue, | ||
| 3680 | }; | ||
| 3662 | const param_type = fn_ty.fnParamType(param_index); | 3681 | const param_type = fn_ty.fnParamType(param_index); |
| 3682 | param_index += 1; | ||
| 3663 | const ty_ref = try sema.addType(param_type); | 3683 | const ty_ref = try sema.addType(param_type); |
| 3664 | const arg_index = @intCast(u32, sema.air_instructions.len); | 3684 | const arg_index = @intCast(u32, sema.air_instructions.len); |
| 3665 | inner_block.instructions.appendAssumeCapacity(arg_index); | 3685 | inner_block.instructions.appendAssumeCapacity(arg_index); |
| 3666 | param_inst.* = Air.indexToRef(arg_index); | 3686 | sema.air_instructions.appendAssumeCapacity(.{ |
| 3667 | try sema.air_instructions.append(gpa, .{ | ||
| 3668 | .tag = .arg, | 3687 | .tag = .arg, |
| 3669 | .data = .{ | 3688 | .data = .{ .ty_str = .{ |
| 3670 | .ty_str = .{ | 3689 | .ty = ty_ref, |
| 3671 | .ty = ty_ref, | 3690 | .str = name, |
| 3672 | .str = undefined, // Set in the semantic analysis of the arg instruction. | 3691 | } }, |
| 3673 | }, | ||
| 3674 | }, | ||
| 3675 | }); | 3692 | }); |
| 3693 | sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index)); | ||
| 3676 | } | 3694 | } |
| 3677 | 3695 | ||
| 3678 | func.state = .in_progress; | 3696 | func.state = .in_progress; |
| 3679 | log.debug("set {s} to in_progress", .{decl.name}); | 3697 | log.debug("set {s} to in_progress", .{decl.name}); |
| 3680 | 3698 | ||
| 3681 | try sema.analyzeFnBody(&inner_block, func.zir_body_inst); | 3699 | _ = sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) { |
| 3700 | error.NeededSourceLocation => unreachable, | ||
| 3701 | else => |e| return e, | ||
| 3702 | }; | ||
| 3682 | 3703 | ||
| 3683 | // Copy the block into place and mark that as the main block. | 3704 | // Copy the block into place and mark that as the main block. |
| 3684 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + | 3705 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| ... | @@ -4330,7 +4351,6 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) CompileError!void | ... | @@ -4330,7 +4351,6 @@ pub fn analyzeStructFields(mod: *Module, struct_obj: *Struct) CompileError!void |
| 4330 | .namespace = &struct_obj.namespace, | 4351 | .namespace = &struct_obj.namespace, |
| 4331 | .owner_func = null, | 4352 | .owner_func = null, |
| 4332 | .func = null, | 4353 | .func = null, |
| 4333 | .param_inst_list = &.{}, | ||
| 4334 | }; | 4354 | }; |
| 4335 | defer sema.deinit(); | 4355 | defer sema.deinit(); |
| 4336 | 4356 | ||
| ... | @@ -4484,7 +4504,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) CompileError!void { | ... | @@ -4484,7 +4504,6 @@ pub fn analyzeUnionFields(mod: *Module, union_obj: *Union) CompileError!void { |
| 4484 | .namespace = &union_obj.namespace, | 4504 | .namespace = &union_obj.namespace, |
| 4485 | .owner_func = null, | 4505 | .owner_func = null, |
| 4486 | .func = null, | 4506 | .func = null, |
| 4487 | .param_inst_list = &.{}, | ||
| 4488 | }; | 4507 | }; |
| 4489 | defer sema.deinit(); | 4508 | defer sema.deinit(); |
| 4490 | 4509 |
src/Sema.zig+21-54| ... | @@ -29,13 +29,6 @@ owner_func: ?*Module.Fn, | ... | @@ -29,13 +29,6 @@ owner_func: ?*Module.Fn, |
| 29 | /// This starts out the same as `owner_func` and then diverges in the case of | 29 | /// This starts out the same as `owner_func` and then diverges in the case of |
| 30 | /// an inline or comptime function call. | 30 | /// an inline or comptime function call. |
| 31 | func: ?*Module.Fn, | 31 | func: ?*Module.Fn, |
| 32 | /// For now, AIR requires arg instructions to be the first N instructions in the | ||
| 33 | /// AIR code. We store references here for the purpose of `resolveInst`. | ||
| 34 | /// This can get reworked with AIR memory layout changes, into simply: | ||
| 35 | /// > Denormalized data to make `resolveInst` faster. This is 0 if not inside a function, | ||
| 36 | /// > otherwise it is the number of parameters of the function. | ||
| 37 | /// > param_count: u32 | ||
| 38 | param_inst_list: []const Air.Inst.Ref, | ||
| 39 | branch_quota: u32 = 1000, | 32 | branch_quota: u32 = 1000, |
| 40 | branch_count: u32 = 0, | 33 | branch_count: u32 = 0, |
| 41 | /// This field is updated when a new source location becomes active, so that | 34 | /// This field is updated when a new source location becomes active, so that |
| ... | @@ -85,43 +78,10 @@ pub fn deinit(sema: *Sema) void { | ... | @@ -85,43 +78,10 @@ pub fn deinit(sema: *Sema) void { |
| 85 | sema.air_values.deinit(gpa); | 78 | sema.air_values.deinit(gpa); |
| 86 | sema.inst_map.deinit(gpa); | 79 | sema.inst_map.deinit(gpa); |
| 87 | sema.decl_val_table.deinit(gpa); | 80 | sema.decl_val_table.deinit(gpa); |
| 81 | sema.params.deinit(gpa); | ||
| 88 | sema.* = undefined; | 82 | sema.* = undefined; |
| 89 | } | 83 | } |
| 90 | 84 | ||
| 91 | pub fn analyzeFnBody( | ||
| 92 | sema: *Sema, | ||
| 93 | block: *Scope.Block, | ||
| 94 | fn_body_inst: Zir.Inst.Index, | ||
| 95 | ) SemaError!void { | ||
| 96 | const tags = sema.code.instructions.items(.tag); | ||
| 97 | const datas = sema.code.instructions.items(.data); | ||
| 98 | const body: []const Zir.Inst.Index = switch (tags[fn_body_inst]) { | ||
| 99 | .func, .func_inferred => blk: { | ||
| 100 | const inst_data = datas[fn_body_inst].pl_node; | ||
| 101 | const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); | ||
| 102 | const body = sema.code.extra[extra.end..][0..extra.data.body_len]; | ||
| 103 | break :blk body; | ||
| 104 | }, | ||
| 105 | .extended => blk: { | ||
| 106 | const extended = datas[fn_body_inst].extended; | ||
| 107 | assert(extended.opcode == .func); | ||
| 108 | const extra = sema.code.extraData(Zir.Inst.ExtendedFunc, extended.operand); | ||
| 109 | const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small); | ||
| 110 | var extra_index: usize = extra.end; | ||
| 111 | extra_index += @boolToInt(small.has_lib_name); | ||
| 112 | extra_index += @boolToInt(small.has_cc); | ||
| 113 | extra_index += @boolToInt(small.has_align); | ||
| 114 | const body = sema.code.extra[extra_index..][0..extra.data.body_len]; | ||
| 115 | break :blk body; | ||
| 116 | }, | ||
| 117 | else => unreachable, | ||
| 118 | }; | ||
| 119 | _ = sema.analyzeBody(block, body) catch |err| switch (err) { | ||
| 120 | error.NeededSourceLocation => unreachable, | ||
| 121 | else => |e| return e, | ||
| 122 | }; | ||
| 123 | } | ||
| 124 | |||
| 125 | /// Returns only the result from the body that is specified. | 85 | /// Returns only the result from the body that is specified. |
| 126 | /// Only appropriate to call when it is determined at comptime that this body | 86 | /// Only appropriate to call when it is determined at comptime that this body |
| 127 | /// has no peers. | 87 | /// has no peers. |
| ... | @@ -1066,7 +1026,6 @@ fn zirEnumDecl( | ... | @@ -1066,7 +1026,6 @@ fn zirEnumDecl( |
| 1066 | .namespace = &enum_obj.namespace, | 1026 | .namespace = &enum_obj.namespace, |
| 1067 | .owner_func = null, | 1027 | .owner_func = null, |
| 1068 | .func = null, | 1028 | .func = null, |
| 1069 | .param_inst_list = &.{}, | ||
| 1070 | .branch_quota = sema.branch_quota, | 1029 | .branch_quota = sema.branch_quota, |
| 1071 | .branch_count = sema.branch_count, | 1030 | .branch_count = sema.branch_count, |
| 1072 | }; | 1031 | }; |
| ... | @@ -2538,10 +2497,6 @@ fn analyzeCall( | ... | @@ -2538,10 +2497,6 @@ fn analyzeCall( |
| 2538 | sema.func = module_fn; | 2497 | sema.func = module_fn; |
| 2539 | defer sema.func = parent_func; | 2498 | defer sema.func = parent_func; |
| 2540 | 2499 | ||
| 2541 | const parent_param_inst_list = sema.param_inst_list; | ||
| 2542 | sema.param_inst_list = args; | ||
| 2543 | defer sema.param_inst_list = parent_param_inst_list; | ||
| 2544 | |||
| 2545 | const parent_next_arg_index = sema.next_arg_index; | 2500 | const parent_next_arg_index = sema.next_arg_index; |
| 2546 | sema.next_arg_index = 0; | 2501 | sema.next_arg_index = 0; |
| 2547 | defer sema.next_arg_index = parent_next_arg_index; | 2502 | defer sema.next_arg_index = parent_next_arg_index; |
| ... | @@ -2565,12 +2520,23 @@ fn analyzeCall( | ... | @@ -2565,12 +2520,23 @@ fn analyzeCall( |
| 2565 | try sema.emitBackwardBranch(&child_block, call_src); | 2520 | try sema.emitBackwardBranch(&child_block, call_src); |
| 2566 | 2521 | ||
| 2567 | // This will have return instructions analyzed as break instructions to | 2522 | // This will have return instructions analyzed as break instructions to |
| 2568 | // the block_inst above. | 2523 | // the block_inst above. Here we are performing "comptime/inline semantic analysis" |
| 2569 | try sema.analyzeFnBody(&child_block, module_fn.zir_body_inst); | 2524 | // for a function body, which means we must map the parameter ZIR instructions to |
| 2570 | 2525 | // the AIR instructions of the callsite. | |
| 2571 | const result = try sema.analyzeBlockBody(block, call_src, &child_block, merges); | 2526 | const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst); |
| 2572 | 2527 | const zir_tags = sema.code.instructions.items(.tag); | |
| 2573 | break :res result; | 2528 | var arg_i: usize = 0; |
| 2529 | try sema.inst_map.ensureUnusedCapacity(gpa, @intCast(u32, args.len)); | ||
| 2530 | for (fn_info.param_body) |inst| { | ||
| 2531 | switch (zir_tags[inst]) { | ||
| 2532 | .param, .param_comptime, .param_anytype, .param_anytype_comptime => {}, | ||
| 2533 | else => continue, | ||
| 2534 | } | ||
| 2535 | sema.inst_map.putAssumeCapacityNoClobber(inst, args[arg_i]); | ||
| 2536 | arg_i += 1; | ||
| 2537 | } | ||
| 2538 | _ = try sema.analyzeBody(&child_block, fn_info.body); | ||
| 2539 | break :res try sema.analyzeBlockBody(block, call_src, &child_block, merges); | ||
| 2574 | } else if (func_ty_info.is_generic) { | 2540 | } else if (func_ty_info.is_generic) { |
| 2575 | const func_val = try sema.resolveConstValue(block, func_src, func); | 2541 | const func_val = try sema.resolveConstValue(block, func_src, func); |
| 2576 | const module_fn = func_val.castTag(.function).?.data; | 2542 | const module_fn = func_val.castTag(.function).?.data; |
| ... | @@ -2601,7 +2567,7 @@ fn analyzeCall( | ... | @@ -2601,7 +2567,7 @@ fn analyzeCall( |
| 2601 | // TODO | 2567 | // TODO |
| 2602 | 2568 | ||
| 2603 | // Queue up a `codegen_func` work item for the new Fn, making sure it will have | 2569 | // Queue up a `codegen_func` work item for the new Fn, making sure it will have |
| 2604 | // `analyzeFnBody` called with the Scope which contains the comptime parameters. | 2570 | // `analyzeBody` called with the ZIR parameters mapped appropriately. |
| 2605 | // TODO | 2571 | // TODO |
| 2606 | 2572 | ||
| 2607 | // Save it into the Module's generic function map. | 2573 | // Save it into the Module's generic function map. |
| ... | @@ -3344,11 +3310,12 @@ fn funcCommon( | ... | @@ -3344,11 +3310,12 @@ fn funcCommon( |
| 3344 | // `resolveSwitchItemVal` to avoid resolving the source location unless | 3310 | // `resolveSwitchItemVal` to avoid resolving the source location unless |
| 3345 | // we actually need to report an error. | 3311 | // we actually need to report an error. |
| 3346 | const param_src = src; | 3312 | const param_src = src; |
| 3347 | param_types[i] = try sema.resolveType(block, param_src, param.ty); | 3313 | param_types[i] = try sema.analyzeAsType(block, param_src, param.ty); |
| 3348 | } | 3314 | } |
| 3349 | comptime_params[i] = param.is_comptime; | 3315 | comptime_params[i] = param.is_comptime; |
| 3350 | any_are_comptime = any_are_comptime or param.is_comptime; | 3316 | any_are_comptime = any_are_comptime or param.is_comptime; |
| 3351 | } | 3317 | } |
| 3318 | sema.params.clearRetainingCapacity(); | ||
| 3352 | 3319 | ||
| 3353 | if (align_val.tag() != .null_value) { | 3320 | if (align_val.tag() != .null_value) { |
| 3354 | return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{}); | 3321 | return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{}); |
src/Zir.zig+51-3| ... | @@ -61,7 +61,7 @@ pub const ExtraIndex = enum(u32) { | ... | @@ -61,7 +61,7 @@ pub const ExtraIndex = enum(u32) { |
| 61 | _, | 61 | _, |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | pub fn getMainStruct(zir: Zir) Zir.Inst.Index { | 64 | pub fn getMainStruct(zir: Zir) Inst.Index { |
| 65 | return zir.extra[@enumToInt(ExtraIndex.main_struct)] - | 65 | return zir.extra[@enumToInt(ExtraIndex.main_struct)] - |
| 66 | @intCast(u32, Inst.Ref.typed_value_map.len); | 66 | @intCast(u32, Inst.Ref.typed_value_map.len); |
| 67 | } | 67 | } |
| ... | @@ -2260,6 +2260,8 @@ pub const Inst = struct { | ... | @@ -2260,6 +2260,8 @@ pub const Inst = struct { |
| 2260 | pub const ExtendedFunc = struct { | 2260 | pub const ExtendedFunc = struct { |
| 2261 | src_node: i32, | 2261 | src_node: i32, |
| 2262 | return_type: Ref, | 2262 | return_type: Ref, |
| 2263 | /// Points to the block that contains the param instructions for this function. | ||
| 2264 | param_block: Index, | ||
| 2263 | body_len: u32, | 2265 | body_len: u32, |
| 2264 | 2266 | ||
| 2265 | pub const Small = packed struct { | 2267 | pub const Small = packed struct { |
| ... | @@ -2297,6 +2299,8 @@ pub const Inst = struct { | ... | @@ -2297,6 +2299,8 @@ pub const Inst = struct { |
| 2297 | /// 1. src_locs: SrcLocs // if body_len != 0 | 2299 | /// 1. src_locs: SrcLocs // if body_len != 0 |
| 2298 | pub const Func = struct { | 2300 | pub const Func = struct { |
| 2299 | return_type: Ref, | 2301 | return_type: Ref, |
| 2302 | /// Points to the block that contains the param instructions for this function. | ||
| 2303 | param_block: Index, | ||
| 2300 | body_len: u32, | 2304 | body_len: u32, |
| 2301 | 2305 | ||
| 2302 | pub const SrcLocs = struct { | 2306 | pub const SrcLocs = struct { |
| ... | @@ -4894,10 +4898,54 @@ fn findDeclsSwitchMulti( | ... | @@ -4894,10 +4898,54 @@ fn findDeclsSwitchMulti( |
| 4894 | 4898 | ||
| 4895 | fn findDeclsBody( | 4899 | fn findDeclsBody( |
| 4896 | zir: Zir, | 4900 | zir: Zir, |
| 4897 | list: *std.ArrayList(Zir.Inst.Index), | 4901 | list: *std.ArrayList(Inst.Index), |
| 4898 | body: []const Zir.Inst.Index, | 4902 | body: []const Inst.Index, |
| 4899 | ) Allocator.Error!void { | 4903 | ) Allocator.Error!void { |
| 4900 | for (body) |member| { | 4904 | for (body) |member| { |
| 4901 | try zir.findDeclsInner(list, member); | 4905 | try zir.findDeclsInner(list, member); |
| 4902 | } | 4906 | } |
| 4903 | } | 4907 | } |
| 4908 | |||
| 4909 | pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) struct { | ||
| 4910 | param_body: []const Inst.Index, | ||
| 4911 | body: []const Inst.Index, | ||
| 4912 | } { | ||
| 4913 | const tags = zir.instructions.items(.tag); | ||
| 4914 | const datas = zir.instructions.items(.data); | ||
| 4915 | const info: struct { | ||
| 4916 | param_block: Inst.Index, | ||
| 4917 | body: []const Inst.Index, | ||
| 4918 | } = switch (tags[fn_inst]) { | ||
| 4919 | .func, .func_inferred => blk: { | ||
| 4920 | const inst_data = datas[fn_inst].pl_node; | ||
| 4921 | const extra = zir.extraData(Inst.Func, inst_data.payload_index); | ||
| 4922 | const body = zir.extra[extra.end..][0..extra.data.body_len]; | ||
| 4923 | break :blk .{ | ||
| 4924 | .param_block = extra.data.param_block, | ||
| 4925 | .body = body, | ||
| 4926 | }; | ||
| 4927 | }, | ||
| 4928 | .extended => blk: { | ||
| 4929 | const extended = datas[fn_inst].extended; | ||
| 4930 | assert(extended.opcode == .func); | ||
| 4931 | const extra = zir.extraData(Inst.ExtendedFunc, extended.operand); | ||
| 4932 | const small = @bitCast(Inst.ExtendedFunc.Small, extended.small); | ||
| 4933 | var extra_index: usize = extra.end; | ||
| 4934 | extra_index += @boolToInt(small.has_lib_name); | ||
| 4935 | extra_index += @boolToInt(small.has_cc); | ||
| 4936 | extra_index += @boolToInt(small.has_align); | ||
| 4937 | const body = zir.extra[extra_index..][0..extra.data.body_len]; | ||
| 4938 | break :blk .{ | ||
| 4939 | .param_block = extra.data.param_block, | ||
| 4940 | .body = body, | ||
| 4941 | }; | ||
| 4942 | }, | ||
| 4943 | else => unreachable, | ||
| 4944 | }; | ||
| 4945 | assert(tags[info.param_block] == .block or tags[info.param_block] == .block_inline); | ||
| 4946 | const param_block = zir.extraData(Inst.Block, datas[info.param_block].pl_node.payload_index); | ||
| 4947 | return .{ | ||
| 4948 | .param_body = zir.extra[param_block.end..][0..param_block.data.body_len], | ||
| 4949 | .body = info.body, | ||
| 4950 | }; | ||
| 4951 | } |