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
This commit is contained in:
mlugg 2024-10-14 07:57:11 +01:00
parent bc797a97b1
commit ec19086aa0
No known key found for this signature in database
GPG Key ID: 3F5B7DCCBF4AF02E
11 changed files with 21 additions and 82 deletions

View File

@ -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

View File

@ -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,

View File

@ -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",
.{

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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(

View File

@ -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,

View File

@ -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();
}