Skip to content

Commit c84f5a5

Browse files
authored
Merge pull request #11749 from Vexu/stage2
Stage2: improve AstGen for array init expressions
2 parents f846dc4 + 0e83077 commit c84f5a5

File tree

6 files changed

+152
-124
lines changed

6 files changed

+152
-124
lines changed

src/AstGen.zig

Lines changed: 36 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,12 +1276,10 @@ fn arrayInitExpr(
12761276
const types: struct {
12771277
array: Zir.Inst.Ref,
12781278
elem: Zir.Inst.Ref,
1279-
sentinel: Zir.Inst.Ref,
12801279
} = inst: {
12811280
if (array_init.ast.type_expr == 0) break :inst .{
12821281
.array = .none,
12831282
.elem = .none,
1284-
.sentinel = .none,
12851283
};
12861284

12871285
infer: {
@@ -1301,7 +1299,6 @@ fn arrayInitExpr(
13011299
break :inst .{
13021300
.array = array_type_inst,
13031301
.elem = elem_type,
1304-
.sentinel = .none,
13051302
};
13061303
} else {
13071304
const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
@@ -1317,50 +1314,38 @@ fn arrayInitExpr(
13171314
break :inst .{
13181315
.array = array_type_inst,
13191316
.elem = elem_type,
1320-
.sentinel = sentinel,
13211317
};
13221318
}
13231319
}
13241320
}
13251321
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
13261322
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
1327-
const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr);
13281323
break :inst .{
13291324
.array = array_type_inst,
1330-
.elem = elem_type,
1331-
.sentinel = .none,
1325+
.elem = .none,
13321326
};
13331327
};
13341328

