diff options
Diffstat (limited to 'lib/Bitcode/Writer/BitcodeWriter.cpp')
| -rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 155 | 
1 files changed, 111 insertions, 44 deletions
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index ebb2022551f7..043441bac4de 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -108,6 +108,14 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {    /// 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. 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; @@ -124,10 +132,12 @@ public:    /// writing to the provided \p Buffer.    ModuleBitcodeWriter(const Module *M, SmallVectorImpl<char> &Buffer,                        BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, -                      const ModuleSummaryIndex *Index, bool GenerateHash) +                      const ModuleSummaryIndex *Index, bool GenerateHash, +                      ModuleHash *ModHash = nullptr)        : BitcodeWriterBase(Stream), Buffer(Buffer), M(*M),          VE(*M, ShouldPreserveUseListOrder), Index(Index), -        GenerateHash(GenerateHash), BitcodeStartBit(Stream.GetCurrentBitNo()) { +        GenerateHash(GenerateHash), ModHash(ModHash), +        BitcodeStartBit(Stream.GetCurrentBitNo()) {      // 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). @@ -466,7 +476,6 @@ public:    void write();  private: -  void writeIndex();    void writeModStrings();    void writeCombinedValueSymbolTable();    void writeCombinedGlobalValueSummary(); @@ -709,22 +718,22 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {  }  void ModuleBitcodeWriter::writeAttributeGroupTable() { -  const std::vector<AttributeSet> &AttrGrps = VE.getAttributeGroups(); +  const std::vector<AttributeList> &AttrGrps = VE.getAttributeGroups();    if (AttrGrps.empty()) return;    Stream.EnterSubblock(bitc::PARAMATTR_GROUP_BLOCK_ID, 3);    SmallVector<uint64_t, 64> Record;    for (unsigned i = 0, e = AttrGrps.size(); i != e; ++i) { -    AttributeSet AS = AttrGrps[i]; +    AttributeList AS = AttrGrps[i];      for (unsigned i = 0, e = AS.getNumSlots(); i != e; ++i) { -      AttributeSet A = AS.getSlotAttributes(i); +      AttributeList A = AS.getSlotAttributes(i);        Record.push_back(VE.getAttributeGroupID(A));        Record.push_back(AS.getSlotIndex(i)); -      for (AttributeSet::iterator I = AS.begin(0), E = AS.end(0); -           I != E; ++I) { +      for (AttributeList::iterator I = AS.begin(0), E = AS.end(0); I != E; +           ++I) {          Attribute Attr = *I;          if (Attr.isEnumAttribute()) {            Record.push_back(0); @@ -756,14 +765,14 @@ void ModuleBitcodeWriter::writeAttributeGroupTable() {  }  void ModuleBitcodeWriter::writeAttributeTable() { -  const std::vector<AttributeSet> &Attrs = VE.getAttributes(); +  const std::vector<AttributeList> &Attrs = VE.getAttributes();    if (Attrs.empty()) return;    Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3);    SmallVector<uint64_t, 64> Record;    for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { -    const AttributeSet &A = Attrs[i]; +    const AttributeList &A = Attrs[i];      for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i)        Record.push_back(VE.getAttributeGroupID(A.getSlotAttributes(i))); @@ -1326,6 +1335,8 @@ static uint64_t getOptimizationFlags(const Value *V) {        Flags |= FastMathFlags::NoSignedZeros;      if (FPMO->hasAllowReciprocal())        Flags |= FastMathFlags::AllowReciprocal; +    if (FPMO->hasAllowContract()) +      Flags |= FastMathFlags::AllowContract;    }    return Flags; @@ -1473,6 +1484,13 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N,    Record.push_back(N->getFlags());    Record.push_back(VE.getMetadataOrNullID(N->getExtraData())); +  // DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means +  // that there is no DWARF address space associated with DIDerivedType. +  if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace()) +    Record.push_back(*DWARFAddressSpace + 1); +  else +    Record.push_back(0); +    Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev);    Record.clear();  } @@ -1549,6 +1567,7 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,    Record.push_back(N->getDWOId());    Record.push_back(VE.getMetadataOrNullID(N->getMacros().get()));    Record.push_back(N->getSplitDebugInlining()); +  Record.push_back(N->getDebugInfoForProfiling());    Stream.EmitRecord(bitc::METADATA_COMPILE_UNIT, Record, Abbrev);    Record.clear(); @@ -2559,7 +2578,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,        Vals.push_back(VE.getTypeID(SI.getCondition()->getType()));        pushValue(SI.getCondition(), InstID, Vals);        Vals.push_back(VE.getValueID(SI.getDefaultDest())); -      for (SwitchInst::ConstCaseIt Case : SI.cases()) { +      for (auto Case : SI.cases()) {          Vals.push_back(VE.getValueID(Case.getCaseValue()));          Vals.push_back(VE.getValueID(Case.getCaseSuccessor()));        } @@ -2905,13 +2924,6 @@ void ModuleBitcodeWriter::writeValueSymbolTable(      NameVals.push_back(VE.getValueID(Name.getValue()));      Function *F = dyn_cast<Function>(Name.getValue()); -    if (!F) { -      // If value is an alias, need to get the aliased base object to -      // see if it is a function. -      auto *GA = dyn_cast<GlobalAlias>(Name.getValue()); -      if (GA && GA->getBaseObject()) -        F = dyn_cast<Function>(GA->getBaseObject()); -    }      // VST_CODE_ENTRY:   [valueid, namechar x N]      // VST_CODE_FNENTRY: [valueid, funcoffset, namechar x N] @@ -3367,6 +3379,49 @@ void IndexBitcodeWriter::writeModStrings() {    Stream.ExitBlock();  } +/// Write the function type metadata related records that need to appear before +/// a function summary entry (whether per-module or combined). +static void writeFunctionTypeMetadataRecords(BitstreamWriter &Stream, +                                             FunctionSummary *FS) { +  if (!FS->type_tests().empty()) +    Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests()); + +  SmallVector<uint64_t, 64> Record; + +  auto WriteVFuncIdVec = [&](uint64_t Ty, +                             ArrayRef<FunctionSummary::VFuncId> VFs) { +    if (VFs.empty()) +      return; +    Record.clear(); +    for (auto &VF : VFs) { +      Record.push_back(VF.GUID); +      Record.push_back(VF.Offset); +    } +    Stream.EmitRecord(Ty, Record); +  }; + +  WriteVFuncIdVec(bitc::FS_TYPE_TEST_ASSUME_VCALLS, +                  FS->type_test_assume_vcalls()); +  WriteVFuncIdVec(bitc::FS_TYPE_CHECKED_LOAD_VCALLS, +                  FS->type_checked_load_vcalls()); + +  auto WriteConstVCallVec = [&](uint64_t Ty, +                                ArrayRef<FunctionSummary::ConstVCall> VCs) { +    for (auto &VC : VCs) { +      Record.clear(); +      Record.push_back(VC.VFunc.GUID); +      Record.push_back(VC.VFunc.Offset); +      Record.insert(Record.end(), VC.Args.begin(), VC.Args.end()); +      Stream.EmitRecord(Ty, Record); +    } +  }; + +  WriteConstVCallVec(bitc::FS_TYPE_TEST_ASSUME_CONST_VCALL, +                     FS->type_test_assume_const_vcalls()); +  WriteConstVCallVec(bitc::FS_TYPE_CHECKED_LOAD_CONST_VCALL, +                     FS->type_checked_load_const_vcalls()); +} +  // Helper to emit a single function summary record.  void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(      SmallVector<uint64_t, 64> &NameVals, GlobalValueSummary *Summary, @@ -3375,8 +3430,7 @@ void ModuleBitcodeWriter::writePerModuleFunctionSummaryRecord(    NameVals.push_back(ValueID);    FunctionSummary *FS = cast<FunctionSummary>(Summary); -  if (!FS->type_tests().empty()) -    Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests()); +  writeFunctionTypeMetadataRecords(Stream, FS);    NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));    NameVals.push_back(FS->instCount()); @@ -3636,8 +3690,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {      }      auto *FS = cast<FunctionSummary>(S); -    if (!FS->type_tests().empty()) -      Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests()); +    writeFunctionTypeMetadataRecords(Stream, FS);      NameVals.push_back(ValueId);      NameVals.push_back(Index.getModuleId(FS->modulePath())); @@ -3659,9 +3712,16 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {      for (auto &EI : FS->calls()) {        // If this GUID doesn't have a value id, it doesn't have a function        // summary and we don't need to record any calls to it. -      if (!hasValueId(EI.first.getGUID())) -        continue; -      NameVals.push_back(getValueId(EI.first.getGUID())); +      GlobalValue::GUID GUID = EI.first.getGUID(); +      if (!hasValueId(GUID)) { +        // For SamplePGO, the indirect call targets for local functions will +        // have its original name annotated in profile. We try to find the +        // corresponding PGOFuncName as the GUID. +        GUID = Index.getGUIDFromOriginalID(GUID); +        if (GUID == 0 || !hasValueId(GUID)) +          continue; +      } +      NameVals.push_back(getValueId(GUID));        if (HasProfileData)          NameVals.push_back(static_cast<uint8_t>(EI.second.Hotness));      } @@ -3697,7 +3757,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {  /// Create the "IDENTIFICATION_BLOCK_ID" containing a single string with the  /// current llvm version, and a record for the epoch number. -void writeIdentificationBlock(BitstreamWriter &Stream) { +static void writeIdentificationBlock(BitstreamWriter &Stream) {    Stream.EnterSubblock(bitc::IDENTIFICATION_BLOCK_ID, 5);    // Write the "user readable" string identifying the bitcode producer @@ -3722,17 +3782,24 @@ void writeIdentificationBlock(BitstreamWriter &Stream) {  void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) {    // Emit the module's hash.    // MODULE_CODE_HASH: [5*i32] -  SHA1 Hasher; -  Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos], -                                  Buffer.size() - BlockStartPos)); -  StringRef Hash = Hasher.result(); -  uint32_t Vals[5]; -  for (int Pos = 0; Pos < 20; Pos += 4) { -    Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos); -  } +  if (GenerateHash) { +    SHA1 Hasher; +    uint32_t Vals[5]; +    Hasher.update(ArrayRef<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos], +                                    Buffer.size() - BlockStartPos)); +    StringRef Hash = Hasher.result(); +    for (int Pos = 0; Pos < 20; Pos += 4) { +      Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos); +    } -  // Emit the finished record. -  Stream.EmitRecord(bitc::MODULE_CODE_HASH, Vals); +    // Emit the finished record. +    Stream.EmitRecord(bitc::MODULE_CODE_HASH, Vals); + +    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() { @@ -3793,9 +3860,7 @@ void ModuleBitcodeWriter::write() {    writeValueSymbolTable(M.getValueSymbolTable(),                          /* IsModuleLevel */ true, &FunctionToBitcodeIndex); -  if (GenerateHash) { -    writeModuleHash(BlockStartPos); -  } +  writeModuleHash(BlockStartPos);    Stream.ExitBlock();  } @@ -3886,9 +3951,10 @@ BitcodeWriter::~BitcodeWriter() = default;  void BitcodeWriter::writeModule(const Module *M,                                  bool ShouldPreserveUseListOrder,                                  const ModuleSummaryIndex *Index, -                                bool GenerateHash) { -  ModuleBitcodeWriter ModuleWriter( -      M, Buffer, *Stream, ShouldPreserveUseListOrder, Index, GenerateHash); +                                bool GenerateHash, ModuleHash *ModHash) { +  ModuleBitcodeWriter ModuleWriter(M, Buffer, *Stream, +                                   ShouldPreserveUseListOrder, Index, +                                   GenerateHash, ModHash);    ModuleWriter.write();  } @@ -3897,7 +3963,7 @@ void BitcodeWriter::writeModule(const Module *M,  void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,                                bool ShouldPreserveUseListOrder,                                const ModuleSummaryIndex *Index, -                              bool GenerateHash) { +                              bool GenerateHash, ModuleHash *ModHash) {    SmallVector<char, 0> Buffer;    Buffer.reserve(256*1024); @@ -3908,7 +3974,8 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,      Buffer.insert(Buffer.begin(), BWH_HeaderSize, 0);    BitcodeWriter Writer(Buffer); -  Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash); +  Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash, +                     ModHash);    if (TT.isOSDarwin() || TT.isOSBinFormatMachO())      emitDarwinBCHeaderAndTrailer(Buffer, TT);  | 
