From 766a42a11c64fc163747ec3c1019741c63cd6a2c Mon Sep 17 00:00:00 2001 From: JP Hafer <146973677+jph-13@users.noreply.github.com> Date: Wed, 29 Apr 2026 11:18:07 -0400 Subject: [PATCH] [CodeGen] Use getFnAttributeAsParsedInteger for patchable-function attributes (#194726) Replace `getAsInteger()` parsing of the `patchable-function-entry` and `patchable-function-prefix` function attributes with the existing `Function::getFnAttributeAsParsedInteger()` helper across AsmPrinter and all backend targets. The IR verifier already validates these attributes as unsigned base-10 integers via `checkUnsignedBaseTenFuncAttr`, so parse failure at point of use indicates a verifier bypass or IR corruption. `getFnAttributeAsParsedInteger()` returns a default of 0 on failure (matching the implicit behavior of the old code) and emits a diagnostic rather than silently continuing. --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 23 +++++++------------ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 9 +++----- llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 8 ++----- .../Target/LoongArch/LoongArchAsmPrinter.cpp | 6 +---- .../Target/LoongArch/LoongArchInstrInfo.cpp | 7 ++---- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 10 ++------ llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 5 +--- llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp | 17 ++++---------- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 8 ++----- llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 6 +---- llvm/lib/Target/X86/X86AsmPrinter.cpp | 7 ++---- llvm/lib/Target/X86/X86MCInstLower.cpp | 13 +++-------- 12 files changed, 32 insertions(+), 87 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 2fb7ecc71819..76703b8ccc63 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1083,14 +1083,10 @@ void AsmPrinter::emitFunctionHeader() { // Emit M NOPs for -fpatchable-function-entry=N,M where M>0. We arbitrarily // place prefix data before NOPs. - unsigned PatchableFunctionPrefix = 0; - unsigned PatchableFunctionEntry = 0; - (void)F.getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PatchableFunctionPrefix); - (void)F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, PatchableFunctionEntry); + unsigned PatchableFunctionPrefix = + F.getFnAttributeAsParsedInteger("patchable-function-prefix"); + unsigned PatchableFunctionEntry = + F.getFnAttributeAsParsedInteger("patchable-function-entry"); if (PatchableFunctionPrefix) { CurrentPatchableFunctionEntrySym = OutContext.createLinkerPrivateTempSymbol(); @@ -5101,13 +5097,10 @@ void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI, void AsmPrinter::emitPatchableFunctionEntries() { const Function &F = MF->getFunction(); - unsigned PatchableFunctionPrefix = 0, PatchableFunctionEntry = 0; - (void)F.getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PatchableFunctionPrefix); - (void)F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, PatchableFunctionEntry); + unsigned PatchableFunctionPrefix = + F.getFnAttributeAsParsedInteger("patchable-function-prefix"); + unsigned PatchableFunctionEntry = + F.getFnAttributeAsParsedInteger("patchable-function-entry"); if (!PatchableFunctionPrefix && !PatchableFunctionEntry) return; const unsigned PointerSize = getPointerSize(); diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 3079a38aa794..4eb475ef606d 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -687,12 +687,9 @@ void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { // Adjust the offset for patchable-function-prefix. This assumes that // patchable-function-prefix is the same for all functions. - int64_t PrefixNops = 0; - (void)MI.getMF() - ->getFunction() - .getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PrefixNops); + int64_t PrefixNops = + MI.getMF()->getFunction().getFnAttributeAsParsedInteger( + "patchable-function-prefix"); // Load the target function type hash. EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi) diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 968c76f60b1b..8b8d0bc9ada1 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1915,12 +1915,8 @@ void ARMAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { const MachineInstr &Call = *std::next(MI.getIterator()); // Adjust the offset for patchable-function-prefix. - int64_t PrefixNops = 0; - MI.getMF() - ->getFunction() - .getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PrefixNops); + int64_t PrefixNops = MI.getMF()->getFunction().getFnAttributeAsParsedInteger( + "patchable-function-prefix"); // Emit the appropriate instruction sequence based on the opcode variant. switch (MI.getOpcode()) { diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp index 79ea4b05d220..980d9858ee58 100644 --- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp @@ -215,11 +215,7 @@ void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER( const MachineInstr &MI) { const Function &F = MF->getFunction(); if (F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; - if (F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num)) - return; + unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry"); emitNops(Num); return; } diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index 441fecf80692..1b79e523b573 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -343,11 +343,8 @@ unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { const MachineFunction *MF = MI.getParent()->getParent(); const Function &F = MF->getFunction(); if (F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; - if (F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num)) - return 0; + unsigned Num = + F.getFnAttributeAsParsedInteger("patchable-function-entry"); return Num * 4; } [[fallthrough]]; diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index e250b36fce64..8df059e34c62 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -952,10 +952,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { assert(!Subtarget->isAIXABI() && "AIX does not support patchable function entry!"); const Function &F = MF->getFunction(); - unsigned Num = 0; - (void)F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num); + unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry"); if (!Num) return; emitNops(Num); @@ -1817,10 +1814,7 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) { // of instructions change. // XRAY is only supported on PPC Linux little endian. const Function &F = MF->getFunction(); - unsigned Num = 0; - (void)F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num); + unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry"); if (!MAI.isLittleEndian() || Num) break; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index b7a77a857deb..ff302862640e 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3023,10 +3023,7 @@ unsigned PPCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { const MachineFunction *MF = MI.getParent()->getParent(); const Function &F = MF->getFunction(); - unsigned Num = 0; - (void)F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num); + unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry"); if (Num || MF->getTarget().getTargetTriple().isOSAIX() || !MF->getTarget().getTargetTriple().isLittleEndian()) return Num * 4; diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp index b59db55169cf..659ff631a3cf 100644 --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -338,12 +338,8 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) { case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { const Function &F = MI->getParent()->getParent()->getFunction(); if (F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; - [[maybe_unused]] bool Result = - F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num); - assert(!Result && "Enforced by the verifier"); + unsigned Num = + F.getFnAttributeAsParsedInteger("patchable-function-entry"); emitNops(Num); return; } @@ -681,12 +677,9 @@ void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { // Adjust the offset for patchable-function-prefix. This assumes that // patchable-function-prefix is the same for all functions. int NopSize = STI->hasStdExtZca() ? 2 : 4; - int64_t PrefixNops = 0; - (void)MI.getMF() - ->getFunction() - .getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PrefixNops); + int64_t PrefixNops = + MI.getMF()->getFunction().getFnAttributeAsParsedInteger( + "patchable-function-prefix"); // Load the target function type hash. EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 15024404b05c..9591b759bf52 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -2086,12 +2086,8 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { const Function &F = MF.getFunction(); if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER && F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; - if (F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num)) - return get(Opcode).getSize(); - + unsigned Num = + F.getFnAttributeAsParsedInteger("patchable-function-entry"); // Number of C.NOP or NOP return (STI.hasStdExtZca() ? 2 : 4) * Num; } diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 687060216ded..e90bbe47a93c 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -938,13 +938,9 @@ void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER( // If patchable-function-entry is set, emit in-function nops here. if (F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; // get M-N from function attribute (CodeGenFunction subtracts N // from M to yield the correct patchable-function-entry). - if (F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num)) - return; + unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry"); // Emit M-N 2-byte nops. Use getNop() here instead of emitNops() // to keep it aligned with the common code implementation emitting // the prefix nops. diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index 8aea7683a113..e9fdb3d3a148 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -153,11 +153,8 @@ void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF, bool HasType) { // Keep the function entry aligned, taking patchable-function-prefix into // account if set. - int64_t PrefixBytes = 0; - (void)MF.getFunction() - .getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PrefixBytes); + int64_t PrefixBytes = MF.getFunction().getFnAttributeAsParsedInteger( + "patchable-function-prefix"); // Also take the type identifier into account if we're emitting // one. Otherwise, just pad with nops. The X86::MOV32ri instruction emitted diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index d497cec8b9c9..d89c6cac9621 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -909,11 +909,8 @@ void X86AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { // bytes. This assumes that patchable-function-prefix is the same for all // functions. const MachineFunction &MF = *MI.getMF(); - int64_t PrefixNops = 0; - (void)MF.getFunction() - .getFnAttribute("patchable-function-prefix") - .getValueAsString() - .getAsInteger(10, PrefixNops); + int64_t PrefixNops = MF.getFunction().getFnAttributeAsParsedInteger( + "patchable-function-prefix"); // KCFI allows indirect calls to any location that's preceded by a valid // type identifier. To avoid encoding the full constant into an instruction, @@ -1310,11 +1307,7 @@ void X86AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI, const Function &F = MF->getFunction(); if (F.hasFnAttribute("patchable-function-entry")) { - unsigned Num; - if (F.getFnAttribute("patchable-function-entry") - .getValueAsString() - .getAsInteger(10, Num)) - return; + unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry"); emitX86Nops(*OutStreamer, Num, Subtarget); return; }