[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.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user