Commit ec19086aa0

mlugg <mlugg@mlugg.co.uk>
2024-10-14 08:57:11
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
1 parent bc797a9
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
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,
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",
             .{
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,
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
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(
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;
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,
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;
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();
+}
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) {