| ... | @@ -2909,7 +2909,17 @@ pub const Object = struct { | ... | @@ -2909,7 +2909,17 @@ pub const Object = struct { |
| 2909 | function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder); | 2909 | function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder); |
| 2910 | | 2910 | |
| 2911 | // Function attributes that are independent of analysis results of the function body. | 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 | if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); | 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,13 +2966,14 @@ pub const Object = struct { |
| 2956 | o: *Object, | 2966 | o: *Object, |
| 2957 | attributes: *Builder.FunctionAttributes.Wip, | 2967 | attributes: *Builder.FunctionAttributes.Wip, |
| 2958 | owner_mod: *Package.Module, | 2968 | owner_mod: *Package.Module, |
| | 2969 | omit_frame_pointer: bool, |
| 2959 | ) Allocator.Error!void { | 2970 | ) Allocator.Error!void { |
| 2960 | const comp = o.pt.zcu.comp; | 2971 | const comp = o.pt.zcu.comp; |
| 2961 | | 2972 | |
| 2962 | if (!owner_mod.red_zone) { | 2973 | if (!owner_mod.red_zone) { |
| 2963 | try attributes.addFnAttr(.noredzone, &o.builder); | 2974 | try attributes.addFnAttr(.noredzone, &o.builder); |
| 2964 | } | 2975 | } |
| 2965 | if (owner_mod.omit_frame_pointer) { | 2976 | if (omit_frame_pointer) { |
| 2966 | try attributes.addFnAttr(.{ .string = .{ | 2977 | try attributes.addFnAttr(.{ .string = .{ |
| 2967 | .kind = try o.builder.string("frame-pointer"), | 2978 | .kind = try o.builder.string("frame-pointer"), |
| 2968 | .value = try o.builder.string("none"), | 2979 | .value = try o.builder.string("none"), |
| ... | @@ -4528,7 +4539,7 @@ pub const Object = struct { | ... | @@ -4528,7 +4539,7 @@ pub const Object = struct { |
| 4528 | | 4539 | |
| 4529 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 4540 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4530 | defer attributes.deinit(&o.builder); | 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 | function_index.setLinkage(.internal, &o.builder); | 4544 | function_index.setLinkage(.internal, &o.builder); |
| 4534 | function_index.setCallConv(.fastcc, &o.builder); | 4545 | function_index.setCallConv(.fastcc, &o.builder); |
| ... | @@ -4557,7 +4568,7 @@ pub const Object = struct { | ... | @@ -4557,7 +4568,7 @@ pub const Object = struct { |
| 4557 | | 4568 | |
| 4558 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 4569 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4559 | defer attributes.deinit(&o.builder); | 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 | function_index.setLinkage(.internal, &o.builder); | 4573 | function_index.setLinkage(.internal, &o.builder); |
| 4563 | function_index.setCallConv(.fastcc, &o.builder); | 4574 | function_index.setCallConv(.fastcc, &o.builder); |
| ... | @@ -6709,8 +6720,6 @@ pub const FuncGen = struct { | ... | @@ -6709,8 +6720,6 @@ pub const FuncGen = struct { |
| 6709 | const operand_ty = self.typeOf(pl_op.operand); | 6720 | const operand_ty = self.typeOf(pl_op.operand); |
| 6710 | const name = self.air.nullTerminatedString(pl_op.payload); | 6721 | const name = self.air.nullTerminatedString(pl_op.payload); |
| 6711 | | 6722 | |
| 6712 | if (needDbgVarWorkaround(o)) return .none; | | |
| 6713 | | | |
| 6714 | const debug_local_var = try o.builder.debugLocalVar( | 6723 | const debug_local_var = try o.builder.debugLocalVar( |
| 6715 | try o.builder.metadataString(name), | 6724 | try o.builder.metadataString(name), |
| 6716 | self.file, | 6725 | self.file, |
| ... | @@ -6734,7 +6743,10 @@ pub const FuncGen = struct { | ... | @@ -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 | const alignment = operand_ty.abiAlignment(pt).toLlvm(); | 6750 | const alignment = operand_ty.abiAlignment(pt).toLlvm(); |
| 6739 | const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); | 6751 | const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment); |
| 6740 | _ = try self.wip.store(.normal, operand, alloca, alignment); | 6752 | _ = try self.wip.store(.normal, operand, alloca, alignment); |
| ... | @@ -8815,7 +8827,6 @@ pub const FuncGen = struct { | ... | @@ -8815,7 +8827,6 @@ pub const FuncGen = struct { |
| 8815 | if (self.is_naked) return arg_val; | 8827 | if (self.is_naked) return arg_val; |
| 8816 | | 8828 | |
| 8817 | const inst_ty = self.typeOfIndex(inst); | 8829 | const inst_ty = self.typeOfIndex(inst); |
| 8818 | if (needDbgVarWorkaround(o)) return arg_val; | | |
| 8819 | | 8830 | |
| 8820 | const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name; | 8831 | const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name; |
| 8821 | if (name == .none) return arg_val; | 8832 | if (name == .none) return arg_val; |
| ... | @@ -9676,7 +9687,7 @@ pub const FuncGen = struct { | ... | @@ -9676,7 +9687,7 @@ pub const FuncGen = struct { |
| 9676 | | 9687 | |
| 9677 | var attributes: Builder.FunctionAttributes.Wip = .{}; | 9688 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 9678 | defer attributes.deinit(&o.builder); | 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 | function_index.setLinkage(.internal, &o.builder); | 9692 | function_index.setLinkage(.internal, &o.builder); |
| 9682 | function_index.setCallConv(.fastcc, &o.builder); | 9693 | function_index.setCallConv(.fastcc, &o.builder); |
| ... | @@ -11820,16 +11831,6 @@ const optional_layout_version = 3; | ... | @@ -11820,16 +11831,6 @@ const optional_layout_version = 3; |
| 11820 | | 11831 | |
| 11821 | const lt_errors_fn_name = "__zig_lt_errors_len"; | 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 | fn compilerRtIntBits(bits: u16) u16 { | 11834 | fn compilerRtIntBits(bits: u16) u16 { |
| 11834 | inline for (.{ 32, 64, 128 }) |b| { | 11835 | inline for (.{ 32, 64, 128 }) |b| { |
| 11835 | if (bits <= b) { | 11836 | if (bits <= b) { |