13351329
switch (rl) {
13361330
.discard => {
1331+
// TODO elements should still be coerced if type is provided
13371332
for (array_init.ast.elements) |elem_init| {
13381333
_ = try expr(gz, scope, .discard, elem_init);
13391334
}
13401335
return Zir.Inst.Ref.void_value;
13411336
},
13421337
.ref => {
1343-
if (types.array != .none) {
1344-
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, true);
1345-
} else {
1346-
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref);
1347-
}
1338+
const tag: Zir.Inst.Tag = if (types.array != .none) .array_init_ref else .array_init_anon_ref;
1339+
return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
13481340
},
13491341
.none => {
1350-
if (types.array != .none) {
1351-
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
1352-
} else {
1353-
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1354-
}
1342+
const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1343+
return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
13551344
},
13561345
.ty, .coerced_ty => {
1357-
if (types.array != .none) {
1358-
const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
1359-
return rvalue(gz, rl, result, node);
1360-
} else {
1361-
const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1362-
return rvalue(gz, rl, result, node);
1363-
}
1346+
const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
1347+
const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1348+
return rvalue(gz, rl, result, node);
13641349
},
13651350
.ptr => |ptr_inst| {
13661351
return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
@@ -1410,52 +1395,47 @@ fn arrayInitExprRlNone(
14101395
return try gz.addPlNodePayloadIndex(tag, node, payload_index);
14111396
}
14121397

1413-
fn arrayInitExprRlTy(
1398+
fn arrayInitExprInner(
14141399
gz: *GenZir,
14151400
scope: *Scope,
14161401
node: Ast.Node.Index,
14171402
elements: []const Ast.Node.Index,
1418-
elem_ty_inst: Zir.Inst.Ref,
1419-
sentinel: Zir.Inst.Ref,
1420-
ref: bool,
1403+
array_ty_inst: Zir.Inst.Ref,
1404+
elem_ty: Zir.Inst.Ref,
1405+
tag: Zir.Inst.Tag,
14211406
) InnerError!Zir.Inst.Ref {
14221407
const astgen = gz.astgen;
14231408

1424-
const info: struct {
1425-
len: usize,
1426-
tag: Zir.Inst.Tag,
1427-
} = blk: {
1428-
if (sentinel != .none) {
1429-
break :blk .{
1430-
.len = elements.len + 1,
1431-
.tag = if (ref) .array_init_sent_ref else .array_init_sent,
1432-
};
1433-
} else {
1434-
break :blk .{
1435-
.len = elements.len,
1436-
.tag = if (ref) .array_init_ref else .array_init,
1437-
};
1438-
}
1439-
};
1440-
1409+
const len = elements.len + @boolToInt(array_ty_inst != .none);
14411410
const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
1442-
.operands_len = @intCast(u32, info.len),
1411+
.operands_len = @intCast(u32, len),
14431412
});
1444-
var extra_index = try reserveExtra(astgen, info.len);
1445-
1446-
const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
1447-
for (elements) |elem_init| {
1448-
const elem_ref = try expr(gz, scope, elem_rl, elem_init);
1449-
astgen.extra.items[extra_index] = @enumToInt(elem_ref);
1413+
var extra_index = try reserveExtra(astgen, len);
1414+
if (array_ty_inst != .none) {
1415+
astgen.extra.items[extra_index] = @enumToInt(array_ty_inst);
14501416
extra_index += 1;
14511417
}
14521418

1453-
if (sentinel != .none) {
1454-
astgen.extra.items[extra_index] = @enumToInt(sentinel);
1419+
for (elements) |elem_init, i| {
1420+
const rl = if (elem_ty != .none)
1421+
ResultLoc{ .coerced_ty = elem_ty }
1422+
else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: {
1423+
const ty_expr = try gz.add(.{
1424+
.tag = .elem_type_index,
1425+
.data = .{ .bin = .{
1426+
.lhs = array_ty_inst,
1427+
.rhs = @intToEnum(Zir.Inst.Ref, i),
1428+
} },
1429+
});
1430+
break :rl ResultLoc{ .coerced_ty = ty_expr };
1431+
} else ResultLoc{ .none = {} };
1432+
1433+
const elem_ref = try expr(gz, scope, rl, elem_init);
1434+
astgen.extra.items[extra_index] = @enumToInt(elem_ref);
14551435
extra_index += 1;
14561436
}
14571437

1458-
return try gz.addPlNodePayloadIndex(info.tag, node, payload_index);
1438+
return try gz.addPlNodePayloadIndex(tag, node, payload_index);
14591439
}
14601440

14611441
fn arrayInitExprRlPtr(
@@ -2243,8 +2223,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
22432223
.array_mul,
22442224
.array_type,
22452225
.array_type_sentinel,
2226+
.elem_type_index,
22462227
.vector_type,
2247-
.elem_type,
22482228
.indexable_ptr_len,
22492229
.anyframe_type,
22502230
.as,
@@ -2347,10 +2327,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
23472327
.struct_init_anon_ref,
23482328
.array_init,
23492329
.array_init_anon,
2350-
.array_init_sent,
23512330
.array_init_ref,
23522331
.array_init_anon_ref,
2353-
.array_init_sent_ref,
23542332
.union_init,
23552333
.field_type,
23562334
.field_type_ref,

src/Sema.zig

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ fn analyzeBodyInner(
726726
.elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
727727
.elem_val => try sema.zirElemVal(block, inst),
728728
.elem_val_node => try sema.zirElemValNode(block, inst),
729-
.elem_type => try sema.zirElemType(block, inst),
729+
.elem_type_index => try sema.zirElemTypeIndex(block, inst),
730730
.enum_literal => try sema.zirEnumLiteral(block, inst),
731731
.enum_to_int => try sema.zirEnumToInt(block, inst),
732732
.int_to_enum => try sema.zirIntToEnum(block, inst),
@@ -798,10 +798,8 @@ fn analyzeBodyInner(
798798
.struct_init_ref => try sema.zirStructInit(block, inst, true),
799799
.struct_init_anon => try sema.zirStructInitAnon(block, inst, false),
800800
.struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true),
801-
.array_init => try sema.zirArrayInit(block, inst, false, false),
802-
.array_init_sent => try sema.zirArrayInit(block, inst, false, true),
803-
.array_init_ref => try sema.zirArrayInit(block, inst, true, false),
804-
.array_init_sent_ref => try sema.zirArrayInit(block, inst, true, true),
801+
.array_init => try sema.zirArrayInit(block, inst, false),
802+
.array_init_ref => try sema.zirArrayInit(block, inst, true),
805803
.array_init_anon => try sema.zirArrayInitAnon(block, inst, false),
806804
.array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true),
807805
.union_init => try sema.zirUnionInit(block, inst),
@@ -3024,7 +3022,10 @@ fn zirArrayBasePtr(
30243022
const elem_ty = sema.typeOf(base_ptr).childType();
30253023
switch (elem_ty.zigTypeTag()) {
30263024
.Array, .Vector => return base_ptr,
3027-
.Struct => if (elem_ty.isTuple()) return base_ptr,
3025+
.Struct => if (elem_ty.isTuple()) {
3026+
// TODO validate element count
3027+
return base_ptr;
3028+
},
30283029
else => {},
30293030
}
30303031
return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
@@ -3065,7 +3066,10 @@ fn validateArrayInitTy(
30653066

30663067
switch (ty.zigTypeTag()) {
30673068
.Array, .Vector => return,
3068-
.Struct => if (ty.isTuple()) return,
3069+
.Struct => if (ty.isTuple()) {
3070+
// TODO validate element count
3071+
return;
3072+
},
30693073
else => {},
30703074
}
30713075
return sema.failWithArrayInitNotSupported(block, src, ty);
@@ -5808,12 +5812,17 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
58085812
return sema.addType(opt_type);
58095813
}
58105814

5811-
fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5812-
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
5813-
const src = inst_data.src();
5814-
const array_type = try sema.resolveType(block, src, inst_data.operand);
5815-
const elem_type = array_type.elemType();
5816-
return sema.addType(elem_type);
5815+
fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5816+
const bin = sema.code.instructions.items(.data)[inst].bin;
5817+
const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
5818+
assert(indexable_ty.isIndexable()); // validated by a previous instruction
5819+
if (indexable_ty.zigTypeTag() == .Struct) {
5820+
const elem_type = indexable_ty.tupleFields().types[@enumToInt(bin.rhs)];
5821+
return sema.addType(elem_type);
5822+
} else {
5823+
const elem_type = indexable_ty.elemType2();
5824+
return sema.addType(elem_type);
5825+
}
58175826
}
58185827

58195828
fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -13280,6 +13289,8 @@ fn zirStructInit(
1328013289
try sema.requireRuntimeBlock(block, src);
1328113290
try sema.queueFullTypeResolution(resolved_ty);
1328213291
return block.addUnionInit(resolved_ty, field_index, init_inst);
13292+
} else if (resolved_ty.isAnonStruct()) {
13293+
return sema.fail(block, src, "TODO anon struct init validation", .{});
1328313294
}
1328413295
unreachable;
1328513296
}
@@ -13436,38 +13447,33 @@ fn zirArrayInit(
1343613447
block: *Block,
1343713448
inst: Zir.Inst.Index,
1343813449
is_ref: bool,
13439-
is_sent: bool,
1344013450
) CompileError!Air.Inst.Ref {
1344113451
const gpa = sema.gpa;
1344213452
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1344313453
const src = inst_data.src();
1344413454

1344513455
const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
1344613456
const args = sema.code.refSlice(extra.end, extra.data.operands_len);
13447-
assert(args.len != 0);
13457+
assert(args.len >= 2); // array_ty + at least one element
1344813458

13449-
const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len);
13450-
defer gpa.free(resolved_args);
13451-
13452-
for (args) |arg, i| resolved_args[i] = try sema.resolveInst(arg);
13459+
const array_ty = try sema.resolveType(block, src, args[0]);
13460+
const sentinel_val = array_ty.sentinel();
1345313461

13454-
const elem_ty = sema.typeOf(resolved_args[0]);
13455-
const array_ty = blk: {
13456-
if (!is_sent) {
13457-
break :blk try Type.Tag.array.create(sema.arena, .{
13458-
.len = resolved_args.len,
13459-
.elem_type = elem_ty,
13460-
});
13461-
}
13462+
const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));
13463+
defer gpa.free(resolved_args);
13464+
for (args[1..]) |arg, i| {
13465+
const resolved_arg = try sema.resolveInst(arg);
13466+
const arg_src = src; // TODO better source location
13467+
const elem_ty = if (array_ty.zigTypeTag() == .Struct)
13468+
array_ty.tupleFields().types[i]
13469+
else
13470+
array_ty.elemType2();
13471+
resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src);
13472+
}
1346213473

