authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-30 21:43:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-30 21:43:18-07:00
log077b8d3def537b9a36330c14c39bfa77b2e122bc
tree4a90916b4a0f6813c82b4fadf7a59b62b082cf41
parentdb7acd83d2fb18fc0fbd1b58e0638f2afaa595fb

stage2: introduce new ZIR instruction: arg

* AstGen: LocalVal and LocalPtr use string table indexes for their names. This is more efficient because local variable declarations do need to include the variable names so that semantic analysis can emit a compile error if a declaration is shadowed. So we take advantage of this fact by comparing string table indexes when resolving names. * The arg ZIR instructions are needed for the above reasoning, as well as to emit equivalent AIR instructions for debug info. Now that we have these arg instructions, get rid of the special `Zir.Inst.Ref` range for parameters. ZIR instructions now refer to the arg instructions for parameters. * Move identAsString and strLitAsString from Module.GenZir to AstGen where they belong.

4 files changed, 167 insertions(+), 155 deletions(-)

src/AstGen.zig+111-52
...@@ -1367,7 +1367,7 @@ pub fn structInitExprRlNone(...@@ -1367,7 +1367,7 @@ pub fn structInitExprRlNone(
13671367
1368 for (struct_init.ast.fields) |field_init, i| {1368 for (struct_init.ast.fields) |field_init, i| {
1369 const name_token = tree.firstToken(field_init) - 2;1369 const name_token = tree.firstToken(field_init) - 2;
1370 const str_index = try gz.identAsString(name_token);1370 const str_index = try astgen.identAsString(name_token);
13711371
1372 fields_list[i] = .{1372 fields_list[i] = .{
1373 .field_name = str_index,1373 .field_name = str_index,
...@@ -1402,7 +1402,7 @@ pub fn structInitExprRlPtr(...@@ -1402,7 +1402,7 @@ pub fn structInitExprRlPtr(
14021402
1403 for (struct_init.ast.fields) |field_init, i| {1403 for (struct_init.ast.fields) |field_init, i| {
1404 const name_token = tree.firstToken(field_init) - 2;1404 const name_token = tree.firstToken(field_init) - 2;
1405 const str_index = try gz.identAsString(name_token);1405 const str_index = try astgen.identAsString(name_token);
1406 const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{1406 const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{
1407 .lhs = result_ptr,1407 .lhs = result_ptr,
1408 .field_name_start = str_index,1408 .field_name_start = str_index,
...@@ -1435,7 +1435,7 @@ pub fn structInitExprRlTy(...@@ -1435,7 +1435,7 @@ pub fn structInitExprRlTy(
14351435
1436 for (struct_init.ast.fields) |field_init, i| {1436 for (struct_init.ast.fields) |field_init, i| {
1437 const name_token = tree.firstToken(field_init) - 2;1437 const name_token = tree.firstToken(field_init) - 2;
1438 const str_index = try gz.identAsString(name_token);1438 const str_index = try astgen.identAsString(name_token);
14391439
1440 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{1440 const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{
1441 .container_type = ty_inst,1441 .container_type = ty_inst,
...@@ -1832,6 +1832,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1832,6 +1832,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1832 // ZIR instructions that might be a type other than `noreturn` or `void`.1832 // ZIR instructions that might be a type other than `noreturn` or `void`.
1833 .add,1833 .add,
1834 .addwrap,1834 .addwrap,
1835 .arg,
1835 .alloc,1836 .alloc,
1836 .alloc_mut,1837 .alloc_mut,
1837 .alloc_comptime,1838 .alloc_comptime,
...@@ -2163,7 +2164,7 @@ fn varDecl(...@@ -2163,7 +2164,7 @@ fn varDecl(
2163 const token_tags = tree.tokens.items(.tag);2164 const token_tags = tree.tokens.items(.tag);
21642165
2165 const name_token = var_decl.ast.mut_token + 1;2166 const name_token = var_decl.ast.mut_token + 1;
2166 const ident_name = try astgen.identifierTokenString(name_token);2167 const ident_name = try astgen.identAsString(name_token);
21672168
2168 // Local variables shadowing detection, including function parameters.2169 // Local variables shadowing detection, including function parameters.
2169 {2170 {
...@@ -2171,9 +2172,9 @@ fn varDecl(...@@ -2171,9 +2172,9 @@ fn varDecl(
2171 while (true) switch (s.tag) {2172 while (true) switch (s.tag) {
2172 .local_val => {2173 .local_val => {
2173 const local_val = s.cast(Scope.LocalVal).?;2174 const local_val = s.cast(Scope.LocalVal).?;
2174 if (mem.eql(u8, local_val.name, ident_name)) {2175 if (local_val.name == ident_name) {
2175 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{2176 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2176 ident_name,2177 @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + ident_name,
2177 }, &[_]u32{2178 }, &[_]u32{
2178 try astgen.errNoteTok(2179 try astgen.errNoteTok(
2179 local_val.token_src,2180 local_val.token_src,
...@@ -2186,9 +2187,9 @@ fn varDecl(...@@ -2186,9 +2187,9 @@ fn varDecl(
2186 },2187 },
2187 .local_ptr => {2188 .local_ptr => {
2188 const local_ptr = s.cast(Scope.LocalPtr).?;2189 const local_ptr = s.cast(Scope.LocalPtr).?;
2189 if (mem.eql(u8, local_ptr.name, ident_name)) {2190 if (local_ptr.name == ident_name) {
2190 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{2191 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2191 ident_name,2192 @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + ident_name,
2192 }, &[_]u32{2193 }, &[_]u32{
2193 try astgen.errNoteTok(2194 try astgen.errNoteTok(
2194 local_ptr.token_src,2195 local_ptr.token_src,
...@@ -2690,7 +2691,6 @@ fn fnDecl(...@@ -2690,7 +2691,6 @@ fn fnDecl(
2690 .decl_node_index = fn_proto.ast.proto_node,2691 .decl_node_index = fn_proto.ast.proto_node,
2691 .parent = &gz.base,2692 .parent = &gz.base,
2692 .astgen = astgen,2693 .astgen = astgen,
2693 .ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len),
2694 };2694 };
2695 defer decl_gz.instructions.deinit(gpa);2695 defer decl_gz.instructions.deinit(gpa);
26962696
...@@ -2757,7 +2757,7 @@ fn fnDecl(...@@ -2757,7 +2757,7 @@ fn fnDecl(
2757 }2757 }
27582758
2759 const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {2759 const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {
2760 const lib_name_str = try decl_gz.strLitAsString(lib_name_token);2760 const lib_name_str = try astgen.strLitAsString(lib_name_token);
2761 break :blk lib_name_str.index;2761 break :blk lib_name_str.index;
2762 } else 0;2762 } else 0;
27632763
...@@ -2812,7 +2812,6 @@ fn fnDecl(...@@ -2812,7 +2812,6 @@ fn fnDecl(
2812 .decl_node_index = fn_proto.ast.proto_node,2812 .decl_node_index = fn_proto.ast.proto_node,
2813 .parent = &decl_gz.base,2813 .parent = &decl_gz.base,
2814 .astgen = astgen,2814 .astgen = astgen,
2815 .ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len + param_count),
2816 };2815 };
2817 defer fn_gz.instructions.deinit(gpa);2816 defer fn_gz.instructions.deinit(gpa);
28182817
...@@ -2832,21 +2831,24 @@ fn fnDecl(...@@ -2832,21 +2831,24 @@ fn fnDecl(
2832 const name_token = param.name_token orelse {2831 const name_token = param.name_token orelse {
2833 return astgen.failNode(param.type_expr, "missing parameter name", .{});2832 return astgen.failNode(param.type_expr, "missing parameter name", .{});
2834 };2833 };
2835 const param_name = try astgen.identifierTokenString(name_token);2834 const param_name = try astgen.identAsString(name_token);
2835 // Create an arg instruction. This is needed to emit a semantic analysis
2836 // error for shadowing decls.
2837 // TODO emit a compile error here for shadowing locals.
2838 const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token);
2836 const sub_scope = try astgen.arena.create(Scope.LocalVal);2839 const sub_scope = try astgen.arena.create(Scope.LocalVal);
2837 sub_scope.* = .{2840 sub_scope.* = .{
2838 .parent = params_scope,2841 .parent = params_scope,
2839 .gen_zir = &fn_gz,2842 .gen_zir = &fn_gz,
2840 .name = param_name,2843 .name = param_name,
2841 // Implicit const list first, then implicit arg list.2844 .inst = arg_inst,
2842 .inst = @intToEnum(Zir.Inst.Ref, @intCast(u32, Zir.Inst.Ref.typed_value_map.len + i)),
2843 .token_src = name_token,2845 .token_src = name_token,
2844 };2846 };
2845 params_scope = &sub_scope.base;2847 params_scope = &sub_scope.base;
28462848
2847 // Additionally put the param name into `string_bytes` and reference it with2849 // Additionally put the param name into `string_bytes` and reference it with
2848 // `extra` so that we have access to the data in codegen, for debug info.2850 // `extra` so that we have access to the data in codegen, for debug info.
2849 const str_index = try fn_gz.identAsString(name_token);2851 const str_index = try astgen.identAsString(name_token);
2850 astgen.extra.appendAssumeCapacity(str_index);2852 astgen.extra.appendAssumeCapacity(str_index);
2851 }2853 }
28522854
...@@ -2880,7 +2882,7 @@ fn fnDecl(...@@ -2880,7 +2882,7 @@ fn fnDecl(
2880 const fn_name_token = fn_proto.name_token orelse {2882 const fn_name_token = fn_proto.name_token orelse {
2881 return astgen.failTok(fn_proto.ast.fn_token, "missing function name", .{});2883 return astgen.failTok(fn_proto.ast.fn_token, "missing function name", .{});
2882 };2884 };
2883 const fn_name_str_index = try decl_gz.identAsString(fn_name_token);2885 const fn_name_str_index = try astgen.identAsString(fn_name_token);
28842886
2885 // We add this at the end so that its instruction index marks the end range2887 // We add this at the end so that its instruction index marks the end range
2886 // of the top level declaration.2888 // of the top level declaration.
...@@ -2953,7 +2955,7 @@ fn globalVarDecl(...@@ -2953,7 +2955,7 @@ fn globalVarDecl(
2953 } else false;2955 } else false;
29542956
2955 const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {2957 const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {
2956 const lib_name_str = try gz.strLitAsString(lib_name_token);2958 const lib_name_str = try astgen.strLitAsString(lib_name_token);
2957 break :blk lib_name_str.index;2959 break :blk lib_name_str.index;
2958 } else 0;2960 } else 0;
29592961
...@@ -3020,7 +3022,7 @@ fn globalVarDecl(...@@ -3020,7 +3022,7 @@ fn globalVarDecl(
3020 try block_scope.setBlockBody(block_inst);3022 try block_scope.setBlockBody(block_inst);
30213023
3022 const name_token = var_decl.ast.mut_token + 1;3024 const name_token = var_decl.ast.mut_token + 1;
3023 const name_str_index = try gz.identAsString(name_token);3025 const name_str_index = try astgen.identAsString(name_token);
30243026
3025 try wip_decls.payload.ensureUnusedCapacity(gpa, 8);3027 try wip_decls.payload.ensureUnusedCapacity(gpa, 8);
3026 {3028 {
...@@ -3156,7 +3158,7 @@ fn testDecl(...@@ -3156,7 +3158,7 @@ fn testDecl(
3156 const test_token = main_tokens[node];3158 const test_token = main_tokens[node];
3157 const str_lit_token = test_token + 1;3159 const str_lit_token = test_token + 1;
3158 if (token_tags[str_lit_token] == .string_literal) {3160 if (token_tags[str_lit_token] == .string_literal) {
3159 break :blk (try decl_block.strLitAsString(str_lit_token)).index;3161 break :blk (try astgen.strLitAsString(str_lit_token)).index;
3160 }3162 }
3161 // String table index 1 has a special meaning here of test decl with no name.3163 // String table index 1 has a special meaning here of test decl with no name.
3162 break :blk 1;3164 break :blk 1;
...@@ -3344,7 +3346,7 @@ fn structDeclInner(...@@ -3344,7 +3346,7 @@ fn structDeclInner(
3344 }3346 }
3345 try fields_data.ensureUnusedCapacity(gpa, 4);3347 try fields_data.ensureUnusedCapacity(gpa, 4);
33463348
3347 const field_name = try gz.identAsString(member.ast.name_token);3349 const field_name = try astgen.identAsString(member.ast.name_token);
3348 fields_data.appendAssumeCapacity(field_name);3350 fields_data.appendAssumeCapacity(field_name);
33493351
3350 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")3352 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
...@@ -3558,7 +3560,7 @@ fn unionDeclInner(...@@ -3558,7 +3560,7 @@ fn unionDeclInner(
3558 }3560 }
3559 try fields_data.ensureUnusedCapacity(gpa, 4);3561 try fields_data.ensureUnusedCapacity(gpa, 4);
35603562
3561 const field_name = try gz.identAsString(member.ast.name_token);3563 const field_name = try astgen.identAsString(member.ast.name_token);
3562 fields_data.appendAssumeCapacity(field_name);3564 fields_data.appendAssumeCapacity(field_name);
35633565
3564 const have_type = member.ast.type_expr != 0;3566 const have_type = member.ast.type_expr != 0;
...@@ -3906,7 +3908,7 @@ fn containerDecl(...@@ -3906,7 +3908,7 @@ fn containerDecl(
3906 assert(member.ast.type_expr == 0);3908 assert(member.ast.type_expr == 0);
3907 assert(member.ast.align_expr == 0);3909 assert(member.ast.align_expr == 0);
39083910
3909 const field_name = try gz.identAsString(member.ast.name_token);3911 const field_name = try astgen.identAsString(member.ast.name_token);
3910 fields_data.appendAssumeCapacity(field_name);3912 fields_data.appendAssumeCapacity(field_name);
39113913
3912 const have_value = member.ast.value_expr != 0;3914 const have_value = member.ast.value_expr != 0;
...@@ -4115,7 +4117,7 @@ fn errorSetDecl(...@@ -4115,7 +4117,7 @@ fn errorSetDecl(
4115 switch (token_tags[tok_i]) {4117 switch (token_tags[tok_i]) {
4116 .doc_comment, .comma => {},4118 .doc_comment, .comma => {},
4117 .identifier => {4119 .identifier => {
4118 const str_index = try gz.identAsString(tok_i);4120 const str_index = try astgen.identAsString(tok_i);
4119 try field_names.append(gpa, str_index);4121 try field_names.append(gpa, str_index);
4120 field_i += 1;4122 field_i += 1;
4121 },4123 },
...@@ -4255,7 +4257,7 @@ fn orelseCatchExpr(...@@ -4255,7 +4257,7 @@ fn orelseCatchExpr(
4255 if (mem.eql(u8, tree.tokenSlice(payload), "_")) {4257 if (mem.eql(u8, tree.tokenSlice(payload), "_")) {
4256 return astgen.failTok(payload, "discard of error capture; omit it instead", .{});4258 return astgen.failTok(payload, "discard of error capture; omit it instead", .{});
4257 }4259 }
4258 const err_name = try astgen.identifierTokenString(payload);4260 const err_name = try astgen.identAsString(payload);
4259 err_val_scope = .{4261 err_val_scope = .{
4260 .parent = &then_scope.base,4262 .parent = &then_scope.base,
4261 .gen_zir = &then_scope,4263 .gen_zir = &then_scope,
...@@ -4386,7 +4388,7 @@ pub fn fieldAccess(...@@ -4386,7 +4388,7 @@ pub fn fieldAccess(
4386 const object_node = node_datas[node].lhs;4388 const object_node = node_datas[node].lhs;
4387 const dot_token = main_tokens[node];4389 const dot_token = main_tokens[node];
4388 const field_ident = dot_token + 1;4390 const field_ident = dot_token + 1;
4389 const str_index = try gz.identAsString(field_ident);4391 const str_index = try astgen.identAsString(field_ident);
4390 switch (rl) {4392 switch (rl) {
4391 .ref => return gz.addPlNode(.field_ptr, node, Zir.Inst.Field{4393 .ref => return gz.addPlNode(.field_ptr, node, Zir.Inst.Field{
4392 .lhs = try expr(gz, scope, .ref, object_node),4394 .lhs = try expr(gz, scope, .ref, object_node),
...@@ -4449,7 +4451,8 @@ fn simpleStrTok(...@@ -4449,7 +4451,8 @@ fn simpleStrTok(
4449 node: ast.Node.Index,4451 node: ast.Node.Index,
4450 op_inst_tag: Zir.Inst.Tag,4452 op_inst_tag: Zir.Inst.Tag,
4451) InnerError!Zir.Inst.Ref {4453) InnerError!Zir.Inst.Ref {
4452 const str_index = try gz.identAsString(ident_token);4454 const astgen = gz.astgen;
4455 const str_index = try astgen.identAsString(ident_token);
4453 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);4456 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);
4454 return rvalue(gz, scope, rl, result, node);4457 return rvalue(gz, scope, rl, result, node);
4455}4458}
...@@ -4545,7 +4548,7 @@ fn ifExpr(...@@ -4545,7 +4548,7 @@ fn ifExpr(
4545 else4548 else
4546 .err_union_payload_unsafe;4549 .err_union_payload_unsafe;
4547 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);4550 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
4548 const ident_name = try astgen.identifierTokenString(error_token);4551 const ident_name = try astgen.identAsString(error_token);
4549 payload_val_scope = .{4552 payload_val_scope = .{
4550 .parent = &then_scope.base,4553 .parent = &then_scope.base,
4551 .gen_zir = &then_scope,4554 .gen_zir = &then_scope,
...@@ -4561,7 +4564,7 @@ fn ifExpr(...@@ -4561,7 +4564,7 @@ fn ifExpr(
4561 else4564 else
4562 .optional_payload_unsafe;4565 .optional_payload_unsafe;
4563 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);4566 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
4564 const ident_name = try astgen.identifierTokenString(ident_token);4567 const ident_name = try astgen.identAsString(ident_token);
4565 payload_val_scope = .{4568 payload_val_scope = .{
4566 .parent = &then_scope.base,4569 .parent = &then_scope.base,
4567 .gen_zir = &then_scope,4570 .gen_zir = &then_scope,
...@@ -4597,7 +4600,7 @@ fn ifExpr(...@@ -4597,7 +4600,7 @@ fn ifExpr(
4597 else4600 else
4598 .err_union_code;4601 .err_union_code;
4599 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);4602 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
4600 const ident_name = try astgen.identifierTokenString(error_token);4603 const ident_name = try astgen.identAsString(error_token);
4601 payload_val_scope = .{4604 payload_val_scope = .{
4602 .parent = &else_scope.base,4605 .parent = &else_scope.base,
4603 .gen_zir = &else_scope,4606 .gen_zir = &else_scope,
...@@ -4804,7 +4807,7 @@ fn whileExpr(...@@ -4804,7 +4807,7 @@ fn whileExpr(
4804 else4807 else
4805 .err_union_payload_unsafe;4808 .err_union_payload_unsafe;
4806 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);4809 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
4807 const ident_name = try astgen.identifierTokenString(error_token);4810 const ident_name = try astgen.identAsString(error_token);
4808 payload_val_scope = .{4811 payload_val_scope = .{
4809 .parent = &then_scope.base,4812 .parent = &then_scope.base,
4810 .gen_zir = &then_scope,4813 .gen_zir = &then_scope,
...@@ -4820,7 +4823,7 @@ fn whileExpr(...@@ -4820,7 +4823,7 @@ fn whileExpr(
4820 else4823 else
4821 .optional_payload_unsafe;4824 .optional_payload_unsafe;
4822 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);4825 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
4823 const ident_name = try astgen.identifierTokenString(ident_token);4826 const ident_name = try astgen.identAsString(ident_token);
4824 payload_val_scope = .{4827 payload_val_scope = .{
4825 .parent = &then_scope.base,4828 .parent = &then_scope.base,
4826 .gen_zir = &then_scope,4829 .gen_zir = &then_scope,
...@@ -4853,7 +4856,7 @@ fn whileExpr(...@@ -4853,7 +4856,7 @@ fn whileExpr(
4853 else4856 else
4854 .err_union_code;4857 .err_union_code;
4855 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);4858 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
4856 const ident_name = try astgen.identifierTokenString(error_token);4859 const ident_name = try astgen.identAsString(error_token);
4857 payload_val_scope = .{4860 payload_val_scope = .{
4858 .parent = &else_scope.base,4861 .parent = &else_scope.base,
4859 .gen_zir = &else_scope,4862 .gen_zir = &else_scope,
...@@ -4988,12 +4991,13 @@ fn forExpr(...@@ -4988,12 +4991,13 @@ fn forExpr(
4988 const value_name = tree.tokenSlice(ident);4991 const value_name = tree.tokenSlice(ident);
4989 var payload_sub_scope: *Scope = undefined;4992 var payload_sub_scope: *Scope = undefined;
4990 if (!mem.eql(u8, value_name, "_")) {4993 if (!mem.eql(u8, value_name, "_")) {
4994 const name_str_index = try astgen.identAsString(ident);
4991 const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;4995 const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;
4992 const payload_inst = try then_scope.addBin(tag, array_ptr, index);4996 const payload_inst = try then_scope.addBin(tag, array_ptr, index);
4993 payload_val_scope = .{4997 payload_val_scope = .{
4994 .parent = &then_scope.base,4998 .parent = &then_scope.base,
4995 .gen_zir = &then_scope,4999 .gen_zir = &then_scope,
4996 .name = value_name,5000 .name = name_str_index,
4997 .inst = payload_inst,5001 .inst = payload_inst,
4998 .token_src = ident,5002 .token_src = ident,
4999 };5003 };
...@@ -5011,7 +5015,7 @@ fn forExpr(...@@ -5011,7 +5015,7 @@ fn forExpr(
5011 if (mem.eql(u8, tree.tokenSlice(index_token), "_")) {5015 if (mem.eql(u8, tree.tokenSlice(index_token), "_")) {
5012 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});5016 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});
5013 }5017 }
5014 const index_name = try astgen.identifierTokenString(index_token);5018 const index_name = try astgen.identAsString(index_token);
5015 index_scope = .{5019 index_scope = .{
5016 .parent = payload_sub_scope,5020 .parent = payload_sub_scope,
5017 .gen_zir = &then_scope,5021 .gen_zir = &then_scope,
...@@ -5364,7 +5368,7 @@ fn switchExpr(...@@ -5364,7 +5368,7 @@ fn switchExpr(
5364 .prong_index = undefined,5368 .prong_index = undefined,
5365 } },5369 } },
5366 });5370 });
5367 const capture_name = try astgen.identifierTokenString(payload_token);5371 const capture_name = try astgen.identAsString(payload_token);
5368 capture_val_scope = .{5372 capture_val_scope = .{
5369 .parent = &case_scope.base,5373 .parent = &case_scope.base,
5370 .gen_zir = &case_scope,5374 .gen_zir = &case_scope,
...@@ -5456,7 +5460,7 @@ fn switchExpr(...@@ -5456,7 +5460,7 @@ fn switchExpr(
5456 .prong_index = capture_index,5460 .prong_index = capture_index,
5457 } },5461 } },
5458 });5462 });
5459 const capture_name = try astgen.identifierTokenString(ident);5463 const capture_name = try astgen.identAsString(ident);
5460 capture_val_scope = .{5464 capture_val_scope = .{
5461 .parent = &case_scope.base,5465 .parent = &case_scope.base,
5462 .gen_zir = &case_scope,5466 .gen_zir = &case_scope,
...@@ -5810,7 +5814,7 @@ fn identifier(...@@ -5810,7 +5814,7 @@ fn identifier(
5810 const ident_token = main_tokens[ident];5814 const ident_token = main_tokens[ident];
5811 const ident_name = try astgen.identifierTokenString(ident_token);5815 const ident_name = try astgen.identifierTokenString(ident_token);
5812 if (mem.eql(u8, ident_name, "_")) {5816 if (mem.eql(u8, ident_name, "_")) {
5813 return astgen.failNode(ident, "TODO implement '_' identifier", .{});5817 return astgen.failNode(ident, "'_' may not be used as an identifier", .{});
5814 }5818 }
58155819
5816 if (simple_types.get(ident_name)) |zir_const_ref| {5820 if (simple_types.get(ident_name)) |zir_const_ref| {
...@@ -5845,19 +5849,20 @@ fn identifier(...@@ -5845,19 +5849,20 @@ fn identifier(
5845 }5849 }
58465850
5847 // Local variables, including function parameters.5851 // Local variables, including function parameters.
5852 const name_str_index = try astgen.identAsString(ident_token);
5848 {5853 {
5849 var s = scope;5854 var s = scope;
5850 while (true) switch (s.tag) {5855 while (true) switch (s.tag) {
5851 .local_val => {5856 .local_val => {
5852 const local_val = s.cast(Scope.LocalVal).?;5857 const local_val = s.cast(Scope.LocalVal).?;
5853 if (mem.eql(u8, local_val.name, ident_name)) {5858 if (local_val.name == name_str_index) {
5854 return rvalue(gz, scope, rl, local_val.inst, ident);5859 return rvalue(gz, scope, rl, local_val.inst, ident);
5855 }5860 }
5856 s = local_val.parent;5861 s = local_val.parent;
5857 },5862 },
5858 .local_ptr => {5863 .local_ptr => {
5859 const local_ptr = s.cast(Scope.LocalPtr).?;5864 const local_ptr = s.cast(Scope.LocalPtr).?;
5860 if (mem.eql(u8, local_ptr.name, ident_name)) {5865 if (local_ptr.name == name_str_index) {
5861 switch (rl) {5866 switch (rl) {
5862 .ref, .none_or_ref => return local_ptr.ptr,5867 .ref, .none_or_ref => return local_ptr.ptr,
5863 else => {5868 else => {
...@@ -5876,11 +5881,10 @@ fn identifier(...@@ -5876,11 +5881,10 @@ fn identifier(
5876 // We can't look up Decls until Sema because the same ZIR code is supposed to be5881 // We can't look up Decls until Sema because the same ZIR code is supposed to be
5877 // used for multiple generic instantiations, and this may refer to a different Decl5882 // used for multiple generic instantiations, and this may refer to a different Decl
5878 // depending on the scope, determined by the generic instantiation.5883 // depending on the scope, determined by the generic instantiation.
5879 const str_index = try gz.identAsString(ident_token);
5880 switch (rl) {5884 switch (rl) {
5881 .ref, .none_or_ref => return gz.addStrTok(.decl_ref, str_index, ident_token),5885 .ref, .none_or_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
5882 else => {5886 else => {
5883 const result = try gz.addStrTok(.decl_val, str_index, ident_token);5887 const result = try gz.addStrTok(.decl_val, name_str_index, ident_token);
5884 return rvalue(gz, scope, rl, result, ident);5888 return rvalue(gz, scope, rl, result, ident);
5885 },5889 },
5886 }5890 }
...@@ -5892,10 +5896,11 @@ fn stringLiteral(...@@ -5892,10 +5896,11 @@ fn stringLiteral(
5892 rl: ResultLoc,5896 rl: ResultLoc,
5893 node: ast.Node.Index,5897 node: ast.Node.Index,
5894) InnerError!Zir.Inst.Ref {5898) InnerError!Zir.Inst.Ref {
5895 const tree = gz.astgen.file.tree;5899 const astgen = gz.astgen;
5900 const tree = astgen.file.tree;
5896 const main_tokens = tree.nodes.items(.main_token);5901 const main_tokens = tree.nodes.items(.main_token);
5897 const str_lit_token = main_tokens[node];5902 const str_lit_token = main_tokens[node];
5898 const str = try gz.strLitAsString(str_lit_token);5903 const str = try astgen.strLitAsString(str_lit_token);
5899 const result = try gz.add(.{5904 const result = try gz.add(.{
5900 .tag = .str,5905 .tag = .str,
5901 .data = .{ .str = .{5906 .data = .{ .str = .{
...@@ -6097,9 +6102,9 @@ fn asmExpr(...@@ -6097,9 +6102,9 @@ fn asmExpr(
60976102
6098 for (full.outputs) |output_node, i| {6103 for (full.outputs) |output_node, i| {
6099 const symbolic_name = main_tokens[output_node];6104 const symbolic_name = main_tokens[output_node];
6100 const name = try gz.identAsString(symbolic_name);6105 const name = try astgen.identAsString(symbolic_name);
6101 const constraint_token = symbolic_name + 2;6106 const constraint_token = symbolic_name + 2;
6102 const constraint = (try gz.strLitAsString(constraint_token)).index;6107 const constraint = (try astgen.strLitAsString(constraint_token)).index;
6103 const has_arrow = token_tags[symbolic_name + 4] == .arrow;6108 const has_arrow = token_tags[symbolic_name + 4] == .arrow;
6104 if (has_arrow) {6109 if (has_arrow) {
6105 output_type_bits |= @as(u32, 1) << @intCast(u5, i);6110 output_type_bits |= @as(u32, 1) << @intCast(u5, i);
...@@ -6112,7 +6117,7 @@ fn asmExpr(...@@ -6112,7 +6117,7 @@ fn asmExpr(
6112 };6117 };
6113 } else {6118 } else {
6114 const ident_token = symbolic_name + 4;6119 const ident_token = symbolic_name + 4;
6115 const str_index = try gz.identAsString(ident_token);6120 const str_index = try astgen.identAsString(ident_token);
6116 // TODO this needs extra code for local variables. Have a look at #215 and related6121 // TODO this needs extra code for local variables. Have a look at #215 and related
6117 // issues and decide how to handle outputs. Do we want this to be identifiers?6122 // issues and decide how to handle outputs. Do we want this to be identifiers?
6118 // Or maybe we want to force this to be expressions with a pointer type.6123 // Or maybe we want to force this to be expressions with a pointer type.
...@@ -6134,9 +6139,9 @@ fn asmExpr(...@@ -6134,9 +6139,9 @@ fn asmExpr(
61346139
6135 for (full.inputs) |input_node, i| {6140 for (full.inputs) |input_node, i| {
6136 const symbolic_name = main_tokens[input_node];6141 const symbolic_name = main_tokens[input_node];
6137 const name = try gz.identAsString(symbolic_name);6142 const name = try astgen.identAsString(symbolic_name);
6138 const constraint_token = symbolic_name + 2;6143 const constraint_token = symbolic_name + 2;
6139 const constraint = (try gz.strLitAsString(constraint_token)).index;6144 const constraint = (try astgen.strLitAsString(constraint_token)).index;
6140 const has_arrow = token_tags[symbolic_name + 4] == .arrow;6145 const has_arrow = token_tags[symbolic_name + 4] == .arrow;
6141 const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs);6146 const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs);
6142 inputs[i] = .{6147 inputs[i] = .{
...@@ -6156,7 +6161,7 @@ fn asmExpr(...@@ -6156,7 +6161,7 @@ fn asmExpr(
6156 if (clobber_i >= clobbers_buffer.len) {6161 if (clobber_i >= clobbers_buffer.len) {
6157 return astgen.failTok(tok_i, "too many asm clobbers", .{});6162 return astgen.failTok(tok_i, "too many asm clobbers", .{});
6158 }6163 }
6159 clobbers_buffer[clobber_i] = (try gz.strLitAsString(tok_i)).index;6164 clobbers_buffer[clobber_i] = (try astgen.strLitAsString(tok_i)).index;
6160 clobber_i += 1;6165 clobber_i += 1;
6161 tok_i += 1;6166 tok_i += 1;
6162 switch (token_tags[tok_i]) {6167 switch (token_tags[tok_i]) {
...@@ -6409,7 +6414,7 @@ fn builtinCall(...@@ -6409,7 +6414,7 @@ fn builtinCall(
6409 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});6414 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});
6410 }6415 }
6411 const str_lit_token = main_tokens[operand_node];6416 const str_lit_token = main_tokens[operand_node];
6412 const str = try gz.strLitAsString(str_lit_token);6417 const str = try astgen.strLitAsString(str_lit_token);
6413 try astgen.imports.put(astgen.gpa, str.index, {});6418 try astgen.imports.put(astgen.gpa, str.index, {});
6414 const result = try gz.addStrTok(.import, str.index, str_lit_token);6419 const result = try gz.addStrTok(.import, str.index, str_lit_token);
6415 return rvalue(gz, scope, rl, result, node);6420 return rvalue(gz, scope, rl, result, node);
...@@ -6451,7 +6456,7 @@ fn builtinCall(...@@ -6451,7 +6456,7 @@ fn builtinCall(
6451 return astgen.failNode(params[0], "the first @export parameter must be an identifier", .{});6456 return astgen.failNode(params[0], "the first @export parameter must be an identifier", .{});
6452 }6457 }
6453 const ident_token = main_tokens[params[0]];6458 const ident_token = main_tokens[params[0]];
6454 const decl_name = try gz.identAsString(ident_token);6459 const decl_name = try astgen.identAsString(ident_token);
6455 // TODO look for local variables in scope matching `decl_name` and emit a compile6460 // TODO look for local variables in scope matching `decl_name` and emit a compile
6456 // error. Only top-level declarations can be exported. Until this is done, the6461 // error. Only top-level declarations can be exported. Until this is done, the
6457 // compile error will end up being "use of undeclared identifier" in Sema.6462 // compile error will end up being "use of undeclared identifier" in Sema.
...@@ -7698,3 +7703,57 @@ pub fn errNoteNode(...@@ -7698,3 +7703,57 @@ pub fn errNoteNode(
7698 .notes = 0,7703 .notes = 0,
7699 });7704 });
7700}7705}
7706
7707fn identAsString(astgen: *AstGen, ident_token: ast.TokenIndex) !u32 {
7708 const gpa = astgen.gpa;
7709 const string_bytes = &astgen.string_bytes;
7710 const str_index = @intCast(u32, string_bytes.items.len);
7711 try astgen.appendIdentStr(ident_token, string_bytes);
7712 const key = string_bytes.items[str_index..];
7713 const gop = try astgen.string_table.getOrPut(gpa, key);
7714 if (gop.found_existing) {
7715 string_bytes.shrinkRetainingCapacity(str_index);
7716 return gop.entry.value;
7717 } else {
7718 // We have to dupe the key into the arena, otherwise the memory
7719 // becomes invalidated when string_bytes gets data appended.
7720 // TODO https://github.com/ziglang/zig/issues/8528
7721 gop.entry.key = try astgen.arena.dupe(u8, key);
7722 gop.entry.value = str_index;
7723 try string_bytes.append(gpa, 0);
7724 return str_index;
7725 }
7726}
7727
7728const IndexSlice = struct { index: u32, len: u32 };
7729
7730fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
7731 const gpa = astgen.gpa;
7732 const string_bytes = &astgen.string_bytes;
7733 const str_index = @intCast(u32, string_bytes.items.len);
7734 const token_bytes = astgen.file.tree.tokenSlice(str_lit_token);
7735 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
7736 const key = string_bytes.items[str_index..];
7737 const gop = try astgen.string_table.getOrPut(gpa, key);
7738 if (gop.found_existing) {
7739 string_bytes.shrinkRetainingCapacity(str_index);
7740 return IndexSlice{
7741 .index = gop.entry.value,
7742 .len = @intCast(u32, key.len),
7743 };
7744 } else {
7745 // We have to dupe the key into the arena, otherwise the memory
7746 // becomes invalidated when string_bytes gets data appended.
7747 // TODO https://github.com/ziglang/zig/issues/8528
7748 gop.entry.key = try astgen.arena.dupe(u8, key);
7749 gop.entry.value = str_index;
7750 // Still need a null byte because we are using the same table
7751 // to lookup null terminated strings, so if we get a match, it has to
7752 // be null terminated for that to work.
7753 try string_bytes.append(gpa, 0);
7754 return IndexSlice{
7755 .index = str_index,
7756 .len = @intCast(u32, key.len),
7757 };
7758 }
7759}
src/Module.zig+18-73
...@@ -1356,62 +1356,6 @@ pub const Scope = struct {...@@ -1356,62 +1356,6 @@ pub const Scope = struct {
1356 }1356 }
1357 }1357 }
13581358
1359 pub fn identAsString(gz: *GenZir, ident_token: ast.TokenIndex) !u32 {
1360 const astgen = gz.astgen;
1361 const gpa = astgen.gpa;
1362 const string_bytes = &astgen.string_bytes;
1363 const str_index = @intCast(u32, string_bytes.items.len);
1364 try astgen.appendIdentStr(ident_token, string_bytes);
1365 const key = string_bytes.items[str_index..];
1366 const gop = try astgen.string_table.getOrPut(gpa, key);
1367 if (gop.found_existing) {
1368 string_bytes.shrinkRetainingCapacity(str_index);
1369 return gop.entry.value;
1370 } else {
1371 // We have to dupe the key into the arena, otherwise the memory
1372 // becomes invalidated when string_bytes gets data appended.
1373 // TODO https://github.com/ziglang/zig/issues/8528
1374 gop.entry.key = try astgen.arena.dupe(u8, key);
1375 gop.entry.value = str_index;
1376 try string_bytes.append(gpa, 0);
1377 return str_index;
1378 }
1379 }
1380
1381 pub const IndexSlice = struct { index: u32, len: u32 };
1382
1383 pub fn strLitAsString(gz: *GenZir, str_lit_token: ast.TokenIndex) !IndexSlice {
1384 const astgen = gz.astgen;
1385 const gpa = astgen.gpa;
1386 const string_bytes = &astgen.string_bytes;
1387 const str_index = @intCast(u32, string_bytes.items.len);
1388 const token_bytes = astgen.file.tree.tokenSlice(str_lit_token);
1389 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
1390 const key = string_bytes.items[str_index..];
1391 const gop = try astgen.string_table.getOrPut(gpa, key);
1392 if (gop.found_existing) {
1393 string_bytes.shrinkRetainingCapacity(str_index);
1394 return IndexSlice{
1395 .index = gop.entry.value,
1396 .len = @intCast(u32, key.len),
1397 };
1398 } else {
1399 // We have to dupe the key into the arena, otherwise the memory
1400 // becomes invalidated when string_bytes gets data appended.
1401 // TODO https://github.com/ziglang/zig/issues/8528
1402 gop.entry.key = try astgen.arena.dupe(u8, key);
1403 gop.entry.value = str_index;
1404 // Still need a null byte because we are using the same table
1405 // to lookup null terminated strings, so if we get a match, it has to
1406 // be null terminated for that to work.
1407 try string_bytes.append(gpa, 0);
1408 return IndexSlice{
1409 .index = str_index,
1410 .len = @intCast(u32, key.len),
1411 };
1412 }
1413 }
1414
1415 pub fn addFunc(gz: *GenZir, args: struct {1359 pub fn addFunc(gz: *GenZir, args: struct {
1416 src_node: ast.Node.Index,1360 src_node: ast.Node.Index,
1417 param_types: []const Zir.Inst.Ref,1361 param_types: []const Zir.Inst.Ref,
...@@ -2053,10 +1997,11 @@ pub const Scope = struct {...@@ -2053,10 +1997,11 @@ pub const Scope = struct {
2053 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.1997 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
2054 parent: *Scope,1998 parent: *Scope,
2055 gen_zir: *GenZir,1999 gen_zir: *GenZir,
2056 name: []const u8,
2057 inst: Zir.Inst.Ref,2000 inst: Zir.Inst.Ref,
2058 /// Source location of the corresponding variable declaration.2001 /// Source location of the corresponding variable declaration.
2059 token_src: ast.TokenIndex,2002 token_src: ast.TokenIndex,
2003 /// String table index.
2004 name: u32,
2060 };2005 };
20612006
2062 /// This could be a `const` or `var` local. It has a pointer instead of a value.2007 /// This could be a `const` or `var` local. It has a pointer instead of a value.
...@@ -2068,10 +2013,11 @@ pub const Scope = struct {...@@ -2068,10 +2013,11 @@ pub const Scope = struct {
2068 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.2013 /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`.
2069 parent: *Scope,2014 parent: *Scope,
2070 gen_zir: *GenZir,2015 gen_zir: *GenZir,
2071 name: []const u8,
2072 ptr: Zir.Inst.Ref,2016 ptr: Zir.Inst.Ref,
2073 /// Source location of the corresponding variable declaration.2017 /// Source location of the corresponding variable declaration.
2074 token_src: ast.TokenIndex,2018 token_src: ast.TokenIndex,
2019 /// String table index.
2020 name: u32,
2075 };2021 };
20762022
2077 pub const Defer = struct {2023 pub const Defer = struct {
...@@ -4026,27 +3972,26 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {...@@ -4026,27 +3972,26 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !void {
4026 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());3972 const param_inst_list = try mod.gpa.alloc(*ir.Inst, fn_ty.fnParamLen());
4027 defer mod.gpa.free(param_inst_list);3973 defer mod.gpa.free(param_inst_list);
40283974
3975 for (param_inst_list) |*param_inst, param_index| {
3976 const param_type = fn_ty.fnParamType(param_index);
3977 const arg_inst = try arena.allocator.create(ir.Inst.Arg);
3978 arg_inst.* = .{
3979 .base = .{
3980 .tag = .arg,
3981 .ty = param_type,
3982 .src = .unneeded,
3983 },
3984 .name = undefined, // Set in the semantic analysis of the arg instruction.
3985 };
3986 param_inst.* = &arg_inst.base;
3987 }
3988
4029 var f = false;3989 var f = false;
4030 if (f) {3990 if (f) {
4031 return error.AnalysisFail;3991 return error.AnalysisFail;
4032 }3992 }
4033 @panic("TODO reimplement analyzeFnBody now that ZIR is whole-file");3993 @panic("TODO reimplement analyzeFnBody now that ZIR is whole-file");
40343994
4035 //for (param_inst_list) |*param_inst, param_index| {
4036 // const param_type = fn_ty.fnParamType(param_index);
4037 // const name = func.zir.nullTerminatedString(func.zir.extra[param_index]);
4038 // const arg_inst = try arena.allocator.create(ir.Inst.Arg);
4039 // arg_inst.* = .{
4040 // .base = .{
4041 // .tag = .arg,
4042 // .ty = param_type,
4043 // .src = .unneeded,
4044 // },
4045 // .name = name,
4046 // };
4047 // param_inst.* = &arg_inst.base;
4048 //}
4049
4050 //var sema: Sema = .{3995 //var sema: Sema = .{
4051 // .mod = mod,3996 // .mod = mod,
4052 // .gpa = mod.gpa,3997 // .gpa = mod.gpa,
src/Sema.zig+26-11
...@@ -40,6 +40,7 @@ branch_count: u32 = 0,...@@ -40,6 +40,7 @@ branch_count: u32 = 0,
40/// access to the source location set by the previous instruction which did40/// access to the source location set by the previous instruction which did
41/// contain a mapped source location.41/// contain a mapped source location.
42src: LazySrcLoc = .{ .token_offset = 0 },42src: LazySrcLoc = .{ .token_offset = 0 },
43next_arg_index: usize = 0,
4344
44const std = @import("std");45const std = @import("std");
45const mem = std.mem;46const mem = std.mem;
...@@ -110,6 +111,7 @@ pub fn analyzeBody(...@@ -110,6 +111,7 @@ pub fn analyzeBody(
110 const inst = body[i];111 const inst = body[i];
111 map[inst] = switch (tags[inst]) {112 map[inst] = switch (tags[inst]) {
112 // zig fmt: off113 // zig fmt: off
114 .arg => try sema.zirArg(block, inst),
113 .alloc => try sema.zirAlloc(block, inst),115 .alloc => try sema.zirAlloc(block, inst),
114 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),116 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
115 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),117 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
...@@ -521,12 +523,6 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.In...@@ -521,12 +523,6 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.In
521 }523 }
522 i -= Zir.Inst.Ref.typed_value_map.len;524 i -= Zir.Inst.Ref.typed_value_map.len;
523525
524 // Next section of indexes correspond to function parameters, if any.
525 if (i < sema.param_inst_list.len) {
526 return sema.param_inst_list[i];
527 }
528 i -= sema.param_inst_list.len;
529
530 // Finally, the last section of indexes refers to the map of ZIR=>AIR.526 // Finally, the last section of indexes refers to the map of ZIR=>AIR.
531 return sema.inst_map[i];527 return sema.inst_map[i];
532}528}
...@@ -1110,6 +1106,25 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In...@@ -1110,6 +1106,25 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
1110 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);1106 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
1111}1107}
11121108
1109fn zirArg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1110 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
1111 const src = inst_data.src();
1112 const arg_name = inst_data.get(sema.code);
1113 const arg_index = sema.next_arg_index;
1114 sema.next_arg_index += 1;
1115
1116 // TODO check if arg_name shadows a Decl
1117
1118 if (block.inlining) |inlining| {
1119 return sema.param_inst_list[arg_index];
1120 }
1121
1122 // Need to set the name of the Air.Arg instruction.
1123 const air_arg = sema.param_inst_list[arg_index].castTag(.arg).?;
1124 air_arg.name = arg_name;
1125 return &air_arg.base;
1126}
1127
1113fn zirAllocExtended(1128fn zirAllocExtended(
1114 sema: *Sema,1129 sema: *Sema,
1115 block: *Scope.Block,1130 block: *Scope.Block,
...@@ -2038,15 +2053,13 @@ fn analyzeCall(...@@ -2038,15 +2053,13 @@ fn analyzeCall(
2038 .block_inst = block_inst,2053 .block_inst = block_inst,
2039 },2054 },
2040 };2055 };
2041 if (true) {2056 const callee_zir = module_fn.owner_decl.namespace.file_scope.zir;
2042 @panic("TODO reimplement inline fn call after whole-file astgen");
2043 }
2044 var inline_sema: Sema = .{2057 var inline_sema: Sema = .{
2045 .mod = sema.mod,2058 .mod = sema.mod,
2046 .gpa = sema.mod.gpa,2059 .gpa = sema.mod.gpa,
2047 .arena = sema.arena,2060 .arena = sema.arena,
2048 .code = module_fn.zir,2061 .code = callee_zir,
2049 .inst_map = try sema.gpa.alloc(*ir.Inst, module_fn.zir.instructions.len),2062 .inst_map = try sema.gpa.alloc(*ir.Inst, callee_zir.instructions.len),
2050 .owner_decl = sema.owner_decl,2063 .owner_decl = sema.owner_decl,
2051 .namespace = sema.owner_decl.namespace,2064 .namespace = sema.owner_decl.namespace,
2052 .owner_func = sema.owner_func,2065 .owner_func = sema.owner_func,
...@@ -2075,6 +2088,8 @@ fn analyzeCall(...@@ -2075,6 +2088,8 @@ fn analyzeCall(
20752088
2076 try inline_sema.emitBackwardBranch(&child_block, call_src);2089 try inline_sema.emitBackwardBranch(&child_block, call_src);
20772090
2091 if (true) @panic("TODO re-implement inline function calls");
2092
2078 // This will have return instructions analyzed as break instructions to2093 // This will have return instructions analyzed as break instructions to
2079 // the block_inst above.2094 // the block_inst above.
2080 _ = try inline_sema.root(&child_block);2095 _ = try inline_sema.root(&child_block);
src/Zir.zig+12-19
...@@ -124,7 +124,6 @@ pub fn renderAsTextToFile(...@@ -124,7 +124,6 @@ pub fn renderAsTextToFile(
124 .code = scope_file.zir,124 .code = scope_file.zir,
125 .indent = 0,125 .indent = 0,
126 .parent_decl_node = 0,126 .parent_decl_node = 0,
127 .param_count = 0,
128 };127 };
129128
130 const main_struct_inst = scope_file.zir.extra[@enumToInt(ExtraIndex.main_struct)] -129 const main_struct_inst = scope_file.zir.extra[@enumToInt(ExtraIndex.main_struct)] -
...@@ -159,6 +158,11 @@ pub const Inst = struct {...@@ -159,6 +158,11 @@ pub const Inst = struct {
159 /// Twos complement wrapping integer addition.158 /// Twos complement wrapping integer addition.
160 /// Uses the `pl_node` union field. Payload is `Bin`.159 /// Uses the `pl_node` union field. Payload is `Bin`.
161 addwrap,160 addwrap,
161 /// Declares a parameter of the current function. Used for debug info and
162 /// for checking shadowing against declarations in the current namespace.
163 /// Uses the `str_tok` field. Token is the parameter name, string is the
164 /// parameter name.
165 arg,
162 /// Array concatenation. `a ++ b`166 /// Array concatenation. `a ++ b`
163 /// Uses the `pl_node` union field. Payload is `Bin`.167 /// Uses the `pl_node` union field. Payload is `Bin`.
164 array_cat,168 array_cat,
...@@ -956,6 +960,7 @@ pub const Inst = struct {...@@ -956,6 +960,7 @@ pub const Inst = struct {
956 /// Function calls do not count.960 /// Function calls do not count.
957 pub fn isNoReturn(tag: Tag) bool {961 pub fn isNoReturn(tag: Tag) bool {
958 return switch (tag) {962 return switch (tag) {
963 .arg,
959 .add,964 .add,
960 .addwrap,965 .addwrap,
961 .alloc,966 .alloc,
...@@ -1220,6 +1225,7 @@ pub const Inst = struct {...@@ -1220,6 +1225,7 @@ pub const Inst = struct {
1220 break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{1225 break :list std.enums.directEnumArray(Tag, Data.FieldEnum, 0, .{
1221 .add = .pl_node,1226 .add = .pl_node,
1222 .addwrap = .pl_node,1227 .addwrap = .pl_node,
1228 .arg = .str_tok,
1223 .array_cat = .pl_node,1229 .array_cat = .pl_node,
1224 .array_mul = .pl_node,1230 .array_mul = .pl_node,
1225 .array_type = .bin,1231 .array_type = .bin,
...@@ -1587,20 +1593,15 @@ pub const Inst = struct {...@@ -1587,20 +1593,15 @@ pub const Inst = struct {
1587 /// The position of a ZIR instruction within the `Zir` instructions array.1593 /// The position of a ZIR instruction within the `Zir` instructions array.
1588 pub const Index = u32;1594 pub const Index = u32;
15891595
1590 /// A reference to a TypedValue, parameter of the current function,1596 /// A reference to a TypedValue or ZIR instruction.
1591 /// or ZIR instruction.
1592 ///1597 ///
1593 /// If the Ref has a tag in this enum, it refers to a TypedValue which may be1598 /// If the Ref has a tag in this enum, it refers to a TypedValue which may be
1594 /// retrieved with Ref.toTypedValue().1599 /// retrieved with Ref.toTypedValue().
1595 ///1600 ///
1596 /// If the value of a Ref does not have a tag, it referes to either a parameter1601 /// If the value of a Ref does not have a tag, it refers to a ZIR instruction.
1597 /// of the current function or a ZIR instruction.
1598 ///1602 ///
1599 /// The first values after the the last tag refer to parameters which may be1603 /// The first values after the the last tag refer to ZIR instructions which may
1600 /// derived by subtracting typed_value_map.len.1604 /// be derived by subtracting `typed_value_map.len`.
1601 ///
1602 /// All further values refer to ZIR instructions which may be derived by
1603 /// subtracting typed_value_map.len and the number of parameters.
1604 ///1605 ///
1605 /// When adding a tag to this enum, consider adding a corresponding entry to1606 /// When adding a tag to this enum, consider adding a corresponding entry to
1606 /// `simple_types` in astgen.1607 /// `simple_types` in astgen.
...@@ -2697,7 +2698,6 @@ const Writer = struct {...@@ -2697,7 +2698,6 @@ const Writer = struct {
2697 code: Zir,2698 code: Zir,
2698 indent: u32,2699 indent: u32,
2699 parent_decl_node: u32,2700 parent_decl_node: u32,
2700 param_count: usize,
27012701
2702 fn relativeToNodeIndex(self: *Writer, offset: i32) ast.Node.Index {2702 fn relativeToNodeIndex(self: *Writer, offset: i32) ast.Node.Index {
2703 return @bitCast(ast.Node.Index, offset + @bitCast(i32, self.parent_decl_node));2703 return @bitCast(ast.Node.Index, offset + @bitCast(i32, self.parent_decl_node));
...@@ -2991,6 +2991,7 @@ const Writer = struct {...@@ -2991,6 +2991,7 @@ const Writer = struct {
2991 .decl_ref,2991 .decl_ref,
2992 .decl_val,2992 .decl_val,
2993 .import,2993 .import,
2994 .arg,
2994 => try self.writeStrTok(stream, inst),2995 => try self.writeStrTok(stream, inst),
29952996
2996 .func => try self.writeFunc(stream, inst, false),2997 .func => try self.writeFunc(stream, inst, false),
...@@ -4128,10 +4129,7 @@ const Writer = struct {...@@ -4128,10 +4129,7 @@ const Writer = struct {
4128 } else {4129 } else {
4129 try stream.writeAll(", {\n");4130 try stream.writeAll(", {\n");
4130 self.indent += 2;4131 self.indent += 2;
4131 const prev_param_count = self.param_count;
4132 self.param_count = param_types.len;
4133 try self.writeBody(stream, body);4132 try self.writeBody(stream, body);
4134 self.param_count = prev_param_count;
4135 self.indent -= 2;4133 self.indent -= 2;
4136 try stream.writeByteNTimes(' ', self.indent);4134 try stream.writeByteNTimes(' ', self.indent);
4137 try stream.writeAll("}) ");4135 try stream.writeAll("}) ");
...@@ -4153,11 +4151,6 @@ const Writer = struct {...@@ -4153,11 +4151,6 @@ const Writer = struct {
4153 }4151 }
4154 i -= Inst.Ref.typed_value_map.len;4152 i -= Inst.Ref.typed_value_map.len;
41554153
4156 if (i < self.param_count) {
4157 return stream.print("${d}", .{i});
4158 }
4159 i -= self.param_count;
4160
4161 return self.writeInstIndex(stream, @intCast(Inst.Index, i));4154 return self.writeInstIndex(stream, @intCast(Inst.Index, i));
4162 }4155 }
41634156