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