Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 36 additions & 58 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1276,12 +1276,10 @@ fn arrayInitExpr(
const types: struct {
array: Zir.Inst.Ref,
elem: Zir.Inst.Ref,
sentinel: Zir.Inst.Ref,
} = inst: {
if (array_init.ast.type_expr == 0) break :inst .{
.array = .none,
.elem = .none,
.sentinel = .none,
};

infer: {
Expand All @@ -1301,7 +1299,6 @@ fn arrayInitExpr(
break :inst .{
.array = array_type_inst,
.elem = elem_type,
.sentinel = .none,
};
} else {
const sentinel = try comptimeExpr(gz, scope, .{ .ty = elem_type }, array_type.ast.sentinel);
Expand All @@ -1317,50 +1314,38 @@ fn arrayInitExpr(
break :inst .{
.array = array_type_inst,
.elem = elem_type,
.sentinel = sentinel,
};
}
}
}
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
const elem_type = try gz.addUnNode(.elem_type, array_type_inst, array_init.ast.type_expr);
break :inst .{
.array = array_type_inst,
.elem = elem_type,
.sentinel = .none,
.elem = .none,
};
};

switch (rl) {
.discard => {
// TODO elements should still be coerced if type is provided
for (array_init.ast.elements) |elem_init| {
_ = try expr(gz, scope, .discard, elem_init);
}
return Zir.Inst.Ref.void_value;
},
.ref => {
if (types.array != .none) {
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, true);
} else {
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon_ref);
}
const tag: Zir.Inst.Tag = if (types.array != .none) .array_init_ref else .array_init_anon_ref;
return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
},
.none => {
if (types.array != .none) {
return arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
} else {
return arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
}
const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
},
.ty, .coerced_ty => {
if (types.array != .none) {
const result = try arrayInitExprRlTy(gz, scope, node, array_init.ast.elements, types.elem, types.sentinel, false);
return rvalue(gz, rl, result, node);
} else {
const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
return rvalue(gz, rl, result, node);
}
const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;
const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
return rvalue(gz, rl, result, node);
},
.ptr => |ptr_inst| {
return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);
Expand Down Expand Up @@ -1410,52 +1395,47 @@ fn arrayInitExprRlNone(
return try gz.addPlNodePayloadIndex(tag, node, payload_index);
}

