Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
35266 views
//===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"9#include "llvm/IR/Function.h"10#include "llvm/IR/Module.h"11#include "llvm/Support/CommandLine.h"12#include "llvm/Support/Debug.h"13#include "llvm/Support/LineIterator.h"14#include "llvm/Support/MemoryBuffer.h"15#include "llvm/Support/raw_ostream.h"16using namespace llvm;1718#define DEBUG_TYPE "forceattrs"1920static cl::list<std::string> ForceAttributes(21"force-attribute", cl::Hidden,22cl::desc(23"Add an attribute to a function. This can be a "24"pair of 'function-name:attribute-name', to apply an attribute to a "25"specific function. For "26"example -force-attribute=foo:noinline. Specifying only an attribute "27"will apply the attribute to every function in the module. This "28"option can be specified multiple times."));2930static cl::list<std::string> ForceRemoveAttributes(31"force-remove-attribute", cl::Hidden,32cl::desc("Remove an attribute from a function. This can be a "33"pair of 'function-name:attribute-name' to remove an attribute "34"from a specific function. For "35"example -force-remove-attribute=foo:noinline. Specifying only an "36"attribute will remove the attribute from all functions in the "37"module. This "38"option can be specified multiple times."));3940static cl::opt<std::string> CSVFilePath(41"forceattrs-csv-path", cl::Hidden,42cl::desc(43"Path to CSV file containing lines of function names and attributes to "44"add to them in the form of `f1,attr1` or `f2,attr2=str`."));4546/// If F has any forced attributes given on the command line, add them.47/// If F has any forced remove attributes given on the command line, remove48/// them. When both force and force-remove are given to a function, the latter49/// takes precedence.50static void forceAttributes(Function &F) {51auto ParseFunctionAndAttr = [&](StringRef S) {52StringRef AttributeText;53if (S.contains(':')) {54auto KV = StringRef(S).split(':');55if (KV.first != F.getName())56return Attribute::None;57AttributeText = KV.second;58} else {59AttributeText = S;60}61auto Kind = Attribute::getAttrKindFromName(AttributeText);62if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) {63LLVM_DEBUG(dbgs() << "ForcedAttribute: " << AttributeText64<< " unknown or not a function attribute!\n");65}66return Kind;67};6869for (const auto &S : ForceAttributes) {70auto Kind = ParseFunctionAndAttr(S);71if (Kind == Attribute::None || F.hasFnAttribute(Kind))72continue;73F.addFnAttr(Kind);74}7576for (const auto &S : ForceRemoveAttributes) {77auto Kind = ParseFunctionAndAttr(S);78if (Kind == Attribute::None || !F.hasFnAttribute(Kind))79continue;80F.removeFnAttr(Kind);81}82}8384static bool hasForceAttributes() {85return !ForceAttributes.empty() || !ForceRemoveAttributes.empty();86}8788PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,89ModuleAnalysisManager &) {90bool Changed = false;91if (!CSVFilePath.empty()) {92auto BufferOrError = MemoryBuffer::getFileOrSTDIN(CSVFilePath);93if (!BufferOrError)94report_fatal_error("Cannot open CSV file.");95StringRef Buffer = BufferOrError.get()->getBuffer();96auto MemoryBuffer = MemoryBuffer::getMemBuffer(Buffer);97line_iterator It(*MemoryBuffer);98for (; !It.is_at_end(); ++It) {99auto SplitPair = It->split(',');100if (SplitPair.second.empty())101continue;102Function *Func = M.getFunction(SplitPair.first);103if (Func) {104if (Func->isDeclaration())105continue;106auto SecondSplitPair = SplitPair.second.split('=');107if (!SecondSplitPair.second.empty()) {108Func->addFnAttr(SecondSplitPair.first, SecondSplitPair.second);109Changed = true;110} else {111auto AttrKind = Attribute::getAttrKindFromName(SplitPair.second);112if (AttrKind != Attribute::None &&113Attribute::canUseAsFnAttr(AttrKind)) {114// TODO: There could be string attributes without a value, we should115// support those, too.116Func->addFnAttr(AttrKind);117Changed = true;118} else119errs() << "Cannot add " << SplitPair.second120<< " as an attribute name.\n";121}122} else {123errs() << "Function in CSV file at line " << It.line_number()124<< " does not exist.\n";125// TODO: `report_fatal_error at end of pass for missing functions.126continue;127}128}129}130if (hasForceAttributes()) {131for (Function &F : M.functions())132forceAttributes(F);133Changed = true;134}135// Just conservatively invalidate analyses if we've made any changes, this136// isn't likely to be important.137return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();138}139140141