From ec19086aa0491024622c444b0d9310560de9e6f0 Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 14 Oct 2024 07:57:11 +0100 Subject: [PATCH] compiler: remove @setAlignStack This commit finishes implementing #21209 by removing the `@setAlignStack` builtin in favour of `CallingConvention` payloads. The x86_64 backend is updated to use the stack alignment given in the calling convention (the LLVM backend was already updated in a previous commit). Resolves: #21209 --- lib/std/zig/AstGen.zig | 9 --------- lib/std/zig/AstRlAnnotate.zig | 1 - lib/std/zig/BuiltinFn.zig | 9 --------- lib/std/zig/Zir.zig | 4 ---- src/InternPool.zig | 22 +--------------------- src/Sema.zig | 34 ---------------------------------- src/Zcu.zig | 2 +- src/arch/wasm/CodeGen.zig | 2 +- src/arch/x86_64/CodeGen.zig | 3 ++- src/print_zir.zig | 1 - src/target.zig | 16 ++++++++++++++++ 11 files changed, 21 insertions(+), 82 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 16d2a99632..dc39ce62f5 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -2902,7 +2902,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .breakpoint, .disable_instrumentation, .set_float_mode, - .set_align_stack, .branch_hint, => break :b true, else => break :b false, @@ -9324,14 +9323,6 @@ fn builtinCall( }); return rvalue(gz, ri, .void_value, node); }, - .set_align_stack => { - const order = try expr(gz, scope, coerced_align_ri, params[0]); - _ = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{ - .node = gz.nodeIndexToRelative(node), - .operand = order, - }); - return rvalue(gz, ri, .void_value, node); - }, .src => { // Incorporate the source location into the source hash, so that diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig index 68d423ade7..e790612505 100644 --- a/lib/std/zig/AstRlAnnotate.zig +++ b/lib/std/zig/AstRlAnnotate.zig @@ -909,7 +909,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. .wasm_memory_size, .splat, .set_float_mode, - .set_align_stack, .type_info, .work_item_id, .work_group_size, diff --git a/lib/std/zig/BuiltinFn.zig b/lib/std/zig/BuiltinFn.zig index 236092fb13..baf9bd91e3 100644 --- a/lib/std/zig/BuiltinFn.zig +++ b/lib/std/zig/BuiltinFn.zig @@ -82,7 +82,6 @@ pub const Tag = enum { rem, return_address, select, - set_align_stack, set_eval_branch_quota, set_float_mode, set_runtime_safety, @@ -744,14 +743,6 @@ pub const list = list: { .param_count = 4, }, }, - .{ - "@setAlignStack", - .{ - .tag = .set_align_stack, - .param_count = 1, - .illegal_outside_function = true, - }, - }, .{ "@setEvalBranchQuota", .{ diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 9c76f72663..ab6bcf1b0e 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -1982,9 +1982,6 @@ pub const Inst = struct { /// Implement builtin `@setFloatMode`. /// `operand` is payload index to `UnNode`. set_float_mode, - /// Implement builtin `@setAlignStack`. - /// `operand` is payload index to `UnNode`. - set_align_stack, /// Implements the `@errorCast` builtin. /// `operand` is payload index to `BinNode`. `lhs` is dest type, `rhs` is operand. error_cast, @@ -4012,7 +4009,6 @@ fn findDeclsInner( .wasm_memory_grow, .prefetch, .set_float_mode, - .set_align_stack, .error_cast, .await_nosuspend, .breakpoint, diff --git a/src/InternPool.zig b/src/InternPool.zig index c81dbd3c8c..cb4cddc968 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -5618,12 +5618,11 @@ pub const FuncAnalysis = packed struct(u32) { branch_hint: std.builtin.BranchHint, is_noinline: bool, calls_or_awaits_errorable_fn: bool, - stack_alignment: Alignment, /// True if this function has an inferred error set. inferred_error_set: bool, disable_instrumentation: bool, - _: u17 = 0, + _: u23 = 0, pub const State = enum(u2) { /// The runtime function has never been referenced. @@ -8696,7 +8695,6 @@ pub fn getFuncDecl( .branch_hint = .none, .is_noinline = key.is_noinline, .calls_or_awaits_errorable_fn = false, - .stack_alignment = .none, .inferred_error_set = false, .disable_instrumentation = false, }, @@ -8800,7 +8798,6 @@ pub fn getFuncDeclIes( .branch_hint = .none, .is_noinline = key.is_noinline, .calls_or_awaits_errorable_fn = false, - .stack_alignment = .none, .inferred_error_set = true, .disable_instrumentation = false, }, @@ -8992,7 +8989,6 @@ pub fn getFuncInstance( .branch_hint = .none, .is_noinline = arg.is_noinline, .calls_or_awaits_errorable_fn = false, - .stack_alignment = .none, .inferred_error_set = false, .disable_instrumentation = false, }, @@ -9092,7 +9088,6 @@ pub fn getFuncInstanceIes( .branch_hint = .none, .is_noinline = arg.is_noinline, .calls_or_awaits_errorable_fn = false, - .stack_alignment = .none, .inferred_error_set = true, .disable_instrumentation = false, }, @@ -11871,21 +11866,6 @@ pub fn funcAnalysisUnordered(ip: *const InternPool, func: Index) FuncAnalysis { return @atomicLoad(FuncAnalysis, @constCast(ip).funcAnalysisPtr(func), .unordered); } -pub fn funcMaxStackAlignment(ip: *InternPool, func: Index, new_stack_alignment: Alignment) void { - const unwrapped_func = func.unwrap(ip); - const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; - extra_mutex.lock(); - defer extra_mutex.unlock(); - - const analysis_ptr = ip.funcAnalysisPtr(func); - var analysis = analysis_ptr.*; - analysis.stack_alignment = switch (analysis.stack_alignment) { - .none => new_stack_alignment, - else => |old_stack_alignment| old_stack_alignment.maxStrict(new_stack_alignment), - }; - @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); -} - pub fn funcSetCallsOrAwaitsErrorableFn(ip: *InternPool, func: Index) void { const unwrapped_func = func.unwrap(ip); const extra_mutex = &ip.getLocal(unwrapped_func.tid).mutate.extra.mutex; diff --git a/src/Sema.zig b/src/Sema.zig index ac1a79a2b3..eea49b4713 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1326,11 +1326,6 @@ fn analyzeBodyInner( i += 1; continue; }, - .set_align_stack => { - try sema.zirSetAlignStack(block, extended); - i += 1; - continue; - }, .breakpoint => { if (!block.is_comptime) { _ = try block.addNoOp(.breakpoint); @@ -6510,35 +6505,6 @@ pub fn analyzeExport( }); } -fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const operand_src = block.builtinCallArgSrc(extra.node, 0); - const src = block.nodeOffset(extra.node); - const alignment = try sema.resolveAlign(block, operand_src, extra.operand); - - const func = switch (sema.owner.unwrap()) { - .func => |func| func, - .cau => return sema.fail(block, src, "@setAlignStack outside of function scope", .{}), - }; - - if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { - return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ - alignment.toByteUnits().?, - }); - } - - switch (Value.fromInterned(func).typeOf(zcu).fnCallingConvention(zcu)) { - .naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), - .@"inline" => return sema.fail(block, src, "@setAlignStack in inline function", .{}), - else => {}, - } - - zcu.intern_pool.funcMaxStackAlignment(sema.func_index, alignment); - sema.allow_memoize = false; -} - fn zirDisableInstrumentation(sema: *Sema) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; diff --git a/src/Zcu.zig b/src/Zcu.zig index 778d2b68ad..9dfc165e55 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3592,7 +3592,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu else => false, }, .stage2_x86_64 => switch (cc) { - .x86_64_sysv, .x86_64_win, .naked => true, + .x86_64_sysv, .x86_64_win, .naked => true, // stack alignment supported else => false, }, .stage2_aarch64 => switch (cc) { diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index a04a8528dc..012210223f 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -710,7 +710,7 @@ stack_size: u32 = 0, /// The stack alignment, which is 16 bytes by default. This is specified by the /// tool-conventions: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md /// and also what the llvm backend will emit. -/// However, local variables or the usage of `@setAlignStack` can overwrite this default. +/// However, local variables or the usage of `incoming_stack_alignment` in a `CallingConvention` can overwrite this default. stack_alignment: Alignment = .@"16", // For each individual Wasm valtype we store a seperate free list which diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index f6ab8d3e87..0b3ccc7ecc 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -11,6 +11,7 @@ const verbose_tracking_log = std.log.scoped(.verbose_tracking); const wip_mir_log = std.log.scoped(.wip_mir); const math = std.math; const mem = std.mem; +const target_util = @import("../../target.zig"); const trace = @import("../../tracy.zig").trace; const Air = @import("../../Air.zig"); @@ -872,7 +873,7 @@ pub fn generate( @intFromEnum(FrameIndex.stack_frame), FrameAlloc.init(.{ .size = 0, - .alignment = func.analysisUnordered(ip).stack_alignment.max(.@"1"), + .alignment = target_util.stackAlignment(function.target.*, fn_type.fnCallingConvention(zcu)), }), ); function.frame_allocs.set( diff --git a/src/print_zir.zig b/src/print_zir.zig index 5467dcd27a..7cc381955f 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -567,7 +567,6 @@ const Writer = struct { .c_undef, .c_include, .set_float_mode, - .set_align_stack, .wasm_memory_size, .int_from_error, .error_from_int, diff --git a/src/target.zig b/src/target.zig index 7d30781f43..7a5c3387b6 100644 --- a/src/target.zig +++ b/src/target.zig @@ -607,3 +607,19 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt }, }; } + +pub fn stackAlignment(target: std.Target, cc: std.builtin.CallingConvention) u64 { + switch (cc) { + inline else => |payload| switch (@TypeOf(payload)) { + std.builtin.CallingConvention.CommonOptions, + std.builtin.CallingConvention.X86RegparmOptions, + std.builtin.CallingConvention.ArmInterruptOptions, + std.builtin.CallingConvention.MipsInterruptOptions, + std.builtin.CallingConvention.RiscvInterruptOptions, + => if (payload.incoming_stack_alignment) |a| return a, + void => {}, + else => comptime unreachable, + }, + } + return target.stackAlignment(); +}