fn arrayInitExprRlTy(
fn arrayInitExprInner(
gz: *GenZir,
scope: *Scope,
node: Ast.Node.Index,
elements: []const Ast.Node.Index,
elem_ty_inst: Zir.Inst.Ref,
sentinel: Zir.Inst.Ref,
ref: bool,
array_ty_inst: Zir.Inst.Ref,
elem_ty: Zir.Inst.Ref,
tag: Zir.Inst.Tag,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;

const info: struct {
len: usize,
tag: Zir.Inst.Tag,
} = blk: {
if (sentinel != .none) {
break :blk .{
.len = elements.len + 1,
.tag = if (ref) .array_init_sent_ref else .array_init_sent,
};
} else {
break :blk .{
.len = elements.len,
.tag = if (ref) .array_init_ref else .array_init,
};
}
};

const len = elements.len + @boolToInt(array_ty_inst != .none);
const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{
.operands_len = @intCast(u32, info.len),
.operands_len = @intCast(u32, len),
});
var extra_index = try reserveExtra(astgen, info.len);

const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
for (elements) |elem_init| {
const elem_ref = try expr(gz, scope, elem_rl, elem_init);
astgen.extra.items[extra_index] = @enumToInt(elem_ref);
var extra_index = try reserveExtra(astgen, len);
if (array_ty_inst != .none) {
astgen.extra.items[extra_index] = @enumToInt(array_ty_inst);
extra_index += 1;
}

if (sentinel != .none) {
astgen.extra.items[extra_index] = @enumToInt(sentinel);
for (elements) |elem_init, i| {
const rl = if (elem_ty != .none)
ResultLoc{ .coerced_ty = elem_ty }
else if (array_ty_inst != .none and nodeMayNeedMemoryLocation(astgen.tree, elem_init, true)) rl: {
const ty_expr = try gz.add(.{
.tag = .elem_type_index,
.data = .{ .bin = .{
.lhs = array_ty_inst,
.rhs = @intToEnum(Zir.Inst.Ref, i),
} },
});
break :rl ResultLoc{ .coerced_ty = ty_expr };
} else ResultLoc{ .none = {} };

const elem_ref = try expr(gz, scope, rl, elem_init);
astgen.extra.items[extra_index] = @enumToInt(elem_ref);
extra_index += 1;
}

return try gz.addPlNodePayloadIndex(info.tag, node, payload_index);
return try gz.addPlNodePayloadIndex(tag, node, payload_index);
}

fn arrayInitExprRlPtr(
Expand Down Expand Up @@ -2243,8 +2223,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.array_mul,
.array_type,
.array_type_sentinel,
.elem_type_index,
.vector_type,
.elem_type,
.indexable_ptr_len,
.anyframe_type,
.as,
Expand Down Expand Up @@ -2347,10 +2327,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.struct_init_anon_ref,
.array_init,
.array_init_anon,
.array_init_sent,
.array_init_ref,
.array_init_anon_ref,
.array_init_sent_ref,
.union_init,
.field_type,
.field_type_ref,
Expand Down
101 changes: 64 additions & 37 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ fn analyzeBodyInner(
.elem_ptr_imm => try sema.zirElemPtrImm(block, inst),
.elem_val => try sema.zirElemVal(block, inst),
.elem_val_node => try sema.zirElemValNode(block, inst),
.elem_type => try sema.zirElemType(block, inst),
.elem_type_index => try sema.zirElemTypeIndex(block, inst),
.enum_literal => try sema.zirEnumLiteral(block, inst),
.enum_to_int => try sema.zirEnumToInt(block, inst),
.int_to_enum => try sema.zirIntToEnum(block, inst),
Expand Down Expand Up @@ -798,10 +798,8 @@ fn analyzeBodyInner(
.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, false),
.array_init_sent => try sema.zirArrayInit(block, inst, false, true),
.array_init_ref => try sema.zirArrayInit(block, inst, true, false),
.array_init_sent_ref => try sema.zirArrayInit(block, inst, true, true),
.array_init => try sema.zirArrayInit(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 => try sema.zirUnionInit(block, inst),
Expand Down Expand Up @@ -3024,7 +3022,10 @@ fn zirArrayBasePtr(
const elem_ty = sema.typeOf(base_ptr).childType();
switch (elem_ty.zigTypeTag()) {
.Array, .Vector => return base_ptr,
.Struct => if (elem_ty.isTuple()) return base_ptr,
.Struct => if (elem_ty.isTuple()) {
// TODO validate element count
return base_ptr;
},
else => {},
}
return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
Expand Down Expand Up @@ -3065,7 +3066,10 @@ fn validateArrayInitTy(

switch (ty.zigTypeTag()) {
.Array, .Vector => return,
.Struct => if (ty.isTuple()) return,
.Struct => if (ty.isTuple()) {
// TODO validate element count
return;
},
else => {},
}
return sema.failWithArrayInitNotSupported(block, src, ty);
Expand Down Expand Up @@ -5808,12 +5812,17 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
return sema.addType(opt_type);
}

fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
const array_type = try sema.resolveType(block, src, inst_data.operand);
const elem_type = array_type.elemType();
return sema.addType(elem_type);
fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const bin = sema.code.instructions.items(.data)[inst].bin;
const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
assert(indexable_ty.isIndexable()); // validated by a previous instruction
if (indexable_ty.zigTypeTag() == .Struct) {
const elem_type = indexable_ty.tupleFields().types[@enumToInt(bin.rhs)];
return sema.addType(elem_type);
} else {
const elem_type = indexable_ty.elemType2();
return sema.addType(elem_type);
}
}

fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
Expand Down Expand Up @@ -13280,6 +13289,8 @@ fn zirStructInit(
try sema.requireRuntimeBlock(block, src);
try sema.queueFullTypeResolution(resolved_ty);
return block.addUnionInit(resolved_ty, field_index, init_inst);
} else if (resolved_ty.isAnonStruct()) {
return sema.fail(block, src, "TODO anon struct init validation", .{});
}
unreachable;
}
Expand Down Expand Up @@ -13436,38 +13447,33 @@ fn zirArrayInit(
block: *Block,
inst: Zir.Inst.Index,
is_ref: bool,
is_sent: bool,
) CompileError!Air.Inst.Ref {
const gpa = sema.gpa;
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();

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

const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len);
defer gpa.free(resolved_args);

for (args) |arg, i| resolved_args[i] = try sema.resolveInst(arg);
const array_ty = try sema.resolveType(block, src, args[0]);
const sentinel_val = array_ty.sentinel();

const elem_ty = sema.typeOf(resolved_args[0]);
const array_ty = blk: {
if (!is_sent) {
break :blk try Type.Tag.array.create(sema.arena, .{
.len = resolved_args.len,
.elem_type = elem_ty,
});
}
const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));
defer gpa.free(resolved_args);
for (args[1..]) |arg, i| {
const resolved_arg = try sema.resolveInst(arg);
const arg_src = src; // TODO better source location
const elem_ty = if (array_ty.zigTypeTag() == .Struct)
array_ty.tupleFields().types[i]
else
array_ty.elemType2();
resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src);
}

const sentinel_ref = resolved_args[resolved_args.len - 1];
const val = try sema.resolveConstValue(block, src, sentinel_ref);
break :blk try Type.Tag.array_sentinel.create(sema.arena, .{
.len = resolved_args.len - 1,
.sentinel = val,
.elem_type = elem_ty,
});
};
if (sentinel_val) |some| {
resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(), some);
}

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

try sema.requireRuntimeBlock(block, runtime_src);
try sema.queueFullTypeResolution(elem_ty);
try sema.queueFullTypeResolution(array_ty);

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

if (array_ty.isTuple()) {
const types = array_ty.tupleFields().types;
for (resolved_args) |arg, i| {
const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
.mutable = true,
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
.pointee_type = types[i],
});
const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);

const index = try sema.addIntUnsigned(Type.usize, i);
const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);
_ = try block.addBinOp(.store, elem_ptr, arg);
}
return alloc;
}

const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
.mutable = true,
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
.pointee_type = elem_ty,
.pointee_type = array_ty.elemType2(),
});
const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);

Expand Down Expand Up @@ -13643,6 +13666,10 @@ fn fieldType(
while (true) {
switch (cur_ty.zigTypeTag()) {
.Struct => {
if (cur_ty.isAnonStruct()) {
const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
return sema.addType(cur_ty.tupleFields().types[field_index]);
}
const struct_obj = cur_ty.castTag(.@"struct").?.data;
const field = struct_obj.fields.get(field_name) orelse
return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
Expand Down
Loading