authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-23 23:40:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-23 23:40:10-07:00
log27fa4bc2bead4635038c06f8c1231cbc81674c2f
tree8456e2725136e0bb3baeb6160ca5958a6aac0b29
parentd2b06c2612fd3bf6d798373228d546c41ad76622

AstGen: support struct init with ref result location


3 files changed, 69 insertions(+), 31 deletions(-)

src/AstGen.zig+52-26
...@@ -1300,40 +1300,28 @@ pub fn structInitExpr(...@@ -1300,40 +1300,28 @@ pub fn structInitExpr(
1300 }1300 }
1301 return Zir.Inst.Ref.void_value;1301 return Zir.Inst.Ref.void_value;
1302 },1302 },
1303 .none, .none_or_ref => {1303 .ref => {
1304 if (struct_init.ast.type_expr != 0) {1304 if (struct_init.ast.type_expr != 0) {
1305 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1305 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1306 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst);1306 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init_ref);
1307 }1307 } else {
1308 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);1308 return structInitExprRlNone(gz, scope, rl, node, struct_init, .struct_init_anon_ref);
1309 defer gpa.free(fields_list);
1310
1311 for (struct_init.ast.fields) |field_init, i| {
1312 const name_token = tree.firstToken(field_init) - 2;
1313 const str_index = try gz.identAsString(name_token);
1314
1315 fields_list[i] = .{
1316 .field_name = str_index,
1317 .init = try expr(gz, scope, .none, field_init),
1318 };
1319 }1309 }
1320 const init_inst = try gz.addPlNode(.struct_init_anon, node, Zir.Inst.StructInitAnon{1310 },
1321 .fields_len = @intCast(u32, fields_list.len),1311 .none, .none_or_ref => {
1322 });1312 if (struct_init.ast.type_expr != 0) {
1323 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +1313 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1324 fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len);1314 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init);
1325 for (fields_list) |field| {1315 } else {
1326 _ = gz.astgen.addExtraAssumeCapacity(field);1316 return structInitExprRlNone(gz, scope, rl, node, struct_init, .struct_init_anon);
1327 }1317 }
1328 return init_inst;
1329 },1318 },
1330 .ref => return astgen.failNode(node, "cannot take address of struct literal", .{}),
1331 .ty => |ty_inst| {1319 .ty => |ty_inst| {
1332 if (struct_init.ast.type_expr == 0) {1320 if (struct_init.ast.type_expr == 0) {
1333 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst);1321 return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init);
1334 }1322 }
1335 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1323 const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1336 const result = try structInitExprRlTy(gz, scope, rl, node, struct_init, inner_ty_inst);1324 const result = try structInitExprRlTy(gz, scope, rl, node, struct_init, inner_ty_inst, .struct_init);
1337 return rvalue(gz, scope, rl, result, node);1325 return rvalue(gz, scope, rl, result, node);
1338 },1326 },
1339 .ptr, .inferred_ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst),1327 .ptr, .inferred_ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst),
...@@ -1341,6 +1329,41 @@ pub fn structInitExpr(...@@ -1341,6 +1329,41 @@ pub fn structInitExpr(
1341 }1329 }
1342}1330}
13431331
1332pub fn structInitExprRlNone(
1333 gz: *GenZir,
1334 scope: *Scope,
1335 rl: ResultLoc,
1336 node: ast.Node.Index,
1337 struct_init: ast.full.StructInit,
1338 tag: Zir.Inst.Tag,
1339) InnerError!Zir.Inst.Ref {
1340 const astgen = gz.astgen;
1341 const gpa = astgen.gpa;
1342 const tree = &astgen.file.tree;
1343
1344 const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len);
1345 defer gpa.free(fields_list);
1346
1347 for (struct_init.ast.fields) |field_init, i| {
1348 const name_token = tree.firstToken(field_init) - 2;
1349 const str_index = try gz.identAsString(name_token);
1350
1351 fields_list[i] = .{
1352 .field_name = str_index,
1353 .init = try expr(gz, scope, .none, field_init),
1354 };
1355 }
1356 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{
1357 .fields_len = @intCast(u32, fields_list.len),
1358 });
1359 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
1360 fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len);
1361 for (fields_list) |field| {
1362 _ = gz.astgen.addExtraAssumeCapacity(field);
1363 }
1364 return init_inst;
1365}
1366
1344pub fn structInitExprRlPtr(1367pub fn structInitExprRlPtr(
1345 gz: *GenZir,1368 gz: *GenZir,
1346 scope: *Scope,1369 scope: *Scope,
...@@ -1380,6 +1403,7 @@ pub fn structInitExprRlTy(...@@ -1380,6 +1403,7 @@ pub fn structInitExprRlTy(
1380 node: ast.Node.Index,1403 node: ast.Node.Index,
1381 struct_init: ast.full.StructInit,1404 struct_init: ast.full.StructInit,
1382 ty_inst: Zir.Inst.Ref,1405 ty_inst: Zir.Inst.Ref,
1406 tag: Zir.Inst.Tag,
1383) InnerError!Zir.Inst.Ref {1407) InnerError!Zir.Inst.Ref {
1384 const astgen = gz.astgen;1408 const astgen = gz.astgen;
1385 const gpa = astgen.gpa;1409 const gpa = astgen.gpa;
...@@ -1401,7 +1425,7 @@ pub fn structInitExprRlTy(...@@ -1401,7 +1425,7 @@ pub fn structInitExprRlTy(
1401 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),1425 .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),
1402 };1426 };
1403 }1427 }
1404 const init_inst = try gz.addPlNode(.struct_init, node, Zir.Inst.StructInit{1428 const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{
1405 .fields_len = @intCast(u32, fields_list.len),1429 .fields_len = @intCast(u32, fields_list.len),
1406 });1430 });
1407 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +1431 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
...@@ -1886,7 +1910,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1886,7 +1910,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1886 .switch_capture_else_ref,1910 .switch_capture_else_ref,
1887 .struct_init_empty,1911 .struct_init_empty,
1888 .struct_init,1912 .struct_init,
1913 .struct_init_ref,
1889 .struct_init_anon,1914 .struct_init_anon,
1915 .struct_init_anon_ref,
1890 .array_init,1916 .array_init,
1891 .array_init_anon,1917 .array_init_anon,
1892 .array_init_ref,1918 .array_init_ref,
src/Sema.zig+7-5
...@@ -256,11 +256,13 @@ pub fn analyzeBody(...@@ -256,11 +256,13 @@ pub fn analyzeBody(
256 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),256 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
257 .xor => try sema.zirBitwise(block, inst, .xor),257 .xor => try sema.zirBitwise(block, inst, .xor),
258 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),258 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),
259 .struct_init => try sema.zirStructInit(block, inst),259 .struct_init => try sema.zirStructInit(block, inst, false),
260 .struct_init_anon => try sema.zirStructInitAnon(block, inst),260 .struct_init_ref => try sema.zirStructInit(block, inst, true),
261 .struct_init_anon => try sema.zirStructInitAnon(block, inst, false),
262 .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true),
261 .array_init => try sema.zirArrayInit(block, inst, false),263 .array_init => try sema.zirArrayInit(block, inst, false),
262 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
263 .array_init_ref => try sema.zirArrayInit(block, inst, true),264 .array_init_ref => try sema.zirArrayInit(block, inst, true),
265 .array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
264 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),266 .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),
265 .union_init_ptr => try sema.zirUnionInitPtr(block, inst),267 .union_init_ptr => try sema.zirUnionInitPtr(block, inst),
266 .field_type => try sema.zirFieldType(block, inst),268 .field_type => try sema.zirFieldType(block, inst),
...@@ -5078,13 +5080,13 @@ fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner...@@ -5078,13 +5080,13 @@ fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner
5078 return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnionInitPtr", .{});5080 return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnionInitPtr", .{});
5079}5081}
50805082
5081fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {5083fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst {
5082 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5084 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5083 const src = inst_data.src();5085 const src = inst_data.src();
5084 return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{});5086 return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{});
5085}5087}
50865088
5087fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {5089fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst {
5088 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;5090 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
5089 const src = inst_data.src();5091 const src = inst_data.src();
5090 return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInitAnon", .{});5092 return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInitAnon", .{});
src/Zir.zig+10
...@@ -660,9 +660,15 @@ pub const Inst = struct {...@@ -660,9 +660,15 @@ pub const Inst = struct {
660 /// struct value.660 /// struct value.
661 /// Uses the `pl_node` field. Payload is `StructInit`.661 /// Uses the `pl_node` field. Payload is `StructInit`.
662 struct_init,662 struct_init,
663 /// Struct initialization syntax, make the result a pointer.
664 /// Uses the `pl_node` field. Payload is `StructInit`.
665 struct_init_ref,
663 /// Struct initialization without a type.666 /// Struct initialization without a type.
664 /// Uses the `pl_node` field. Payload is `StructInitAnon`.667 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
665 struct_init_anon,668 struct_init_anon,
669 /// Anonymous struct initialization syntax, make the result a pointer.
670 /// Uses the `pl_node` field. Payload is `StructInitAnon`.
671 struct_init_anon_ref,
666 /// Array initialization syntax.672 /// Array initialization syntax.
667 /// Uses the `pl_node` field. Payload is `MultiOp`.673 /// Uses the `pl_node` field. Payload is `MultiOp`.
668 array_init,674 array_init,
...@@ -1093,7 +1099,9 @@ pub const Inst = struct {...@@ -1093,7 +1099,9 @@ pub const Inst = struct {
1093 .validate_array_init_ptr,1099 .validate_array_init_ptr,
1094 .struct_init_empty,1100 .struct_init_empty,
1095 .struct_init,1101 .struct_init,
1102 .struct_init_ref,
1096 .struct_init_anon,1103 .struct_init_anon,
1104 .struct_init_anon_ref,
1097 .array_init,1105 .array_init,
1098 .array_init_anon,1106 .array_init_anon,
1099 .array_init_ref,1107 .array_init_ref,
...@@ -2442,7 +2450,9 @@ const Writer = struct {...@@ -2442,7 +2450,9 @@ const Writer = struct {
2442 .slice_end,2450 .slice_end,
2443 .slice_sentinel,2451 .slice_sentinel,
2444 .struct_init,2452 .struct_init,
2453 .struct_init_ref,
2445 .struct_init_anon,2454 .struct_init_anon,
2455 .struct_init_anon_ref,
2446 .array_init,2456 .array_init,
2447 .array_init_anon,2457 .array_init_anon,
2448 .array_init_ref,2458 .array_init_ref,