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...@@ -984,17 +984,17 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
984984
985 .fn_proto_simple => {985 .fn_proto_simple => {
986 var params: [1]Ast.Node.Index = undefined;986 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));
988 },988 },
989 .fn_proto_multi => {989 .fn_proto_multi => {
990 return fnProtoExpr(gz, scope, rl, tree.fnProtoMulti(node));990 return fnProtoExpr(gz, scope, rl, node, tree.fnProtoMulti(node));
991 },991 },
992 .fn_proto_one => {992 .fn_proto_one => {
993 var params: [1]Ast.Node.Index = undefined;993 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));
995 },995 },
996 .fn_proto => {996 .fn_proto => {
997 return fnProtoExpr(gz, scope, rl, tree.fnProto(node));997 return fnProtoExpr(gz, scope, rl, node, tree.fnProto(node));
998 },998 },
999 }999 }
1000}1000}
...@@ -1101,6 +1101,7 @@ fn fnProtoExpr(...@@ -1101,6 +1101,7 @@ fn fnProtoExpr(
1101 gz: *GenZir,1101 gz: *GenZir,
1102 scope: *Scope,1102 scope: *Scope,
1103 rl: ResultLoc,1103 rl: ResultLoc,
1104 node: Ast.Node.Index,
1104 fn_proto: Ast.full.FnProto,1105 fn_proto: Ast.full.FnProto,
1105) InnerError!Zir.Inst.Ref {1106) InnerError!Zir.Inst.Ref {
1106 const astgen = gz.astgen;1107 const astgen = gz.astgen;
...@@ -1113,6 +1114,11 @@ fn fnProtoExpr(...@@ -1113,6 +1114,11 @@ fn fnProtoExpr(
1113 };1114 };
1114 assert(!is_extern);1115 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
1116 const is_var_args = is_var_args: {1122 const is_var_args = is_var_args: {
1117 var param_type_i: usize = 0;1123 var param_type_i: usize = 0;
1118 var it = fn_proto.iterate(tree.*);1124 var it = fn_proto.iterate(tree.*);
...@@ -1144,11 +1150,11 @@ fn fnProtoExpr(...@@ -1144,11 +1150,11 @@ fn fnProtoExpr(
1144 .param_anytype_comptime1150 .param_anytype_comptime
1145 else1151 else
1146 .param_anytype;1152 .param_anytype;
1147 _ = try gz.addStrTok(tag, param_name, name_token);1153 _ = try block_scope.addStrTok(tag, param_name, name_token);
1148 } else {1154 } else {
1149 const param_type_node = param.type_expr;1155 const param_type_node = param.type_expr;
1150 assert(param_type_node != 0);1156 assert(param_type_node != 0);
1151 var param_gz = gz.makeSubBlock(scope);1157 var param_gz = block_scope.makeSubBlock(scope);
1152 defer param_gz.unstack();1158 defer param_gz.unstack();
1153 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);1159 const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node);
1154 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);1160 const param_inst_expected = @intCast(u32, astgen.instructions.len + 1);
...@@ -1156,7 +1162,7 @@ fn fnProtoExpr(...@@ -1156,7 +1162,7 @@ fn fnProtoExpr(
1156 const main_tokens = tree.nodes.items(.main_token);1162 const main_tokens = tree.nodes.items(.main_token);
1157 const name_token = param.name_token orelse main_tokens[param_type_node];1163 const name_token = param.name_token orelse main_tokens[param_type_node];
1158 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;1164 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);
1160 assert(param_inst_expected == param_inst);1166 assert(param_inst_expected == param_inst);
1161 }1167 }
1162 }1168 }
...@@ -1164,7 +1170,7 @@ fn fnProtoExpr(...@@ -1164,7 +1170,7 @@ fn fnProtoExpr(
1164 };1170 };
11651171
1166 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {1172 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);
1168 };1174 };
11691175
1170 if (fn_proto.ast.addrspace_expr != 0) {1176 if (fn_proto.ast.addrspace_expr != 0) {
...@@ -1177,7 +1183,7 @@ fn fnProtoExpr(...@@ -1177,7 +1183,7 @@ fn fnProtoExpr(
11771183
1178 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)1184 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
1179 try expr(1185 try expr(
1180 gz,1186 &block_scope,
1181 scope,1187 scope,
1182 .{ .ty = .calling_convention_type },1188 .{ .ty = .calling_convention_type },
1183 fn_proto.ast.callconv_expr,1189 fn_proto.ast.callconv_expr,
...@@ -1190,14 +1196,14 @@ fn fnProtoExpr(...@@ -1190,14 +1196,14 @@ fn fnProtoExpr(
1190 if (is_inferred_error) {1196 if (is_inferred_error) {
1191 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});1197 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
1192 }1198 }
1193 var ret_gz = gz.makeSubBlock(scope);1199 var ret_gz = block_scope.makeSubBlock(scope);
1194 defer ret_gz.unstack();1200 defer ret_gz.unstack();
1195 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);1201 const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type);
1196 const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty);1202 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(.{
1199 .src_node = fn_proto.ast.proto_node,1205 .src_node = fn_proto.ast.proto_node,
1200 .param_block = 0,1206 .param_block = block_inst,
1201 .ret_gz = &ret_gz,1207 .ret_gz = &ret_gz,
1202 .ret_br = ret_br,1208 .ret_br = ret_br,
1203 .body_gz = null,1209 .body_gz = null,
...@@ -1209,7 +1215,12 @@ fn fnProtoExpr(...@@ -1209,7 +1215,12 @@ fn fnProtoExpr(
1209 .is_test = false,1215 .is_test = false,
1210 .is_extern = false,1216 .is_extern = false,
1211 });1217 });
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);
1213}1224}
12141225
1215fn arrayInitExpr(1226fn arrayInitExpr(