diff --git a/src/AstGen.zig b/src/AstGen.zig index e4af8af66b..69ef73dc4a 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1300,40 +1300,28 @@ pub fn structInitExpr( } return Zir.Inst.Ref.void_value; }, + .ref => { + if (struct_init.ast.type_expr != 0) { + const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); + return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init_ref); + } else { + return structInitExprRlNone(gz, scope, rl, node, struct_init, .struct_init_anon_ref); + } + }, .none, .none_or_ref => { if (struct_init.ast.type_expr != 0) { const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); - return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst); + return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init); + } else { + return structInitExprRlNone(gz, scope, rl, node, struct_init, .struct_init_anon); } - const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len); - defer gpa.free(fields_list); - - for (struct_init.ast.fields) |field_init, i| { - const name_token = tree.firstToken(field_init) - 2; - const str_index = try gz.identAsString(name_token); - - fields_list[i] = .{ - .field_name = str_index, - .init = try expr(gz, scope, .none, field_init), - }; - } - const init_inst = try gz.addPlNode(.struct_init_anon, node, Zir.Inst.StructInitAnon{ - .fields_len = @intCast(u32, fields_list.len), - }); - try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + - fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len); - for (fields_list) |field| { - _ = gz.astgen.addExtraAssumeCapacity(field); - } - return init_inst; }, - .ref => return astgen.failNode(node, "cannot take address of struct literal", .{}), .ty => |ty_inst| { if (struct_init.ast.type_expr == 0) { - return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst); + return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst, .struct_init); } const inner_ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); - const result = try structInitExprRlTy(gz, scope, rl, node, struct_init, inner_ty_inst); + const result = try structInitExprRlTy(gz, scope, rl, node, struct_init, inner_ty_inst, .struct_init); return rvalue(gz, scope, rl, result, node); }, .ptr, .inferred_ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst), @@ -1341,6 +1329,41 @@ pub fn structInitExpr( } } +pub fn structInitExprRlNone( + gz: *GenZir, + scope: *Scope, + rl: ResultLoc, + node: ast.Node.Index, + struct_init: ast.full.StructInit, + tag: Zir.Inst.Tag, +) InnerError!Zir.Inst.Ref { + const astgen = gz.astgen; + const gpa = astgen.gpa; + const tree = &astgen.file.tree; + + const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len); + defer gpa.free(fields_list); + + for (struct_init.ast.fields) |field_init, i| { + const name_token = tree.firstToken(field_init) - 2; + const str_index = try gz.identAsString(name_token); + + fields_list[i] = .{ + .field_name = str_index, + .init = try expr(gz, scope, .none, field_init), + }; + } + const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{ + .fields_len = @intCast(u32, fields_list.len), + }); + try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + + fields_list.len * @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len); + for (fields_list) |field| { + _ = gz.astgen.addExtraAssumeCapacity(field); + } + return init_inst; +} + pub fn structInitExprRlPtr( gz: *GenZir, scope: *Scope, @@ -1380,6 +1403,7 @@ pub fn structInitExprRlTy( node: ast.Node.Index, struct_init: ast.full.StructInit, ty_inst: Zir.Inst.Ref, + tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const gpa = astgen.gpa; @@ -1401,7 +1425,7 @@ pub fn structInitExprRlTy( .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), }; } - const init_inst = try gz.addPlNode(.struct_init, node, Zir.Inst.StructInit{ + const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{ .fields_len = @intCast(u32, fields_list.len), }); try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + @@ -1886,7 +1910,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner .switch_capture_else_ref, .struct_init_empty, .struct_init, + .struct_init_ref, .struct_init_anon, + .struct_init_anon_ref, .array_init, .array_init_anon, .array_init_ref, diff --git a/src/Sema.zig b/src/Sema.zig index a6739d74f3..6d0dc807bf 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -256,11 +256,13 @@ pub fn analyzeBody( .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst), .xor => try sema.zirBitwise(block, inst, .xor), .struct_init_empty => try sema.zirStructInitEmpty(block, inst), - .struct_init => try sema.zirStructInit(block, inst), - .struct_init_anon => try sema.zirStructInitAnon(block, inst), + .struct_init => try sema.zirStructInit(block, inst, false), + .struct_init_ref => try sema.zirStructInit(block, inst, true), + .struct_init_anon => try sema.zirStructInitAnon(block, inst, false), + .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true), .array_init => try sema.zirArrayInit(block, inst, false), - .array_init_anon => try sema.zirArrayInitAnon(block, inst, false), .array_init_ref => try sema.zirArrayInit(block, inst, true), + .array_init_anon => try sema.zirArrayInitAnon(block, inst, false), .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true), .union_init_ptr => try sema.zirUnionInitPtr(block, inst), .field_type => try sema.zirFieldType(block, inst), @@ -5078,13 +5080,13 @@ fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnionInitPtr", .{}); } -fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { +fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{}); } -fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { +fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) InnerError!*Inst { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInitAnon", .{}); diff --git a/src/Zir.zig b/src/Zir.zig index 4800261422..746c101e23 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -660,9 +660,15 @@ pub const Inst = struct { /// struct value. /// Uses the `pl_node` field. Payload is `StructInit`. struct_init, + /// Struct initialization syntax, make the result a pointer. + /// Uses the `pl_node` field. Payload is `StructInit`. + struct_init_ref, /// Struct initialization without a type. /// Uses the `pl_node` field. Payload is `StructInitAnon`. struct_init_anon, + /// Anonymous struct initialization syntax, make the result a pointer. + /// Uses the `pl_node` field. Payload is `StructInitAnon`. + struct_init_anon_ref, /// Array initialization syntax. /// Uses the `pl_node` field. Payload is `MultiOp`. array_init, @@ -1093,7 +1099,9 @@ pub const Inst = struct { .validate_array_init_ptr, .struct_init_empty, .struct_init, + .struct_init_ref, .struct_init_anon, + .struct_init_anon_ref, .array_init, .array_init_anon, .array_init_ref, @@ -2442,7 +2450,9 @@ const Writer = struct { .slice_end, .slice_sentinel, .struct_init, + .struct_init_ref, .struct_init_anon, + .struct_init_anon_ref, .array_init, .array_init_anon, .array_init_ref,