diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 71d5e51bb9..ae12fc043f 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1590,7 +1590,6 @@ fn renderStructInit( return renderToken(ais, tree, rbrace, space); } -// TODO: handle comments between elements fn renderArrayInit( gpa: *Allocator, ais: *Ais, diff --git a/src/AstGen.zig b/src/AstGen.zig index dc989b70bd..7a22420d76 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -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), diff --git a/src/Module.zig b/src/Module.zig index 996b83c7ed..660ef9125d 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -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; } diff --git a/src/Sema.zig b/src/Sema.zig index 1d13261458..f25a1e5615 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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; diff --git a/src/Zir.zig b/src/Zir.zig index 5e72e96799..e18396688d 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -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,