diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 | 
| commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
| tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/Bitcode/Writer/BitcodeWriter.cpp | |
| parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) | |
Notes
Diffstat (limited to 'lib/Bitcode/Writer/BitcodeWriter.cpp')
| -rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 461 | 
1 files changed, 367 insertions, 94 deletions
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index dcffde1742cd7..fd13dbc1f1e2b 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1,4 +1,4 @@ -//===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===// +//===- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ------------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -13,39 +13,81 @@  #include "llvm/Bitcode/BitcodeWriter.h"  #include "ValueEnumerator.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h"  #include "llvm/ADT/Triple.h" +#include "llvm/Bitcode/BitCodes.h"  #include "llvm/Bitcode/BitstreamWriter.h"  #include "llvm/Bitcode/LLVMBitCodes.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h"  #include "llvm/IR/CallSite.h" +#include "llvm/IR/Comdat.h" +#include "llvm/IR/Constant.h"  #include "llvm/IR/Constants.h"  #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DebugLoc.h"  #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalIFunc.h" +#include "llvm/IR/GlobalObject.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h"  #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h"  #include "llvm/IR/Instructions.h"  #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h"  #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h"  #include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h"  #include "llvm/IR/UseListOrder.h" +#include "llvm/IR/Value.h"  #include "llvm/IR/ValueSymbolTable.h"  #include "llvm/MC/StringTableBuilder.h"  #include "llvm/Object/IRSymtab.h" +#include "llvm/Support/AtomicOrdering.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/MathExtras.h" -#include "llvm/Support/Program.h"  #include "llvm/Support/SHA1.h"  #include "llvm/Support/TargetRegistry.h"  #include "llvm/Support/raw_ostream.h" -#include <cctype> +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator>  #include <map> -using namespace llvm; +#include <memory> +#include <string> +#include <utility> +#include <vector> -namespace { +using namespace llvm; -cl::opt<unsigned> +static cl::opt<unsigned>      IndexThreshold("bitcode-mdindex-threshold", cl::Hidden, cl::init(25),                     cl::desc("Number of metadatas above which we emit an index "                              "to enable lazy-loading")); + +namespace { +  /// These are manifest constants used by the bitcode writer. They do not need to  /// be kept in sync with the reader, but need to be consistent within this file.  enum { @@ -97,11 +139,10 @@ void BitcodeWriterBase::writeModuleVersion() {    Stream.EmitRecord(bitc::MODULE_CODE_VERSION, ArrayRef<uint64_t>{2});  } -/// Class to manage the bitcode writing for a module. -class ModuleBitcodeWriter : public BitcodeWriterBase { -  /// Pointer to the buffer allocated by caller for bitcode writing. -  const SmallVectorImpl<char> &Buffer; - +/// Base class to manage the module bitcode writing, currently subclassed for +/// ModuleBitcodeWriter and ThinLinkBitcodeWriter. +class ModuleBitcodeWriterBase : public BitcodeWriterBase { +protected:    /// The Module to write to bitcode.    const Module &M; @@ -111,22 +152,6 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {    /// Optional per-module index to write for ThinLTO.    const ModuleSummaryIndex *Index; -  /// True if a module hash record should be written. -  bool GenerateHash; - -  SHA1 Hasher; - -  /// If non-null, when GenerateHash is true, the resulting hash is written -  /// into ModHash. When GenerateHash is false, that specified value -  /// is used as the hash instead of computing from the generated bitcode. -  /// Can be used to produce the same module hash for a minimized bitcode -  /// used just for the thin link as in the regular full bitcode that will -  /// be used in the backend. -  ModuleHash *ModHash; - -  /// The start bit of the identification block. -  uint64_t BitcodeStartBit; -    /// Map that holds the correspondence between GUIDs in the summary index,    /// that came from indirect call profiles, and a value id generated by this    /// class to use in the VST and summary block records. @@ -140,17 +165,14 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {    uint64_t VSTOffsetPlaceholder = 0;  public: -  /// Constructs a ModuleBitcodeWriter object for the given Module, +  /// Constructs a ModuleBitcodeWriterBase object for the given Module,    /// writing to the provided \p Buffer. -  ModuleBitcodeWriter(const Module *M, SmallVectorImpl<char> &Buffer, -                      StringTableBuilder &StrtabBuilder, -                      BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, -                      const ModuleSummaryIndex *Index, bool GenerateHash, -                      ModuleHash *ModHash = nullptr) -      : BitcodeWriterBase(Stream, StrtabBuilder), Buffer(Buffer), M(*M), -        VE(*M, ShouldPreserveUseListOrder), Index(Index), -        GenerateHash(GenerateHash), ModHash(ModHash), -        BitcodeStartBit(Stream.GetCurrentBitNo()) { +  ModuleBitcodeWriterBase(const Module *M, StringTableBuilder &StrtabBuilder, +                          BitstreamWriter &Stream, +                          bool ShouldPreserveUseListOrder, +                          const ModuleSummaryIndex *Index) +      : BitcodeWriterBase(Stream, StrtabBuilder), M(*M), +        VE(*M, ShouldPreserveUseListOrder), Index(Index) {      // Assign ValueIds to any callee values in the index that came from      // indirect call profiles and were recorded as a GUID not a Value*      // (which would have been assigned an ID by the ValueEnumerator). @@ -172,6 +194,73 @@ public:                assignValueId(CallEdge.first.getGUID());    } +protected: +  void writePerModuleGlobalValueSummary(); + +private: +  void writePerModuleFunctionSummaryRecord(SmallVector<uint64_t, 64> &NameVals, +                                           GlobalValueSummary *Summary, +                                           unsigned ValueID, +                                           unsigned FSCallsAbbrev, +                                           unsigned FSCallsProfileAbbrev, +                                           const Function &F); +  void writeModuleLevelReferences(const GlobalVariable &V, +                                  SmallVector<uint64_t, 64> &NameVals, +                                  unsigned FSModRefsAbbrev); + +  void assignValueId(GlobalValue::GUID ValGUID) { +    GUIDToValueIdMap[ValGUID] = ++GlobalValueId; +  } + +  unsigned getValueId(GlobalValue::GUID ValGUID) { +    const auto &VMI = GUIDToValueIdMap.find(ValGUID); +    // Expect that any GUID value had a value Id assigned by an +    // earlier call to assignValueId. +    assert(VMI != GUIDToValueIdMap.end() && +           "GUID does not have assigned value Id"); +    return VMI->second; +  } + +  // Helper to get the valueId for the type of value recorded in VI. +  unsigned getValueId(ValueInfo VI) { +    if (!VI.getValue()) +      return getValueId(VI.getGUID()); +    return VE.getValueID(VI.getValue()); +  } + +  std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; } +}; + +/// Class to manage the bitcode writing for a module. +class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { +  /// Pointer to the buffer allocated by caller for bitcode writing. +  const SmallVectorImpl<char> &Buffer; + +  /// True if a module hash record should be written. +  bool GenerateHash; + +  /// If non-null, when GenerateHash is true, the resulting hash is written +  /// into ModHash. +  ModuleHash *ModHash; + +  SHA1 Hasher; + +  /// The start bit of the identification block. +  uint64_t BitcodeStartBit; + +public: +  /// Constructs a ModuleBitcodeWriter object for the given Module, +  /// writing to the provided \p Buffer. +  ModuleBitcodeWriter(const Module *M, SmallVectorImpl<char> &Buffer, +                      StringTableBuilder &StrtabBuilder, +                      BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, +                      const ModuleSummaryIndex *Index, bool GenerateHash, +                      ModuleHash *ModHash = nullptr) +      : ModuleBitcodeWriterBase(M, StrtabBuilder, Stream, +                                ShouldPreserveUseListOrder, Index), +        Buffer(Buffer), GenerateHash(GenerateHash), ModHash(ModHash), +        BitcodeStartBit(Stream.GetCurrentBitNo()) {} +    /// Emit the current module to the bitstream.    void write(); @@ -287,37 +376,8 @@ private:    writeFunction(const Function &F,                  DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex);    void writeBlockInfo(); -  void writePerModuleFunctionSummaryRecord(SmallVector<uint64_t, 64> &NameVals, -                                           GlobalValueSummary *Summary, -                                           unsigned ValueID, -                                           unsigned FSCallsAbbrev, -                                           unsigned FSCallsProfileAbbrev, -                                           const Function &F); -  void writeModuleLevelReferences(const GlobalVariable &V, -                                  SmallVector<uint64_t, 64> &NameVals, -                                  unsigned FSModRefsAbbrev); -  void writePerModuleGlobalValueSummary();    void writeModuleHash(size_t BlockStartPos); -  void assignValueId(GlobalValue::GUID ValGUID) { -    GUIDToValueIdMap[ValGUID] = ++GlobalValueId; -  } -  unsigned getValueId(GlobalValue::GUID ValGUID) { -    const auto &VMI = GUIDToValueIdMap.find(ValGUID); -    // Expect that any GUID value had a value Id assigned by an -    // earlier call to assignValueId. -    assert(VMI != GUIDToValueIdMap.end() && -           "GUID does not have assigned value Id"); -    return VMI->second; -  } -  // Helper to get the valueId for the type of value recorded in VI. -  unsigned getValueId(ValueInfo VI) { -    if (!VI.getValue()) -      return getValueId(VI.getGUID()); -    return VE.getValueID(VI.getValue()); -  } -  std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; } -    unsigned getEncodedSyncScopeID(SyncScope::ID SSID) {      return unsigned(SSID);    } @@ -353,13 +413,13 @@ public:      // in writing out the call graph edges. Save the mapping from GUID      // to the new global value id to use when writing those edges, which      // are currently saved in the index in terms of GUID. -    forEachSummary([&](GVInfo I) { +    forEachSummary([&](GVInfo I, bool) {        GUIDToValueIdMap[I.first] = ++GlobalValueId;      });    }    /// The below iterator returns the GUID and associated summary. -  typedef std::pair<GlobalValue::GUID, GlobalValueSummary *> GVInfo; +  using GVInfo = std::pair<GlobalValue::GUID, GlobalValueSummary *>;    /// Calls the callback for each value GUID and summary to be written to    /// bitcode. This hides the details of whether they are being pulled from the @@ -368,12 +428,18 @@ public:    void forEachSummary(Functor Callback) {      if (ModuleToSummariesForIndex) {        for (auto &M : *ModuleToSummariesForIndex) -        for (auto &Summary : M.second) -          Callback(Summary); +        for (auto &Summary : M.second) { +          Callback(Summary, false); +          // Ensure aliasee is handled, e.g. for assigning a valueId, +          // even if we are not importing the aliasee directly (the +          // imported alias will contain a copy of aliasee). +          if (auto *AS = dyn_cast<AliasSummary>(Summary.getSecond())) +            Callback({AS->getAliaseeGUID(), &AS->getAliasee()}, true); +        }      } else {        for (auto &Summaries : Index)          for (auto &Summary : Summaries.second.SummaryList) -          Callback({Summaries.first, Summary.get()}); +          Callback({Summaries.first, Summary.get()}, false);      }    } @@ -413,8 +479,10 @@ private:        return None;      return VMI->second;    } +    std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; }  }; +  } // end anonymous namespace  static unsigned getEncodedCastOpcode(unsigned Opcode) { @@ -595,10 +663,14 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {      return bitc::ATTR_KIND_STACK_PROTECT_STRONG;    case Attribute::SafeStack:      return bitc::ATTR_KIND_SAFESTACK; +  case Attribute::StrictFP: +    return bitc::ATTR_KIND_STRICT_FP;    case Attribute::StructRet:      return bitc::ATTR_KIND_STRUCT_RET;    case Attribute::SanitizeAddress:      return bitc::ATTR_KIND_SANITIZE_ADDRESS; +  case Attribute::SanitizeHWAddress: +    return bitc::ATTR_KIND_SANITIZE_HWADDRESS;    case Attribute::SanitizeThread:      return bitc::ATTR_KIND_SANITIZE_THREAD;    case Attribute::SanitizeMemory: @@ -709,7 +781,6 @@ void ModuleBitcodeWriter::writeTypeTable() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));  // isvararg    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); -    unsigned FunctionAbbrev = Stream.EmitAbbrev(std::move(Abbv));    // Abbrev for TYPE_CODE_STRUCT_ANON. @@ -718,7 +789,6 @@ void ModuleBitcodeWriter::writeTypeTable() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));  // ispacked    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); -    unsigned StructAnonAbbrev = Stream.EmitAbbrev(std::move(Abbv));    // Abbrev for TYPE_CODE_STRUCT_NAME. @@ -734,7 +804,6 @@ void ModuleBitcodeWriter::writeTypeTable() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));  // ispacked    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); -    unsigned StructNamedAbbrev = Stream.EmitAbbrev(std::move(Abbv));    // Abbrev for TYPE_CODE_ARRAY. @@ -742,7 +811,6 @@ void ModuleBitcodeWriter::writeTypeTable() {    Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY));    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // size    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); -    unsigned ArrayAbbrev = Stream.EmitAbbrev(std::move(Abbv));    // Emit an entry count so the reader can reserve space. @@ -880,12 +948,23 @@ static unsigned getEncodedLinkage(const GlobalValue &GV) {    return getEncodedLinkage(GV.getLinkage());  } +static uint64_t getEncodedFFlags(FunctionSummary::FFlags Flags) { +  uint64_t RawFlags = 0; +  RawFlags |= Flags.ReadNone; +  RawFlags |= (Flags.ReadOnly << 1); +  RawFlags |= (Flags.NoRecurse << 2); +  RawFlags |= (Flags.ReturnDoesNotAlias << 3); +  return RawFlags; +} +  // Decode the flags for GlobalValue in the summary  static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) {    uint64_t RawFlags = 0;    RawFlags |= Flags.NotEligibleToImport; // bool    RawFlags |= (Flags.Live << 1); +  RawFlags |= (Flags.DSOLocal << 2); +    // Linkage don't need to be remapped at that time for the summary. Any future    // change to the getEncodedLinkage() function will need to be taken into    // account here as well. @@ -1128,7 +1207,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {      // GLOBALVAR: [strtab offset, strtab size, type, isconst, initid,      //             linkage, alignment, section, visibility, threadlocal,      //             unnamed_addr, externally_initialized, dllstorageclass, -    //             comdat, attributes] +    //             comdat, attributes, DSO_Local]      Vals.push_back(addToStrtab(GV.getName()));      Vals.push_back(GV.getName().size());      Vals.push_back(VE.getTypeID(GV.getValueType())); @@ -1144,7 +1223,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {          GV.isExternallyInitialized() ||          GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||          GV.hasComdat() || -        GV.hasAttributes()) { +        GV.hasAttributes() || +        GV.isDSOLocal()) {        Vals.push_back(getEncodedVisibility(GV));        Vals.push_back(getEncodedThreadLocalMode(GV));        Vals.push_back(getEncodedUnnamedAddr(GV)); @@ -1154,6 +1234,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {        auto AL = GV.getAttributesAsList(AttributeList::FunctionIndex);        Vals.push_back(VE.getAttributeListID(AL)); + +      Vals.push_back(GV.isDSOLocal());      } else {        AbbrevToUse = SimpleGVarAbbrev;      } @@ -1167,7 +1249,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {      // FUNCTION:  [strtab offset, strtab size, type, callingconv, isproto,      //             linkage, paramattrs, alignment, section, visibility, gc,      //             unnamed_addr, prologuedata, dllstorageclass, comdat, -    //             prefixdata, personalityfn] +    //             prefixdata, personalityfn, DSO_Local]      Vals.push_back(addToStrtab(F.getName()));      Vals.push_back(F.getName().size());      Vals.push_back(VE.getTypeID(F.getFunctionType())); @@ -1189,6 +1271,7 @@ void ModuleBitcodeWriter::writeModuleInfo() {      Vals.push_back(          F.hasPersonalityFn() ? (VE.getValueID(F.getPersonalityFn()) + 1) : 0); +    Vals.push_back(F.isDSOLocal());      unsigned AbbrevToUse = 0;      Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);      Vals.clear(); @@ -1197,7 +1280,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {    // Emit the alias information.    for (const GlobalAlias &A : M.aliases()) {      // ALIAS: [strtab offset, strtab size, alias type, aliasee val#, linkage, -    //         visibility, dllstorageclass, threadlocal, unnamed_addr] +    //         visibility, dllstorageclass, threadlocal, unnamed_addr, +    //         DSO_Local]      Vals.push_back(addToStrtab(A.getName()));      Vals.push_back(A.getName().size());      Vals.push_back(VE.getTypeID(A.getValueType())); @@ -1208,6 +1292,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {      Vals.push_back(getEncodedDLLStorageClass(A));      Vals.push_back(getEncodedThreadLocalMode(A));      Vals.push_back(getEncodedUnnamedAddr(A)); +    Vals.push_back(A.isDSOLocal()); +      unsigned AbbrevToUse = 0;      Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);      Vals.clear(); @@ -1243,8 +1329,8 @@ static uint64_t getOptimizationFlags(const Value *V) {      if (PEO->isExact())        Flags |= 1 << bitc::PEO_EXACT;    } else if (const auto *FPMO = dyn_cast<FPMathOperator>(V)) { -    if (FPMO->hasUnsafeAlgebra()) -      Flags |= FastMathFlags::UnsafeAlgebra; +    if (FPMO->hasAllowReassoc()) +      Flags |= FastMathFlags::AllowReassoc;      if (FPMO->hasNoNaNs())        Flags |= FastMathFlags::NoNaNs;      if (FPMO->hasNoInfs()) @@ -1255,6 +1341,8 @@ static uint64_t getOptimizationFlags(const Value *V) {        Flags |= FastMathFlags::AllowReciprocal;      if (FPMO->hasAllowContract())        Flags |= FastMathFlags::AllowContract; +    if (FPMO->hasApproxFunc()) +      Flags |= FastMathFlags::ApproxFunc;    }    return Flags; @@ -1486,6 +1574,7 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,    Record.push_back(VE.getMetadataOrNullID(N->getMacros().get()));    Record.push_back(N->getSplitDebugInlining());    Record.push_back(N->getDebugInfoForProfiling()); +  Record.push_back(N->getGnuPubnames());    Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev);    Record.clear(); @@ -1688,7 +1777,7 @@ void ModuleBitcodeWriter::writeDIGlobalVariableExpression(    Record.push_back(N->isDistinct());    Record.push_back(VE.getMetadataOrNullID(N->getVariable()));    Record.push_back(VE.getMetadataOrNullID(N->getExpression())); -   +    Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR_EXPR, Record, Abbrev);    Record.clear();  } @@ -2180,7 +2269,7 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,          Record.push_back(p[0]);          Record.push_back(p[1]);        } else { -        assert (0 && "Unknown FP type!"); +        assert(0 && "Unknown FP type!");        }      } else if (isa<ConstantDataSequential>(C) &&                 cast<ConstantDataSequential>(C)->isString()) { @@ -3025,8 +3114,6 @@ void ModuleBitcodeWriter::writeBlockInfo() {        llvm_unreachable("Unexpected abbrev ordering!");    } - -    { // SETTYPE abbrev for CONSTANTS_BLOCK.      auto Abbv = std::make_shared<BitCodeAbbrev>();      Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); @@ -3267,7 +3354,7 @@ static void writeFunctionTypeMetadataRecords(BitstreamWriter &Stream,  }  // Helper to emit a single function summary record. -void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord( +void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(      SmallVector<uint64_t, 64> &NameVals, GlobalValueSummary *Summary,      unsigned ValueID, unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev,      const Function &F) { @@ -3278,6 +3365,7 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(    NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));    NameVals.push_back(FS->instCount()); +  NameVals.push_back(getEncodedFFlags(FS->fflags()));    NameVals.push_back(FS->refs().size());    for (auto &RI : FS->refs()) @@ -3301,7 +3389,7 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(  // Collect the global value references in the given variable's initializer,  // and emit them in a summary record. -void ModuleBitcodeWriter::writeModuleLevelReferences( +void ModuleBitcodeWriterBase::writeModuleLevelReferences(      const GlobalVariable &V, SmallVector<uint64_t, 64> &NameVals,      unsigned FSModRefsAbbrev) {    auto VI = Index->getValueInfo(GlobalValue::getGUID(V.getName())); @@ -3331,11 +3419,11 @@ void ModuleBitcodeWriter::writeModuleLevelReferences(  // Current version for the summary.  // This is bumped whenever we introduce changes in the way some record are  // interpreted, like flags for instance. -static const uint64_t INDEX_VERSION = 3; +static const uint64_t INDEX_VERSION = 4;  /// Emit the per-module summary section alongside the rest of  /// the module's bitcode. -void ModuleBitcodeWriter::writePerModuleGlobalValueSummary() { +void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() {    // By default we compile with ThinLTO if the module has a summary, but the    // client can request full LTO with a module flag.    bool IsThinLTO = true; @@ -3364,6 +3452,7 @@ void ModuleBitcodeWriter::writePerModuleGlobalValueSummary() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // valueid    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // flags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount +  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // fflags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs    // numrefs x valueid, n x (valueid)    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -3376,6 +3465,7 @@ void ModuleBitcodeWriter::writePerModuleGlobalValueSummary() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // valueid    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // flags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount +  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // fflags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs    // numrefs x valueid, n x (valueid, hotness)    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -3461,6 +3551,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // modid    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // flags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount +  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // fflags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs    // numrefs x valueid, n x (valueid)    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -3474,6 +3565,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // modid    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // flags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));   // instcount +  Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // fflags    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4));   // numrefs    // numrefs x valueid, n x (valueid, hotness)    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -3518,7 +3610,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {      NameVals.clear();    }; -  forEachSummary([&](GVInfo I) { +  forEachSummary([&](GVInfo I, bool IsAliasee) {      GlobalValueSummary *S = I.second;      assert(S); @@ -3526,6 +3618,12 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {      assert(ValueId);      SummaryToValueIdMap[S] = *ValueId; +    // If this is invoked for an aliasee, we want to record the above +    // mapping, but then not emit a summary entry (if the aliasee is +    // to be imported, we will invoke this separately with IsAliasee=false). +    if (IsAliasee) +      return; +      if (auto *AS = dyn_cast<AliasSummary>(S)) {        // Will process aliases as a post-pass because the reader wants all        // global to be loaded first. @@ -3559,6 +3657,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {      NameVals.push_back(Index.getModuleId(FS->modulePath()));      NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));      NameVals.push_back(FS->instCount()); +    NameVals.push_back(getEncodedFFlags(FS->fflags()));      // Fill in below      NameVals.push_back(0); @@ -3570,7 +3669,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {        NameVals.push_back(*RefValueId);        Count++;      } -    NameVals[4] = Count; +    NameVals[5] = Count;      bool HasProfileData = false;      for (auto &EI : FS->calls()) { @@ -3594,6 +3693,20 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {          CallValueId = getValueId(GUID);          if (!CallValueId)            continue; +        // The mapping from OriginalId to GUID may return a GUID +        // that corresponds to a static variable. Filter it out here. +        // This can happen when  +        // 1) There is a call to a library function which does not have +        // a CallValidId; +        // 2) There is a static variable with the  OriginalGUID identical +        // to the GUID of the library function in 1); +        // When this happens, the logic for SamplePGO kicks in and +        // the static variable in 2) will be found, which needs to be +        // filtered out. +        auto *GVSum = Index.getGlobalValueSummary(GUID, false); +        if (GVSum && +            GVSum->getSummaryKind() == GlobalValueSummary::GlobalVarKind) +          continue;        }        NameVals.push_back(*CallValueId);        if (HasProfileData) @@ -3689,8 +3802,7 @@ void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) {      if (ModHash)        // Save the written hash value.        std::copy(std::begin(Vals), std::end(Vals), std::begin(*ModHash)); -  } else if (ModHash) -    Stream.EmitRecord(bitc::MODULE_CODE_HASH, ArrayRef<uint32_t>(*ModHash)); +  }  }  void ModuleBitcodeWriter::write() { @@ -3985,3 +4097,164 @@ void llvm::WriteIndexToFile(    Out.write((char *)&Buffer.front(), Buffer.size());  } + +namespace { + +/// Class to manage the bitcode writing for a thin link bitcode file. +class ThinLinkBitcodeWriter : public ModuleBitcodeWriterBase { +  /// ModHash is for use in ThinLTO incremental build, generated while writing +  /// the module bitcode file. +  const ModuleHash *ModHash; + +public: +  ThinLinkBitcodeWriter(const Module *M, StringTableBuilder &StrtabBuilder, +                        BitstreamWriter &Stream, +                        const ModuleSummaryIndex &Index, +                        const ModuleHash &ModHash) +      : ModuleBitcodeWriterBase(M, StrtabBuilder, Stream, +                                /*ShouldPreserveUseListOrder=*/false, &Index), +        ModHash(&ModHash) {} + +  void write(); + +private: +  void writeSimplifiedModuleInfo(); +}; + +} // end anonymous namespace + +// This function writes a simpilified module info for thin link bitcode file. +// It only contains the source file name along with the name(the offset and +// size in strtab) and linkage for global values. For the global value info +// entry, in order to keep linkage at offset 5, there are three zeros used +// as padding. +void ThinLinkBitcodeWriter::writeSimplifiedModuleInfo() { +  SmallVector<unsigned, 64> Vals; +  // Emit the module's source file name. +  { +    StringEncoding Bits = getStringEncoding(M.getSourceFileName()); +    BitCodeAbbrevOp AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8); +    if (Bits == SE_Char6) +      AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Char6); +    else if (Bits == SE_Fixed7) +      AbbrevOpToUse = BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7); + +    // MODULE_CODE_SOURCE_FILENAME: [namechar x N] +    auto Abbv = std::make_shared<BitCodeAbbrev>(); +    Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_SOURCE_FILENAME)); +    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); +    Abbv->Add(AbbrevOpToUse); +    unsigned FilenameAbbrev = Stream.EmitAbbrev(std::move(Abbv)); + +    for (const auto P : M.getSourceFileName()) +      Vals.push_back((unsigned char)P); + +    Stream.EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, FilenameAbbrev); +    Vals.clear(); +  } + +  // Emit the global variable information. +  for (const GlobalVariable &GV : M.globals()) { +    // GLOBALVAR: [strtab offset, strtab size, 0, 0, 0, linkage] +    Vals.push_back(StrtabBuilder.add(GV.getName())); +    Vals.push_back(GV.getName().size()); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(getEncodedLinkage(GV)); + +    Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals); +    Vals.clear(); +  } + +  // Emit the function proto information. +  for (const Function &F : M) { +    // FUNCTION:  [strtab offset, strtab size, 0, 0, 0, linkage] +    Vals.push_back(StrtabBuilder.add(F.getName())); +    Vals.push_back(F.getName().size()); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(getEncodedLinkage(F)); + +    Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals); +    Vals.clear(); +  } + +  // Emit the alias information. +  for (const GlobalAlias &A : M.aliases()) { +    // ALIAS: [strtab offset, strtab size, 0, 0, 0, linkage] +    Vals.push_back(StrtabBuilder.add(A.getName())); +    Vals.push_back(A.getName().size()); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(getEncodedLinkage(A)); + +    Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals); +    Vals.clear(); +  } + +  // Emit the ifunc information. +  for (const GlobalIFunc &I : M.ifuncs()) { +    // IFUNC: [strtab offset, strtab size, 0, 0, 0, linkage] +    Vals.push_back(StrtabBuilder.add(I.getName())); +    Vals.push_back(I.getName().size()); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(0); +    Vals.push_back(getEncodedLinkage(I)); + +    Stream.EmitRecord(bitc::MODULE_CODE_IFUNC, Vals); +    Vals.clear(); +  } +} + +void ThinLinkBitcodeWriter::write() { +  Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); + +  writeModuleVersion(); + +  writeSimplifiedModuleInfo(); + +  writePerModuleGlobalValueSummary(); + +  // Write module hash. +  Stream.EmitRecord(bitc::MODULE_CODE_HASH, ArrayRef<uint32_t>(*ModHash)); + +  Stream.ExitBlock(); +} + +void BitcodeWriter::writeThinLinkBitcode(const Module *M, +                                         const ModuleSummaryIndex &Index, +                                         const ModuleHash &ModHash) { +  assert(!WroteStrtab); + +  // The Mods vector is used by irsymtab::build, which requires non-const +  // Modules in case it needs to materialize metadata. But the bitcode writer +  // requires that the module is materialized, so we can cast to non-const here, +  // after checking that it is in fact materialized. +  assert(M->isMaterialized()); +  Mods.push_back(const_cast<Module *>(M)); + +  ThinLinkBitcodeWriter ThinLinkWriter(M, StrtabBuilder, *Stream, Index, +                                       ModHash); +  ThinLinkWriter.write(); +} + +// Write the specified thin link bitcode file to the given raw output stream, +// where it will be written in a new bitcode block. This is used when +// writing the per-module index file for ThinLTO. +void llvm::WriteThinLinkBitcodeToFile(const Module *M, raw_ostream &Out, +                                      const ModuleSummaryIndex &Index, +                                      const ModuleHash &ModHash) { +  SmallVector<char, 0> Buffer; +  Buffer.reserve(256 * 1024); + +  BitcodeWriter Writer(Buffer); +  Writer.writeThinLinkBitcode(M, Index, ModHash); +  Writer.writeSymtab(); +  Writer.writeStrtab(); + +  Out.write((char *)&Buffer.front(), Buffer.size()); +}  | 
