Home | History | Annotate | Download | only in IPO
      1 //===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
     11 #include "llvm/ADT/StringSwitch.h"
     12 #include "llvm/IR/Function.h"
     13 #include "llvm/IR/LLVMContext.h"
     14 #include "llvm/IR/Module.h"
     15 #include "llvm/Support/Debug.h"
     16 #include "llvm/Support/raw_ostream.h"
     17 using namespace llvm;
     18 
     19 #define DEBUG_TYPE "forceattrs"
     20 
     21 static cl::list<std::string>
     22     ForceAttributes("force-attribute", cl::Hidden,
     23                     cl::desc("Add an attribute to a function. This should be a "
     24                              "pair of 'function-name:attribute-name', for "
     25                              "example -force-attribute=foo:noinline. This "
     26                              "option can be specified multiple times."));
     27 
     28 static Attribute::AttrKind parseAttrKind(StringRef Kind) {
     29   return StringSwitch<Attribute::AttrKind>(Kind)
     30       .Case("alwaysinline", Attribute::AlwaysInline)
     31       .Case("builtin", Attribute::Builtin)
     32       .Case("cold", Attribute::Cold)
     33       .Case("convergent", Attribute::Convergent)
     34       .Case("inlinehint", Attribute::InlineHint)
     35       .Case("jumptable", Attribute::JumpTable)
     36       .Case("minsize", Attribute::MinSize)
     37       .Case("naked", Attribute::Naked)
     38       .Case("nobuiltin", Attribute::NoBuiltin)
     39       .Case("noduplicate", Attribute::NoDuplicate)
     40       .Case("noimplicitfloat", Attribute::NoImplicitFloat)
     41       .Case("noinline", Attribute::NoInline)
     42       .Case("nonlazybind", Attribute::NonLazyBind)
     43       .Case("noredzone", Attribute::NoRedZone)
     44       .Case("noreturn", Attribute::NoReturn)
     45       .Case("norecurse", Attribute::NoRecurse)
     46       .Case("nounwind", Attribute::NoUnwind)
     47       .Case("optnone", Attribute::OptimizeNone)
     48       .Case("optsize", Attribute::OptimizeForSize)
     49       .Case("readnone", Attribute::ReadNone)
     50       .Case("readonly", Attribute::ReadOnly)
     51       .Case("argmemonly", Attribute::ArgMemOnly)
     52       .Case("returns_twice", Attribute::ReturnsTwice)
     53       .Case("safestack", Attribute::SafeStack)
     54       .Case("sanitize_address", Attribute::SanitizeAddress)
     55       .Case("sanitize_memory", Attribute::SanitizeMemory)
     56       .Case("sanitize_thread", Attribute::SanitizeThread)
     57       .Case("ssp", Attribute::StackProtect)
     58       .Case("sspreq", Attribute::StackProtectReq)
     59       .Case("sspstrong", Attribute::StackProtectStrong)
     60       .Case("uwtable", Attribute::UWTable)
     61       .Default(Attribute::None);
     62 }
     63 
     64 /// If F has any forced attributes given on the command line, add them.
     65 static void addForcedAttributes(Function &F) {
     66   for (auto &S : ForceAttributes) {
     67     auto KV = StringRef(S).split(':');
     68     if (KV.first != F.getName())
     69       continue;
     70 
     71     auto Kind = parseAttrKind(KV.second);
     72     if (Kind == Attribute::None) {
     73       DEBUG(dbgs() << "ForcedAttribute: " << KV.second
     74                    << " unknown or not handled!\n");
     75       continue;
     76     }
     77     if (F.hasFnAttribute(Kind))
     78       continue;
     79     F.addFnAttr(Kind);
     80   }
     81 }
     82 
     83 PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
     84                                               ModuleAnalysisManager &) {
     85   if (ForceAttributes.empty())
     86     return PreservedAnalyses::all();
     87 
     88   for (Function &F : M.functions())
     89     addForcedAttributes(F);
     90 
     91   // Just conservatively invalidate analyses, this isn't likely to be important.
     92   return PreservedAnalyses::none();
     93 }
     94 
     95 namespace {
     96 struct ForceFunctionAttrsLegacyPass : public ModulePass {
     97   static char ID; // Pass identification, replacement for typeid
     98   ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
     99     initializeForceFunctionAttrsLegacyPassPass(
    100         *PassRegistry::getPassRegistry());
    101   }
    102 
    103   bool runOnModule(Module &M) override {
    104     if (ForceAttributes.empty())
    105       return false;
    106 
    107     for (Function &F : M.functions())
    108       addForcedAttributes(F);
    109 
    110     // Conservatively assume we changed something.
    111     return true;
    112   }
    113 };
    114 }
    115 
    116 char ForceFunctionAttrsLegacyPass::ID = 0;
    117 INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
    118                 "Force set function attributes", false, false)
    119 
    120 Pass *llvm::createForceFunctionAttrsLegacyPass() {
    121   return new ForceFunctionAttrsLegacyPass();
    122 }
    123