Home | History | Annotate | Download | only in Utils
      1 //===- NameAnonFunctions.cpp - ThinLTO Summary-based Function Import ------===//
      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 // This file implements naming anonymous function to make sure they can be
     11 // refered to by ThinLTO.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/ADT/SmallString.h"
     16 #include "llvm/IR/Module.h"
     17 #include "llvm/Support/MD5.h"
     18 #include "llvm/Transforms/Utils/ModuleUtils.h"
     19 
     20 using namespace llvm;
     21 
     22 // Compute a "unique" hash for the module based on the name of the public
     23 // functions.
     24 class ModuleHasher {
     25   Module &TheModule;
     26   std::string TheHash;
     27 
     28 public:
     29   ModuleHasher(Module &M) : TheModule(M) {}
     30 
     31   /// Return the lazily computed hash.
     32   std::string &get() {
     33     if (!TheHash.empty())
     34       // Cache hit :)
     35       return TheHash;
     36 
     37     MD5 Hasher;
     38     for (auto &F : TheModule) {
     39       if (F.isDeclaration() || F.hasLocalLinkage() || !F.hasName())
     40         continue;
     41       auto Name = F.getName();
     42       Hasher.update(Name);
     43     }
     44     for (auto &GV : TheModule.globals()) {
     45       if (GV.isDeclaration() || GV.hasLocalLinkage() || !GV.hasName())
     46         continue;
     47       auto Name = GV.getName();
     48       Hasher.update(Name);
     49     }
     50 
     51     // Now return the result.
     52     MD5::MD5Result Hash;
     53     Hasher.final(Hash);
     54     SmallString<32> Result;
     55     MD5::stringifyResult(Hash, Result);
     56     TheHash = Result.str();
     57     return TheHash;
     58   }
     59 };
     60 
     61 // Rename all the anon functions in the module
     62 bool llvm::nameUnamedFunctions(Module &M) {
     63   bool Changed = false;
     64   ModuleHasher ModuleHash(M);
     65   int count = 0;
     66   for (auto &F : M) {
     67     if (F.hasName())
     68       continue;
     69     F.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++));
     70     Changed = true;
     71   }
     72   return Changed;
     73 }
     74 
     75 namespace {
     76 
     77 // Simple pass that provides a name to every anon function.
     78 class NameAnonFunction : public ModulePass {
     79 
     80 public:
     81   /// Pass identification, replacement for typeid
     82   static char ID;
     83 
     84   /// Specify pass name for debug output
     85   const char *getPassName() const override { return "Name Anon Functions"; }
     86 
     87   explicit NameAnonFunction() : ModulePass(ID) {}
     88 
     89   bool runOnModule(Module &M) override { return nameUnamedFunctions(M); }
     90 };
     91 char NameAnonFunction::ID = 0;
     92 
     93 } // anonymous namespace
     94 
     95 INITIALIZE_PASS_BEGIN(NameAnonFunction, "name-anon-functions",
     96                       "Provide a name to nameless functions", false, false)
     97 INITIALIZE_PASS_END(NameAnonFunction, "name-anon-functions",
     98                     "Provide a name to nameless functions", false, false)
     99 
    100 namespace llvm {
    101 ModulePass *createNameAnonFunctionPass() { return new NameAnonFunction(); }
    102 }
    103