AstGen: implement array initialization expressions

This commit is contained in:
Andrew Kelley 2021-04-19 23:23:24 -07:00
parent 693dbeeef2
commit e315120b79
5 changed files with 401 additions and 120 deletions

View File

@ -1590,7 +1590,6 @@ fn renderStructInit(
return renderToken(ais, tree, rbrace, space);
}
// TODO: handle comments between elements
fn renderArrayInit(
gpa: *Allocator,
ais: *Ais,

View File

@ -822,15 +822,20 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
.@"errdefer" => return astgen.failNode(node, "TODO implement astgen.expr for .errdefer", .{}),
.@"try" => return astgen.failNode(node, "TODO implement astgen.expr for .Try", .{}),
.array_init_one,
.array_init_one_comma,
.array_init_dot_two,
.array_init_dot_two_comma,
.array_init_one, .array_init_one_comma => {
var elements: [1]ast.Node.Index = undefined;
return arrayInitExpr(gz, scope, rl, node, tree.arrayInitOne(&elements, node));
},
.array_init_dot_two, .array_init_dot_two_comma => {
var elements: [2]ast.Node.Index = undefined;
return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDotTwo(&elements, node));
},
.array_init_dot,
.array_init_dot_comma,
=> return arrayInitExpr(gz, scope, rl, node, tree.arrayInitDot(node)),
.array_init,
.array_init_comma,
=> return astgen.failNode(node, "TODO implement astgen.expr for array literals", .{}),
=> return arrayInitExpr(gz, scope, rl, node, tree.arrayInit(node)),
.struct_init_one, .struct_init_one_comma => {
var fields: [1]ast.Node.Index = undefined;
@ -856,6 +861,182 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
}
}
pub fn arrayInitExpr(
gz: *GenZir,
scope: *Scope,
rl: ResultLoc,
node: ast.Node.Index,
array_init: ast.full.ArrayInit,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const tree = &astgen.file.tree;
const gpa = astgen.gpa;
const node_tags = tree.nodes.items(.tag);
const main_tokens = tree.nodes.items(.main_token);
assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
const types: struct {
array: Zir.Inst.Ref,
elem: Zir.Inst.Ref,
} = inst: {
if (array_init.ast.type_expr == 0) break :inst .{
.array = .none,
.elem = .none,
};
infer: {
const array_type: ast.full.ArrayType = switch (node_tags[array_init.ast.type_expr]) {
.array_type => tree.arrayType(array_init.ast.type_expr),
.array_type_sentinel => tree.arrayTypeSentinel(array_init.ast.type_expr),
else => break :infer,
};
// This intentionally does not support `@"_"` syntax.
if (node_tags[array_type.ast.elem_count] == .identifier and
mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"))
{
const tag: Zir.Inst.Tag = switch (node_tags[array_init.ast.type_expr]) {
.array_type => .array_type,
.array_type_sentinel => .array_type_sentinel,
else => unreachable,
};
const len_inst = try gz.addInt(array_init.ast.elements.len);
const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
const array_type_inst = try gz.addBin(tag, len_inst, elem_type);
break :inst .{
.array = array_type_inst,
.elem = elem_type,
};
}
}
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
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,
};
};
switch (rl) {
.discard => {
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, rl, node, array_init.ast.elements, types.array, types.elem, .array_init_ref);
} else {
return arrayInitExprRlNone(gz, scope, rl, node, array_init.ast.elements, .array_init_anon_ref);
}
},
.none, .none_or_ref => {
if (types.array != .none) {
return arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, types.array, types.elem, .array_init);
} else {
return arrayInitExprRlNone(gz, scope, rl, node, array_init.ast.elements, .array_init_anon);
}
},
.ty => |ty_inst| {
if (types.array != .none) {
const result = try arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, types.array, types.elem, .array_init);
return rvalue(gz, scope, rl, result, node);
} else {
const elem_type = try gz.addUnNode(.elem_type, ty_inst, node);
return arrayInitExprRlTy(gz, scope, rl, node, array_init.ast.elements, ty_inst, elem_type, .array_init);
}
},
.ptr, .inferred_ptr => |ptr_inst| {
return arrayInitExprRlPtr(gz, scope, rl, node, array_init.ast.elements, ptr_inst);
},
.block_ptr => |block_gz| {
return arrayInitExprRlPtr(gz, scope, rl, node, array_init.ast.elements, block_gz.rl_ptr);
},
}
}
pub fn arrayInitExprRlNone(
gz: *GenZir,
scope: *Scope,
rl: ResultLoc,
node: ast.Node.Index,
elements: []const ast.Node.Index,
tag: Zir.Inst.Tag,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const gpa = astgen.gpa;
const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);
defer gpa.free(elem_list);
for (elements) |elem_init, i| {
elem_list[i] = try expr(gz, scope, .none, elem_init);
}
const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
.operands_len = @intCast(u32, elem_list.len),
});
try astgen.appendRefs(elem_list);
return init_inst;
}
pub fn arrayInitExprRlTy(
gz: *GenZir,
scope: *Scope,
rl: ResultLoc,
node: ast.Node.Index,
elements: []const ast.Node.Index,
array_ty_inst: Zir.Inst.Ref,
elem_ty_inst: Zir.Inst.Ref,
tag: Zir.Inst.Tag,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const gpa = astgen.gpa;
const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len);
defer gpa.free(elem_list);
const elem_rl: ResultLoc = .{ .ty = elem_ty_inst };
for (elements) |elem_init, i| {
elem_list[i] = try expr(gz, scope, elem_rl, elem_init);
}
const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{
.operands_len = @intCast(u32, elem_list.len),
});
try astgen.appendRefs(elem_list);
return init_inst;
}
pub fn arrayInitExprRlPtr(
gz: *GenZir,
scope: *Scope,
rl: ResultLoc,
node: ast.Node.Index,
elements: []const ast.Node.Index,
result_ptr: Zir.Inst.Ref,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const gpa = astgen.gpa;
const elem_ptr_list = try gpa.alloc(Zir.Inst.Index, elements.len);
defer gpa.free(elem_ptr_list);
for (elements) |elem_init, i| {
const index_inst = try gz.addInt(i);
const elem_ptr = try gz.addPlNode(.elem_ptr_node, elem_init, Zir.Inst.Bin{
.lhs = result_ptr,
.rhs = index_inst,
});
elem_ptr_list[i] = gz.refToIndex(elem_ptr).?;
_ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);
}
_ = try gz.addPlNode(.validate_array_init_ptr, node, Zir.Inst.Block{
.body_len = @intCast(u32, elem_ptr_list.len),
});
try astgen.extra.appendSlice(gpa, elem_ptr_list);
return .void_value;
}
pub fn structInitExpr(
gz: *GenZir,
scope: *Scope,
@ -911,7 +1092,14 @@ pub fn structInitExpr(
return init_inst;
},
.ref => unreachable, // struct literal not valid as l-value
.ty => |ty_inst| return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst),
.ty => |ty_inst| {
if (struct_init.ast.type_expr == 0) {
return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst);
}
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);
return rvalue(gz, scope, rl, result, node);
},
.ptr, .inferred_ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst),
.block_ptr => |block_gz| return structInitExprRlPtr(gz, scope, rl, node, struct_init, block_gz.rl_ptr),
}
@ -942,11 +1130,11 @@ pub fn structInitExprRlPtr(
field_ptr_list[i] = gz.refToIndex(field_ptr).?;
_ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
}
const validate_inst = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{
_ = try gz.addPlNode(.validate_struct_init_ptr, node, Zir.Inst.Block{
.body_len = @intCast(u32, field_ptr_list.len),
});
try astgen.extra.appendSlice(gpa, field_ptr_list);
return validate_inst;
return .void_value;
}
pub fn structInitExprRlTy(
@ -1336,6 +1524,7 @@ fn blockExprStmts(
.array_mul,
.array_type,
.array_type_sentinel,
.elem_type,
.indexable_ptr_len,
.as,
.as_node,
@ -1393,8 +1582,6 @@ fn blockExprStmts(
.param_type,
.ptrtoint,
.ref,
.ret_ptr,
.ret_type,
.shl,
.shr,
.str,
@ -1453,6 +1640,10 @@ fn blockExprStmts(
.struct_init_empty,
.struct_init,
.struct_init_anon,
.array_init,
.array_init_anon,
.array_init_ref,
.array_init_anon_ref,
.union_init_ptr,
.field_type,
.field_type_ref,
@ -1469,18 +1660,12 @@ fn blockExprStmts(
.type_info,
.size_of,
.bit_size_of,
.this,
.ret_addr,
.builtin_src,
.add_with_overflow,
.sub_with_overflow,
.mul_with_overflow,
.shl_with_overflow,
.log2_int_type,
.typeof_log2_int_type,
.error_return_trace,
.frame,
.frame_address,
.ptr_to_int,
.align_of,
.bool_to_int,
@ -1575,6 +1760,7 @@ fn blockExprStmts(
.repeat,
.repeat_inline,
.validate_struct_init_ptr,
.validate_array_init_ptr,
.panic,
.set_align_stack,
.set_cold,
@ -2572,13 +2758,17 @@ fn structDeclInner(
field_index += 1;
}
if (field_index != 0) {
{
const empty_slot_count = 16 - (field_index % 16);
cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
if (empty_slot_count < 16) {
cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
}
}
if (wip_decls.decl_index != 0) {
{
const empty_slot_count = 16 - (wip_decls.decl_index % 16);
wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
if (empty_slot_count < 16) {
wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
}
}
const decl_inst = try gz.addBlock(tag, node);
@ -4609,9 +4799,9 @@ fn ret(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref
const operand_node = node_datas[node].lhs;
const operand: Zir.Inst.Ref = if (operand_node != 0) operand: {
const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node)) .{
.ptr = try gz.addNode(.ret_ptr, node),
.ptr = try gz.addNodeExtended(.ret_ptr, node),
} else .{
.ty = try gz.addNode(.ret_type, node),
.ty = try gz.addNodeExtended(.ret_type, node),
};
break :operand try expr(gz, scope, rl, operand_node);
} else .void_value;
@ -5203,12 +5393,12 @@ fn builtinCall(
.breakpoint => return simpleNoOpVoid(gz, scope, rl, node, .breakpoint),
.fence => return simpleNoOpVoid(gz, scope, rl, node, .fence),
.This => return rvalue(gz, scope, rl, try gz.addNode(.this, node), node),
.return_address => return rvalue(gz, scope, rl, try gz.addNode(.ret_addr, node), node),
.src => return rvalue(gz, scope, rl, try gz.addNode(.builtin_src, node), node),
.error_return_trace => return rvalue(gz, scope, rl, try gz.addNode(.error_return_trace, node), node),
.frame => return rvalue(gz, scope, rl, try gz.addNode(.frame, node), node),
.frame_address => return rvalue(gz, scope, rl, try gz.addNode(.frame_address, node), node),
.This => return rvalue(gz, scope, rl, try gz.addNodeExtended(.this, node), node),
.return_address => return rvalue(gz, scope, rl, try gz.addNodeExtended(.ret_addr, node), node),
.src => return rvalue(gz, scope, rl, try gz.addNodeExtended(.builtin_src, node), node),
.error_return_trace => return rvalue(gz, scope, rl, try gz.addNodeExtended(.error_return_trace, node), node),
.frame => return rvalue(gz, scope, rl, try gz.addNodeExtended(.frame, node), node),
.frame_address => return rvalue(gz, scope, rl, try gz.addNodeExtended(.frame_address, node), node),
.type_info => return simpleUnOpType(gz, scope, rl, node, params[0], .type_info),
.size_of => return simpleUnOpType(gz, scope, rl, node, params[0], .size_of),

View File

@ -1622,6 +1622,22 @@ pub const Scope = struct {
});
}
pub fn addNodeExtended(
gz: *GenZir,
opcode: Zir.Inst.Extended,
/// Absolute node index. This function does the conversion to offset from Decl.
src_node: ast.Node.Index,
) !Zir.Inst.Ref {
return gz.add(.{
.tag = .extended,
.data = .{ .extended = .{
.opcode = opcode,
.small = undefined,
.operand = @bitCast(u32, gz.nodeIndexToRelative(src_node)),
} },
});
}
/// Asserts that `str` is 8 or fewer bytes.
pub fn addSmallStr(
gz: *GenZir,
@ -2583,6 +2599,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
return error.AnalysisFail;
}
log.debug("AstGen success: {s}", .{file.sub_file_path});
file.status = .success;
}

View File

@ -175,6 +175,7 @@ pub fn analyzeBody(
.elem_ptr_node => try sema.zirElemPtrNode(block, inst),
.elem_val => try sema.zirElemVal(block, inst),
.elem_val_node => try sema.zirElemValNode(block, inst),
.elem_type => try sema.zirElemType(block, inst),
.enum_literal => try sema.zirEnumLiteral(block, inst),
.enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
.enum_to_int => try sema.zirEnumToInt(block, inst),
@ -223,8 +224,6 @@ pub fn analyzeBody(
.ptr_type_simple => try sema.zirPtrTypeSimple(block, inst),
.ptrtoint => try sema.zirPtrtoint(block, inst),
.ref => try sema.zirRef(block, inst),
.ret_ptr => try sema.zirRetPtr(block, inst),
.ret_type => try sema.zirRetType(block, inst),
.shl => try sema.zirShl(block, inst),
.shr => try sema.zirShr(block, inst),
.slice_end => try sema.zirSliceEnd(block, inst),
@ -252,9 +251,6 @@ pub fn analyzeBody(
.type_info => try sema.zirTypeInfo(block, inst),
.size_of => try sema.zirSizeOf(block, inst),
.bit_size_of => try sema.zirBitSizeOf(block, inst),
.this => try sema.zirThis(block, inst),
.ret_addr => try sema.zirRetAddr(block, inst),
.builtin_src => try sema.zirBuiltinSrc(block, inst),
.typeof => try sema.zirTypeof(block, inst),
.typeof_elem => try sema.zirTypeofElem(block, inst),
.typeof_peer => try sema.zirTypeofPeer(block, inst),
@ -264,12 +260,13 @@ pub fn analyzeBody(
.struct_init_empty => try sema.zirStructInitEmpty(block, inst),
.struct_init => try sema.zirStructInit(block, inst),
.struct_init_anon => try sema.zirStructInitAnon(block, inst),
.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_ref => try sema.zirArrayInitAnon(block, inst, true),
.union_init_ptr => try sema.zirUnionInitPtr(block, inst),
.field_type => try sema.zirFieldType(block, inst),
.field_type_ref => try sema.zirFieldTypeRef(block, inst),
.error_return_trace => try sema.zirErrorReturnTrace(block, inst),
.frame => try sema.zirFrame(block, inst),
.frame_address => try sema.zirFrameAddress(block, inst),
.ptr_to_int => try sema.zirPtrToInt(block, inst),
.align_of => try sema.zirAlignOf(block, inst),
.bool_to_int => try sema.zirBoolToInt(block, inst),
@ -435,6 +432,10 @@ pub fn analyzeBody(
try sema.zirValidateStructInitPtr(block, inst);
continue;
},
.validate_array_init_ptr => {
try sema.zirValidateArrayInitPtr(block, inst);
continue;
},
.@"export" => {
try sema.zirExport(block, inst);
continue;
@ -499,6 +500,28 @@ pub fn analyzeBody(
}
}
fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const extended = sema.code.instructions.items(.data)[inst].extended;
switch (extended.opcode) {
// zig fmt: off
.func => return sema.zirFuncExtended( block, extended),
.ret_ptr => return sema.zirRetPtr( block, extended),
.ret_type => return sema.zirRetType( block, extended),
.this => return sema.zirThis( block, extended),
.ret_addr => return sema.zirRetAddr( block, extended),
.builtin_src => return sema.zirBuiltinSrc( block, extended),
.error_return_trace => return sema.zirErrorReturnTrace(block, extended),
.frame => return sema.zirFrame( block, extended),
.frame_address => return sema.zirFrameAddress( block, extended),
.c_undef => return sema.zirCUndef( block, extended),
.c_include => return sema.zirCInclude( block, extended),
.c_define => return sema.zirCDefine( block, extended),
.wasm_memory_size => return sema.zirWasmMemorySize( block, extended),
.wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),
// zig fmt: on
}
}
/// TODO when we rework TZIR memory layout, this function will no longer have a possible error.
pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {
var i: usize = @enumToInt(zir_ref);
@ -990,11 +1013,15 @@ fn zirErrorSetDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inner
return sema.mod.fail(&block.base, sema.src, "TODO implement zirErrorSetDecl", .{});
}
fn zirRetPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
fn zirRetPtr(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
const src: LazySrcLoc = .unneeded;
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
try sema.requireFunctionBlock(block, src);
const fn_ty = sema.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
const ret_type = fn_ty.fnReturnType();
@ -1011,11 +1038,15 @@ fn zirRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*In
return sema.analyzeRef(block, inst_data.src(), operand);
}
fn zirRetType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
fn zirRetType(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
const src: LazySrcLoc = .unneeded;
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
try sema.requireFunctionBlock(block, src);
const fn_ty = sema.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
const ret_type = fn_ty.fnReturnType();
@ -1247,6 +1278,12 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind
}
}
fn zirValidateArrayInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO implement Sema.zirValidateArrayInitPtr", .{});
}
fn failWithBadFieldAccess(
sema: *Sema,
block: *Scope.Block,
@ -2064,6 +2101,14 @@ fn zirOptionalTypeFromPtrElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.I
return sema.mod.constType(sema.arena, inst_data.src(), opt_ty);
}
fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
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.mod.constType(sema.arena, src, elem_type);
}
fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
@ -4512,21 +4557,30 @@ fn zirBitSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
return sema.mod.constIntUnsigned(sema.arena, src, Type.initTag(.comptime_int), bit_size);
}
fn zirThis(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
fn zirThis(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirThis", .{});
}
fn zirRetAddr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
fn zirRetAddr(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirRetAddr", .{});
}
fn zirBuiltinSrc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
fn zirBuiltinSrc(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinSrc", .{});
}
@ -4983,6 +5037,18 @@ fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Inn
return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInitAnon", .{});
}
fn zirArrayInit(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.zirArrayInit", .{});
}
fn zirArrayInitAnon(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.zirArrayInitAnon", .{});
}
fn zirFieldTypeRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
@ -4995,21 +5061,30 @@ fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldType", .{});
}
fn zirErrorReturnTrace(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
fn zirErrorReturnTrace(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorReturnTrace", .{});
}
fn zirFrame(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
fn zirFrame(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrame", .{});
}
fn zirFrameAddress(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
fn zirFrameAddress(
sema: *Sema,
block: *Scope.Block,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameAddress", .{});
}
@ -5295,24 +5370,9 @@ fn zirBuiltinAsyncCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) I
return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinAsyncCall", .{});
}
fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const extended = sema.code.instructions.items(.data)[inst].extended;
switch (extended.opcode) {
// zig fmt: off
.func => return sema.zirFuncExtended( block, inst, extended),
.c_undef => return sema.zirCUndef( block, inst, extended),
.c_include => return sema.zirCInclude( block, inst, extended),
.c_define => return sema.zirCDefine( block, inst, extended),
.wasm_memory_size => return sema.zirWasmMemorySize(block, inst, extended),
.wasm_memory_grow => return sema.zirWasmMemoryGrow(block, inst, extended),
// zig fmt: on
}
}
fn zirFuncExtended(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const tracy = trace(@src());
@ -5364,7 +5424,6 @@ fn zirFuncExtended(
fn zirCUndef(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
@ -5375,7 +5434,6 @@ fn zirCUndef(
fn zirCInclude(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
@ -5386,7 +5444,6 @@ fn zirCInclude(
fn zirCDefine(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
@ -5397,7 +5454,6 @@ fn zirCDefine(
fn zirWasmMemorySize(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
@ -5408,7 +5464,6 @@ fn zirWasmMemorySize(
fn zirWasmMemoryGrow(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;

View File

@ -169,6 +169,9 @@ pub const Inst = struct {
/// `[N:S]T` syntax. No source location provided.
/// Uses the `array_type_sentinel` field.
array_type_sentinel,
/// Given an array type, returns the element type.
/// Uses the `un_node` union field.
elem_type,
/// Given a pointer to an indexable object, returns the len property. This is
/// used by for loops. This instruction also emits a for-loop specific compile
/// error if the indexable object is not indexable.
@ -457,12 +460,6 @@ pub const Inst = struct {
/// instruction.
/// Uses the `un_tok` union field.
ref,
/// Obtains a pointer to the return value.
/// Uses the `node` union field.
ret_ptr,
/// Obtains the return type of the in-scope function.
/// Uses the `node` union field.
ret_type,
/// Sends control flow back to the function's callee.
/// Includes an operand as the return value.
/// Includes an AST node source location.
@ -674,6 +671,13 @@ pub const Inst = struct {
/// because it must use one of them to find out the struct type.
/// Uses the `pl_node` field. Payload is `Block`.
validate_struct_init_ptr,
/// Given a set of `elem_ptr_node` instructions, assumes they are all part of an
/// array initialization expression, and emits a compile error if the number of
/// elements does not match the array type.
/// This instruction asserts that there is at least one elem_ptr_node instruction,
/// because it must use one of them to find out the array type.
/// Uses the `pl_node` field. Payload is `Block`.
validate_array_init_ptr,
/// A struct literal with a specified type, with no fields.
/// Uses the `un_node` field.
struct_init_empty,
@ -690,6 +694,18 @@ pub const Inst = struct {
/// Struct initialization without a type.
/// Uses the `pl_node` field. Payload is `StructInitAnon`.
struct_init_anon,
/// Array initialization syntax.
/// Uses the `pl_node` field. Payload is `MultiOp`.
array_init,
/// Anonymous array initialization syntax.
/// Uses the `pl_node` field. Payload is `MultiOp`.
array_init_anon,
/// Array initialization syntax, make the result a pointer.
/// Uses the `pl_node` field. Payload is `MultiOp`.
array_init_ref,
/// Anonymous array initialization syntax, make the result a pointer.
/// Uses the `pl_node` field. Payload is `MultiOp`.
array_init_anon_ref,
/// Given a pointer to a union and a comptime known field name, activates that field
/// and returns a pointer to it.
/// Uses the `pl_node` field. Payload is `UnionInitPtr`.
@ -700,14 +716,8 @@ pub const Inst = struct {
size_of,
/// Implements the `@bitSizeOf` builtin. Uses `un_node`.
bit_size_of,
/// Implements the `@This` builtin. Uses `node`.
this,
/// Implements the `@fence` builtin. Uses `un_node`.
/// Implements the `@fence` builtin. Uses `node`.
fence,
/// Implements the `@returnAddress` builtin. Uses `un_node`.
ret_addr,
/// Implements the `@src` builtin. Uses `un_node`.
builtin_src,
/// Implements the `@addWithOverflow` builtin. Uses `pl_node` with `OverflowArithmetic`.
add_with_overflow,
/// Implements the `@subWithOverflow` builtin. Uses `pl_node` with `OverflowArithmetic`.
@ -717,16 +727,6 @@ pub const Inst = struct {
/// Implements the `@shlWithOverflow` builtin. Uses `pl_node` with `OverflowArithmetic`.
shl_with_overflow,
/// Implements the `@errorReturnTrace` builtin.
/// Uses the `un_node` field.
error_return_trace,
/// Implements the `@frame` builtin.
/// Uses the `un_node` field.
frame,
/// Implements the `@frameAddress` builtin.
/// Uses the `un_node` field.
frame_address,
/// Implement builtin `@ptrToInt`. Uses `un_node`.
ptr_to_int,
/// Implement builtin `@errToInt`. Uses `un_node`.
@ -951,6 +951,7 @@ pub const Inst = struct {
.array_mul,
.array_type,
.array_type_sentinel,
.elem_type,
.indexable_ptr_len,
.as,
.as_node,
@ -970,6 +971,7 @@ pub const Inst = struct {
.bool_and,
.bool_or,
.breakpoint,
.fence,
.call,
.call_chkused,
.call_compile_time,
@ -1026,8 +1028,6 @@ pub const Inst = struct {
.param_type,
.ptrtoint,
.ref,
.ret_ptr,
.ret_type,
.shl,
.shr,
.store,
@ -1094,9 +1094,14 @@ pub const Inst = struct {
.switch_block_ref_under,
.switch_block_ref_under_multi,
.validate_struct_init_ptr,
.validate_array_init_ptr,
.struct_init_empty,
.struct_init,
.struct_init_anon,
.array_init,
.array_init_anon,
.array_init_ref,
.array_init_anon_ref,
.union_init_ptr,
.field_type,
.field_type_ref,
@ -1105,17 +1110,10 @@ pub const Inst = struct {
.type_info,
.size_of,
.bit_size_of,
.this,
.fence,
.ret_addr,
.builtin_src,
.add_with_overflow,
.sub_with_overflow,
.mul_with_overflow,
.shl_with_overflow,
.error_return_trace,
.frame,
.frame_address,
.ptr_to_int,
.align_of,
.bool_to_int,
@ -1211,6 +1209,30 @@ pub const Inst = struct {
/// `operand` is payload index to `ExtendedFunc`.
/// `small` is `ExtendedFunc.Small`.
func,
/// Obtains a pointer to the return value.
/// `operand` is `src_node: i32`.
ret_ptr,
/// Obtains the return type of the in-scope function.
/// `operand` is `src_node: i32`.
ret_type,
/// Implements the `@This` builtin.
/// `operand` is `src_node: i32`.
this,
/// Implements the `@returnAddress` builtin.
/// `operand` is `src_node: i32`.
ret_addr,
/// Implements the `@src` builtin.
/// `operand` is `src_node: i32`.
builtin_src,
/// Implements the `@errorReturnTrace` builtin.
/// `operand` is `src_node: i32`.
error_return_trace,
/// Implements the `@frame` builtin.
/// `operand` is `src_node: i32`.
frame,
/// Implements the `@frameAddress` builtin.
/// `operand` is `src_node: i32`.
frame_address,
/// `operand` is payload index to `UnNode`.
c_undef,
/// `operand` is payload index to `UnNode`.
@ -2281,6 +2303,7 @@ const Writer = struct {
.pop_count,
.byte_swap,
.bit_reverse,
.elem_type,
=> try self.writeUnNode(stream, inst),
.ref,
@ -2317,6 +2340,10 @@ const Writer = struct {
.union_decl,
.struct_init,
.struct_init_anon,
.array_init,
.array_init_anon,
.array_init_ref,
.array_init_anon_ref,
.union_init_ptr,
.field_type,
.field_type_ref,
@ -2409,6 +2436,7 @@ const Writer = struct {
.block_inline_var,
.loop,
.validate_struct_init_ptr,
.validate_array_init_ptr,
.c_import,
=> try self.writePlNodeBlock(stream, inst),
@ -2450,21 +2478,13 @@ const Writer = struct {
.as_node => try self.writeAs(stream, inst),
.breakpoint,
.fence,
.opaque_decl,
.dbg_stmt_node,
.ret_ptr,
.ret_type,
.repeat,
.repeat_inline,
.alloc_inferred,
.alloc_inferred_mut,
.this,
.fence,
.ret_addr,
.builtin_src,
.error_return_trace,
.frame,
.frame_address,
=> try self.writeNode(stream, inst),
.error_value,