1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/lib/Transforms/IPO/ForceFunctionAttrs.cpp
Nikita Popov 495f2550b0 [Attributes] Determine attribute properties from TableGen data
Continuing from D105763, this allows placing certain properties
about attributes in the TableGen definition. In particular, we
store whether an attribute applies to fn/param/ret (or a combination
thereof). This information is used by the Verifier, as well as the
ForceFunctionAttrs pass. I also plan to use this in LLParser,
which also duplicates info on which attributes are valid where.

This keeps metadata about attributes in one place, and makes it
more likely that it stays in sync, rather than in various
functions spread across the codebase.

Differential Revision: https://reviews.llvm.org/D105780
2021-07-12 22:13:38 +02:00

112 lines
3.8 KiB
C++

//===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "forceattrs"
static cl::list<std::string>
ForceAttributes("force-attribute", cl::Hidden,
cl::desc("Add an attribute to a function. This should be a "
"pair of 'function-name:attribute-name', for "
"example -force-attribute=foo:noinline. This "
"option can be specified multiple times."));
static cl::list<std::string> ForceRemoveAttributes(
"force-remove-attribute", cl::Hidden,
cl::desc("Remove an attribute from a function. This should be a "
"pair of 'function-name:attribute-name', for "
"example -force-remove-attribute=foo:noinline. This "
"option can be specified multiple times."));
/// If F has any forced attributes given on the command line, add them.
/// If F has any forced remove attributes given on the command line, remove
/// them. When both force and force-remove are given to a function, the latter
/// takes precedence.
static void forceAttributes(Function &F) {
auto ParseFunctionAndAttr = [&](StringRef S) {
auto Kind = Attribute::None;
auto KV = StringRef(S).split(':');
if (KV.first != F.getName())
return Kind;
Kind = Attribute::getAttrKindFromName(KV.second);
if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) {
LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
<< " unknown or not a function attribute!\n");
}
return Kind;
};
for (auto &S : ForceAttributes) {
auto Kind = ParseFunctionAndAttr(S);
if (Kind == Attribute::None || F.hasFnAttribute(Kind))
continue;
F.addFnAttr(Kind);
}
for (auto &S : ForceRemoveAttributes) {
auto Kind = ParseFunctionAndAttr(S);
if (Kind == Attribute::None || !F.hasFnAttribute(Kind))
continue;
F.removeFnAttr(Kind);
}
}
static bool hasForceAttributes() {
return !ForceAttributes.empty() || !ForceRemoveAttributes.empty();
}
PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
ModuleAnalysisManager &) {
if (!hasForceAttributes())
return PreservedAnalyses::all();
for (Function &F : M.functions())
forceAttributes(F);
// Just conservatively invalidate analyses, this isn't likely to be important.
return PreservedAnalyses::none();
}
namespace {
struct ForceFunctionAttrsLegacyPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
initializeForceFunctionAttrsLegacyPassPass(
*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override {
if (!hasForceAttributes())
return false;
for (Function &F : M.functions())
forceAttributes(F);
// Conservatively assume we changed something.
return true;
}
};
}
char ForceFunctionAttrsLegacyPass::ID = 0;
INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
"Force set function attributes", false, false)
Pass *llvm::createForceFunctionAttrsLegacyPass() {
return new ForceFunctionAttrsLegacyPass();
}