@@ -2909,7 +2909,17 @@ pub const Object = struct {
2909
2909
function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder);
2910
2910
2911
2911
// Function attributes that are independent of analysis results of the function body.
2912
- try o.addCommonFnAttributes(&attributes, owner_mod);
2912
+ try o.addCommonFnAttributes(
2913
+ &attributes,
2914
+ owner_mod,
2915
+ // Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`,
2916
+ // so for these backends, LLVM will happily emit code that accesses the stack through
2917
+ // the frame pointer. This is nonsensical since what the `naked` attribute does is
2918
+ // suppress generation of the prologue and epilogue, and the prologue is where the
2919
+ // frame pointer normally gets set up. At time of writing, this is the case for at
2920
+ // least x86 and RISC-V.
2921
+ owner_mod.omit_frame_pointer or fn_info.cc == .Naked,
2922
+ );
2913
2923
2914
2924
if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
2915
2925
@@ -2956,13 +2966,14 @@ pub const Object = struct {
2956
2966
o: *Object,
2957
2967
attributes: *Builder.FunctionAttributes.Wip,
2958
2968
owner_mod: *Package.Module,
2969
+ omit_frame_pointer: bool,
2959
2970
) Allocator.Error!void {
2960
2971
const comp = o.pt.zcu.comp;
2961
2972
2962
2973
if (!owner_mod.red_zone) {
2963
2974
try attributes.addFnAttr(.noredzone, &o.builder);
2964
2975
}
2965
- if (owner_mod. omit_frame_pointer) {
2976
+ if (omit_frame_pointer) {
2966
2977
try attributes.addFnAttr(.{ .string = .{
2967
2978
.kind = try o.builder.string("frame-pointer"),
2968
2979
.value = try o.builder.string("none"),
@@ -4528,7 +4539,7 @@ pub const Object = struct {
4528
4539
4529
4540
var attributes: Builder.FunctionAttributes.Wip = .{};
4530
4541
defer attributes.deinit(&o.builder);
4531
- try o.addCommonFnAttributes(&attributes, zcu.root_mod);
4542
+ try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer );
4532
4543
4533
4544
function_index.setLinkage(.internal, &o.builder);
4534
4545
function_index.setCallConv(.fastcc, &o.builder);
@@ -4557,7 +4568,7 @@ pub const Object = struct {
4557
4568
4558
4569
var attributes: Builder.FunctionAttributes.Wip = .{};
4559
4570
defer attributes.deinit(&o.builder);
4560
- try o.addCommonFnAttributes(&attributes, zcu.root_mod);
4571
+ try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer );
4561
4572
4562
4573
function_index.setLinkage(.internal, &o.builder);
4563
4574
function_index.setCallConv(.fastcc, &o.builder);
@@ -6709,8 +6720,6 @@ pub const FuncGen = struct {
6709
6720
const operand_ty = self.typeOf(pl_op.operand);
6710
6721
const name = self.air.nullTerminatedString(pl_op.payload);
6711
6722
6712
- if (needDbgVarWorkaround(o)) return .none;
6713
-
6714
6723
const debug_local_var = try o.builder.debugLocalVar(
6715
6724
try o.builder.metadataString(name),
6716
6725
self.file,
@@ -6734,7 +6743,10 @@ pub const FuncGen = struct {
6734
6743
},
6735
6744
"",
6736
6745
);
6737
- } else if (owner_mod.optimize_mode == .Debug) {
6746
+ } else if (owner_mod.optimize_mode == .Debug and !self.is_naked) {
6747
+ // We avoid taking this path for naked functions because there's no guarantee that such
6748
+ // functions even have a valid stack pointer, making the `alloca` + `store` unsafe.
6749
+
6738
6750
const alignment = operand_ty.abiAlignment(pt).toLlvm();
6739
6751
const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
6740
6752
_ = try self.wip.store(.normal, operand, alloca, alignment);
@@ -8815,7 +8827,6 @@ pub const FuncGen = struct {
8815
8827
if (self.is_naked) return arg_val;
8816
8828
8817
8829
const inst_ty = self.typeOfIndex(inst);
8818
- if (needDbgVarWorkaround(o)) return arg_val;
8819
8830
8820
8831
const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
8821
8832
if (name == .none) return arg_val;
@@ -9676,7 +9687,7 @@ pub const FuncGen = struct {
9676
9687
9677
9688
var attributes: Builder.FunctionAttributes.Wip = .{};
9678
9689
defer attributes.deinit(&o.builder);
9679
- try o.addCommonFnAttributes(&attributes, zcu.root_mod);
9690
+ try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer );
9680
9691
9681
9692
function_index.setLinkage(.internal, &o.builder);
9682
9693
function_index.setCallConv(.fastcc, &o.builder);
@@ -11820,16 +11831,6 @@ const optional_layout_version = 3;
11820
11831
11821
11832
const lt_errors_fn_name = "__zig_lt_errors_len";
11822
11833
11823
- /// Without this workaround, LLVM crashes with "unknown codeview register H1"
11824
- /// https://github.com/llvm/llvm-project/issues/56484
11825
- fn needDbgVarWorkaround(o: *Object) bool {
11826
- const target = o.pt.zcu.getTarget();
11827
- if (target.os.tag == .windows and target.cpu.arch == .aarch64) {
11828
- return true;
11829
- }
11830
- return false;
11831
- }
11832
-
11833
11834
fn compilerRtIntBits(bits: u16) u16 {
11834
11835
inline for (.{ 32, 64, 128 }) |b| {
11835
11836
if (bits <= b) {
0 commit comments