13463-
const sentinel_ref = resolved_args[resolved_args.len - 1];
13464-
const val = try sema.resolveConstValue(block, src, sentinel_ref);
13465-
break :blk try Type.Tag.array_sentinel.create(sema.arena, .{
13466-
.len = resolved_args.len - 1,
13467-
.sentinel = val,
13468-
.elem_type = elem_ty,
13469-
});
13470-
};
13474+
if (sentinel_val) |some| {
13475+
resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(), some);
13476+
}
1347113477

1347213478
const opt_runtime_src: ?LazySrcLoc = for (resolved_args) |arg| {
1347313479
const arg_src = src; // TODO better source location
@@ -13488,7 +13494,7 @@ fn zirArrayInit(
1348813494
};
1348913495

1349013496
try sema.requireRuntimeBlock(block, runtime_src);
13491-
try sema.queueFullTypeResolution(elem_ty);
13497+
try sema.queueFullTypeResolution(array_ty);
1349213498

1349313499
if (is_ref) {
1349413500
const target = sema.mod.getTarget();
@@ -13498,10 +13504,27 @@ fn zirArrayInit(
1349813504
});
1349913505
const alloc = try block.addTy(.alloc, alloc_ty);
1350013506

13507+
if (array_ty.isTuple()) {
13508+
const types = array_ty.tupleFields().types;
13509+
for (resolved_args) |arg, i| {
13510+
const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
13511+
.mutable = true,
13512+
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
13513+
.pointee_type = types[i],
13514+
});
13515+
const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
13516+
13517+
const index = try sema.addIntUnsigned(Type.usize, i);
13518+
const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);
13519+
_ = try block.addBinOp(.store, elem_ptr, arg);
13520+
}
13521+
return alloc;
13522+
}
13523+
1350113524
const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
1350213525
.mutable = true,
1350313526
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
13504-
.pointee_type = elem_ty,
13527+
.pointee_type = array_ty.elemType2(),
1350513528
});
1350613529
const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1350713530

@@ -13643,6 +13666,10 @@ fn fieldType(
1364313666
while (true) {
1364413667
switch (cur_ty.zigTypeTag()) {
1364513668
.Struct => {
13669+
if (cur_ty.isAnonStruct()) {
13670+
const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
13671+
return sema.addType(cur_ty.tupleFields().types[field_index]);
13672+
}
1364613673
const struct_obj = cur_ty.castTag(.@"struct").?.data;
1364713674
const field = struct_obj.fields.get(field_name) orelse
1364813675
return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);

0 commit comments

Comments
 (0)