From 5e48cdcd10dc81a650c0fab7f4eba53df6b6f720 Mon Sep 17 00:00:00 2001 From: mlugg Date: Wed, 18 Dec 2024 04:01:38 +0000 Subject: [PATCH] compiler: disallow `callconv` etc from depending on function parameters Resolves: #22261 --- lib/std/zig/AstGen.zig | 421 +++++++++++++++------------------------- lib/std/zig/Zir.zig | 111 ++--------- src/InternPool.zig | 47 +---- src/Sema.zig | 358 +++++++++------------------------- src/Zcu/PerThread.zig | 104 +++++----- src/print_zir.zig | 54 ------ test/behavior/align.zig | 41 ---- test/behavior/fn.zig | 25 --- 8 files changed, 320 insertions(+), 841 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 0751de120a91..0a92c5d1886f 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -1420,19 +1420,9 @@ fn fnProtoExpr( .cc_ref = cc, .cc_gz = null, - .align_ref = .none, - .align_gz = null, .ret_ref = ret_ty, .ret_gz = null, - .section_ref = .none, - .section_gz = null, - .addrspace_ref = .none, - .addrspace_gz = null, - - .align_param_refs = &.{}, - .addrspace_param_refs = &.{}, - .section_param_refs = &.{}, - .cc_param_refs = &.{}, + .ret_param_refs = &.{}, .param_insts = &.{}, @@ -4129,6 +4119,8 @@ fn fnDecl( const decl_inst = try gz.makeDeclaration(fn_proto.ast.proto_node); astgen.advanceSourceCursorToNode(decl_node); + const saved_cursor = astgen.saveSourceCursor(); + var decl_gz: GenZir = .{ .is_comptime = true, .decl_node_index = fn_proto.ast.proto_node, @@ -4140,17 +4132,6 @@ fn fnDecl( }; defer decl_gz.unstack(); - var fn_gz: GenZir = .{ - .is_comptime = false, - .decl_node_index = fn_proto.ast.proto_node, - .decl_line = decl_gz.decl_line, - .parent = &decl_gz.base, - .astgen = astgen, - .instructions = gz.instructions, - .instructions_top = GenZir.unstacked_top, - }; - defer fn_gz.unstack(); - // Set this now, since parameter types, return type, etc may be generic. const prev_within_fn = astgen.within_fn; defer astgen.within_fn = prev_within_fn; @@ -4180,7 +4161,7 @@ fn fnDecl( var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len); var noalias_bits: u32 = 0; - var params_scope = &fn_gz.base; + var params_scope = scope; const is_var_args = is_var_args: { var param_type_i: usize = 0; var it = fn_proto.iterate(tree); @@ -4303,47 +4284,26 @@ fn fnDecl( // instructions inside the expression blocks for align, addrspace, cc, and ret_ty // to use the function instruction as the "block" to break from. - var align_gz = decl_gz.makeSubBlock(params_scope); - defer align_gz.unstack(); - const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, coerced_align_ri, fn_proto.ast.align_expr); - if (align_gz.instructionsSlice().len == 0) { - // In this case we will send a len=0 body which can be encoded more efficiently. - break :inst inst; - } - _ = try align_gz.addBreak(.break_inline, @enumFromInt(0), inst); - break :inst inst; - }; - const align_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items); - - var addrspace_gz = decl_gz.makeSubBlock(params_scope); - defer addrspace_gz.unstack(); - const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { - const addrspace_ty = try decl_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space); - const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr); - if (addrspace_gz.instructionsSlice().len == 0) { + var ret_gz = decl_gz.makeSubBlock(params_scope); + defer ret_gz.unstack(); + const ret_ref: Zir.Inst.Ref = inst: { + // Parameters are in scope for the return type, so we use `params_scope` here. + // The calling convention will not have parameters in scope, so we'll just use `scope`. + // See #22263 for a proposal to solve the inconsistency here. + const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal); + if (ret_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; } - _ = try addrspace_gz.addBreak(.break_inline, @enumFromInt(0), inst); + _ = try ret_gz.addBreak(.break_inline, @enumFromInt(0), inst); break :inst inst; }; - const addrspace_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items); + const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items); - var section_gz = decl_gz.makeSubBlock(params_scope); - defer section_gz.unstack(); - const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, fn_proto.ast.section_expr); - if (section_gz.instructionsSlice().len == 0) { - // In this case we will send a len=0 body which can be encoded more efficiently. - break :inst inst; - } - _ = try section_gz.addBreak(.break_inline, @enumFromInt(0), inst); - break :inst inst; - }; - const section_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items); + // We're jumping back in source, so restore the cursor. + astgen.restoreSourceCursor(saved_cursor); - var cc_gz = decl_gz.makeSubBlock(params_scope); + var cc_gz = decl_gz.makeSubBlock(scope); defer cc_gz.unstack(); const cc_ref: Zir.Inst.Ref = blk: { if (fn_proto.ast.callconv_expr != 0) { @@ -4356,7 +4316,7 @@ fn fnDecl( } const inst = try expr( &cc_gz, - params_scope, + scope, .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, fn_proto.ast.callconv_expr, ); @@ -4378,20 +4338,6 @@ fn fnDecl( break :blk .none; } }; - const cc_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items); - - var ret_gz = decl_gz.makeSubBlock(params_scope); - defer ret_gz.unstack(); - const ret_ref: Zir.Inst.Ref = inst: { - const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal); - if (ret_gz.instructionsSlice().len == 0) { - // In this case we will send a len=0 body which can be encoded more efficiently. - break :inst inst; - } - _ = try ret_gz.addBreak(.break_inline, @enumFromInt(0), inst); - break :inst inst; - }; - const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items); const func_inst: Zir.Inst.Ref = if (body_node == 0) func: { if (!is_extern) { @@ -4404,19 +4350,9 @@ fn fnDecl( .src_node = decl_node, .cc_ref = cc_ref, .cc_gz = &cc_gz, - .cc_param_refs = cc_body_param_refs, - .align_ref = align_ref, - .align_gz = &align_gz, - .align_param_refs = align_body_param_refs, .ret_ref = ret_ref, .ret_gz = &ret_gz, .ret_param_refs = ret_body_param_refs, - .section_ref = section_ref, - .section_gz = §ion_gz, - .section_param_refs = section_body_param_refs, - .addrspace_ref = addrspace_ref, - .addrspace_gz = &addrspace_gz, - .addrspace_param_refs = addrspace_body_param_refs, .param_block = decl_inst, .param_insts = param_insts.items, .body_gz = null, @@ -4430,8 +4366,23 @@ fn fnDecl( .proto_hash = undefined, // ignored for `body_gz == null` }); } else func: { - // as a scope, fn_gz encloses ret_gz, but for instruction list, fn_gz stacks on ret_gz - fn_gz.instructions_top = ret_gz.instructions.items.len; + var body_gz: GenZir = .{ + .is_comptime = false, + .decl_node_index = fn_proto.ast.proto_node, + .decl_line = decl_gz.decl_line, + .parent = params_scope, + .astgen = astgen, + .instructions = gz.instructions, + .instructions_top = gz.instructions.items.len, + }; + defer body_gz.unstack(); + + // We want `params_scope` to be stacked like this: + // body_gz (top) + // param2 + // param1 + // param0 + // decl_gz (bottom) // Construct the prototype hash. // Leave `astgen.src_hasher` unmodified; this will be used for hashing @@ -4448,13 +4399,13 @@ fn fnDecl( astgen.fn_block = prev_fn_block; astgen.fn_ret_ty = prev_fn_ret_ty; } - astgen.fn_block = &fn_gz; + astgen.fn_block = &body_gz; astgen.fn_ret_ty = if (is_inferred_error or ret_ref.toIndex() != null) r: { // We're essentially guaranteed to need the return type at some point, // since the return type is likely not `void` or `noreturn` so there // will probably be an explicit return requiring RLS. Fetch this // return type now so the rest of the function can use it. - break :r try fn_gz.addNode(.ret_type, decl_node); + break :r try body_gz.addNode(.ret_type, decl_node); } else ret_ref; const prev_var_args = astgen.fn_var_args; @@ -4465,39 +4416,29 @@ fn fnDecl( const lbrace_line = astgen.source_line - decl_gz.decl_line; const lbrace_column = astgen.source_column; - _ = try fullBodyExpr(&fn_gz, params_scope, .{ .rl = .none }, body_node, .allow_branch_hint); - try checkUsed(gz, &fn_gz.base, params_scope); + _ = try fullBodyExpr(&body_gz, &body_gz.base, .{ .rl = .none }, body_node, .allow_branch_hint); + try checkUsed(gz, scope, params_scope); - if (!fn_gz.endsWithNoReturn()) { + if (!body_gz.endsWithNoReturn()) { // As our last action before the return, "pop" the error trace if needed - _ = try fn_gz.addRestoreErrRetIndex(.ret, .always, decl_node); + _ = try body_gz.addRestoreErrRetIndex(.ret, .always, decl_node); // Add implicit return at end of function. - _ = try fn_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node)); + _ = try body_gz.addUnTok(.ret_implicit, .void_value, tree.lastToken(body_node)); } break :func try decl_gz.addFunc(.{ .src_node = decl_node, .cc_ref = cc_ref, .cc_gz = &cc_gz, - .cc_param_refs = cc_body_param_refs, - .align_ref = align_ref, - .align_gz = &align_gz, - .align_param_refs = align_body_param_refs, .ret_ref = ret_ref, .ret_gz = &ret_gz, .ret_param_refs = ret_body_param_refs, - .section_ref = section_ref, - .section_gz = §ion_gz, - .section_param_refs = section_body_param_refs, - .addrspace_ref = addrspace_ref, - .addrspace_gz = &addrspace_gz, - .addrspace_param_refs = addrspace_body_param_refs, .lbrace_line = lbrace_line, .lbrace_column = lbrace_column, .param_block = decl_inst, .param_insts = param_insts.items, - .body_gz = &fn_gz, + .body_gz = &body_gz, .lib_name = lib_name, .is_var_args = is_var_args, .is_inferred_error = is_inferred_error, @@ -4509,13 +4450,39 @@ fn fnDecl( }); }; + // Before we stack more stuff onto `decl_gz`, add its final instruction. + _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst); + + // Now that `cc_gz,` `ret_gz`, and `body_gz` are unstacked, we evaluate align, addrspace, and linksection. + + // We're jumping back in source, so restore the cursor. + astgen.restoreSourceCursor(saved_cursor); + + var align_gz = decl_gz.makeSubBlock(scope); + defer align_gz.unstack(); + if (fn_proto.ast.align_expr != 0) { + const inst = try expr(&decl_gz, &decl_gz.base, coerced_align_ri, fn_proto.ast.align_expr); + _ = try align_gz.addBreak(.break_inline, decl_inst, inst); + } + + var section_gz = align_gz.makeSubBlock(scope); + defer section_gz.unstack(); + if (fn_proto.ast.section_expr != 0) { + const inst = try expr(&decl_gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, fn_proto.ast.section_expr); + _ = try section_gz.addBreak(.break_inline, decl_inst, inst); + } + + var addrspace_gz = section_gz.makeSubBlock(scope); + defer addrspace_gz.unstack(); + if (fn_proto.ast.addrspace_expr != 0) { + const addrspace_ty = try decl_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space); + const inst = try expr(&decl_gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr); + _ = try addrspace_gz.addBreak(.break_inline, decl_inst, inst); + } + // *Now* we can incorporate the full source code into the hasher. astgen.src_hasher.update(tree.getNodeSource(decl_node)); - // We add this at the end so that its instruction index marks the end range - // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. - _ = try decl_gz.addBreak(.break_inline, decl_inst, func_inst); - var hash: std.zig.SrcHash = undefined; astgen.src_hasher.final(&hash); try setDeclaration( @@ -4526,9 +4493,11 @@ fn fnDecl( is_pub, is_export, &decl_gz, - // align, linksection, and addrspace are passed in the func instruction in this case. - // TODO: move them from the function instruction to the declaration instruction? - null, + .{ + .align_gz = &align_gz, + .linksection_gz = §ion_gz, + .addrspace_gz = &addrspace_gz, + }, ); } @@ -4972,19 +4941,9 @@ fn testDecl( .cc_ref = .none, .cc_gz = null, - .align_ref = .none, - .align_gz = null, .ret_ref = .anyerror_void_error_union_type, .ret_gz = null, - .section_ref = .none, - .section_gz = null, - .addrspace_ref = .none, - .addrspace_gz = null, - - .align_param_refs = &.{}, - .addrspace_param_refs = &.{}, - .section_param_refs = &.{}, - .cc_param_refs = &.{}, + .ret_param_refs = &.{}, .param_insts = &.{}, @@ -11937,6 +11896,14 @@ const GenZir = struct { self.instructions.items[self.instructions_top..]; } + fn instructionsSliceUptoOpt(gz: *const GenZir, maybe_stacked_gz: ?*GenZir) []Zir.Inst.Index { + if (maybe_stacked_gz) |stacked_gz| { + return gz.instructionsSliceUpto(stacked_gz); + } else { + return gz.instructionsSlice(); + } + } + fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { return .{ .is_comptime = gz.is_comptime, @@ -12073,11 +12040,8 @@ const GenZir = struct { /// Must be called with the following stack set up: /// * gz (bottom) - /// * align_gz - /// * addrspace_gz - /// * section_gz - /// * cc_gz /// * ret_gz + /// * cc_gz /// * body_gz (top) /// Unstacks all of those except for `gz`. fn addFunc( @@ -12088,23 +12052,13 @@ const GenZir = struct { lbrace_column: u32 = 0, param_block: Zir.Inst.Index, - align_gz: ?*GenZir, - addrspace_gz: ?*GenZir, - section_gz: ?*GenZir, - cc_gz: ?*GenZir, ret_gz: ?*GenZir, body_gz: ?*GenZir, + cc_gz: ?*GenZir, - align_param_refs: []Zir.Inst.Index, - addrspace_param_refs: []Zir.Inst.Index, - section_param_refs: []Zir.Inst.Index, - cc_param_refs: []Zir.Inst.Index, ret_param_refs: []Zir.Inst.Index, param_insts: []Zir.Inst.Index, // refs to params in `body_gz` should still be in `astgen.ref_table` - align_ref: Zir.Inst.Ref, - addrspace_ref: Zir.Inst.Ref, - section_ref: Zir.Inst.Ref, cc_ref: Zir.Inst.Ref, ret_ref: Zir.Inst.Ref, @@ -12126,13 +12080,31 @@ const GenZir = struct { const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref; const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); + try gz.instructions.ensureUnusedCapacity(gpa, 1); try astgen.instructions.ensureUnusedCapacity(gpa, 1); - var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; - var ret_body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; + const body, const cc_body, const ret_body = bodies: { + var stacked_gz: ?*GenZir = null; + const body: []const Zir.Inst.Index = if (args.body_gz) |body_gz| body: { + const body = body_gz.instructionsSliceUptoOpt(stacked_gz); + stacked_gz = body_gz; + break :body body; + } else &.{}; + const cc_body: []const Zir.Inst.Index = if (args.cc_gz) |cc_gz| body: { + const cc_body = cc_gz.instructionsSliceUptoOpt(stacked_gz); + stacked_gz = cc_gz; + break :body cc_body; + } else &.{}; + const ret_body: []const Zir.Inst.Index = if (args.ret_gz) |ret_gz| body: { + const ret_body = ret_gz.instructionsSliceUptoOpt(stacked_gz); + stacked_gz = ret_gz; + break :body ret_body; + } else &.{}; + break :bodies .{ body, cc_body, ret_body }; + }; + var src_locs_and_hash_buffer: [7]u32 = undefined; - var src_locs_and_hash: []u32 = src_locs_and_hash_buffer[0..0]; - if (args.body_gz) |body_gz| { + const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: { const tree = astgen.tree; const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); @@ -12158,39 +12130,19 @@ const GenZir = struct { proto_hash_arr[2], proto_hash_arr[3], }; - src_locs_and_hash = &src_locs_and_hash_buffer; + break :src_locs_and_hash &src_locs_and_hash_buffer; + } else &.{}; - body = body_gz.instructionsSlice(); - if (args.ret_gz) |ret_gz| - ret_body = ret_gz.instructionsSliceUpto(body_gz); - } else { - if (args.ret_gz) |ret_gz| - ret_body = ret_gz.instructionsSlice(); - } const body_len = astgen.countBodyLenAfterFixupsExtraRefs(body, args.param_insts); - if (args.cc_ref != .none or args.lib_name != .empty or args.is_var_args or args.is_test or - args.is_extern or args.align_ref != .none or args.section_ref != .none or - args.addrspace_ref != .none or args.noalias_bits != 0 or args.is_noinline) - { - var align_body: []Zir.Inst.Index = &.{}; - var addrspace_body: []Zir.Inst.Index = &.{}; - var section_body: []Zir.Inst.Index = &.{}; - var cc_body: []Zir.Inst.Index = &.{}; - if (args.ret_gz != null) { - align_body = args.align_gz.?.instructionsSliceUpto(args.addrspace_gz.?); - addrspace_body = args.addrspace_gz.?.instructionsSliceUpto(args.section_gz.?); - section_body = args.section_gz.?.instructionsSliceUpto(args.cc_gz.?); - cc_body = args.cc_gz.?.instructionsSliceUpto(args.ret_gz.?); - } - + const tag: Zir.Inst.Tag, const payload_index: u32 = if (args.cc_ref != .none or args.lib_name != .empty or + args.is_var_args or args.is_test or args.is_extern or + args.noalias_bits != 0 or args.is_noinline) + inst_info: { try astgen.extra.ensureUnusedCapacity( gpa, @typeInfo(Zir.Inst.FuncFancy).@"struct".fields.len + - fancyFnExprExtraLen(astgen, args.align_param_refs, align_body, args.align_ref) + - fancyFnExprExtraLen(astgen, args.addrspace_param_refs, addrspace_body, args.addrspace_ref) + - fancyFnExprExtraLen(astgen, args.section_param_refs, section_body, args.section_ref) + - fancyFnExprExtraLen(astgen, args.cc_param_refs, cc_body, args.cc_ref) + + fancyFnExprExtraLen(astgen, &.{}, cc_body, args.cc_ref) + fancyFnExprExtraLen(astgen, args.ret_param_refs, ret_body, ret_ref) + body_len + src_locs_and_hash.len + @intFromBool(args.lib_name != .empty) + @@ -12208,15 +12160,9 @@ const GenZir = struct { .has_lib_name = args.lib_name != .empty, .has_any_noalias = args.noalias_bits != 0, - .has_align_ref = args.align_ref != .none, - .has_addrspace_ref = args.addrspace_ref != .none, - .has_section_ref = args.section_ref != .none, .has_cc_ref = args.cc_ref != .none, .has_ret_ty_ref = ret_ref != .none, - .has_align_body = align_body.len != 0, - .has_addrspace_body = addrspace_body.len != 0, - .has_section_body = section_body.len != 0, .has_cc_body = cc_body.len != 0, .has_ret_ty_body = ret_body.len != 0, }, @@ -12226,53 +12172,8 @@ const GenZir = struct { } const zir_datas = astgen.instructions.items(.data); - if (align_body.len != 0) { - astgen.extra.appendAssumeCapacity( - astgen.countBodyLenAfterFixups(args.align_param_refs) + - astgen.countBodyLenAfterFixups(align_body), - ); - astgen.appendBodyWithFixups(args.align_param_refs); - astgen.appendBodyWithFixups(align_body); - const break_extra = zir_datas[@intFromEnum(align_body[align_body.len - 1])].@"break".payload_index; - astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] = - @intFromEnum(new_index); - } else if (args.align_ref != .none) { - astgen.extra.appendAssumeCapacity(@intFromEnum(args.align_ref)); - } - if (addrspace_body.len != 0) { - astgen.extra.appendAssumeCapacity( - astgen.countBodyLenAfterFixups(args.addrspace_param_refs) + - astgen.countBodyLenAfterFixups(addrspace_body), - ); - astgen.appendBodyWithFixups(args.addrspace_param_refs); - astgen.appendBodyWithFixups(addrspace_body); - const break_extra = - zir_datas[@intFromEnum(addrspace_body[addrspace_body.len - 1])].@"break".payload_index; - astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] = - @intFromEnum(new_index); - } else if (args.addrspace_ref != .none) { - astgen.extra.appendAssumeCapacity(@intFromEnum(args.addrspace_ref)); - } - if (section_body.len != 0) { - astgen.extra.appendAssumeCapacity( - astgen.countBodyLenAfterFixups(args.section_param_refs) + - astgen.countBodyLenAfterFixups(section_body), - ); - astgen.appendBodyWithFixups(args.section_param_refs); - astgen.appendBodyWithFixups(section_body); - const break_extra = - zir_datas[@intFromEnum(section_body[section_body.len - 1])].@"break".payload_index; - astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] = - @intFromEnum(new_index); - } else if (args.section_ref != .none) { - astgen.extra.appendAssumeCapacity(@intFromEnum(args.section_ref)); - } if (cc_body.len != 0) { - astgen.extra.appendAssumeCapacity( - astgen.countBodyLenAfterFixups(args.cc_param_refs) + - astgen.countBodyLenAfterFixups(cc_body), - ); - astgen.appendBodyWithFixups(args.cc_param_refs); + astgen.extra.appendAssumeCapacity(astgen.countBodyLenAfterFixups(cc_body)); astgen.appendBodyWithFixups(cc_body); const break_extra = zir_datas[@intFromEnum(cc_body[cc_body.len - 1])].@"break".payload_index; astgen.extra.items[break_extra + std.meta.fieldIndex(Zir.Inst.Break, "block_inst").?] = @@ -12301,28 +12202,8 @@ const GenZir = struct { astgen.appendBodyWithFixupsExtraRefsArrayList(&astgen.extra, body, args.param_insts); astgen.extra.appendSliceAssumeCapacity(src_locs_and_hash); - // Order is important when unstacking. - if (args.body_gz) |body_gz| body_gz.unstack(); - if (args.ret_gz != null) { - args.ret_gz.?.unstack(); - args.cc_gz.?.unstack(); - args.section_gz.?.unstack(); - args.addrspace_gz.?.unstack(); - args.align_gz.?.unstack(); - } - - try gz.instructions.ensureUnusedCapacity(gpa, 1); - - astgen.instructions.appendAssumeCapacity(.{ - .tag = .func_fancy, - .data = .{ .pl_node = .{ - .src_node = gz.nodeIndexToRelative(args.src_node), - .payload_index = payload_index, - } }, - }); - gz.instructions.appendAssumeCapacity(new_index); - return new_index.toRef(); - } else { + break :inst_info .{ .func_fancy, payload_index }; + } else inst_info: { try astgen.extra.ensureUnusedCapacity( gpa, @typeInfo(Zir.Inst.Func).@"struct".fields.len + 1 + @@ -12354,30 +12235,29 @@ const GenZir = struct { astgen.appendBodyWithFixupsExtraRefsArrayList(&astgen.extra, body, args.param_insts); astgen.extra.appendSliceAssumeCapacity(src_locs_and_hash); - // Order is important when unstacking. - if (args.body_gz) |body_gz| body_gz.unstack(); - if (args.ret_gz) |ret_gz| ret_gz.unstack(); - if (args.cc_gz) |cc_gz| cc_gz.unstack(); - if (args.section_gz) |section_gz| section_gz.unstack(); - if (args.addrspace_gz) |addrspace_gz| addrspace_gz.unstack(); - if (args.align_gz) |align_gz| align_gz.unstack(); + break :inst_info .{ + if (args.is_inferred_error) .func_inferred else .func, + payload_index, + }; + }; - try gz.instructions.ensureUnusedCapacity(gpa, 1); + // Order is important when unstacking. + if (args.body_gz) |body_gz| body_gz.unstack(); + if (args.cc_gz) |cc_gz| cc_gz.unstack(); + if (args.ret_gz) |ret_gz| ret_gz.unstack(); - const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; - astgen.instructions.appendAssumeCapacity(.{ - .tag = tag, - .data = .{ .pl_node = .{ - .src_node = gz.nodeIndexToRelative(args.src_node), - .payload_index = payload_index, - } }, - }); - gz.instructions.appendAssumeCapacity(new_index); - return new_index.toRef(); - } + astgen.instructions.appendAssumeCapacity(.{ + .tag = tag, + .data = .{ .pl_node = .{ + .src_node = gz.nodeIndexToRelative(args.src_node), + .payload_index = payload_index, + } }, + }); + gz.instructions.appendAssumeCapacity(new_index); + return new_index.toRef(); } - fn fancyFnExprExtraLen(astgen: *AstGen, param_refs_body: []Zir.Inst.Index, main_body: []Zir.Inst.Index, ref: Zir.Inst.Ref) u32 { + fn fancyFnExprExtraLen(astgen: *AstGen, param_refs_body: []const Zir.Inst.Index, main_body: []const Zir.Inst.Index, ref: Zir.Inst.Ref) u32 { return countBodyLenAfterFixups(astgen, param_refs_body) + countBodyLenAfterFixups(astgen, main_body) + // If there is a body, we need an element for its length; otherwise, if there is a ref, we need to include that. @@ -13561,6 +13441,27 @@ fn advanceSourceCursor(astgen: *AstGen, end: usize) void { astgen.source_column = column; } +const SourceCursor = struct { + offset: u32, + line: u32, + column: u32, +}; + +/// Get the current source cursor, to be restored later with `restoreSourceCursor`. +/// This is useful when analyzing source code out-of-order. +fn saveSourceCursor(astgen: *const AstGen) SourceCursor { + return .{ + .offset = astgen.source_offset, + .line = astgen.source_line, + .column = astgen.source_column, + }; +} +fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void { + astgen.source_offset = cursor.offset; + astgen.source_line = cursor.line; + astgen.source_column = cursor.column; +} + /// Detects name conflicts for decls and fields, and populates `namespace.decls` with all named declarations. /// Returns the number of declarations in the namespace, including unnamed declarations (e.g. `comptime` decls). fn scanContainer( diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 193f83104934..7550fcd1fd11 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2494,46 +2494,25 @@ pub const Inst = struct { /// Trailing: /// 0. lib_name: NullTerminatedString, // null terminated string index, if has_lib_name is set - /// if (has_align_ref and !has_align_body) { - /// 1. align: Ref, - /// } - /// if (has_align_body) { - /// 2. align_body_len: u32 - /// 3. align_body: u32 // for each align_body_len - /// } - /// if (has_addrspace_ref and !has_addrspace_body) { - /// 4. addrspace: Ref, - /// } - /// if (has_addrspace_body) { - /// 5. addrspace_body_len: u32 - /// 6. addrspace_body: u32 // for each addrspace_body_len - /// } - /// if (has_section_ref and !has_section_body) { - /// 7. section: Ref, - /// } - /// if (has_section_body) { - /// 8. section_body_len: u32 - /// 9. section_body: u32 // for each section_body_len - /// } /// if (has_cc_ref and !has_cc_body) { - /// 10. cc: Ref, + /// 1. cc: Ref, /// } /// if (has_cc_body) { - /// 11. cc_body_len: u32 - /// 12. cc_body: u32 // for each cc_body_len + /// 2. cc_body_len: u32 + /// 3. cc_body: u32 // for each cc_body_len /// } /// if (has_ret_ty_ref and !has_ret_ty_body) { - /// 13. ret_ty: Ref, + /// 4. ret_ty: Ref, /// } /// if (has_ret_ty_body) { - /// 14. ret_ty_body_len: u32 - /// 15. ret_ty_body: u32 // for each ret_ty_body_len + /// 5. ret_ty_body_len: u32 + /// 6. ret_ty_body: u32 // for each ret_ty_body_len /// } - /// 16. noalias_bits: u32 // if has_any_noalias - /// - each bit starting with LSB corresponds to parameter indexes - /// 17. body: Index // for each body_len - /// 18. src_locs: Func.SrcLocs // if body_len != 0 - /// 19. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype + /// 7. noalias_bits: u32 // if has_any_noalias + /// - each bit starting with LSB corresponds to parameter indexes + /// 8. body: Index // for each body_len + /// 9. src_locs: Func.SrcLocs // if body_len != 0 + /// 10. proto_hash: std.zig.SrcHash // if body_len != 0; hash of function prototype pub const FuncFancy = struct { /// Points to the block that contains the param instructions for this function. /// If this is a `declaration`, it refers to the declaration's value body. @@ -2542,29 +2521,20 @@ pub const Inst = struct { bits: Bits, /// If both has_cc_ref and has_cc_body are false, it means auto calling convention. - /// If both has_align_ref and has_align_body are false, it means default alignment. /// If both has_ret_ty_ref and has_ret_ty_body are false, it means void return type. - /// If both has_section_ref and has_section_body are false, it means default section. - /// If both has_addrspace_ref and has_addrspace_body are false, it means default addrspace. pub const Bits = packed struct { is_var_args: bool, is_inferred_error: bool, is_test: bool, is_extern: bool, is_noinline: bool, - has_align_ref: bool, - has_align_body: bool, - has_addrspace_ref: bool, - has_addrspace_body: bool, - has_section_ref: bool, - has_section_body: bool, has_cc_ref: bool, has_cc_body: bool, has_ret_ty_ref: bool, has_ret_ty_body: bool, has_lib_name: bool, has_any_noalias: bool, - _: u15 = undefined, + _: u21 = undefined, }; }; @@ -4268,36 +4238,6 @@ fn findTrackableInner( var extra_index: usize = extra.end; extra_index += @intFromBool(extra.data.bits.has_lib_name); - if (extra.data.bits.has_align_body) { - const body_len = zir.extra[extra_index]; - extra_index += 1; - const body = zir.bodySlice(extra_index, body_len); - try zir.findTrackableBody(gpa, contents, defers, body); - extra_index += body.len; - } else if (extra.data.bits.has_align_ref) { - extra_index += 1; - } - - if (extra.data.bits.has_addrspace_body) { - const body_len = zir.extra[extra_index]; - extra_index += 1; - const body = zir.bodySlice(extra_index, body_len); - try zir.findTrackableBody(gpa, contents, defers, body); - extra_index += body.len; - } else if (extra.data.bits.has_addrspace_ref) { - extra_index += 1; - } - - if (extra.data.bits.has_section_body) { - const body_len = zir.extra[extra_index]; - extra_index += 1; - const body = zir.bodySlice(extra_index, body_len); - try zir.findTrackableBody(gpa, contents, defers, body); - extra_index += body.len; - } else if (extra.data.bits.has_section_ref) { - extra_index += 1; - } - if (extra.data.bits.has_cc_body) { const body_len = zir.extra[extra_index]; extra_index += 1; @@ -4586,21 +4526,6 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo { var ret_ty_body: []const Inst.Index = &.{}; extra_index += @intFromBool(extra.data.bits.has_lib_name); - if (extra.data.bits.has_align_body) { - extra_index += zir.extra[extra_index] + 1; - } else if (extra.data.bits.has_align_ref) { - extra_index += 1; - } - if (extra.data.bits.has_addrspace_body) { - extra_index += zir.extra[extra_index] + 1; - } else if (extra.data.bits.has_addrspace_ref) { - extra_index += 1; - } - if (extra.data.bits.has_section_body) { - extra_index += zir.extra[extra_index] + 1; - } else if (extra.data.bits.has_section_ref) { - extra_index += 1; - } if (extra.data.bits.has_cc_body) { extra_index += zir.extra[extra_index] + 1; } else if (extra.data.bits.has_cc_ref) { @@ -4711,18 +4636,6 @@ pub fn getAssociatedSrcHash(zir: Zir, inst: Zir.Inst.Index) ?std.zig.SrcHash { const bits = extra.data.bits; var extra_index = extra.end; extra_index += @intFromBool(bits.has_lib_name); - if (bits.has_align_body) { - const body_len = zir.extra[extra_index]; - extra_index += 1 + body_len; - } else extra_index += @intFromBool(bits.has_align_ref); - if (bits.has_addrspace_body) { - const body_len = zir.extra[extra_index]; - extra_index += 1 + body_len; - } else extra_index += @intFromBool(bits.has_addrspace_ref); - if (bits.has_section_body) { - const body_len = zir.extra[extra_index]; - extra_index += 1 + body_len; - } else extra_index += @intFromBool(bits.has_section_ref); if (bits.has_cc_body) { const body_len = zir.extra[extra_index]; extra_index += 1 + body_len; diff --git a/src/InternPool.zig b/src/InternPool.zig index db55ba2465d9..cf3b9c196b8e 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -1961,9 +1961,6 @@ pub const Key = union(enum) { is_var_args: bool, is_generic: bool, is_noinline: bool, - cc_is_generic: bool, - section_is_generic: bool, - addrspace_is_generic: bool, pub fn paramIsComptime(self: @This(), i: u5) bool { assert(i < self.param_types.len); @@ -5456,10 +5453,7 @@ pub const Tag = enum(u8) { has_comptime_bits: bool, has_noalias_bits: bool, is_noinline: bool, - cc_is_generic: bool, - section_is_generic: bool, - addrspace_is_generic: bool, - _: u6 = 0, + _: u9 = 0, }; }; @@ -6885,9 +6879,6 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke .cc = type_function.data.flags.cc.unpack(), .is_var_args = type_function.data.flags.is_var_args, .is_noinline = type_function.data.flags.is_noinline, - .cc_is_generic = type_function.data.flags.cc_is_generic, - .section_is_generic = type_function.data.flags.section_is_generic, - .addrspace_is_generic = type_function.data.flags.addrspace_is_generic, .is_generic = type_function.data.flags.is_generic, }; } @@ -8529,9 +8520,6 @@ pub fn getFuncType( .has_noalias_bits = key.noalias_bits != 0, .is_generic = key.is_generic, .is_noinline = key.is_noinline, - .cc_is_generic = key.cc == null, - .section_is_generic = key.section_is_generic, - .addrspace_is_generic = key.addrspace_is_generic, }, }); @@ -8703,10 +8691,6 @@ pub const GetFuncDeclIesKey = struct { bare_return_type: Index, /// null means generic. cc: ?std.builtin.CallingConvention, - /// null means generic. - alignment: ?Alignment, - section_is_generic: bool, - addrspace_is_generic: bool, is_var_args: bool, is_generic: bool, is_noinline: bool, @@ -8792,9 +8776,6 @@ pub fn getFuncDeclIes( .has_noalias_bits = key.noalias_bits != 0, .is_generic = key.is_generic, .is_noinline = key.is_noinline, - .cc_is_generic = key.cc == null, - .section_is_generic = key.section_is_generic, - .addrspace_is_generic = key.addrspace_is_generic, }, }); if (key.comptime_bits != 0) extra.appendAssumeCapacity(.{key.comptime_bits}); @@ -8926,9 +8907,6 @@ pub const GetFuncInstanceKey = struct { comptime_args: []const Index, noalias_bits: u32, bare_return_type: Index, - cc: std.builtin.CallingConvention, - alignment: Alignment, - section: OptionalNullTerminatedString, is_noinline: bool, generic_owner: Index, inferred_error_set: bool, @@ -8943,11 +8921,14 @@ pub fn getFuncInstance( if (arg.inferred_error_set) return getFuncInstanceIes(ip, gpa, tid, arg); + const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); + const generic_owner_ty = ip.indexToKey(ip.funcDeclInfo(generic_owner).ty).func_type; + const func_ty = try ip.getFuncType(gpa, tid, .{ .param_types = arg.param_types, .return_type = arg.bare_return_type, .noalias_bits = arg.noalias_bits, - .cc = arg.cc, + .cc = generic_owner_ty.cc, .is_noinline = arg.is_noinline, }); @@ -8957,8 +8938,6 @@ pub fn getFuncInstance( try extra.ensureUnusedCapacity(@typeInfo(Tag.FuncInstance).@"struct".fields.len + arg.comptime_args.len); - const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); - assert(arg.comptime_args.len == ip.funcTypeParamsLen(ip.typeOf(generic_owner))); const prev_extra_len = extra.mutate.len; @@ -9005,8 +8984,6 @@ pub fn getFuncInstance( generic_owner, func_index, func_extra_index, - arg.alignment, - arg.section, ); return gop.put(); } @@ -9031,6 +9008,7 @@ pub fn getFuncInstanceIes( try items.ensureUnusedCapacity(4); const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner); + const generic_owner_ty = ip.indexToKey(ip.funcDeclInfo(arg.generic_owner).ty).func_type; // The strategy here is to add the function decl unconditionally, then to // ask if it already exists, and if so, revert the lengths of the mutated @@ -9086,15 +9064,12 @@ pub fn getFuncInstanceIes( .params_len = params_len, .return_type = error_union_type, .flags = .{ - .cc = .pack(arg.cc), + .cc = .pack(generic_owner_ty.cc), .is_var_args = false, .has_comptime_bits = false, .has_noalias_bits = arg.noalias_bits != 0, .is_generic = false, .is_noinline = arg.is_noinline, - .cc_is_generic = false, - .section_is_generic = false, - .addrspace_is_generic = false, }, }); // no comptime_bits because has_comptime_bits is false @@ -9158,8 +9133,6 @@ pub fn getFuncInstanceIes( generic_owner, func_index, func_extra_index, - arg.alignment, - arg.section, ); func_gop.putFinal(func_index); @@ -9177,8 +9150,6 @@ fn finishFuncInstance( generic_owner: Index, func_index: Index, func_extra_index: u32, - alignment: Alignment, - section: OptionalNullTerminatedString, ) Allocator.Error!void { const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav); const fn_namespace = ip.getCau(fn_owner_nav.analysis_owner.unwrap().?).namespace; @@ -9191,8 +9162,8 @@ fn finishFuncInstance( .name = nav_name, .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), .val = func_index, - .alignment = alignment, - .@"linksection" = section, + .alignment = fn_owner_nav.status.resolved.alignment, + .@"linksection" = fn_owner_nav.status.resolved.@"linksection", .@"addrspace" = fn_owner_nav.status.resolved.@"addrspace", }); diff --git a/src/Sema.zig b/src/Sema.zig index f46032fc3231..110476adf9e3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7815,11 +7815,9 @@ fn analyzeCall( .param_types = new_param_types, .return_type = owner_info.return_type, .noalias_bits = owner_info.noalias_bits, - .cc = if (owner_info.cc_is_generic) null else owner_info.cc, + .cc = owner_info.cc, .is_var_args = owner_info.is_var_args, .is_noinline = owner_info.is_noinline, - .section_is_generic = owner_info.section_is_generic, - .addrspace_is_generic = owner_info.addrspace_is_generic, .is_generic = owner_info.is_generic, }; @@ -9555,9 +9553,6 @@ fn zirFunc( block, inst_data.src_node, inst, - .none, - target_util.defaultAddressSpace(target, .function), - .default, cc, ret_ty, false, @@ -9843,13 +9838,7 @@ fn funcCommon( block: *Block, src_node_offset: i32, func_inst: Zir.Inst.Index, - /// null means generic poison - alignment: ?Alignment, - /// null means generic poison - address_space: ?std.builtin.AddressSpace, - section: Section, - /// null means generic poison - cc: ?std.builtin.CallingConvention, + cc: std.builtin.CallingConvention, /// this might be Type.generic_poison bare_return_type: Type, var_args: bool, @@ -9870,26 +9859,17 @@ fn funcCommon( const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); const func_src = block.nodeOffset(src_node_offset); - var is_generic = bare_return_type.isGenericPoison() or - alignment == null or - address_space == null or - section == .generic or - cc == null; + var is_generic = bare_return_type.isGenericPoison(); if (var_args) { if (is_generic) { return sema.fail(block, func_src, "generic function cannot be variadic", .{}); } - try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?); + try sema.checkCallConvSupportsVarArgs(block, cc_src, cc); } const is_source_decl = sema.generic_owner == .none; - // In the case of generic calling convention, or generic alignment, we use - // default values which are only meaningful for the generic function, *not* - // the instantiation, which can depend on comptime parameters. - // Related proposal: https://github.com/ziglang/zig/issues/11834 - const cc_resolved = cc orelse .auto; var comptime_bits: u32 = 0; for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { const param_ty = Type.fromInterned(param_ty_ip); @@ -9907,11 +9887,11 @@ fn funcCommon( } const this_generic = param_ty.isGenericPoison(); is_generic = is_generic or this_generic; - if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(cc_resolved)) { - return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); + if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(cc)) { + return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); } - if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(cc_resolved)) { - return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)}); + if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(cc)) { + return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); } if (!param_ty.isValidParamType(zcu)) { const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; @@ -9919,10 +9899,10 @@ fn funcCommon( opaque_str, param_ty.fmt(pt), }); } - if (!this_generic and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) { + if (!this_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) { const msg = msg: { const msg = try sema.errMsg(param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ - param_ty.fmt(pt), @tagName(cc_resolved), + param_ty.fmt(pt), @tagName(cc), }); errdefer msg.destroy(sema.gpa); @@ -9952,13 +9932,13 @@ fn funcCommon( { return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); } - switch (cc_resolved) { + switch (cc) { .x86_64_interrupt, .x86_interrupt => { const err_code_size = target.ptrBitWidth(); switch (i) { - 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc_resolved)}), - 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc_resolved), err_code_size }), - else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc_resolved), i + 1 }), + 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}), + 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }), + else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), i + 1 }), } }, .arm_interrupt, @@ -9970,7 +9950,7 @@ fn funcCommon( .csky_interrupt, .m68k_interrupt, .avr_signal, - => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc_resolved)}), + => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}), else => {}, } } @@ -9985,9 +9965,6 @@ fn funcCommon( assert(has_body); assert(!is_generic); assert(comptime_bits == 0); - assert(cc != null); - assert(section != .generic); - assert(address_space != null); assert(!var_args); if (inferred_error_set) { try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src); @@ -9996,13 +9973,6 @@ fn funcCommon( .param_types = param_types, .noalias_bits = noalias_bits, .bare_return_type = bare_return_type.toIntern(), - .cc = cc_resolved, - .alignment = alignment.?, - .section = switch (section) { - .generic => unreachable, - .default => .none, - .explicit => |x| x.toOptional(), - }, .is_noinline = is_noinline, .inferred_error_set = inferred_error_set, .generic_owner = sema.generic_owner, @@ -10016,7 +9986,7 @@ fn funcCommon( ret_poison, bare_return_type, ret_ty_src, - cc_resolved, + cc, is_source_decl, ret_ty_requires_comptime, func_inst, @@ -10027,12 +9997,6 @@ fn funcCommon( ); } - const section_name: InternPool.OptionalNullTerminatedString = switch (section) { - .generic => .none, - .default => .none, - .explicit => |name| name.toOptional(), - }; - if (inferred_error_set) { assert(!is_extern); assert(has_body); @@ -10046,9 +10010,6 @@ fn funcCommon( .comptime_bits = comptime_bits, .bare_return_type = bare_return_type.toIntern(), .cc = cc, - .alignment = alignment, - .section_is_generic = section == .generic, - .addrspace_is_generic = address_space == null, .is_var_args = var_args, .is_generic = final_is_generic, .is_noinline = is_noinline, @@ -10059,13 +10020,6 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), }); - // func_decl functions take ownership of the `Nav` of Sema'a owner `Cau`. - ip.resolveNavValue(sema.getOwnerCauNav(), .{ - .val = func_index, - .alignment = alignment orelse .none, - .@"linksection" = section_name, - .@"addrspace" = address_space orelse .generic, - }); return finishFunc( sema, block, @@ -10074,7 +10028,7 @@ fn funcCommon( ret_poison, bare_return_type, ret_ty_src, - cc_resolved, + cc, is_source_decl, ret_ty_requires_comptime, func_inst, @@ -10091,8 +10045,6 @@ fn funcCommon( .comptime_bits = comptime_bits, .return_type = bare_return_type.toIntern(), .cc = cc, - .section_is_generic = section == .generic, - .addrspace_is_generic = address_space == null, .is_var_args = var_args, .is_generic = final_is_generic, .is_noinline = is_noinline, @@ -10100,38 +10052,20 @@ fn funcCommon( if (is_extern) { assert(comptime_bits == 0); - assert(cc != null); - assert(alignment != null); - assert(section != .generic); - assert(address_space != null); assert(!is_generic); if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, block.src(.{ .node_offset_lib_name = src_node_offset, }), lib_name); - const func_index = try pt.getExtern(.{ - .name = sema.getOwnerCauNavName(), - .ty = func_ty, - .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, opt_lib_name, .no_embedded_nulls), - .is_const = true, - .is_threadlocal = false, - .is_weak_linkage = false, - .is_dll_import = false, - .alignment = alignment orelse .none, - .@"addrspace" = address_space orelse .generic, - .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction - .owner_nav = undefined, // ignored by `getExtern` - }); - // Note that unlike function declaration, extern functions don't touch the - // Sema's owner Cau's owner Nav. The alignment etc were passed above. + const extern_func_index = try sema.resolveExternDecl(block, .fromInterned(func_ty), opt_lib_name, true, false); return finishFunc( sema, block, - func_index, + extern_func_index, func_ty, ret_poison, bare_return_type, ret_ty_src, - cc_resolved, + cc, is_source_decl, ret_ty_requires_comptime, func_inst, @@ -10154,13 +10088,6 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), }); - // func_decl functions take ownership of the `Nav` of Sema'a owner `Cau`. - ip.resolveNavValue(sema.getOwnerCauNav(), .{ - .val = func_index, - .alignment = alignment orelse .none, - .@"linksection" = section_name, - .@"addrspace" = address_space orelse .generic, - }); return finishFunc( sema, block, @@ -10169,7 +10096,7 @@ fn funcCommon( ret_poison, bare_return_type, ret_ty_src, - cc_resolved, + cc, is_source_decl, ret_ty_requires_comptime, func_inst, @@ -10188,7 +10115,7 @@ fn funcCommon( ret_poison, bare_return_type, ret_ty_src, - cc_resolved, + cc, is_source_decl, ret_ty_requires_comptime, func_inst, @@ -26839,52 +26766,8 @@ fn zirVarExtended( try sema.validateVarType(block, ty_src, var_ty, small.is_extern); if (small.is_extern) { - // We need to resolve the alignment and addrspace early. - // Keep in sync with logic in `Zcu.PerThread.semaCau`. - const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); - const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); - - const decl_inst, const decl_bodies = decl: { - const decl_inst = sema.getOwnerCauDeclInst().resolve(ip) orelse return error.AnalysisFail; - const zir_decl, const extra_end = sema.code.getDeclaration(decl_inst); - break :decl .{ decl_inst, zir_decl.getBodies(extra_end, sema.code) }; - }; - - const alignment: InternPool.Alignment = a: { - const align_body = decl_bodies.align_body orelse break :a .none; - const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst); - break :a try sema.analyzeAsAlign(block, align_src, align_ref); - }; - - const @"addrspace": std.builtin.AddressSpace = as: { - const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(var_ty.toIntern())) { - .func_type => .function, - else => .variable, - }; - const target = zcu.getTarget(); - const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) { - .function => target_util.defaultAddressSpace(target, .function), - .variable => target_util.defaultAddressSpace(target, .global_mutable), - .constant => target_util.defaultAddressSpace(target, .global_constant), - else => unreachable, - }; - const addrspace_ref = try sema.resolveInlineBody(block, addrspace_body, decl_inst); - break :as try sema.analyzeAsAddressSpace(block, addrspace_src, addrspace_ref, addrspace_ctx); - }; - - return Air.internedToRef(try pt.getExtern(.{ - .name = sema.getOwnerCauNavName(), - .ty = var_ty.toIntern(), - .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls), - .is_const = small.is_const, - .is_threadlocal = small.is_threadlocal, - .is_weak_linkage = false, - .is_dll_import = false, - .alignment = alignment, - .@"addrspace" = @"addrspace", - .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction - .owner_nav = undefined, // ignored by `getExtern` - })); + const extern_val = try sema.resolveExternDecl(block, var_ty, lib_name, small.is_const, small.is_threadlocal); + return Air.internedToRef(extern_val); } assert(!small.is_const); // non-const non-extern variable is not legal return Air.internedToRef(try pt.intern(.{ .variable = .{ @@ -26897,6 +26780,66 @@ fn zirVarExtended( } })); } +fn resolveExternDecl( + sema: *Sema, + block: *Block, + ty: Type, + opt_lib_name: ?[]const u8, + is_const: bool, + is_threadlocal: bool, +) CompileError!InternPool.Index { + const pt = sema.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + + // We need to resolve the alignment and addrspace early. + // Keep in sync with logic in `Zcu.PerThread.semaCau`. + const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); + const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); + + const decl_inst, const decl_bodies = decl: { + const decl_inst = sema.getOwnerCauDeclInst().resolve(ip) orelse return error.AnalysisFail; + const zir_decl, const extra_end = sema.code.getDeclaration(decl_inst); + break :decl .{ decl_inst, zir_decl.getBodies(extra_end, sema.code) }; + }; + + const alignment: InternPool.Alignment = a: { + const align_body = decl_bodies.align_body orelse break :a .none; + const align_ref = try sema.resolveInlineBody(block, align_body, decl_inst); + break :a try sema.analyzeAsAlign(block, align_src, align_ref); + }; + + const @"addrspace": std.builtin.AddressSpace = as: { + const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(ty.toIntern())) { + .func_type => .function, + else => .variable, + }; + const target = zcu.getTarget(); + const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) { + .function => target_util.defaultAddressSpace(target, .function), + .variable => target_util.defaultAddressSpace(target, .global_mutable), + .constant => target_util.defaultAddressSpace(target, .global_constant), + else => unreachable, + }; + const addrspace_ref = try sema.resolveInlineBody(block, addrspace_body, decl_inst); + break :as try sema.analyzeAsAddressSpace(block, addrspace_src, addrspace_ref, addrspace_ctx); + }; + + return pt.getExtern(.{ + .name = sema.getOwnerCauNavName(), + .ty = ty.toIntern(), + .lib_name = try ip.getOrPutStringOpt(sema.gpa, pt.tid, opt_lib_name, .no_embedded_nulls), + .is_const = is_const, + .is_threadlocal = is_threadlocal, + .is_weak_linkage = false, + .is_dll_import = false, + .alignment = alignment, + .@"addrspace" = @"addrspace", + .zir_index = sema.getOwnerCauDeclInst(), // `declaration` instruction + .owner_nav = undefined, // ignored by `getExtern` + }); +} + fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -26908,9 +26851,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); const target = zcu.getTarget(); - const align_src = block.src(.{ .node_offset_fn_type_align = inst_data.src_node }); - const addrspace_src = block.src(.{ .node_offset_fn_type_addrspace = inst_data.src_node }); - const section_src = block.src(.{ .node_offset_fn_type_section = inst_data.src_node }); const cc_src = block.src(.{ .node_offset_fn_type_cc = inst_data.src_node }); const ret_src = block.src(.{ .node_offset_fn_type_ret_ty = inst_data.src_node }); const has_body = extra.data.body_len != 0; @@ -26924,112 +26864,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A break :blk lib_name; } else null; - if (has_body and - (extra.data.bits.has_align_body or extra.data.bits.has_align_ref) and - !target_util.supportsFunctionAlignment(target)) - { - return sema.fail(block, align_src, "target does not support function alignment", .{}); - } - - const @"align": ?Alignment = if (extra.data.bits.has_align_body) blk: { - const body_len = sema.code.extra[extra_index]; - extra_index += 1; - const body = sema.code.bodySlice(extra_index, body_len); - extra_index += body.len; - - const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u29, .{ - .needed_comptime_reason = "alignment must be comptime-known", - }); - if (val.isGenericPoison()) { - break :blk null; - } - break :blk try sema.validateAlign(block, align_src, try val.toUnsignedIntSema(pt)); - } else if (extra.data.bits.has_align_ref) blk: { - const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); - extra_index += 1; - const uncoerced_align = sema.resolveInst(align_ref) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - const coerced_align = sema.coerce(block, Type.u29, uncoerced_align, align_src) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - const align_val = sema.resolveConstDefinedValue(block, align_src, coerced_align, .{ - .needed_comptime_reason = "alignment must be comptime-known", - }) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - break :blk try sema.validateAlign(block, align_src, try align_val.toUnsignedIntSema(pt)); - } else .none; - - const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: { - const body_len = sema.code.extra[extra_index]; - extra_index += 1; - const body = sema.code.bodySlice(extra_index, body_len); - extra_index += body.len; - - const addrspace_ty = try sema.getBuiltinType("AddressSpace"); - const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, .{ - .needed_comptime_reason = "addrspace must be comptime-known", - }); - if (val.isGenericPoison()) { - break :blk null; - } - break :blk zcu.toEnum(std.builtin.AddressSpace, val); - } else if (extra.data.bits.has_addrspace_ref) blk: { - const addrspace_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); - extra_index += 1; - const addrspace_ty = try sema.getBuiltinType("AddressSpace"); - const uncoerced_addrspace = sema.resolveInst(addrspace_ref) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - const coerced_addrspace = sema.coerce(block, addrspace_ty, uncoerced_addrspace, addrspace_src) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - const addrspace_val = sema.resolveConstDefinedValue(block, addrspace_src, coerced_addrspace, .{ - .needed_comptime_reason = "addrspace must be comptime-known", - }) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - break :blk zcu.toEnum(std.builtin.AddressSpace, addrspace_val); - } else target_util.defaultAddressSpace(target, .function); - - const section: Section = if (extra.data.bits.has_section_body) blk: { - const body_len = sema.code.extra[extra_index]; - extra_index += 1; - const body = sema.code.bodySlice(extra_index, body_len); - extra_index += body.len; - - const ty = Type.slice_const_u8; - const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, .{ - .needed_comptime_reason = "linksection must be comptime-known", - }); - if (val.isGenericPoison()) { - break :blk .generic; - } - break :blk .{ .explicit = try sema.sliceToIpString(block, section_src, val, .{ - .needed_comptime_reason = "linksection must be comptime-known", - }) }; - } else if (extra.data.bits.has_section_ref) blk: { - const section_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); - extra_index += 1; - const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, .{ - .needed_comptime_reason = "linksection must be comptime-known", - }) catch |err| switch (err) { - error.GenericPoison => { - break :blk .generic; - }, - else => |e| return e, - }; - break :blk .{ .explicit = section_name }; - } else .default; - - const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { + const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { const body_len = sema.code.extra[extra_index]; extra_index += 1; const body = sema.code.bodySlice(extra_index, body_len); @@ -27039,28 +26874,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, .{ .needed_comptime_reason = "calling convention must be comptime-known", }); - if (val.isGenericPoison()) { - break :blk null; - } break :blk try sema.analyzeValueAsCallconv(block, cc_src, val); } else if (extra.data.bits.has_cc_ref) blk: { const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; const cc_ty = try sema.getBuiltinType("CallingConvention"); - const uncoerced_cc = sema.resolveInst(cc_ref) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - const coerced_cc = sema.coerce(block, cc_ty, uncoerced_cc, cc_src) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; - const cc_val = sema.resolveConstDefinedValue(block, cc_src, coerced_cc, .{ + const uncoerced_cc = try sema.resolveInst(cc_ref); + const coerced_cc = try sema.coerce(block, cc_ty, uncoerced_cc, cc_src); + const cc_val = try sema.resolveConstDefinedValue(block, cc_src, coerced_cc, .{ .needed_comptime_reason = "calling convention must be comptime-known", - }) catch |err| switch (err) { - error.GenericPoison => break :blk null, - else => |e| return e, - }; + }); break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val); } else cc: { if (has_body) { @@ -27142,9 +26965,6 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A block, inst_data.src_node, inst, - @"align", - @"addrspace", - section, cc, ret_ty, is_var_args, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index acd14135fa3e..03576708e7c9 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -1314,67 +1314,61 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult { }; } - const nav_already_populated, const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) { - .func => |f| .{ f.owner_nav == nav_index, true }, - .variable => |v| .{ false, v.owner_nav == nav_index }, - .@"extern" => .{ false, false }, - else => .{ false, true }, + const queue_linker_work = switch (ip.indexToKey(decl_val.toIntern())) { + .func => true, // mote that this lets function aliases reach codegen + .variable => |v| v.owner_nav == nav_index, + .@"extern" => false, + else => true, }; - if (nav_already_populated) { - // This is a function declaration. - // Logic in `Sema.funcCommon` has already populated the `Nav` for us. - assert(ip.getNav(nav_index).status.resolved.val == decl_val.toIntern()); - } else { - // Keep in sync with logic in `Sema.zirVarExtended`. - const alignment: InternPool.Alignment = a: { - const align_body = decl_bodies.align_body orelse break :a .none; - const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst); - break :a try sema.analyzeAsAlign(&block, align_src, align_ref); - }; + // Keep in sync with logic in `Sema.zirVarExtended`. + const alignment: InternPool.Alignment = a: { + const align_body = decl_bodies.align_body orelse break :a .none; + const align_ref = try sema.resolveInlineBody(&block, align_body, inst_info.inst); + break :a try sema.analyzeAsAlign(&block, align_src, align_ref); + }; - const @"linksection": InternPool.OptionalNullTerminatedString = ls: { - const linksection_body = decl_bodies.linksection_body orelse break :ls .none; - const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst); - const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{ - .needed_comptime_reason = "linksection must be comptime-known", - }); - if (std.mem.indexOfScalar(u8, bytes, 0) != null) { - return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{}); - } else if (bytes.len == 0) { - return sema.fail(&block, section_src, "linksection cannot be empty", .{}); - } - break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls); - }; + const @"linksection": InternPool.OptionalNullTerminatedString = ls: { + const linksection_body = decl_bodies.linksection_body orelse break :ls .none; + const linksection_ref = try sema.resolveInlineBody(&block, linksection_body, inst_info.inst); + const bytes = try sema.toConstString(&block, section_src, linksection_ref, .{ + .needed_comptime_reason = "linksection must be comptime-known", + }); + if (std.mem.indexOfScalar(u8, bytes, 0) != null) { + return sema.fail(&block, section_src, "linksection cannot contain null bytes", .{}); + } else if (bytes.len == 0) { + return sema.fail(&block, section_src, "linksection cannot be empty", .{}); + } + break :ls try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls); + }; - const @"addrspace": std.builtin.AddressSpace = as: { - const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) { - .func => .function, - .variable => .variable, - .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type) - .function - else - .variable, - else => .constant, - }; - const target = zcu.getTarget(); - const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) { - .function => target_util.defaultAddressSpace(target, .function), - .variable => target_util.defaultAddressSpace(target, .global_mutable), - .constant => target_util.defaultAddressSpace(target, .global_constant), - else => unreachable, - }; - const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst); - break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx); + const @"addrspace": std.builtin.AddressSpace = as: { + const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) { + .func => .function, + .variable => .variable, + .@"extern" => |e| if (ip.indexToKey(e.ty) == .func_type) + .function + else + .variable, + else => .constant, }; + const target = zcu.getTarget(); + const addrspace_body = decl_bodies.addrspace_body orelse break :as switch (addrspace_ctx) { + .function => target_util.defaultAddressSpace(target, .function), + .variable => target_util.defaultAddressSpace(target, .global_mutable), + .constant => target_util.defaultAddressSpace(target, .global_constant), + else => unreachable, + }; + const addrspace_ref = try sema.resolveInlineBody(&block, addrspace_body, inst_info.inst); + break :as try sema.analyzeAsAddressSpace(&block, addrspace_src, addrspace_ref, addrspace_ctx); + }; - ip.resolveNavValue(nav_index, .{ - .val = decl_val.toIntern(), - .alignment = alignment, - .@"linksection" = @"linksection", - .@"addrspace" = @"addrspace", - }); - } + ip.resolveNavValue(nav_index, .{ + .val = decl_val.toIntern(), + .alignment = alignment, + .@"linksection" = @"linksection", + .@"addrspace" = @"addrspace", + }); // Mark the `Cau` as completed before evaluating the export! assert(zcu.analysis_in_progress.swapRemove(anal_unit)); diff --git a/src/print_zir.zig b/src/print_zir.zig index 52e22fb7adc2..f8f7db89e8d9 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -2349,12 +2349,6 @@ const Writer = struct { false, false, - .none, - &.{}, - .none, - &.{}, - .none, - &.{}, .none, &.{}, ret_ty_ref, @@ -2372,12 +2366,6 @@ const Writer = struct { const extra = self.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); var extra_index: usize = extra.end; - var align_ref: Zir.Inst.Ref = .none; - var align_body: []const Zir.Inst.Index = &.{}; - var addrspace_ref: Zir.Inst.Ref = .none; - var addrspace_body: []const Zir.Inst.Index = &.{}; - var section_ref: Zir.Inst.Ref = .none; - var section_body: []const Zir.Inst.Index = &.{}; var cc_ref: Zir.Inst.Ref = .none; var cc_body: []const Zir.Inst.Index = &.{}; var ret_ty_ref: Zir.Inst.Ref = .none; @@ -2390,33 +2378,6 @@ const Writer = struct { } try self.writeFlag(stream, "test, ", extra.data.bits.is_test); - if (extra.data.bits.has_align_body) { - const body_len = self.code.extra[extra_index]; - extra_index += 1; - align_body = self.code.bodySlice(extra_index, body_len); - extra_index += align_body.len; - } else if (extra.data.bits.has_align_ref) { - align_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - } - if (extra.data.bits.has_addrspace_body) { - const body_len = self.code.extra[extra_index]; - extra_index += 1; - addrspace_body = self.code.bodySlice(extra_index, body_len); - extra_index += addrspace_body.len; - } else if (extra.data.bits.has_addrspace_ref) { - addrspace_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - } - if (extra.data.bits.has_section_body) { - const body_len = self.code.extra[extra_index]; - extra_index += 1; - section_body = self.code.bodySlice(extra_index, body_len); - extra_index += section_body.len; - } else if (extra.data.bits.has_section_ref) { - section_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - } if (extra.data.bits.has_cc_body) { const body_len = self.code.extra[extra_index]; extra_index += 1; @@ -2455,12 +2416,6 @@ const Writer = struct { extra.data.bits.is_var_args, extra.data.bits.is_extern, extra.data.bits.is_noinline, - align_ref, - align_body, - addrspace_ref, - addrspace_body, - section_ref, - section_body, cc_ref, cc_body, ret_ty_ref, @@ -2651,12 +2606,6 @@ const Writer = struct { var_args: bool, is_extern: bool, is_noinline: bool, - align_ref: Zir.Inst.Ref, - align_body: []const Zir.Inst.Index, - addrspace_ref: Zir.Inst.Ref, - addrspace_body: []const Zir.Inst.Index, - section_ref: Zir.Inst.Ref, - section_body: []const Zir.Inst.Index, cc_ref: Zir.Inst.Ref, cc_body: []const Zir.Inst.Index, ret_ty_ref: Zir.Inst.Ref, @@ -2666,9 +2615,6 @@ const Writer = struct { src_locs: Zir.Inst.Func.SrcLocs, noalias_bits: u32, ) !void { - try self.writeOptionalInstRefOrBody(stream, "align=", align_ref, align_body); - try self.writeOptionalInstRefOrBody(stream, "addrspace=", addrspace_ref, addrspace_body); - try self.writeOptionalInstRefOrBody(stream, "section=", section_ref, section_body); try self.writeOptionalInstRefOrBody(stream, "cc=", cc_ref, cc_body); try self.writeOptionalInstRefOrBody(stream, "ret_ty=", ret_ty_ref, ret_ty_body); try self.writeFlag(stream, "vargs, ", var_args); diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 6e6a1ac31930..9b3696e0a12f 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -361,47 +361,6 @@ fn simple4() align(4) i32 { return 0x19; } -test "function align expression depends on generic parameter" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - - // function alignment is a compile error on wasm32/wasm64 - if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest; - if (native_arch == .thumb) return error.SkipZigTest; - - const S = struct { - fn doTheTest() !void { - try expect(foobar(1) == 2); - try expect(foobar(4) == 5); - try expect(foobar(8) == 9); - } - - fn foobar(comptime align_bytes: u8) align(align_bytes) u8 { - return align_bytes + 1; - } - }; - try S.doTheTest(); - try comptime S.doTheTest(); -} - -test "function callconv expression depends on generic parameter" { - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - - const S = struct { - fn doTheTest() !void { - try expect(foobar(.C, 1) == 2); - try expect(foobar(.Unspecified, 2) == 3); - } - - fn foobar(comptime cc: std.builtin.CallingConvention, arg: u8) callconv(cc) u8 { - return arg + 1; - } - }; - try S.doTheTest(); - try comptime S.doTheTest(); -} - test "runtime-known array index has best alignment possible" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index ab4f820d1c9a..b041be93d900 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -637,24 +637,6 @@ test "address of function parameter is consistent in other parameter type" { S.paramAddrMatch(1, 2); } -test "address of function parameter is consistent in function align" { - switch (builtin.target.cpu.arch) { - .wasm32, .wasm64 => return, // function alignment not supported - else => {}, - } - const S = struct { - fn paramAddrMatch(comptime x: u8) align(if (&x != &x) unreachable else 1) void {} - }; - S.paramAddrMatch(1); -} - -test "address of function parameter is consistent in function callconv" { - const S = struct { - fn paramAddrMatch(comptime x: u8) callconv(if (&x != &x) unreachable else .auto) void {} - }; - S.paramAddrMatch(1); -} - test "address of function parameter is consistent in function return type" { const S = struct { fn paramAddrMatch(comptime x: u8) if (&x != &x) unreachable else void {} @@ -662,13 +644,6 @@ test "address of function parameter is consistent in function return type" { S.paramAddrMatch(1); } -test "address of function parameter is consistent in function addrspace" { - const S = struct { - fn paramAddrMatch(comptime x: u8) addrspace(if (&x != &x) unreachable else .generic) void {} - }; - S.paramAddrMatch(1); -} - test "function parameter self equality" { const S = struct { fn equal(x: u32) bool {