diff --git a/llvm/include/llvm/Bitcode/BitcodeWriterBase.h b/llvm/include/llvm/Bitcode/BitcodeWriterBase.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Bitcode/BitcodeWriterBase.h @@ -0,0 +1,106 @@ +//===- llvm/Bitcode/BitcodeWriterBase.h - Bitcode writer --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Base classes for writing LLVM objects to bitcode +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODEWRITERBASE_H +#define LLVM_BITCODE_BITCODEWRITERBASE_H + +#include "llvm/Bitcode/ValueEnumerator.h" +#include "llvm/Bitstream/BitstreamWriter.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/Support/SHA1.h" + +namespace llvm { + +class GlobalValueSummary; +class Module; +class ModuleSummaryIndex; +class StringTableBuilder; + +// Generates an enum to use as an index in the Abbrev array of Metadata record. +enum MetadataAbbrev : unsigned { +#define HANDLE_MDNODE_LEAF(CLASS) CLASS##AbbrevID, +#include "llvm/IR/Metadata.def" + LastPlusOne +}; + +/// Abstract class to manage the bitcode writing, subclassed for each bitcode +/// file type. +class BitcodeWriterBase { +protected: + /// The stream created and owned by the client. + BitstreamWriter &Stream; + + StringTableBuilder &StrtabBuilder; + + /// 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 { + // VALUE_SYMTAB_BLOCK abbrev id's. + VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + VST_ENTRY_7_ABBREV, + VST_ENTRY_6_ABBREV, + VST_BBENTRY_6_ABBREV, + + // CONSTANTS_BLOCK abbrev id's. + CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + CONSTANTS_INTEGER_ABBREV, + CONSTANTS_CE_CAST_Abbrev, + CONSTANTS_NULL_Abbrev, + + // FUNCTION_BLOCK abbrev id's. + FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + FUNCTION_INST_UNOP_ABBREV, + FUNCTION_INST_UNOP_FLAGS_ABBREV, + FUNCTION_INST_BINOP_ABBREV, + FUNCTION_INST_BINOP_FLAGS_ABBREV, + FUNCTION_INST_CAST_ABBREV, + FUNCTION_INST_RET_VOID_ABBREV, + FUNCTION_INST_RET_VAL_ABBREV, + FUNCTION_INST_UNREACHABLE_ABBREV, + FUNCTION_INST_GEP_ABBREV, + }; + +public: + /// Constructs a BitcodeWriterBase object that writes to the provided + /// \p Stream. + BitcodeWriterBase(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder) + : Stream(Stream), StrtabBuilder(StrtabBuilder) {} + + static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind); + static void writeStringRecord(BitstreamWriter &Stream, unsigned Code, + StringRef Str, unsigned AbbrevToUse); + static void writeIdentificationBlock(BitstreamWriter &Stream); + static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V); + static void emitWideAPInt(SmallVectorImpl &Vals, const APInt &A); + + static unsigned getEncodedComdatSelectionKind(const Comdat &C); + static unsigned getEncodedLinkage(const GlobalValue::LinkageTypes Linkage); + static unsigned getEncodedLinkage(const GlobalValue &GV); + static unsigned getEncodedVisibility(const GlobalValue &GV); + static unsigned getEncodedThreadLocalMode(const GlobalValue &GV); + static unsigned getEncodedDLLStorageClass(const GlobalValue &GV); + static unsigned getEncodedCastOpcode(unsigned Opcode); + static unsigned getEncodedUnaryOpcode(unsigned Opcode); + static unsigned getEncodedBinaryOpcode(unsigned Opcode); + static unsigned getEncodedRMWOperation(AtomicRMWInst::BinOp Op); + static unsigned getEncodedOrdering(AtomicOrdering Ordering); + static uint64_t getOptimizationFlags(const Value *V); + +protected: + void writeModuleVersion(); +}; + +} // namespace llvm +#endif // LLVM_BITCODE_BITCODEWRITERBASE_H diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/llvm/include/llvm/Bitcode/ValueEnumerator.h rename from llvm/lib/Bitcode/Writer/ValueEnumerator.h rename to llvm/include/llvm/Bitcode/ValueEnumerator.h --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ b/llvm/include/llvm/Bitcode/ValueEnumerator.h @@ -1,4 +1,4 @@ -//===- Bitcode/Writer/ValueEnumerator.h - Number values ---------*- C++ -*-===// +//===- llvm/Bitcode/ValueEnumerator.h - Number values -----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H -#define LLVM_LIB_BITCODE_WRITER_VALUEENUMERATOR_H +#ifndef LLVM_BITCODE_VALUEENUMERATOR_H +#define LLVM_BITCODE_VALUEENUMERATOR_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Bitcode/BitcodeWriter.h" -#include "ValueEnumerator.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" @@ -26,7 +25,9 @@ #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/BitcodeCommon.h" #include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriterBase.h" #include "llvm/Bitcode/LLVMBitCodes.h" +#include "llvm/Bitcode/ValueEnumerator.h" #include "llvm/Bitstream/BitCodes.h" #include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/Config/llvm-config.h" @@ -96,152 +97,12 @@ extern FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold; -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 { - // VALUE_SYMTAB_BLOCK abbrev id's. - VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV, - VST_ENTRY_7_ABBREV, - VST_ENTRY_6_ABBREV, - VST_BBENTRY_6_ABBREV, - - // CONSTANTS_BLOCK abbrev id's. - CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV, - CONSTANTS_INTEGER_ABBREV, - CONSTANTS_CE_CAST_Abbrev, - CONSTANTS_NULL_Abbrev, - - // FUNCTION_BLOCK abbrev id's. - FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, - FUNCTION_INST_UNOP_ABBREV, - FUNCTION_INST_UNOP_FLAGS_ABBREV, - FUNCTION_INST_BINOP_ABBREV, - FUNCTION_INST_BINOP_FLAGS_ABBREV, - FUNCTION_INST_CAST_ABBREV, - FUNCTION_INST_RET_VOID_ABBREV, - FUNCTION_INST_RET_VAL_ABBREV, - FUNCTION_INST_UNREACHABLE_ABBREV, - FUNCTION_INST_GEP_ABBREV, -}; - -/// Abstract class to manage the bitcode writing, subclassed for each bitcode -/// file type. -class BitcodeWriterBase { -protected: - /// The stream created and owned by the client. - BitstreamWriter &Stream; - - StringTableBuilder &StrtabBuilder; - -public: - /// Constructs a BitcodeWriterBase object that writes to the provided - /// \p Stream. - BitcodeWriterBase(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder) - : Stream(Stream), StrtabBuilder(StrtabBuilder) {} - -protected: - void writeModuleVersion(); -}; - void BitcodeWriterBase::writeModuleVersion() { // VERSION: [version#] Stream.EmitRecord(bitc::MODULE_CODE_VERSION, ArrayRef{2}); } -/// 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; - - /// Enumerates ids for all values in the module. - ValueEnumerator VE; - - /// Optional per-module index to write for ThinLTO. - const ModuleSummaryIndex *Index; - - /// 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. - std::map GUIDToValueIdMap; - - /// Tracks the last value id recorded in the GUIDToValueMap. - unsigned GlobalValueId; - - /// Saves the offset of the VSTOffset record that must eventually be - /// backpatched with the offset of the actual VST. - uint64_t VSTOffsetPlaceholder = 0; - -public: - /// Constructs a ModuleBitcodeWriterBase object for the given Module, - /// writing to the provided \p Buffer. - 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). - // The starting ValueId is just after the number of values in the - // ValueEnumerator, so that they can be emitted in the VST. - GlobalValueId = VE.getValues().size(); - if (!Index) - return; - for (const auto &GUIDSummaryLists : *Index) - // Examine all summaries for this GUID. - for (auto &Summary : GUIDSummaryLists.second.SummaryList) - if (auto FS = dyn_cast(Summary.get())) - // For each call in the function summary, see if the call - // is to a GUID (which means it is for an indirect call, - // otherwise we would have a Value for it). If so, synthesize - // a value id. - for (auto &CallEdge : FS->calls()) - if (!CallEdge.first.haveGVs() || !CallEdge.first.getValue()) - assignValueId(CallEdge.first.getGUID()); - } - -protected: - void writePerModuleGlobalValueSummary(); - -private: - void writePerModuleFunctionSummaryRecord(SmallVector &NameVals, - GlobalValueSummary *Summary, - unsigned ValueID, - unsigned FSCallsAbbrev, - unsigned FSCallsProfileAbbrev, - const Function &F); - void writeModuleLevelReferences(const GlobalVariable &V, - SmallVector &NameVals, - unsigned FSModRefsAbbrev, - unsigned FSModVTableRefsAbbrev); - - 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.haveGVs() || !VI.getValue()) - return getValueId(VI.getGUID()); - return VE.getValueID(VI.getValue()); - } - - std::map &valueIds() { return GUIDToValueIdMap; } -}; +namespace { /// Class to manage the bitcode writing for a module. class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { @@ -509,7 +370,7 @@ } // end anonymous namespace -static unsigned getEncodedCastOpcode(unsigned Opcode) { +unsigned BitcodeWriterBase::getEncodedCastOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown cast instruction!"); case Instruction::Trunc : return bitc::CAST_TRUNC; @@ -528,14 +389,14 @@ } } -static unsigned getEncodedUnaryOpcode(unsigned Opcode) { +unsigned BitcodeWriterBase::getEncodedUnaryOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown binary instruction!"); case Instruction::FNeg: return bitc::UNOP_FNEG; } } -static unsigned getEncodedBinaryOpcode(unsigned Opcode) { +unsigned BitcodeWriterBase::getEncodedBinaryOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown binary instruction!"); case Instruction::Add: @@ -559,7 +420,7 @@ } } -static unsigned getEncodedRMWOperation(AtomicRMWInst::BinOp Op) { +unsigned BitcodeWriterBase::getEncodedRMWOperation(AtomicRMWInst::BinOp Op) { switch (Op) { default: llvm_unreachable("Unknown RMW operation!"); case AtomicRMWInst::Xchg: return bitc::RMW_XCHG; @@ -578,7 +439,7 @@ } } -static unsigned getEncodedOrdering(AtomicOrdering Ordering) { +unsigned BitcodeWriterBase::getEncodedOrdering(AtomicOrdering Ordering) { switch (Ordering) { case AtomicOrdering::NotAtomic: return bitc::ORDERING_NOTATOMIC; case AtomicOrdering::Unordered: return bitc::ORDERING_UNORDERED; @@ -591,8 +452,9 @@ llvm_unreachable("Invalid ordering"); } -static void writeStringRecord(BitstreamWriter &Stream, unsigned Code, - StringRef Str, unsigned AbbrevToUse) { +void BitcodeWriterBase::writeStringRecord(BitstreamWriter &Stream, + unsigned Code, StringRef Str, + unsigned AbbrevToUse) { SmallVector Vals; // Code: [strchar x N] @@ -606,7 +468,7 @@ Stream.EmitRecord(Code, Vals, AbbrevToUse); } -static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { +uint64_t BitcodeWriterBase::getAttrKindEncoding(Attribute::AttrKind Kind) { switch (Kind) { case Attribute::Alignment: return bitc::ATTR_KIND_ALIGNMENT; @@ -1027,7 +889,8 @@ Stream.ExitBlock(); } -static unsigned getEncodedLinkage(const GlobalValue::LinkageTypes Linkage) { +unsigned +BitcodeWriterBase::getEncodedLinkage(const GlobalValue::LinkageTypes Linkage) { switch (Linkage) { case GlobalValue::ExternalLinkage: return 0; @@ -1055,7 +918,7 @@ llvm_unreachable("Invalid linkage"); } -static unsigned getEncodedLinkage(const GlobalValue &GV) { +unsigned BitcodeWriterBase::getEncodedLinkage(const GlobalValue &GV) { return getEncodedLinkage(GV.getLinkage()); } @@ -1100,7 +963,7 @@ return RawFlags; } -static unsigned getEncodedVisibility(const GlobalValue &GV) { +unsigned BitcodeWriterBase::getEncodedVisibility(const GlobalValue &GV) { switch (GV.getVisibility()) { case GlobalValue::DefaultVisibility: return 0; case GlobalValue::HiddenVisibility: return 1; @@ -1109,7 +972,7 @@ llvm_unreachable("Invalid visibility"); } -static unsigned getEncodedDLLStorageClass(const GlobalValue &GV) { +unsigned BitcodeWriterBase::getEncodedDLLStorageClass(const GlobalValue &GV) { switch (GV.getDLLStorageClass()) { case GlobalValue::DefaultStorageClass: return 0; case GlobalValue::DLLImportStorageClass: return 1; @@ -1118,7 +981,7 @@ llvm_unreachable("Invalid DLL storage class"); } -static unsigned getEncodedThreadLocalMode(const GlobalValue &GV) { +unsigned BitcodeWriterBase::getEncodedThreadLocalMode(const GlobalValue &GV) { switch (GV.getThreadLocalMode()) { case GlobalVariable::NotThreadLocal: return 0; case GlobalVariable::GeneralDynamicTLSModel: return 1; @@ -1129,7 +992,7 @@ llvm_unreachable("Invalid TLS model"); } -static unsigned getEncodedComdatSelectionKind(const Comdat &C) { +unsigned BitcodeWriterBase::getEncodedComdatSelectionKind(const Comdat &C) { switch (C.getSelectionKind()) { case Comdat::Any: return bitc::COMDAT_SELECTION_KIND_ANY; @@ -1462,7 +1325,7 @@ writeValueSymbolTableForwardDecl(); } -static uint64_t getOptimizationFlags(const Value *V) { +uint64_t BitcodeWriterBase::getOptimizationFlags(const Value *V) { uint64_t Flags = 0; if (const auto *OBO = dyn_cast(V)) { @@ -1607,14 +1470,16 @@ Record.clear(); } -static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { +void BitcodeWriterBase::emitSignedInt64(SmallVectorImpl &Vals, + uint64_t V) { if ((int64_t)V >= 0) Vals.push_back(V << 1); else Vals.push_back((-V << 1) | 1); } -static void emitWideAPInt(SmallVectorImpl &Vals, const APInt &A) { +void BitcodeWriterBase::emitWideAPInt(SmallVectorImpl &Vals, + const APInt &A) { // We have an arbitrary precision integer value to write whose // bit width is > 64. However, in canonical unsigned integer // format it is likely that the high bits are going to be zero. @@ -2146,13 +2011,6 @@ Record.clear(); } -// Generates an enum to use as an index in the Abbrev array of Metadata record. -enum MetadataAbbrev : unsigned { -#define HANDLE_MDNODE_LEAF(CLASS) CLASS##AbbrevID, -#include "llvm/IR/Metadata.def" - LastPlusOne -}; - void ModuleBitcodeWriter::writeMetadataRecords( ArrayRef MDs, SmallVectorImpl &Record, std::vector *MDAbbrevs, std::vector *IndexPos) { @@ -3716,8 +3574,8 @@ Range = Range.sextOrTrunc(FunctionSummary::ParamAccess::RangeWidth); assert(Range.getLower().getNumWords() == 1); assert(Range.getUpper().getNumWords() == 1); - emitSignedInt64(Record, *Range.getLower().getRawData()); - emitSignedInt64(Record, *Range.getUpper().getRawData()); + BitcodeWriterBase::emitSignedInt64(Record, *Range.getLower().getRawData()); + BitcodeWriterBase::emitSignedInt64(Record, *Range.getUpper().getRawData()); }; if (!FS->paramAccesses().empty()) { @@ -4358,7 +4216,7 @@ /// Create the "IDENTIFICATION_BLOCK_ID" containing a single string with the /// current llvm version, and a record for the epoch number. -static void writeIdentificationBlock(BitstreamWriter &Stream) { +void BitcodeWriterBase::writeIdentificationBlock(BitstreamWriter &Stream) { Stream.EnterSubblock(bitc::IDENTIFICATION_BLOCK_ID, 5); // Write the "user readable" string identifying the bitcode producer diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "ValueEnumerator.h" +#include "llvm/Bitcode/ValueEnumerator.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Argument.h"