authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-12-17 18:44:39+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-12-21 01:41:50+01:00
loge18c3f3109cffa76e4369c810f82d36eb02c56af
tree299eed669838fa6a254bb36765afe23baa855168
parent993197cd868f312d19ab694dd3a5250e39077f67

stage2: wrap function prototypes in an inline block.

Previously, function parameter instructions for function prototypes would be generated in the parent block. This caused issues in blocks where multiple prototypes would be generated in, such as the block for struct fields for example. This change introduces an inline block around every prototype such that all parameters for a prototype are confined to a unique block.

1 files changed, 24 insertions(+), 13 deletions(-)

src/AstGen.zig+24-13
......@@ -984,17 +984,17 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
984984
985985 .fn_proto_simple => {
986986 var params: [1]Ast.Node.Index = undefined;
987 return fnProtoExpr(gz, scope, rl, tree.fnProtoSimple(&params, node));
987 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoSimple(&params, node));
988988 },
989989 .fn_proto_multi => {
990 return fnProtoExpr(gz, scope, rl, tree.fnProtoMulti(node));
990 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoMulti(node));
991991 },
992992 .fn_proto_one => {
993993 var params: [1]Ast.Node.Index = undefined;
994 return fnProtoExpr(gz, scope, rl, tree.fnProtoOne(&params, node));
994 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoOne(&params, node));
995995 },
996996 .fn_proto => {
997 return fnProtoExpr(gz, scope, rl, tree.fnProto(node));
997 return fnProtoExpr(gz, scope, rl, node, tree.fnProto(node));
998998 },
999999 }
10001000}
......@@ -1101,6 +1101,7 @@ fn fnProtoExpr(
11011101 gz: *GenZir,
11021102 scope: *Scope,
11031103 rl: ResultLoc,
1104 node: Ast.Node.Index,
11041105 fn_proto: Ast.full.FnProto,
11051106) InnerError!Zir.Inst.Ref {
11061107 const astgen = gz.astgen;
......@@ -1113,6 +1114,11 @@ fn fnProtoExpr(
11131114 };
11141115 assert(!is_extern);
11151116
1117 var block_scope = gz.makeSubBlock(scope);
1118 defer block_scope.unstack();
1119
1120 const block_inst = try gz.makeBlockInst(.block_inline, node);
1121
11161122 const is_var_args = is_var_args: {
11171123 var param_type_i: usize = 0;
11181124 var it = fn_proto.iterate(tree.*);
......@@ -1144,11 +1150,11 @@ fn fnProtoExpr(
11441150 .param_anytype_comptime
11451151 else
11461152 .param_anytype;
1147 _ = try gz.addStrTok(tag, param_name, name_token);
1153 _ = try block_scope.addStrTok(tag, param_name, name_token);
11481154 } else {
11491155 const param_type_node = param.type_expr;
11501156 assert(param_type_node != 0);
1151 var param_gz = gz.makeSubBlock(scope);
1157 var param_gz = block_scope.makeSubBlock(scope);
11521158 defer param_gz.unstack();
11531159 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);
11541160 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
......@@ -1156,7 +1162,7 @@ fn fnProtoExpr(
11561162 const main_tokens = tree.nodes.items(.main_token);
11571163 const name_token = param.name_token orelse main_tokens[param_type_node];
11581164 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
1159 const param_inst = try gz.addParam(&param_gz, tag, name_token, param_name);
1165 const param_inst = try block_scope.addParam(&param_gz, tag, name_token, param_name);
11601166 assert(param_inst_expected == param_inst);
11611167 }
11621168 }
......@@ -1164,7 +1170,7 @@ fn fnProtoExpr(
11641170 };
11651171
11661172 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
1167 break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr);
1173 break :inst try expr(&block_scope, scope, align_rl, fn_proto.ast.align_expr);
11681174 };
11691175
11701176 if (fn_proto.ast.addrspace_expr != 0) {
......@@ -1177,7 +1183,7 @@ fn fnProtoExpr(
11771183
11781184 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
11791185 try expr(
1180 gz,
1186 &block_scope,
11811187 scope,
11821188 .{ .ty = .calling_convention_type },
11831189 fn_proto.ast.callconv_expr,
......@@ -1190,14 +1196,14 @@ fn fnProtoExpr(
11901196 if (is_inferred_error) {
11911197 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
11921198 }
1193 var ret_gz = gz.makeSubBlock(scope);
1199 var ret_gz = block_scope.makeSubBlock(scope);
11941200 defer ret_gz.unstack();
11951201 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
11961202 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);
11971203
1198 const result = try gz.addFunc(.{
1204 const result = try block_scope.addFunc(.{
11991205 .src_node = fn_proto.ast.proto_node,
1200 .param_block = 0,
1206 .param_block = block_inst,
12011207 .ret_gz = &ret_gz,
12021208 .ret_br = ret_br,
12031209 .body_gz = null,
......@@ -1209,7 +1215,12 @@ fn fnProtoExpr(
12091215 .is_test = false,
12101216 .is_extern = false,
12111217 });
1212 return rvalue(gz, rl, result, fn_proto.ast.proto_node);
1218
1219 _ = try block_scope.addBreak(.break_inline, block_inst, result);
1220 try block_scope.setBlockBody(block_inst);
1221 try gz.instructions.append(astgen.gpa, block_inst);
1222
1223 return rvalue(gz, rl, indexToRef(block_inst), fn_proto.ast.proto_node);
12131224}
12141225
12151226fn arrayInitExpr(