AstGen: support struct init with ref result location

This commit is contained in:
Andrew Kelley 2021-04-23 23:40:10 -07:00
parent d2b06c2612
commit 27fa4bc2be
3 changed files with 69 additions and 31 deletions

View File

@ -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,

View File

@ -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", .{});

View File

@ -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,