aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Bitcode
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Bitcode')
-rw-r--r--contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp918
-rw-r--r--contrib/llvm/lib/Bitcode/Reader/MetadataLoader.cpp93
-rw-r--r--contrib/llvm/lib/Bitcode/Reader/MetadataLoader.h3
-rw-r--r--contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp627
-rw-r--r--contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp21
-rw-r--r--contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h37
6 files changed, 1018 insertions, 681 deletions
diff --git a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index a46e49ccde83..6d727ce83346 100644
--- a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -372,12 +372,26 @@ Expected<std::string> readTriple(BitstreamCursor &Stream) {
class BitcodeReaderBase {
protected:
- BitcodeReaderBase(BitstreamCursor Stream) : Stream(std::move(Stream)) {
+ BitcodeReaderBase(BitstreamCursor Stream, StringRef Strtab)
+ : Stream(std::move(Stream)), Strtab(Strtab) {
this->Stream.setBlockInfo(&BlockInfo);
}
BitstreamBlockInfo BlockInfo;
BitstreamCursor Stream;
+ StringRef Strtab;
+
+ /// In version 2 of the bitcode we store names of global values and comdats in
+ /// a string table rather than in the VST.
+ bool UseStrtab = false;
+
+ Expected<unsigned> parseVersionRecord(ArrayRef<uint64_t> Record);
+
+ /// If this module uses a string table, pop the reference to the string table
+ /// and return the referenced string and the rest of the record. Otherwise
+ /// just return the record itself.
+ std::pair<StringRef, ArrayRef<uint64_t>>
+ readNameFromStrtab(ArrayRef<uint64_t> Record);
bool readBlockInfo();
@@ -395,6 +409,27 @@ Error BitcodeReaderBase::error(const Twine &Message) {
return ::error(FullMsg);
}
+Expected<unsigned>
+BitcodeReaderBase::parseVersionRecord(ArrayRef<uint64_t> Record) {
+ if (Record.size() < 1)
+ return error("Invalid record");
+ unsigned ModuleVersion = Record[0];
+ if (ModuleVersion > 2)
+ return error("Invalid value");
+ UseStrtab = ModuleVersion >= 2;
+ return ModuleVersion;
+}
+
+std::pair<StringRef, ArrayRef<uint64_t>>
+BitcodeReaderBase::readNameFromStrtab(ArrayRef<uint64_t> Record) {
+ if (!UseStrtab)
+ return {"", Record};
+ // Invalid reference. Let the caller complain about the record being empty.
+ if (Record[0] + Record[1] > Strtab.size())
+ return {"", {}};
+ return {StringRef(Strtab.data() + Record[0], Record[1]), Record.slice(2)};
+}
+
class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
LLVMContext &Context;
Module *TheModule = nullptr;
@@ -405,6 +440,9 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
bool SeenValueSymbolTable = false;
uint64_t VSTOffset = 0;
+ std::vector<std::string> SectionTable;
+ std::vector<std::string> GCTable;
+
std::vector<Type*> TypeList;
BitcodeReaderValueList ValueList;
Optional<MetadataLoader> MDLoader;
@@ -419,10 +457,10 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
/// The set of attributes by index. Index zero in the file is for null, and
/// is thus not represented here. As such all indices are off by one.
- std::vector<AttributeSet> MAttributes;
+ std::vector<AttributeList> MAttributes;
/// The set of attribute groups.
- std::map<unsigned, AttributeSet> MAttributeGroups;
+ std::map<unsigned, AttributeList> MAttributeGroups;
/// While parsing a function body, this is a list of the basic blocks for the
/// function.
@@ -477,8 +515,8 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
std::vector<std::string> BundleTags;
public:
- BitcodeReader(BitstreamCursor Stream, StringRef ProducerIdentification,
- LLVMContext &Context);
+ BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
+ StringRef ProducerIdentification, LLVMContext &Context);
Error materializeForwardReferencedFunctions();
@@ -520,10 +558,10 @@ private:
return FunctionBBs[ID];
}
- AttributeSet getAttributes(unsigned i) const {
+ AttributeList getAttributes(unsigned i) const {
if (i-1 < MAttributes.size())
return MAttributes[i-1];
- return AttributeSet();
+ return AttributeList();
}
/// Read a value/type pair out of the specified record from slot 'Slot'.
@@ -598,6 +636,13 @@ private:
Error parseAlignmentValue(uint64_t Exponent, unsigned &Alignment);
Error parseAttrKind(uint64_t Code, Attribute::AttrKind *Kind);
Error parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata = false);
+
+ Error parseComdatRecord(ArrayRef<uint64_t> Record);
+ Error parseGlobalVarRecord(ArrayRef<uint64_t> Record);
+ Error parseFunctionRecord(ArrayRef<uint64_t> Record);
+ Error parseGlobalIndirectSymbolRecord(unsigned BitCode,
+ ArrayRef<uint64_t> Record);
+
Error parseAttributeBlock();
Error parseAttributeGroupBlock();
Error parseTypeTable();
@@ -606,7 +651,10 @@ private:
Expected<Value *> recordValue(SmallVectorImpl<uint64_t> &Record,
unsigned NameIndex, Triple &TT);
+ void setDeferredFunctionInfo(unsigned FuncBitcodeOffsetDelta, Function *F,
+ ArrayRef<uint64_t> Record);
Error parseValueSymbolTable(uint64_t Offset = 0);
+ Error parseGlobalValueSymbolTable();
Error parseConstants();
Error rememberAndSkipFunctionBodies();
Error rememberAndSkipFunctionBody();
@@ -659,12 +707,15 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
std::string SourceFileName;
public:
- ModuleSummaryIndexBitcodeReader(
- BitstreamCursor Stream, ModuleSummaryIndex &TheIndex);
+ ModuleSummaryIndexBitcodeReader(BitstreamCursor Stream, StringRef Strtab,
+ ModuleSummaryIndex &TheIndex);
Error parseModule(StringRef ModulePath);
private:
+ void setValueGUID(uint64_t ValueID, StringRef ValueName,
+ GlobalValue::LinkageTypes Linkage,
+ StringRef SourceFileName);
Error parseValueSymbolTable(
uint64_t Offset,
DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap);
@@ -694,10 +745,10 @@ std::error_code llvm::errorToErrorCodeAndEmitErrors(LLVMContext &Ctx,
return std::error_code();
}
-BitcodeReader::BitcodeReader(BitstreamCursor Stream,
+BitcodeReader::BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
StringRef ProducerIdentification,
LLVMContext &Context)
- : BitcodeReaderBase(std::move(Stream)), Context(Context),
+ : BitcodeReaderBase(std::move(Stream), Strtab), Context(Context),
ValueList(Context) {
this->ProducerIdentification = ProducerIdentification;
}
@@ -971,6 +1022,8 @@ static FastMathFlags getDecodedFastMathFlags(unsigned Val) {
FMF.setNoSignedZeros();
if (0 != (Val & FastMathFlags::AllowReciprocal))
FMF.setAllowReciprocal();
+ if (0 != (Val & FastMathFlags::AllowContract))
+ FMF.setAllowContract(true);
return FMF;
}
@@ -1132,7 +1185,7 @@ Error BitcodeReader::parseAttributeBlock() {
SmallVector<uint64_t, 64> Record;
- SmallVector<AttributeSet, 8> Attrs;
+ SmallVector<AttributeList, 8> Attrs;
// Read all the records.
while (true) {
@@ -1162,10 +1215,10 @@ Error BitcodeReader::parseAttributeBlock() {
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
AttrBuilder B;
decodeLLVMAttributesForBitcode(B, Record[i+1]);
- Attrs.push_back(AttributeSet::get(Context, Record[i], B));
+ Attrs.push_back(AttributeList::get(Context, Record[i], B));
}
- MAttributes.push_back(AttributeSet::get(Context, Attrs));
+ MAttributes.push_back(AttributeList::get(Context, Attrs));
Attrs.clear();
break;
}
@@ -1173,7 +1226,7 @@ Error BitcodeReader::parseAttributeBlock() {
for (unsigned i = 0, e = Record.size(); i != e; ++i)
Attrs.push_back(MAttributeGroups[Record[i]]);
- MAttributes.push_back(AttributeSet::get(Context, Attrs));
+ MAttributes.push_back(AttributeList::get(Context, Attrs));
Attrs.clear();
break;
}
@@ -1391,7 +1444,7 @@ Error BitcodeReader::parseAttributeGroupBlock() {
}
}
- MAttributeGroups[GrpID] = AttributeSet::get(Context, Idx, B);
+ MAttributeGroups[GrpID] = AttributeList::get(Context, Idx, B);
break;
}
}
@@ -1725,6 +1778,54 @@ static uint64_t jumpToValueSymbolTable(uint64_t Offset,
return CurrentBit;
}
+void BitcodeReader::setDeferredFunctionInfo(unsigned FuncBitcodeOffsetDelta,
+ Function *F,
+ ArrayRef<uint64_t> Record) {
+ // Note that we subtract 1 here because the offset is relative to one word
+ // before the start of the identification or module block, which was
+ // historically always the start of the regular bitcode header.
+ uint64_t FuncWordOffset = Record[1] - 1;
+ uint64_t FuncBitOffset = FuncWordOffset * 32;
+ DeferredFunctionInfo[F] = FuncBitOffset + FuncBitcodeOffsetDelta;
+ // Set the LastFunctionBlockBit to point to the last function block.
+ // Later when parsing is resumed after function materialization,
+ // we can simply skip that last function block.
+ if (FuncBitOffset > LastFunctionBlockBit)
+ LastFunctionBlockBit = FuncBitOffset;
+}
+
+/// Read a new-style GlobalValue symbol table.
+Error BitcodeReader::parseGlobalValueSymbolTable() {
+ unsigned FuncBitcodeOffsetDelta =
+ Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;
+
+ if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return error("Invalid record");
+
+ SmallVector<uint64_t, 64> Record;
+ while (true) {
+ BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::SubBlock:
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return Error::success();
+ case BitstreamEntry::Record:
+ break;
+ }
+
+ Record.clear();
+ switch (Stream.readRecord(Entry.ID, Record)) {
+ case bitc::VST_CODE_FNENTRY: // [valueid, offset]
+ setDeferredFunctionInfo(FuncBitcodeOffsetDelta,
+ cast<Function>(ValueList[Record[0]]), Record);
+ break;
+ }
+ }
+}
+
/// Parse the value symbol table at either the current parsing location or
/// at the given bit offset if provided.
Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
@@ -1732,8 +1833,18 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
// Pass in the Offset to distinguish between calling for the module-level
// VST (where we want to jump to the VST offset) and the function-level
// VST (where we don't).
- if (Offset > 0)
+ if (Offset > 0) {
CurrentBit = jumpToValueSymbolTable(Offset, Stream);
+ // If this module uses a string table, read this as a module-level VST.
+ if (UseStrtab) {
+ if (Error Err = parseGlobalValueSymbolTable())
+ return Err;
+ Stream.JumpToBit(CurrentBit);
+ return Error::success();
+ }
+ // Otherwise, the VST will be in a similar format to a function-level VST,
+ // and will contain symbol names.
+ }
// Compute the delta between the bitcode indices in the VST (the word offset
// to the word-aligned ENTER_SUBBLOCK for the function block, and that
@@ -1794,29 +1905,10 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
return Err;
Value *V = ValOrErr.get();
- auto *GO = dyn_cast<GlobalObject>(V);
- if (!GO) {
- // If this is an alias, need to get the actual Function object
- // it aliases, in order to set up the DeferredFunctionInfo entry below.
- auto *GA = dyn_cast<GlobalAlias>(V);
- if (GA)
- GO = GA->getBaseObject();
- assert(GO);
- }
-
- // Note that we subtract 1 here because the offset is relative to one word
- // before the start of the identification or module block, which was
- // historically always the start of the regular bitcode header.
- uint64_t FuncWordOffset = Record[1] - 1;
- Function *F = dyn_cast<Function>(GO);
- assert(F);
- uint64_t FuncBitOffset = FuncWordOffset * 32;
- DeferredFunctionInfo[F] = FuncBitOffset + FuncBitcodeOffsetDelta;
- // Set the LastFunctionBlockBit to point to the last function block.
- // Later when parsing is resumed after function materialization,
- // we can simply skip that last function block.
- if (FuncBitOffset > LastFunctionBlockBit)
- LastFunctionBlockBit = FuncBitOffset;
+ // Ignore function offsets emitted for aliases of functions in older
+ // versions of LLVM.
+ if (auto *F = dyn_cast<Function>(V))
+ setDeferredFunctionInfo(FuncBitcodeOffsetDelta, F, Record);
break;
}
case bitc::VST_CODE_BBENTRY: {
@@ -2539,6 +2631,7 @@ Error BitcodeReader::globalCleanup() {
// Look for intrinsic functions which need to be upgraded at some point
for (Function &F : *TheModule) {
+ MDLoader->upgradeDebugIntrinsics(F);
Function *NewFn;
if (UpgradeIntrinsicFunction(&F, NewFn))
UpgradedIntrinsics[&F] = NewFn;
@@ -2607,6 +2700,267 @@ bool BitcodeReaderBase::readBlockInfo() {
return false;
}
+Error BitcodeReader::parseComdatRecord(ArrayRef<uint64_t> Record) {
+ // v1: [selection_kind, name]
+ // v2: [strtab_offset, strtab_size, selection_kind]
+ StringRef Name;
+ std::tie(Name, Record) = readNameFromStrtab(Record);
+
+ if (Record.size() < 1)
+ return error("Invalid record");
+ Comdat::SelectionKind SK = getDecodedComdatSelectionKind(Record[0]);
+ std::string OldFormatName;
+ if (!UseStrtab) {
+ if (Record.size() < 2)
+ return error("Invalid record");
+ unsigned ComdatNameSize = Record[1];
+ OldFormatName.reserve(ComdatNameSize);
+ for (unsigned i = 0; i != ComdatNameSize; ++i)
+ OldFormatName += (char)Record[2 + i];
+ Name = OldFormatName;
+ }
+ Comdat *C = TheModule->getOrInsertComdat(Name);
+ C->setSelectionKind(SK);
+ ComdatList.push_back(C);
+ return Error::success();
+}
+
+Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
+ // v1: [pointer type, isconst, initid, linkage, alignment, section,
+ // visibility, threadlocal, unnamed_addr, externally_initialized,
+ // dllstorageclass, comdat] (name in VST)
+ // v2: [strtab_offset, strtab_size, v1]
+ StringRef Name;
+ std::tie(Name, Record) = readNameFromStrtab(Record);
+
+ if (Record.size() < 6)
+ return error("Invalid record");
+ Type *Ty = getTypeByID(Record[0]);
+ if (!Ty)
+ return error("Invalid record");
+ bool isConstant = Record[1] & 1;
+ bool explicitType = Record[1] & 2;
+ unsigned AddressSpace;
+ if (explicitType) {
+ AddressSpace = Record[1] >> 2;
+ } else {
+ if (!Ty->isPointerTy())
+ return error("Invalid type for value");
+ AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
+ Ty = cast<PointerType>(Ty)->getElementType();
+ }
+
+ uint64_t RawLinkage = Record[3];
+ GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
+ unsigned Alignment;
+ if (Error Err = parseAlignmentValue(Record[4], Alignment))
+ return Err;
+ std::string Section;
+ if (Record[5]) {
+ if (Record[5] - 1 >= SectionTable.size())
+ return error("Invalid ID");
+ Section = SectionTable[Record[5] - 1];
+ }
+ GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
+ // Local linkage must have default visibility.
+ if (Record.size() > 6 && !GlobalValue::isLocalLinkage(Linkage))
+ // FIXME: Change to an error if non-default in 4.0.
+ Visibility = getDecodedVisibility(Record[6]);
+
+ GlobalVariable::ThreadLocalMode TLM = GlobalVariable::NotThreadLocal;
+ if (Record.size() > 7)
+ TLM = getDecodedThreadLocalMode(Record[7]);
+
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
+ if (Record.size() > 8)
+ UnnamedAddr = getDecodedUnnamedAddrType(Record[8]);
+
+ bool ExternallyInitialized = false;
+ if (Record.size() > 9)
+ ExternallyInitialized = Record[9];
+
+ GlobalVariable *NewGV =
+ new GlobalVariable(*TheModule, Ty, isConstant, Linkage, nullptr, Name,
+ nullptr, TLM, AddressSpace, ExternallyInitialized);
+ NewGV->setAlignment(Alignment);
+ if (!Section.empty())
+ NewGV->setSection(Section);
+ NewGV->setVisibility(Visibility);
+ NewGV->setUnnamedAddr(UnnamedAddr);
+
+ if (Record.size() > 10)
+ NewGV->setDLLStorageClass(getDecodedDLLStorageClass(Record[10]));
+ else
+ upgradeDLLImportExportLinkage(NewGV, RawLinkage);
+
+ ValueList.push_back(NewGV);
+
+ // Remember which value to use for the global initializer.
+ if (unsigned InitID = Record[2])
+ GlobalInits.push_back(std::make_pair(NewGV, InitID - 1));
+
+ if (Record.size() > 11) {
+ if (unsigned ComdatID = Record[11]) {
+ if (ComdatID > ComdatList.size())
+ return error("Invalid global variable comdat ID");
+ NewGV->setComdat(ComdatList[ComdatID - 1]);
+ }
+ } else if (hasImplicitComdat(RawLinkage)) {
+ NewGV->setComdat(reinterpret_cast<Comdat *>(1));
+ }
+ return Error::success();
+}
+
+Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
+ // v1: [type, callingconv, isproto, linkage, paramattr, alignment, section,
+ // visibility, gc, unnamed_addr, prologuedata, dllstorageclass, comdat,
+ // prefixdata] (name in VST)
+ // v2: [strtab_offset, strtab_size, v1]
+ StringRef Name;
+ std::tie(Name, Record) = readNameFromStrtab(Record);
+
+ if (Record.size() < 8)
+ return error("Invalid record");
+ Type *Ty = getTypeByID(Record[0]);
+ if (!Ty)
+ return error("Invalid record");
+ if (auto *PTy = dyn_cast<PointerType>(Ty))
+ Ty = PTy->getElementType();
+ auto *FTy = dyn_cast<FunctionType>(Ty);
+ if (!FTy)
+ return error("Invalid type for value");
+ auto CC = static_cast<CallingConv::ID>(Record[1]);
+ if (CC & ~CallingConv::MaxID)
+ return error("Invalid calling convention ID");
+
+ Function *Func =
+ Function::Create(FTy, GlobalValue::ExternalLinkage, Name, TheModule);
+
+ Func->setCallingConv(CC);
+ bool isProto = Record[2];
+ uint64_t RawLinkage = Record[3];
+ Func->setLinkage(getDecodedLinkage(RawLinkage));
+ Func->setAttributes(getAttributes(Record[4]));
+
+ unsigned Alignment;
+ if (Error Err = parseAlignmentValue(Record[5], Alignment))
+ return Err;
+ Func->setAlignment(Alignment);
+ if (Record[6]) {
+ if (Record[6] - 1 >= SectionTable.size())
+ return error("Invalid ID");
+ Func->setSection(SectionTable[Record[6] - 1]);
+ }
+ // Local linkage must have default visibility.
+ if (!Func->hasLocalLinkage())
+ // FIXME: Change to an error if non-default in 4.0.
+ Func->setVisibility(getDecodedVisibility(Record[7]));
+ if (Record.size() > 8 && Record[8]) {
+ if (Record[8] - 1 >= GCTable.size())
+ return error("Invalid ID");
+ Func->setGC(GCTable[Record[8] - 1]);
+ }
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
+ if (Record.size() > 9)
+ UnnamedAddr = getDecodedUnnamedAddrType(Record[9]);
+ Func->setUnnamedAddr(UnnamedAddr);
+ if (Record.size() > 10 && Record[10] != 0)
+ FunctionPrologues.push_back(std::make_pair(Func, Record[10] - 1));
+
+ if (Record.size() > 11)
+ Func->setDLLStorageClass(getDecodedDLLStorageClass(Record[11]));
+ else
+ upgradeDLLImportExportLinkage(Func, RawLinkage);
+
+ if (Record.size() > 12) {
+ if (unsigned ComdatID = Record[12]) {
+ if (ComdatID > ComdatList.size())
+ return error("Invalid function comdat ID");
+ Func->setComdat(ComdatList[ComdatID - 1]);
+ }
+ } else if (hasImplicitComdat(RawLinkage)) {
+ Func->setComdat(reinterpret_cast<Comdat *>(1));
+ }
+
+ if (Record.size() > 13 && Record[13] != 0)
+ FunctionPrefixes.push_back(std::make_pair(Func, Record[13] - 1));
+
+ if (Record.size() > 14 && Record[14] != 0)
+ FunctionPersonalityFns.push_back(std::make_pair(Func, Record[14] - 1));
+
+ ValueList.push_back(Func);
+
+ // If this is a function with a body, remember the prototype we are
+ // creating now, so that we can match up the body with them later.
+ if (!isProto) {
+ Func->setIsMaterializable(true);
+ FunctionsWithBodies.push_back(Func);
+ DeferredFunctionInfo[Func] = 0;
+ }
+ return Error::success();
+}
+
+Error BitcodeReader::parseGlobalIndirectSymbolRecord(
+ unsigned BitCode, ArrayRef<uint64_t> Record) {
+ // v1 ALIAS_OLD: [alias type, aliasee val#, linkage] (name in VST)
+ // v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,
+ // dllstorageclass] (name in VST)
+ // v1 IFUNC: [alias type, addrspace, aliasee val#, linkage,
+ // visibility, dllstorageclass] (name in VST)
+ // v2: [strtab_offset, strtab_size, v1]
+ StringRef Name;
+ std::tie(Name, Record) = readNameFromStrtab(Record);
+
+ bool NewRecord = BitCode != bitc::MODULE_CODE_ALIAS_OLD;
+ if (Record.size() < (3 + (unsigned)NewRecord))
+ return error("Invalid record");
+ unsigned OpNum = 0;
+ Type *Ty = getTypeByID(Record[OpNum++]);
+ if (!Ty)
+ return error("Invalid record");
+
+ unsigned AddrSpace;
+ if (!NewRecord) {
+ auto *PTy = dyn_cast<PointerType>(Ty);
+ if (!PTy)
+ return error("Invalid type for value");
+ Ty = PTy->getElementType();
+ AddrSpace = PTy->getAddressSpace();
+ } else {
+ AddrSpace = Record[OpNum++];
+ }
+
+ auto Val = Record[OpNum++];
+ auto Linkage = Record[OpNum++];
+ GlobalIndirectSymbol *NewGA;
+ if (BitCode == bitc::MODULE_CODE_ALIAS ||
+ BitCode == bitc::MODULE_CODE_ALIAS_OLD)
+ NewGA = GlobalAlias::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name,
+ TheModule);
+ else
+ NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name,
+ nullptr, TheModule);
+ // Old bitcode files didn't have visibility field.
+ // Local linkage must have default visibility.
+ if (OpNum != Record.size()) {
+ auto VisInd = OpNum++;
+ if (!NewGA->hasLocalLinkage())
+ // FIXME: Change to an error if non-default in 4.0.
+ NewGA->setVisibility(getDecodedVisibility(Record[VisInd]));
+ }
+ if (OpNum != Record.size())
+ NewGA->setDLLStorageClass(getDecodedDLLStorageClass(Record[OpNum++]));
+ else
+ upgradeDLLImportExportLinkage(NewGA, Linkage);
+ if (OpNum != Record.size())
+ NewGA->setThreadLocalMode(getDecodedThreadLocalMode(Record[OpNum++]));
+ if (OpNum != Record.size())
+ NewGA->setUnnamedAddr(getDecodedUnnamedAddrType(Record[OpNum++]));
+ ValueList.push_back(NewGA);
+ IndirectSymbolInits.push_back(std::make_pair(NewGA, Val));
+ return Error::success();
+}
+
Error BitcodeReader::parseModule(uint64_t ResumeBit,
bool ShouldLazyLoadMetadata) {
if (ResumeBit)
@@ -2615,8 +2969,6 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
return error("Invalid record");
SmallVector<uint64_t, 64> Record;
- std::vector<std::string> SectionTable;
- std::vector<std::string> GCTable;
// Read all the records for this module.
while (true) {
@@ -2762,21 +3114,11 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
auto BitCode = Stream.readRecord(Entry.ID, Record);
switch (BitCode) {
default: break; // Default behavior, ignore unknown content.
- case bitc::MODULE_CODE_VERSION: { // VERSION: [version#]
- if (Record.size() < 1)
- return error("Invalid record");
- // Only version #0 and #1 are supported so far.
- unsigned module_version = Record[0];
- switch (module_version) {
- default:
- return error("Invalid value");
- case 0:
- UseRelativeIDs = false;
- break;
- case 1:
- UseRelativeIDs = true;
- break;
- }
+ case bitc::MODULE_CODE_VERSION: {
+ Expected<unsigned> VersionOrErr = parseVersionRecord(Record);
+ if (!VersionOrErr)
+ return VersionOrErr.takeError();
+ UseRelativeIDs = *VersionOrErr >= 1;
break;
}
case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
@@ -2822,249 +3164,28 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
GCTable.push_back(S);
break;
}
- case bitc::MODULE_CODE_COMDAT: { // COMDAT: [selection_kind, name]
- if (Record.size() < 2)
- return error("Invalid record");
- Comdat::SelectionKind SK = getDecodedComdatSelectionKind(Record[0]);
- unsigned ComdatNameSize = Record[1];
- std::string ComdatName;
- ComdatName.reserve(ComdatNameSize);
- for (unsigned i = 0; i != ComdatNameSize; ++i)
- ComdatName += (char)Record[2 + i];
- Comdat *C = TheModule->getOrInsertComdat(ComdatName);
- C->setSelectionKind(SK);
- ComdatList.push_back(C);
- break;
- }
- // GLOBALVAR: [pointer type, isconst, initid,
- // linkage, alignment, section, visibility, threadlocal,
- // unnamed_addr, externally_initialized, dllstorageclass,
- // comdat]
+ case bitc::MODULE_CODE_COMDAT: {
+ if (Error Err = parseComdatRecord(Record))
+ return Err;
+ break;
+ }
case bitc::MODULE_CODE_GLOBALVAR: {
- if (Record.size() < 6)
- return error("Invalid record");
- Type *Ty = getTypeByID(Record[0]);
- if (!Ty)
- return error("Invalid record");
- bool isConstant = Record[1] & 1;
- bool explicitType = Record[1] & 2;
- unsigned AddressSpace;
- if (explicitType) {
- AddressSpace = Record[1] >> 2;
- } else {
- if (!Ty->isPointerTy())
- return error("Invalid type for value");
- AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
- Ty = cast<PointerType>(Ty)->getElementType();
- }
-
- uint64_t RawLinkage = Record[3];
- GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
- unsigned Alignment;
- if (Error Err = parseAlignmentValue(Record[4], Alignment))
+ if (Error Err = parseGlobalVarRecord(Record))
return Err;
- std::string Section;
- if (Record[5]) {
- if (Record[5]-1 >= SectionTable.size())
- return error("Invalid ID");
- Section = SectionTable[Record[5]-1];
- }
- GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility;
- // Local linkage must have default visibility.
- if (Record.size() > 6 && !GlobalValue::isLocalLinkage(Linkage))
- // FIXME: Change to an error if non-default in 4.0.
- Visibility = getDecodedVisibility(Record[6]);
-
- GlobalVariable::ThreadLocalMode TLM = GlobalVariable::NotThreadLocal;
- if (Record.size() > 7)
- TLM = getDecodedThreadLocalMode(Record[7]);
-
- GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
- if (Record.size() > 8)
- UnnamedAddr = getDecodedUnnamedAddrType(Record[8]);
-
- bool ExternallyInitialized = false;
- if (Record.size() > 9)
- ExternallyInitialized = Record[9];
-
- GlobalVariable *NewGV =
- new GlobalVariable(*TheModule, Ty, isConstant, Linkage, nullptr, "", nullptr,
- TLM, AddressSpace, ExternallyInitialized);
- NewGV->setAlignment(Alignment);
- if (!Section.empty())
- NewGV->setSection(Section);
- NewGV->setVisibility(Visibility);
- NewGV->setUnnamedAddr(UnnamedAddr);
-
- if (Record.size() > 10)
- NewGV->setDLLStorageClass(getDecodedDLLStorageClass(Record[10]));
- else
- upgradeDLLImportExportLinkage(NewGV, RawLinkage);
-
- ValueList.push_back(NewGV);
-
- // Remember which value to use for the global initializer.
- if (unsigned InitID = Record[2])
- GlobalInits.push_back(std::make_pair(NewGV, InitID-1));
-
- if (Record.size() > 11) {
- if (unsigned ComdatID = Record[11]) {
- if (ComdatID > ComdatList.size())
- return error("Invalid global variable comdat ID");
- NewGV->setComdat(ComdatList[ComdatID - 1]);
- }
- } else if (hasImplicitComdat(RawLinkage)) {
- NewGV->setComdat(reinterpret_cast<Comdat *>(1));
- }
-
break;
}
- // FUNCTION: [type, callingconv, isproto, linkage, paramattr,
- // alignment, section, visibility, gc, unnamed_addr,
- // prologuedata, dllstorageclass, comdat, prefixdata]
case bitc::MODULE_CODE_FUNCTION: {
- if (Record.size() < 8)
- return error("Invalid record");
- Type *Ty = getTypeByID(Record[0]);
- if (!Ty)
- return error("Invalid record");
- if (auto *PTy = dyn_cast<PointerType>(Ty))
- Ty = PTy->getElementType();
- auto *FTy = dyn_cast<FunctionType>(Ty);
- if (!FTy)
- return error("Invalid type for value");
- auto CC = static_cast<CallingConv::ID>(Record[1]);
- if (CC & ~CallingConv::MaxID)
- return error("Invalid calling convention ID");
-
- Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
- "", TheModule);
-
- Func->setCallingConv(CC);
- bool isProto = Record[2];
- uint64_t RawLinkage = Record[3];
- Func->setLinkage(getDecodedLinkage(RawLinkage));
- Func->setAttributes(getAttributes(Record[4]));
-
- unsigned Alignment;
- if (Error Err = parseAlignmentValue(Record[5], Alignment))
+ if (Error Err = parseFunctionRecord(Record))
return Err;
- Func->setAlignment(Alignment);
- if (Record[6]) {
- if (Record[6]-1 >= SectionTable.size())
- return error("Invalid ID");
- Func->setSection(SectionTable[Record[6]-1]);
- }
- // Local linkage must have default visibility.
- if (!Func->hasLocalLinkage())
- // FIXME: Change to an error if non-default in 4.0.
- Func->setVisibility(getDecodedVisibility(Record[7]));
- if (Record.size() > 8 && Record[8]) {
- if (Record[8]-1 >= GCTable.size())
- return error("Invalid ID");
- Func->setGC(GCTable[Record[8] - 1]);
- }
- GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
- if (Record.size() > 9)
- UnnamedAddr = getDecodedUnnamedAddrType(Record[9]);
- Func->setUnnamedAddr(UnnamedAddr);
- if (Record.size() > 10 && Record[10] != 0)
- FunctionPrologues.push_back(std::make_pair(Func, Record[10]-1));
-
- if (Record.size() > 11)
- Func->setDLLStorageClass(getDecodedDLLStorageClass(Record[11]));
- else
- upgradeDLLImportExportLinkage(Func, RawLinkage);
-
- if (Record.size() > 12) {
- if (unsigned ComdatID = Record[12]) {
- if (ComdatID > ComdatList.size())
- return error("Invalid function comdat ID");
- Func->setComdat(ComdatList[ComdatID - 1]);
- }
- } else if (hasImplicitComdat(RawLinkage)) {
- Func->setComdat(reinterpret_cast<Comdat *>(1));
- }
-
- if (Record.size() > 13 && Record[13] != 0)
- FunctionPrefixes.push_back(std::make_pair(Func, Record[13]-1));
-
- if (Record.size() > 14 && Record[14] != 0)
- FunctionPersonalityFns.push_back(std::make_pair(Func, Record[14] - 1));
-
- ValueList.push_back(Func);
-
- // If this is a function with a body, remember the prototype we are
- // creating now, so that we can match up the body with them later.
- if (!isProto) {
- Func->setIsMaterializable(true);
- FunctionsWithBodies.push_back(Func);
- DeferredFunctionInfo[Func] = 0;
- }
break;
}
- // ALIAS: [alias type, addrspace, aliasee val#, linkage]
- // ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility, dllstorageclass]
- // IFUNC: [alias type, addrspace, aliasee val#, linkage, visibility, dllstorageclass]
case bitc::MODULE_CODE_IFUNC:
case bitc::MODULE_CODE_ALIAS:
case bitc::MODULE_CODE_ALIAS_OLD: {
- bool NewRecord = BitCode != bitc::MODULE_CODE_ALIAS_OLD;
- if (Record.size() < (3 + (unsigned)NewRecord))
- return error("Invalid record");
- unsigned OpNum = 0;
- Type *Ty = getTypeByID(Record[OpNum++]);
- if (!Ty)
- return error("Invalid record");
-
- unsigned AddrSpace;
- if (!NewRecord) {
- auto *PTy = dyn_cast<PointerType>(Ty);
- if (!PTy)
- return error("Invalid type for value");
- Ty = PTy->getElementType();
- AddrSpace = PTy->getAddressSpace();
- } else {
- AddrSpace = Record[OpNum++];
- }
-
- auto Val = Record[OpNum++];
- auto Linkage = Record[OpNum++];
- GlobalIndirectSymbol *NewGA;
- if (BitCode == bitc::MODULE_CODE_ALIAS ||
- BitCode == bitc::MODULE_CODE_ALIAS_OLD)
- NewGA = GlobalAlias::create(Ty, AddrSpace, getDecodedLinkage(Linkage),
- "", TheModule);
- else
- NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage),
- "", nullptr, TheModule);
- // Old bitcode files didn't have visibility field.
- // Local linkage must have default visibility.
- if (OpNum != Record.size()) {
- auto VisInd = OpNum++;
- if (!NewGA->hasLocalLinkage())
- // FIXME: Change to an error if non-default in 4.0.
- NewGA->setVisibility(getDecodedVisibility(Record[VisInd]));
- }
- if (OpNum != Record.size())
- NewGA->setDLLStorageClass(getDecodedDLLStorageClass(Record[OpNum++]));
- else
- upgradeDLLImportExportLinkage(NewGA, Linkage);
- if (OpNum != Record.size())
- NewGA->setThreadLocalMode(getDecodedThreadLocalMode(Record[OpNum++]));
- if (OpNum != Record.size())
- NewGA->setUnnamedAddr(getDecodedUnnamedAddrType(Record[OpNum++]));
- ValueList.push_back(NewGA);
- IndirectSymbolInits.push_back(std::make_pair(NewGA, Val));
- break;
- }
- /// MODULE_CODE_PURGEVALS: [numvals]
- case bitc::MODULE_CODE_PURGEVALS:
- // Trim down the value list to the specified size.
- if (Record.size() < 1 || Record[0] > ValueList.size())
- return error("Invalid record");
- ValueList.shrinkTo(Record[0]);
+ if (Error Err = parseGlobalIndirectSymbolRecord(BitCode, Record))
+ return Err;
break;
+ }
/// MODULE_CODE_VSTOFFSET: [offset]
case bitc::MODULE_CODE_VSTOFFSET:
if (Record.size() < 1)
@@ -3840,7 +3961,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
if (Record.size() < 4)
return error("Invalid record");
unsigned OpNum = 0;
- AttributeSet PAL = getAttributes(Record[OpNum++]);
+ AttributeList PAL = getAttributes(Record[OpNum++]);
unsigned CCInfo = Record[OpNum++];
BasicBlock *NormalBB = getBasicBlock(Record[OpNum++]);
BasicBlock *UnwindBB = getBasicBlock(Record[OpNum++]);
@@ -4017,7 +4138,12 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
}
if (!Ty || !Size)
return error("Invalid record");
- AllocaInst *AI = new AllocaInst(Ty, Size, Align);
+
+ // FIXME: Make this an optional field.
+ const DataLayout &DL = TheModule->getDataLayout();
+ unsigned AS = DL.getAllocaAddrSpace();
+
+ AllocaInst *AI = new AllocaInst(Ty, AS, Size, Align);
AI->setUsedWithInAlloca(InAlloca);
AI->setSwiftError(SwiftError);
I = AI;
@@ -4225,7 +4351,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
return error("Invalid record");
unsigned OpNum = 0;
- AttributeSet PAL = getAttributes(Record[OpNum++]);
+ AttributeList PAL = getAttributes(Record[OpNum++]);
unsigned CCInfo = Record[OpNum++];
FastMathFlags FMF;
@@ -4540,8 +4666,8 @@ std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
}
ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
- BitstreamCursor Cursor, ModuleSummaryIndex &TheIndex)
- : BitcodeReaderBase(std::move(Cursor)), TheIndex(TheIndex) {}
+ BitstreamCursor Cursor, StringRef Strtab, ModuleSummaryIndex &TheIndex)
+ : BitcodeReaderBase(std::move(Cursor), Strtab), TheIndex(TheIndex) {}
std::pair<GlobalValue::GUID, GlobalValue::GUID>
ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
@@ -4550,12 +4676,32 @@ ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
return VGI->second;
}
+void ModuleSummaryIndexBitcodeReader::setValueGUID(
+ uint64_t ValueID, StringRef ValueName, GlobalValue::LinkageTypes Linkage,
+ StringRef SourceFileName) {
+ std::string GlobalId =
+ GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName);
+ auto ValueGUID = GlobalValue::getGUID(GlobalId);
+ auto OriginalNameID = ValueGUID;
+ if (GlobalValue::isLocalLinkage(Linkage))
+ OriginalNameID = GlobalValue::getGUID(ValueName);
+ if (PrintSummaryGUIDs)
+ dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
+ << ValueName << "\n";
+ ValueIdToCallGraphGUIDMap[ValueID] =
+ std::make_pair(ValueGUID, OriginalNameID);
+}
+
// Specialized value symbol table parser used when reading module index
// blocks where we don't actually create global values. The parsed information
// is saved in the bitcode reader for use when later parsing summaries.
Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
uint64_t Offset,
DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap) {
+ // With a strtab the VST is not required to parse the summary.
+ if (UseStrtab)
+ return Error::success();
+
assert(Offset > 0 && "Expected non-zero VST offset");
uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream);
@@ -4597,17 +4743,7 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
assert(VLI != ValueIdToLinkageMap.end() &&
"No linkage found for VST entry?");
auto Linkage = VLI->second;
- std::string GlobalId =
- GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName);
- auto ValueGUID = GlobalValue::getGUID(GlobalId);
- auto OriginalNameID = ValueGUID;
- if (GlobalValue::isLocalLinkage(Linkage))
- OriginalNameID = GlobalValue::getGUID(ValueName);
- if (PrintSummaryGUIDs)
- dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
- << ValueName << "\n";
- ValueIdToCallGraphGUIDMap[ValueID] =
- std::make_pair(ValueGUID, OriginalNameID);
+ setValueGUID(ValueID, ValueName, Linkage, SourceFileName);
ValueName.clear();
break;
}
@@ -4621,18 +4757,7 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
assert(VLI != ValueIdToLinkageMap.end() &&
"No linkage found for VST entry?");
auto Linkage = VLI->second;
- std::string FunctionGlobalId = GlobalValue::getGlobalIdentifier(
- ValueName, VLI->second, SourceFileName);
- auto FunctionGUID = GlobalValue::getGUID(FunctionGlobalId);
- auto OriginalNameID = FunctionGUID;
- if (GlobalValue::isLocalLinkage(Linkage))
- OriginalNameID = GlobalValue::getGUID(ValueName);
- if (PrintSummaryGUIDs)
- dbgs() << "GUID " << FunctionGUID << "(" << OriginalNameID << ") is "
- << ValueName << "\n";
- ValueIdToCallGraphGUIDMap[ValueID] =
- std::make_pair(FunctionGUID, OriginalNameID);
-
+ setValueGUID(ValueID, ValueName, Linkage, SourceFileName);
ValueName.clear();
break;
}
@@ -4719,6 +4844,11 @@ Error ModuleSummaryIndexBitcodeReader::parseModule(StringRef ModulePath) {
switch (BitCode) {
default:
break; // Default behavior, ignore unknown content.
+ case bitc::MODULE_CODE_VERSION: {
+ if (Error Err = parseVersionRecord(Record).takeError())
+ return Err;
+ break;
+ }
/// MODULE_CODE_SOURCE_FILENAME: [namechar x N]
case bitc::MODULE_CODE_SOURCE_FILENAME: {
SmallString<128> ValueName;
@@ -4753,37 +4883,26 @@ Error ModuleSummaryIndexBitcodeReader::parseModule(StringRef ModulePath) {
// was historically always the start of the regular bitcode header.
VSTOffset = Record[0] - 1;
break;
- // GLOBALVAR: [pointer type, isconst, initid,
- // linkage, alignment, section, visibility, threadlocal,
- // unnamed_addr, externally_initialized, dllstorageclass,
- // comdat]
- case bitc::MODULE_CODE_GLOBALVAR: {
- if (Record.size() < 6)
- return error("Invalid record");
- uint64_t RawLinkage = Record[3];
- GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
- ValueIdToLinkageMap[ValueId++] = Linkage;
- break;
- }
- // FUNCTION: [type, callingconv, isproto, linkage, paramattr,
- // alignment, section, visibility, gc, unnamed_addr,
- // prologuedata, dllstorageclass, comdat, prefixdata]
- case bitc::MODULE_CODE_FUNCTION: {
- if (Record.size() < 8)
- return error("Invalid record");
- uint64_t RawLinkage = Record[3];
- GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
- ValueIdToLinkageMap[ValueId++] = Linkage;
- break;
- }
- // ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,
- // dllstorageclass]
+ // v1 GLOBALVAR: [pointer type, isconst, initid, linkage, ...]
+ // v1 FUNCTION: [type, callingconv, isproto, linkage, ...]
+ // v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, ...]
+ // v2: [strtab offset, strtab size, v1]
+ case bitc::MODULE_CODE_GLOBALVAR:
+ case bitc::MODULE_CODE_FUNCTION:
case bitc::MODULE_CODE_ALIAS: {
- if (Record.size() < 6)
+ StringRef Name;
+ ArrayRef<uint64_t> GVRecord;
+ std::tie(Name, GVRecord) = readNameFromStrtab(Record);
+ if (GVRecord.size() <= 3)
return error("Invalid record");
- uint64_t RawLinkage = Record[3];
+ uint64_t RawLinkage = GVRecord[3];
GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
- ValueIdToLinkageMap[ValueId++] = Linkage;
+ if (!UseStrtab) {
+ ValueIdToLinkageMap[ValueId++] = Linkage;
+ break;
+ }
+
+ setValueGUID(ValueId++, Name, Linkage, SourceFileName);
break;
}
}
@@ -4846,8 +4965,17 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
// Keep around the last seen summary to be used when we see an optional
// "OriginalName" attachement.
GlobalValueSummary *LastSeenSummary = nullptr;
+ GlobalValue::GUID LastSeenGUID = 0;
bool Combined = false;
+
+ // We can expect to see any number of type ID information records before
+ // each function summary records; these variables store the information
+ // collected so far so that it can be used to create the summary object.
std::vector<GlobalValue::GUID> PendingTypeTests;
+ std::vector<FunctionSummary::VFuncId> PendingTypeTestAssumeVCalls,
+ PendingTypeCheckedLoadVCalls;
+ std::vector<FunctionSummary::ConstVCall> PendingTypeTestAssumeConstVCalls,
+ PendingTypeCheckedLoadConstVCalls;
while (true) {
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
@@ -4885,6 +5013,12 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
switch (BitCode) {
default: // Default behavior: ignore.
break;
+ case bitc::FS_VALUE_GUID: { // [valueid, refguid]
+ uint64_t ValueID = Record[0];
+ GlobalValue::GUID RefGUID = Record[1];
+ ValueIdToCallGraphGUIDMap[ValueID] = std::make_pair(RefGUID, RefGUID);
+ break;
+ }
// FS_PERMODULE: [valueid, flags, instcount, numrefs, numrefs x valueid,
// n x (valueid)]
// FS_PERMODULE_PROFILE: [valueid, flags, instcount, numrefs,
@@ -4914,8 +5048,15 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
IsOldProfileFormat, HasProfile);
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Calls),
- std::move(PendingTypeTests));
+ std::move(PendingTypeTests), std::move(PendingTypeTestAssumeVCalls),
+ std::move(PendingTypeCheckedLoadVCalls),
+ std::move(PendingTypeTestAssumeConstVCalls),
+ std::move(PendingTypeCheckedLoadConstVCalls));
PendingTypeTests.clear();
+ PendingTypeTestAssumeVCalls.clear();
+ PendingTypeCheckedLoadVCalls.clear();
+ PendingTypeTestAssumeConstVCalls.clear();
+ PendingTypeCheckedLoadConstVCalls.clear();
auto GUID = getGUIDFromValueId(ValueID);
FS->setModulePath(TheIndex.addModulePath(ModulePath, 0)->first());
FS->setOriginalName(GUID.second);
@@ -4989,9 +5130,17 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, std::move(Refs), std::move(Edges),
- std::move(PendingTypeTests));
+ std::move(PendingTypeTests), std::move(PendingTypeTestAssumeVCalls),
+ std::move(PendingTypeCheckedLoadVCalls),
+ std::move(PendingTypeTestAssumeConstVCalls),
+ std::move(PendingTypeCheckedLoadConstVCalls));
PendingTypeTests.clear();
+ PendingTypeTestAssumeVCalls.clear();
+ PendingTypeCheckedLoadVCalls.clear();
+ PendingTypeTestAssumeConstVCalls.clear();
+ PendingTypeCheckedLoadConstVCalls.clear();
LastSeenSummary = FS.get();
+ LastSeenGUID = GUID;
FS->setModulePath(ModuleIdMap[ModuleId]);
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
Combined = true;
@@ -5018,6 +5167,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
AS->setAliasee(AliaseeInModule);
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
+ LastSeenGUID = GUID;
TheIndex.addGlobalValueSummary(GUID, std::move(AS));
Combined = true;
break;
@@ -5034,6 +5184,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
LastSeenSummary = FS.get();
FS->setModulePath(ModuleIdMap[ModuleId]);
GlobalValue::GUID GUID = getGUIDFromValueId(ValueID).first;
+ LastSeenGUID = GUID;
TheIndex.addGlobalValueSummary(GUID, std::move(FS));
Combined = true;
break;
@@ -5044,8 +5195,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
if (!LastSeenSummary)
return error("Name attachment that does not follow a combined record");
LastSeenSummary->setOriginalName(OriginalName);
+ TheIndex.addOriginalName(LastSeenGUID, OriginalName);
// Reset the LastSeenSummary
LastSeenSummary = nullptr;
+ LastSeenGUID = 0;
break;
}
case bitc::FS_TYPE_TESTS: {
@@ -5054,6 +5207,28 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(
Record.end());
break;
}
+ case bitc::FS_TYPE_TEST_ASSUME_VCALLS: {
+ assert(PendingTypeTestAssumeVCalls.empty());
+ for (unsigned I = 0; I != Record.size(); I += 2)
+ PendingTypeTestAssumeVCalls.push_back({Record[I], Record[I+1]});
+ break;
+ }
+ case bitc::FS_TYPE_CHECKED_LOAD_VCALLS: {
+ assert(PendingTypeCheckedLoadVCalls.empty());
+ for (unsigned I = 0; I != Record.size(); I += 2)
+ PendingTypeCheckedLoadVCalls.push_back({Record[I], Record[I+1]});
+ break;
+ }
+ case bitc::FS_TYPE_TEST_ASSUME_CONST_VCALL: {
+ PendingTypeTestAssumeConstVCalls.push_back(
+ {{Record[0], Record[1]}, {Record.begin() + 2, Record.end()}});
+ break;
+ }
+ case bitc::FS_TYPE_CHECKED_LOAD_CONST_VCALL: {
+ PendingTypeCheckedLoadConstVCalls.push_back(
+ {{Record[0], Record[1]}, {Record.begin() + 2, Record.end()}});
+ break;
+ }
}
}
llvm_unreachable("Exit infinite loop");
@@ -5148,6 +5323,35 @@ const std::error_category &llvm::BitcodeErrorCategory() {
return *ErrorCategory;
}
+static Expected<StringRef> readStrtab(BitstreamCursor &Stream) {
+ if (Stream.EnterSubBlock(bitc::STRTAB_BLOCK_ID))
+ return error("Invalid record");
+
+ StringRef Strtab;
+ while (1) {
+ BitstreamEntry Entry = Stream.advance();
+ switch (Entry.Kind) {
+ case BitstreamEntry::EndBlock:
+ return Strtab;
+
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+
+ case BitstreamEntry::SubBlock:
+ if (Stream.SkipBlock())
+ return error("Malformed block");
+ break;
+
+ case BitstreamEntry::Record:
+ StringRef Blob;
+ SmallVector<uint64_t, 1> Record;
+ if (Stream.readRecord(Entry.ID, Record, &Blob) == bitc::STRTAB_BLOB)
+ Strtab = Blob;
+ break;
+ }
+ }
+}
+
//===----------------------------------------------------------------------===//
// External interface
//===----------------------------------------------------------------------===//
@@ -5200,6 +5404,22 @@ llvm::getBitcodeModuleList(MemoryBufferRef Buffer) {
continue;
}
+ if (Entry.ID == bitc::STRTAB_BLOCK_ID) {
+ Expected<StringRef> Strtab = readStrtab(Stream);
+ if (!Strtab)
+ return Strtab.takeError();
+ // This string table is used by every preceding bitcode module that does
+ // not have its own string table. A bitcode file may have multiple
+ // string tables if it was created by binary concatenation, for example
+ // with "llvm-cat -b".
+ for (auto I = Modules.rbegin(), E = Modules.rend(); I != E; ++I) {
+ if (!I->Strtab.empty())
+ break;
+ I->Strtab = *Strtab;
+ }
+ continue;
+ }
+
if (Stream.SkipBlock())
return error("Malformed block");
continue;
@@ -5236,8 +5456,8 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll,
}
Stream.JumpToBit(ModuleBit);
- auto *R =
- new BitcodeReader(std::move(Stream), ProducerIdentification, Context);
+ auto *R = new BitcodeReader(std::move(Stream), Strtab, ProducerIdentification,
+ Context);
std::unique_ptr<Module> M =
llvm::make_unique<Module>(ModuleIdentifier, Context);
@@ -5272,7 +5492,7 @@ Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
Stream.JumpToBit(ModuleBit);
auto Index = llvm::make_unique<ModuleSummaryIndex>();
- ModuleSummaryIndexBitcodeReader R(std::move(Stream), *Index);
+ ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index);
if (Error Err = R.parseModule(ModuleIdentifier))
return std::move(Err);
diff --git a/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index b89f5be4a369..d089684a052f 100644
--- a/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -54,6 +54,7 @@
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndex.h"
@@ -358,6 +359,9 @@ class PlaceholderQueue {
std::deque<DistinctMDOperandPlaceholder> PHs;
public:
+ ~PlaceholderQueue() {
+ assert(empty() && "PlaceholderQueue hasn't been flushed before being destroyed");
+ }
bool empty() { return PHs.empty(); }
DistinctMDOperandPlaceholder &getPlaceholderOp(unsigned ID);
void flush(BitcodeReaderMetadataList &MetadataList);
@@ -449,6 +453,7 @@ class MetadataLoader::MetadataLoaderImpl {
bool StripTBAA = false;
bool HasSeenOldLoopTags = false;
bool NeedUpgradeToDIGlobalVariableExpression = false;
+ bool NeedDeclareExpressionUpgrade = false;
/// True if metadata is being parsed for a module being ThinLTO imported.
bool IsImporting = false;
@@ -457,7 +462,7 @@ class MetadataLoader::MetadataLoaderImpl {
PlaceholderQueue &Placeholders, StringRef Blob,
unsigned &NextMetadataNo);
Error parseMetadataStrings(ArrayRef<uint64_t> Record, StringRef Blob,
- std::function<void(StringRef)> CallBack);
+ function_ref<void(StringRef)> CallBack);
Error parseGlobalObjectAttachment(GlobalObject &GO,
ArrayRef<uint64_t> Record);
Error parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
@@ -508,6 +513,26 @@ class MetadataLoader::MetadataLoaderImpl {
}
}
+ /// Remove a leading DW_OP_deref from DIExpressions in a dbg.declare that
+ /// describes a function argument.
+ void upgradeDeclareExpressions(Function &F) {
+ if (!NeedDeclareExpressionUpgrade)
+ return;
+
+ for (auto &BB : F)
+ for (auto &I : BB)
+ if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
+ if (auto *DIExpr = DDI->getExpression())
+ if (DIExpr->startsWithDeref() &&
+ dyn_cast_or_null<Argument>(DDI->getAddress())) {
+ SmallVector<uint64_t, 8> Ops;
+ Ops.append(std::next(DIExpr->elements_begin()),
+ DIExpr->elements_end());
+ auto *E = DIExpression::get(Context, Ops);
+ DDI->setOperand(2, MetadataAsValue::get(Context, E));
+ }
+ }
+
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
@@ -520,7 +545,7 @@ public:
bool IsImporting)
: MetadataList(TheModule.getContext()), ValueList(ValueList),
Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule),
- getTypeByID(getTypeByID), IsImporting(IsImporting) {}
+ getTypeByID(std::move(getTypeByID)), IsImporting(IsImporting) {}
Error parseMetadata(bool ModuleLevel);
@@ -562,9 +587,10 @@ public:
unsigned size() const { return MetadataList.size(); }
void shrinkTo(unsigned N) { MetadataList.shrinkTo(N); }
+ void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); }
};
-Error error(const Twine &Message) {
+static Error error(const Twine &Message) {
return make_error<StringError>(
Message, make_error_code(BitcodeError::CorruptedBitcode));
}
@@ -1107,9 +1133,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_DERIVED_TYPE: {
- if (Record.size() != 12)
+ if (Record.size() < 12 || Record.size() > 13)
return error("Invalid record");
+ // DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means
+ // that there is no DWARF address space associated with DIDerivedType.
+ Optional<unsigned> DWARFAddressSpace;
+ if (Record.size() > 12 && Record[12])
+ DWARFAddressSpace = Record[12] - 1;
+
IsDistinct = Record[0];
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
MetadataList.assignValue(
@@ -1118,7 +1150,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
getMDOrNull(Record[3]), Record[4],
getDITypeRefOrNull(Record[5]),
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
- Record[9], Flags, getDITypeRefOrNull(Record[11]))),
+ Record[9], DWARFAddressSpace, Flags,
+ getDITypeRefOrNull(Record[11]))),
NextMetadataNo);
NextMetadataNo++;
break;
@@ -1240,7 +1273,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_COMPILE_UNIT: {
- if (Record.size() < 14 || Record.size() > 17)
+ if (Record.size() < 14 || Record.size() > 18)
return error("Invalid record");
// Ignore Record[0], which indicates whether this compile unit is
@@ -1253,7 +1286,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
getMDOrNull(Record[12]), getMDOrNull(Record[13]),
Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]),
Record.size() <= 14 ? 0 : Record[14],
- Record.size() <= 16 ? true : Record[16]);
+ Record.size() <= 16 ? true : Record[16],
+ Record.size() <= 17 ? false : Record[17]);
MetadataList.assignValue(CU, NextMetadataNo);
NextMetadataNo++;
@@ -1433,6 +1467,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
} else if (Version == 0) {
// Upgrade old metadata, which stored a global variable reference or a
// ConstantInt here.
+ NeedUpgradeToDIGlobalVariableExpression = true;
Metadata *Expr = getMDOrNull(Record[9]);
uint32_t AlignInBits = 0;
if (Record.size() > 11) {
@@ -1463,8 +1498,6 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
DIGlobalVariableExpression *DGVE = nullptr;
if (Attach || Expr)
DGVE = DIGlobalVariableExpression::getDistinct(Context, DGV, Expr);
- else
- NeedUpgradeToDIGlobalVariableExpression = true;
if (Attach)
Attach->addDebugInfo(DGVE);
@@ -1485,7 +1518,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
bool HasAlignment = Record[0] & 2;
// 2nd field used to be an artificial tag, either DW_TAG_auto_variable or
// DW_TAG_arg_variable, if we have alignment flag encoded it means, that
- // this is newer version of record which doesn't have artifical tag.
+ // this is newer version of record which doesn't have artificial tag.
bool HasTag = !HasAlignment && Record.size() > 8;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7 + HasTag]);
uint32_t AlignInBits = 0;
@@ -1510,12 +1543,32 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
return error("Invalid record");
IsDistinct = Record[0] & 1;
- bool HasOpFragment = Record[0] & 2;
+ uint64_t Version = Record[0] >> 1;
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
- if (!HasOpFragment)
- if (unsigned N = Elts.size())
- if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
- Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
+ unsigned N = Elts.size();
+ // Perform various upgrades.
+ switch (Version) {
+ case 0:
+ if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
+ Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
+ LLVM_FALLTHROUGH;
+ case 1:
+ // Move DW_OP_deref to the end.
+ if (N && Elts[0] == dwarf::DW_OP_deref) {
+ auto End = Elts.end();
+ if (Elts.size() >= 3 && *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
+ End = std::prev(End, 3);
+ std::move(std::next(Elts.begin()), End, Elts.begin());
+ *std::prev(End) = dwarf::DW_OP_deref;
+ }
+ NeedDeclareExpressionUpgrade = true;
+ LLVM_FALLTHROUGH;
+ case 2:
+ // Up-to-date!
+ break;
+ default:
+ return error("Invalid record");
+ }
MetadataList.assignValue(
GET_OR_DISTINCT(DIExpression, (Context, makeArrayRef(Record).slice(1))),
@@ -1611,7 +1664,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Error MetadataLoader::MetadataLoaderImpl::parseMetadataStrings(
ArrayRef<uint64_t> Record, StringRef Blob,
- std::function<void(StringRef)> CallBack) {
+ function_ref<void(StringRef)> CallBack) {
// All the MDStrings in the block are emitted together in a single
// record. The strings are concatenated and stored in a blob along with
// their sizes.
@@ -1808,8 +1861,8 @@ MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module &TheModule,
BitcodeReaderValueList &ValueList,
bool IsImporting,
std::function<Type *(unsigned)> getTypeByID)
- : Pimpl(llvm::make_unique<MetadataLoaderImpl>(Stream, TheModule, ValueList,
- getTypeByID, IsImporting)) {}
+ : Pimpl(llvm::make_unique<MetadataLoaderImpl>(
+ Stream, TheModule, ValueList, std::move(getTypeByID), IsImporting)) {}
Error MetadataLoader::parseMetadata(bool ModuleLevel) {
return Pimpl->parseMetadata(ModuleLevel);
@@ -1848,3 +1901,7 @@ bool MetadataLoader::isStrippingTBAA() { return Pimpl->isStrippingTBAA(); }
unsigned MetadataLoader::size() const { return Pimpl->size(); }
void MetadataLoader::shrinkTo(unsigned N) { return Pimpl->shrinkTo(N); }
+
+void MetadataLoader::upgradeDebugIntrinsics(Function &F) {
+ return Pimpl->upgradeDebugIntrinsics(F);
+}
diff --git a/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.h b/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.h
index 442dfc94e4e1..f23dcc06cc94 100644
--- a/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.h
+++ b/contrib/llvm/lib/Bitcode/Reader/MetadataLoader.h
@@ -79,6 +79,9 @@ public:
unsigned size() const;
void shrinkTo(unsigned N);
+
+ /// Perform bitcode upgrades on llvm.dbg.* calls.
+ void upgradeDebugIntrinsics(Function &F);
};
}
diff --git a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index ebb2022551f7..e5aba03c8dc1 100644
--- a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -28,6 +28,7 @@
#include "llvm/IR/Operator.h"
#include "llvm/IR/UseListOrder.h"
#include "llvm/IR/ValueSymbolTable.h"
+#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Program.h"
@@ -76,26 +77,28 @@ protected:
/// The stream created and owned by the client.
BitstreamWriter &Stream;
- /// 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 BitcodeWriterBase object that writes to the provided
/// \p Stream.
BitcodeWriterBase(BitstreamWriter &Stream) : Stream(Stream) {}
protected:
- bool hasVSTOffsetPlaceholder() { return VSTOffsetPlaceholder != 0; }
- void writeValueSymbolTableForwardDecl();
void writeBitcodeHeader();
+ void writeModuleVersion();
};
+void BitcodeWriterBase::writeModuleVersion() {
+ // VERSION: [version#]
+ 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;
+ StringTableBuilder &StrtabBuilder;
+
/// The Module to write to bitcode.
const Module &M;
@@ -108,6 +111,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;
@@ -119,15 +130,22 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
/// 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 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)
- : BitcodeWriterBase(Stream), Buffer(Buffer), M(*M),
- VE(*M, ShouldPreserveUseListOrder), Index(Index),
- GenerateHash(GenerateHash), BitcodeStartBit(Stream.GetCurrentBitNo()) {
+ const ModuleSummaryIndex *Index, bool GenerateHash,
+ ModuleHash *ModHash = nullptr)
+ : BitcodeWriterBase(Stream), Buffer(Buffer), StrtabBuilder(StrtabBuilder),
+ M(*M), VE(*M, ShouldPreserveUseListOrder), Index(Index),
+ 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).
@@ -159,6 +177,7 @@ private:
void writeAttributeTable();
void writeTypeTable();
void writeComdats();
+ void writeValueSymbolTableForwardDecl();
void writeModuleInfo();
void writeValueAsMetadata(const ValueAsMetadata *MD,
SmallVectorImpl<uint64_t> &Record);
@@ -251,9 +270,9 @@ private:
SmallVectorImpl<uint64_t> &Vals);
void writeInstruction(const Instruction &I, unsigned InstID,
SmallVectorImpl<unsigned> &Vals);
- void writeValueSymbolTable(
- const ValueSymbolTable &VST, bool IsModuleLevel = false,
- DenseMap<const Function *, uint64_t> *FunctionToBitcodeIndex = nullptr);
+ void writeFunctionLevelValueSymbolTable(const ValueSymbolTable &VST);
+ void writeGlobalValueSymbolTable(
+ DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex);
void writeUseList(UseListOrder &&Order);
void writeUseListBlock(const Function *F);
void
@@ -466,9 +485,7 @@ public:
void write();
private:
- void writeIndex();
void writeModStrings();
- void writeCombinedValueSymbolTable();
void writeCombinedGlobalValueSummary();
/// Indicates whether the provided \p ModulePath should be written into
@@ -483,15 +500,15 @@ private:
const auto &VMI = GUIDToValueIdMap.find(ValGUID);
return VMI != GUIDToValueIdMap.end();
}
+ void assignValueId(GlobalValue::GUID ValGUID) {
+ unsigned &ValueId = GUIDToValueIdMap[ValGUID];
+ if (ValueId == 0)
+ ValueId = ++GlobalValueId;
+ }
unsigned getValueId(GlobalValue::GUID ValGUID) {
- const auto &VMI = GUIDToValueIdMap.find(ValGUID);
- // If this GUID doesn't have an entry, assign one.
- if (VMI == GUIDToValueIdMap.end()) {
- GUIDToValueIdMap[ValGUID] = ++GlobalValueId;
- return GlobalValueId;
- } else {
- return VMI->second;
- }
+ auto VMI = GUIDToValueIdMap.find(ValGUID);
+ assert(VMI != GUIDToValueIdMap.end());
+ return VMI->second;
}
std::map<GlobalValue::GUID, unsigned> &valueIds() { return GUIDToValueIdMap; }
};
@@ -709,63 +726,60 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
}
void ModuleBitcodeWriter::writeAttributeGroupTable() {
- const std::vector<AttributeSet> &AttrGrps = VE.getAttributeGroups();
+ const std::vector<ValueEnumerator::IndexAndAttrSet> &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];
- for (unsigned i = 0, e = AS.getNumSlots(); i != e; ++i) {
- AttributeSet 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) {
- Attribute Attr = *I;
- if (Attr.isEnumAttribute()) {
- Record.push_back(0);
- Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
- } else if (Attr.isIntAttribute()) {
- Record.push_back(1);
- Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
- Record.push_back(Attr.getValueAsInt());
- } else {
- StringRef Kind = Attr.getKindAsString();
- StringRef Val = Attr.getValueAsString();
-
- Record.push_back(Val.empty() ? 3 : 4);
- Record.append(Kind.begin(), Kind.end());
+ for (ValueEnumerator::IndexAndAttrSet Pair : AttrGrps) {
+ unsigned AttrListIndex = Pair.first;
+ AttributeSet AS = Pair.second;
+ Record.push_back(VE.getAttributeGroupID(Pair));
+ Record.push_back(AttrListIndex);
+
+ for (Attribute Attr : AS) {
+ if (Attr.isEnumAttribute()) {
+ Record.push_back(0);
+ Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
+ } else if (Attr.isIntAttribute()) {
+ Record.push_back(1);
+ Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum()));
+ Record.push_back(Attr.getValueAsInt());
+ } else {
+ StringRef Kind = Attr.getKindAsString();
+ StringRef Val = Attr.getValueAsString();
+
+ Record.push_back(Val.empty() ? 3 : 4);
+ Record.append(Kind.begin(), Kind.end());
+ Record.push_back(0);
+ if (!Val.empty()) {
+ Record.append(Val.begin(), Val.end());
Record.push_back(0);
- if (!Val.empty()) {
- Record.append(Val.begin(), Val.end());
- Record.push_back(0);
- }
}
}
-
- Stream.EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record);
- Record.clear();
}
+
+ Stream.EmitRecord(bitc::PARAMATTR_GRP_CODE_ENTRY, Record);
+ Record.clear();
}
Stream.ExitBlock();
}
void ModuleBitcodeWriter::writeAttributeTable() {
- const std::vector<AttributeSet> &Attrs = VE.getAttributes();
+ const std::vector<AttributeList> &Attrs = VE.getAttributeLists();
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)));
+ Record.push_back(
+ VE.getAttributeGroupID({A.getSlotIndex(i), A.getSlotAttributes(i)}));
Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
Record.clear();
@@ -1038,13 +1052,10 @@ static unsigned getEncodedUnnamedAddr(const GlobalValue &GV) {
void ModuleBitcodeWriter::writeComdats() {
SmallVector<unsigned, 64> Vals;
for (const Comdat *C : VE.getComdats()) {
- // COMDAT: [selection_kind, name]
+ // COMDAT: [strtab offset, strtab size, selection_kind]
+ Vals.push_back(StrtabBuilder.add(C->getName()));
+ Vals.push_back(C->getName().size());
Vals.push_back(getEncodedComdatSelectionKind(*C));
- size_t Size = C->getName().size();
- assert(isUInt<32>(Size));
- Vals.push_back(Size);
- for (char Chr : C->getName())
- Vals.push_back((unsigned char)Chr);
Stream.EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0);
Vals.clear();
}
@@ -1053,7 +1064,7 @@ void ModuleBitcodeWriter::writeComdats() {
/// Write a record that will eventually hold the word offset of the
/// module-level VST. For now the offset is 0, which will be backpatched
/// after the real VST is written. Saves the bit offset to backpatch.
-void BitcodeWriterBase::writeValueSymbolTableForwardDecl() {
+void ModuleBitcodeWriter::writeValueSymbolTableForwardDecl() {
// Write a placeholder value in for the offset of the real VST,
// which is written after the function blocks so that it can include
// the offset of each function. The placeholder offset will be
@@ -1156,6 +1167,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Add an abbrev for common globals with no visibility or thread localness.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(MaxGlobalType+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // AddrSpace << 2
@@ -1179,15 +1192,42 @@ void ModuleBitcodeWriter::writeModuleInfo() {
SimpleGVarAbbrev = Stream.EmitAbbrev(std::move(Abbv));
}
- // Emit the global variable information.
SmallVector<unsigned, 64> Vals;
+ // Emit the module's source file name.
+ {
+ StringEncoding Bits = getStringEncoding(M.getSourceFileName().data(),
+ M.getSourceFileName().size());
+ 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);
+
+ // Emit the finished record.
+ Stream.EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, FilenameAbbrev);
+ Vals.clear();
+ }
+
+ // Emit the global variable information.
for (const GlobalVariable &GV : M.globals()) {
unsigned AbbrevToUse = 0;
- // GLOBALVAR: [type, isconst, initid,
+ // GLOBALVAR: [strtab offset, strtab size, type, isconst, initid,
// linkage, alignment, section, visibility, threadlocal,
// unnamed_addr, externally_initialized, dllstorageclass,
// comdat]
+ Vals.push_back(StrtabBuilder.add(GV.getName()));
+ Vals.push_back(GV.getName().size());
Vals.push_back(VE.getTypeID(GV.getValueType()));
Vals.push_back(GV.getType()->getAddressSpace() << 2 | 2 | GV.isConstant());
Vals.push_back(GV.isDeclaration() ? 0 :
@@ -1217,14 +1257,17 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the function proto information.
for (const Function &F : M) {
- // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
- // section, visibility, gc, unnamed_addr, prologuedata,
- // dllstorageclass, comdat, prefixdata, personalityfn]
+ // FUNCTION: [strtab offset, strtab size, type, callingconv, isproto,
+ // linkage, paramattrs, alignment, section, visibility, gc,
+ // unnamed_addr, prologuedata, dllstorageclass, comdat,
+ // prefixdata, personalityfn]
+ Vals.push_back(StrtabBuilder.add(F.getName()));
+ Vals.push_back(F.getName().size());
Vals.push_back(VE.getTypeID(F.getFunctionType()));
Vals.push_back(F.getCallingConv());
Vals.push_back(F.isDeclaration());
Vals.push_back(getEncodedLinkage(F));
- Vals.push_back(VE.getAttributeID(F.getAttributes()));
+ Vals.push_back(VE.getAttributeListID(F.getAttributes()));
Vals.push_back(Log2_32(F.getAlignment())+1);
Vals.push_back(F.hasSection() ? SectionMap[F.getSection()] : 0);
Vals.push_back(getEncodedVisibility(F));
@@ -1246,8 +1289,10 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the alias information.
for (const GlobalAlias &A : M.aliases()) {
- // ALIAS: [alias type, aliasee val#, linkage, visibility, dllstorageclass,
- // threadlocal, unnamed_addr]
+ // ALIAS: [strtab offset, strtab size, alias type, aliasee val#, linkage,
+ // visibility, dllstorageclass, threadlocal, unnamed_addr]
+ Vals.push_back(StrtabBuilder.add(A.getName()));
+ Vals.push_back(A.getName().size());
Vals.push_back(VE.getTypeID(A.getValueType()));
Vals.push_back(A.getType()->getAddressSpace());
Vals.push_back(VE.getValueID(A.getAliasee()));
@@ -1263,7 +1308,10 @@ void ModuleBitcodeWriter::writeModuleInfo() {
// Emit the ifunc information.
for (const GlobalIFunc &I : M.ifuncs()) {
- // IFUNC: [ifunc type, address space, resolver val#, linkage, visibility]
+ // IFUNC: [strtab offset, strtab size, ifunc type, address space, resolver
+ // val#, linkage, visibility]
+ Vals.push_back(StrtabBuilder.add(I.getName()));
+ Vals.push_back(I.getName().size());
Vals.push_back(VE.getTypeID(I.getValueType()));
Vals.push_back(I.getType()->getAddressSpace());
Vals.push_back(VE.getValueID(I.getResolver()));
@@ -1273,34 +1321,6 @@ void ModuleBitcodeWriter::writeModuleInfo() {
Vals.clear();
}
- // Emit the module's source file name.
- {
- StringEncoding Bits = getStringEncoding(M.getSourceFileName().data(),
- M.getSourceFileName().size());
- 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);
-
- // Emit the finished record.
- Stream.EmitRecord(bitc::MODULE_CODE_SOURCE_FILENAME, Vals, FilenameAbbrev);
- Vals.clear();
- }
-
- // If we have a VST, write the VSTOFFSET record placeholder.
- if (M.getValueSymbolTable().empty())
- return;
writeValueSymbolTableForwardDecl();
}
@@ -1326,6 +1346,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 +1495,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 +1578,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();
@@ -1738,9 +1768,8 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.reserve(N->getElements().size() + 1);
-
- const uint64_t HasOpFragmentFlag = 1 << 1;
- Record.push_back((uint64_t)N->isDistinct() | HasOpFragmentFlag);
+ const uint64_t Version = 2 << 1;
+ Record.push_back((uint64_t)N->isDistinct() | Version);
Record.append(N->elements_begin(), N->elements_end());
Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev);
@@ -2559,7 +2588,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()));
}
@@ -2584,7 +2613,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
Code = bitc::FUNC_CODE_INST_INVOKE;
- Vals.push_back(VE.getAttributeID(II->getAttributes()));
+ Vals.push_back(VE.getAttributeListID(II->getAttributes()));
Vals.push_back(II->getCallingConv() | 1 << 13);
Vals.push_back(VE.getValueID(II->getNormalDest()));
Vals.push_back(VE.getValueID(II->getUnwindDest()));
@@ -2776,7 +2805,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
Code = bitc::FUNC_CODE_INST_CALL;
- Vals.push_back(VE.getAttributeID(CI.getAttributes()));
+ Vals.push_back(VE.getAttributeListID(CI.getAttributes()));
unsigned Flags = getOptimizationFlags(&I);
Vals.push_back(CI.getCallingConv() << bitc::CALL_CCONV |
@@ -2820,77 +2849,59 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
Vals.clear();
}
-/// Emit names for globals/functions etc. \p IsModuleLevel is true when
-/// we are writing the module-level VST, where we are including a function
-/// bitcode index and need to backpatch the VST forward declaration record.
-void ModuleBitcodeWriter::writeValueSymbolTable(
- const ValueSymbolTable &VST, bool IsModuleLevel,
- DenseMap<const Function *, uint64_t> *FunctionToBitcodeIndex) {
- if (VST.empty()) {
- // writeValueSymbolTableForwardDecl should have returned early as
- // well. Ensure this handling remains in sync by asserting that
- // the placeholder offset is not set.
- assert(!IsModuleLevel || !hasVSTOffsetPlaceholder());
- return;
- }
+/// Write a GlobalValue VST to the module. The purpose of this data structure is
+/// to allow clients to efficiently find the function body.
+void ModuleBitcodeWriter::writeGlobalValueSymbolTable(
+ DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex) {
+ // Get the offset of the VST we are writing, and backpatch it into
+ // the VST forward declaration record.
+ uint64_t VSTOffset = Stream.GetCurrentBitNo();
+ // The BitcodeStartBit was the stream offset of the identification block.
+ VSTOffset -= bitcodeStartBit();
+ assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");
+ // Note that we add 1 here because the offset is relative to one word
+ // before the start of the identification block, which was historically
+ // always the start of the regular bitcode header.
+ Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32 + 1);
+
+ Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
- if (IsModuleLevel && hasVSTOffsetPlaceholder()) {
- // Get the offset of the VST we are writing, and backpatch it into
- // the VST forward declaration record.
- uint64_t VSTOffset = Stream.GetCurrentBitNo();
- // The BitcodeStartBit was the stream offset of the identification block.
- VSTOffset -= bitcodeStartBit();
- assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");
+ auto Abbv = std::make_shared<BitCodeAbbrev>();
+ Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
+ unsigned FnEntryAbbrev = Stream.EmitAbbrev(std::move(Abbv));
+
+ for (const Function &F : M) {
+ uint64_t Record[2];
+
+ if (F.isDeclaration())
+ continue;
+
+ Record[0] = VE.getValueID(&F);
+
+ // Save the word offset of the function (from the start of the
+ // actual bitcode written to the stream).
+ uint64_t BitcodeIndex = FunctionToBitcodeIndex[&F] - bitcodeStartBit();
+ assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned");
// Note that we add 1 here because the offset is relative to one word
// before the start of the identification block, which was historically
// always the start of the regular bitcode header.
- Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32 + 1);
- }
-
- Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
+ Record[1] = BitcodeIndex / 32 + 1;
- // For the module-level VST, add abbrev Ids for the VST_CODE_FNENTRY
- // records, which are not used in the per-function VSTs.
- unsigned FnEntry8BitAbbrev;
- unsigned FnEntry7BitAbbrev;
- unsigned FnEntry6BitAbbrev;
- unsigned GUIDEntryAbbrev;
- if (IsModuleLevel && hasVSTOffsetPlaceholder()) {
- // 8-bit fixed-width VST_CODE_FNENTRY function strings.
- auto Abbv = std::make_shared<BitCodeAbbrev>();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
- FnEntry8BitAbbrev = Stream.EmitAbbrev(std::move(Abbv));
+ Stream.EmitRecord(bitc::VST_CODE_FNENTRY, Record, FnEntryAbbrev);
+ }
- // 7-bit fixed width VST_CODE_FNENTRY function strings.
- Abbv = std::make_shared<BitCodeAbbrev>();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
- FnEntry7BitAbbrev = Stream.EmitAbbrev(std::move(Abbv));
+ Stream.ExitBlock();
+}
- // 6-bit char6 VST_CODE_FNENTRY function strings.
- Abbv = std::make_shared<BitCodeAbbrev>();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
- FnEntry6BitAbbrev = Stream.EmitAbbrev(std::move(Abbv));
+/// Emit names for arguments, instructions and basic blocks in a function.
+void ModuleBitcodeWriter::writeFunctionLevelValueSymbolTable(
+ const ValueSymbolTable &VST) {
+ if (VST.empty())
+ return;
- // FIXME: Change the name of this record as it is now used by
- // the per-module index as well.
- Abbv = std::make_shared<BitCodeAbbrev>();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_ENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // refguid
- GUIDEntryAbbrev = Stream.EmitAbbrev(std::move(Abbv));
- }
+ Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
// FIXME: Set up the abbrev, we know how many values there are!
// FIXME: We know if the type names can use 7-bit ascii.
@@ -2904,45 +2915,13 @@ void ModuleBitcodeWriter::writeValueSymbolTable(
unsigned AbbrevToUse = VST_ENTRY_8_ABBREV;
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]
// VST_CODE_BBENTRY: [bbid, namechar x N]
unsigned Code;
if (isa<BasicBlock>(Name.getValue())) {
Code = bitc::VST_CODE_BBENTRY;
if (Bits == SE_Char6)
AbbrevToUse = VST_BBENTRY_6_ABBREV;
- } else if (F && !F->isDeclaration()) {
- // Must be the module-level VST, where we pass in the Index and
- // have a VSTOffsetPlaceholder. The function-level VST should not
- // contain any Function symbols.
- assert(FunctionToBitcodeIndex);
- assert(hasVSTOffsetPlaceholder());
-
- // Save the word offset of the function (from the start of the
- // actual bitcode written to the stream).
- uint64_t BitcodeIndex = (*FunctionToBitcodeIndex)[F] - bitcodeStartBit();
- assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned");
- // Note that we add 1 here because the offset is relative to one word
- // before the start of the identification block, which was historically
- // always the start of the regular bitcode header.
- NameVals.push_back(BitcodeIndex / 32 + 1);
-
- Code = bitc::VST_CODE_FNENTRY;
- AbbrevToUse = FnEntry8BitAbbrev;
- if (Bits == SE_Char6)
- AbbrevToUse = FnEntry6BitAbbrev;
- else if (Bits == SE_Fixed7)
- AbbrevToUse = FnEntry7BitAbbrev;
} else {
Code = bitc::VST_CODE_ENTRY;
if (Bits == SE_Char6)
@@ -2958,47 +2937,7 @@ void ModuleBitcodeWriter::writeValueSymbolTable(
Stream.EmitRecord(Code, NameVals, AbbrevToUse);
NameVals.clear();
}
- // Emit any GUID valueIDs created for indirect call edges into the
- // module-level VST.
- if (IsModuleLevel && hasVSTOffsetPlaceholder())
- for (const auto &GI : valueIds()) {
- NameVals.push_back(GI.second);
- NameVals.push_back(GI.first);
- Stream.EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals,
- GUIDEntryAbbrev);
- NameVals.clear();
- }
- Stream.ExitBlock();
-}
-
-/// Emit function names and summary offsets for the combined index
-/// used by ThinLTO.
-void IndexBitcodeWriter::writeCombinedValueSymbolTable() {
- assert(hasVSTOffsetPlaceholder() && "Expected non-zero VSTOffsetPlaceholder");
- // Get the offset of the VST we are writing, and backpatch it into
- // the VST forward declaration record.
- uint64_t VSTOffset = Stream.GetCurrentBitNo();
- assert((VSTOffset & 31) == 0 && "VST block not 32-bit aligned");
- Stream.BackpatchWord(VSTOffsetPlaceholder, VSTOffset / 32);
- Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
-
- auto Abbv = std::make_shared<BitCodeAbbrev>();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_COMBINED_ENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // valueid
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // refguid
- unsigned EntryAbbrev = Stream.EmitAbbrev(std::move(Abbv));
-
- SmallVector<uint64_t, 64> NameVals;
- for (const auto &GVI : valueIds()) {
- // VST_CODE_COMBINED_ENTRY: [valueid, refguid]
- NameVals.push_back(GVI.second);
- NameVals.push_back(GVI.first);
-
- // Emit the finished record.
- Stream.EmitRecord(bitc::VST_CODE_COMBINED_ENTRY, NameVals, EntryAbbrev);
- NameVals.clear();
- }
Stream.ExitBlock();
}
@@ -3102,7 +3041,7 @@ void ModuleBitcodeWriter::writeFunction(
// Emit names for all the instructions etc.
if (auto *Symtab = F.getValueSymbolTable())
- writeValueSymbolTable(*Symtab);
+ writeFunctionLevelValueSymbolTable(*Symtab);
if (NeedsMetadataAttachment)
writeFunctionMetadataAttachment(F);
@@ -3367,6 +3306,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 +3357,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());
@@ -3448,6 +3429,11 @@ void ModuleBitcodeWriter::writePerModuleGlobalValueSummary() {
return;
}
+ for (const auto &GVI : valueIds()) {
+ Stream.EmitRecord(bitc::FS_VALUE_GUID,
+ ArrayRef<uint64_t>{GVI.second, GVI.first});
+ }
+
// Abbrev for FS_PERMODULE.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::FS_PERMODULE));
@@ -3540,6 +3526,39 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
Stream.EmitRecord(bitc::FS_VERSION, ArrayRef<uint64_t>{INDEX_VERSION});
+ // Create value IDs for undefined references.
+ for (const auto &I : *this) {
+ if (auto *VS = dyn_cast<GlobalVarSummary>(I.second)) {
+ for (auto &RI : VS->refs())
+ assignValueId(RI.getGUID());
+ continue;
+ }
+
+ auto *FS = dyn_cast<FunctionSummary>(I.second);
+ if (!FS)
+ continue;
+ for (auto &RI : FS->refs())
+ assignValueId(RI.getGUID());
+
+ for (auto &EI : FS->calls()) {
+ 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;
+ }
+ assignValueId(GUID);
+ }
+ }
+
+ for (const auto &GVI : valueIds()) {
+ Stream.EmitRecord(bitc::FS_VALUE_GUID,
+ ArrayRef<uint64_t>{GVI.second, GVI.first});
+ }
+
// Abbrev for FS_COMBINED.
auto Abbv = std::make_shared<BitCodeAbbrev>();
Abbv->Add(BitCodeAbbrevOp(bitc::FS_COMBINED));
@@ -3636,8 +3655,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 +3677,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 +3722,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 +3747,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() {
@@ -3741,10 +3773,7 @@ void ModuleBitcodeWriter::write() {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
size_t BlockStartPos = Buffer.size();
- SmallVector<unsigned, 1> Vals;
- unsigned CurVersion = 1;
- Vals.push_back(CurVersion);
- Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
+ writeModuleVersion();
// Emit blockinfo, which defines the standard abbreviations etc.
writeBlockInfo();
@@ -3790,12 +3819,9 @@ void ModuleBitcodeWriter::write() {
if (Index)
writePerModuleGlobalValueSummary();
- writeValueSymbolTable(M.getValueSymbolTable(),
- /* IsModuleLevel */ true, &FunctionToBitcodeIndex);
+ writeGlobalValueSymbolTable(FunctionToBitcodeIndex);
- if (GenerateHash) {
- writeModuleHash(BlockStartPos);
- }
+ writeModuleHash(BlockStartPos);
Stream.ExitBlock();
}
@@ -3881,14 +3907,47 @@ BitcodeWriter::BitcodeWriter(SmallVectorImpl<char> &Buffer)
writeBitcodeHeader(*Stream);
}
-BitcodeWriter::~BitcodeWriter() = default;
+BitcodeWriter::~BitcodeWriter() { assert(WroteStrtab); }
+
+void BitcodeWriter::writeBlob(unsigned Block, unsigned Record, StringRef Blob) {
+ Stream->EnterSubblock(Block, 3);
+
+ auto Abbv = std::make_shared<BitCodeAbbrev>();
+ Abbv->Add(BitCodeAbbrevOp(Record));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ auto AbbrevNo = Stream->EmitAbbrev(std::move(Abbv));
+
+ Stream->EmitRecordWithBlob(AbbrevNo, ArrayRef<uint64_t>{Record}, Blob);
+
+ Stream->ExitBlock();
+}
+
+void BitcodeWriter::writeStrtab() {
+ assert(!WroteStrtab);
+
+ std::vector<char> Strtab;
+ StrtabBuilder.finalizeInOrder();
+ Strtab.resize(StrtabBuilder.getSize());
+ StrtabBuilder.write((uint8_t *)Strtab.data());
+
+ writeBlob(bitc::STRTAB_BLOCK_ID, bitc::STRTAB_BLOB,
+ {Strtab.data(), Strtab.size()});
+
+ WroteStrtab = true;
+}
+
+void BitcodeWriter::copyStrtab(StringRef Strtab) {
+ writeBlob(bitc::STRTAB_BLOCK_ID, bitc::STRTAB_BLOB, Strtab);
+ WroteStrtab = true;
+}
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, StrtabBuilder, *Stream,
+ ShouldPreserveUseListOrder, Index,
+ GenerateHash, ModHash);
ModuleWriter.write();
}
@@ -3897,7 +3956,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 +3967,9 @@ 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);
+ Writer.writeStrtab();
if (TT.isOSDarwin() || TT.isOSBinFormatMachO())
emitDarwinBCHeaderAndTrailer(Buffer, TT);
@@ -3920,13 +3981,7 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
void IndexBitcodeWriter::write() {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
- SmallVector<unsigned, 1> Vals;
- unsigned CurVersion = 1;
- Vals.push_back(CurVersion);
- Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
-
- // If we have a VST, write the VSTOFFSET record placeholder.
- writeValueSymbolTableForwardDecl();
+ writeModuleVersion();
// Write the module paths in the combined index.
writeModStrings();
@@ -3934,10 +3989,6 @@ void IndexBitcodeWriter::write() {
// Write the summary combined index records.
writeCombinedGlobalValueSummary();
- // Need a special VST writer for the combined index (we don't have a
- // real VST and real values when this is invoked).
- writeCombinedValueSymbolTable();
-
Stream.ExitBlock();
}
diff --git a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
index 5d5bfab58b81..861150766986 100644
--- a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -432,12 +432,14 @@ unsigned ValueEnumerator::getValueID(const Value *V) const {
return I->second-1;
}
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void ValueEnumerator::dump() const {
print(dbgs(), ValueMap, "Default");
dbgs() << '\n';
print(dbgs(), MetadataMap, "MetaData");
dbgs() << '\n';
}
+#endif
void ValueEnumerator::print(raw_ostream &OS, const ValueMapType &Map,
const char *Name) const {
@@ -452,7 +454,8 @@ void ValueEnumerator::print(raw_ostream &OS, const ValueMapType &Map,
OS << "Value: " << V->getName();
else
OS << "Value: [null]\n";
- V->dump();
+ V->print(errs());
+ errs() << '\n';
OS << " Uses(" << std::distance(V->use_begin(),V->use_end()) << "):";
for (const Use &U : V->uses()) {
@@ -549,7 +552,7 @@ void ValueEnumerator::EnumerateFunctionLocalMetadata(
void ValueEnumerator::dropFunctionFromMetadata(
MetadataMapType::value_type &FirstMD) {
SmallVector<const MDNode *, 64> Worklist;
- auto push = [this, &Worklist](MetadataMapType::value_type &MD) {
+ auto push = [&Worklist](MetadataMapType::value_type &MD) {
auto &Entry = MD.second;
// Nothing to do if this metadata isn't tagged.
@@ -884,23 +887,23 @@ void ValueEnumerator::EnumerateOperandType(const Value *V) {
}
}
-void ValueEnumerator::EnumerateAttributes(AttributeSet PAL) {
+void ValueEnumerator::EnumerateAttributes(AttributeList PAL) {
if (PAL.isEmpty()) return; // null is always 0.
// Do a lookup.
- unsigned &Entry = AttributeMap[PAL];
+ unsigned &Entry = AttributeListMap[PAL];
if (Entry == 0) {
// Never saw this before, add it.
- Attribute.push_back(PAL);
- Entry = Attribute.size();
+ AttributeLists.push_back(PAL);
+ Entry = AttributeLists.size();
}
// Do lookups for all attribute groups.
for (unsigned i = 0, e = PAL.getNumSlots(); i != e; ++i) {
- AttributeSet AS = PAL.getSlotAttributes(i);
- unsigned &Entry = AttributeGroupMap[AS];
+ IndexAndAttrSet Pair = {PAL.getSlotIndex(i), PAL.getSlotAttributes(i)};
+ unsigned &Entry = AttributeGroupMap[Pair];
if (Entry == 0) {
- AttributeGroups.push_back(AS);
+ AttributeGroups.push_back(Pair);
Entry = AttributeGroups.size();
}
}
diff --git a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h
index a8d6cf965a4b..e7ccc8df1e5f 100644
--- a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h
@@ -36,7 +36,7 @@ class LocalAsMetadata;
class MDNode;
class MDOperand;
class NamedMDNode;
-class AttributeSet;
+class AttributeList;
class ValueSymbolTable;
class MDSymbolTable;
class raw_ostream;
@@ -48,6 +48,10 @@ public:
// For each value, we remember its Value* and occurrence frequency.
typedef std::vector<std::pair<const Value*, unsigned> > ValueList;
+ /// Attribute groups as encoded in bitcode are almost AttributeSets, but they
+ /// include the AttributeList index, so we have to track that in our map.
+ typedef std::pair<unsigned, AttributeSet> IndexAndAttrSet;
+
UseListOrderStack UseListOrders;
private:
@@ -102,13 +106,13 @@ private:
bool ShouldPreserveUseListOrder;
- typedef DenseMap<AttributeSet, unsigned> AttributeGroupMapType;
+ typedef DenseMap<IndexAndAttrSet, unsigned> AttributeGroupMapType;
AttributeGroupMapType AttributeGroupMap;
- std::vector<AttributeSet> AttributeGroups;
+ std::vector<IndexAndAttrSet> AttributeGroups;
- typedef DenseMap<AttributeSet, unsigned> AttributeMapType;
- AttributeMapType AttributeMap;
- std::vector<AttributeSet> Attribute;
+ typedef DenseMap<AttributeList, unsigned> AttributeListMapType;
+ AttributeListMapType AttributeListMap;
+ std::vector<AttributeList> AttributeLists;
/// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by
/// the "getGlobalBasicBlockID" method.
@@ -166,16 +170,17 @@ public:
unsigned getInstructionID(const Instruction *I) const;
void setInstructionID(const Instruction *I);
- unsigned getAttributeID(AttributeSet PAL) const {
+ unsigned getAttributeListID(AttributeList PAL) const {
if (PAL.isEmpty()) return 0; // Null maps to zero.
- AttributeMapType::const_iterator I = AttributeMap.find(PAL);
- assert(I != AttributeMap.end() && "Attribute not in ValueEnumerator!");
+ AttributeListMapType::const_iterator I = AttributeListMap.find(PAL);
+ assert(I != AttributeListMap.end() && "Attribute not in ValueEnumerator!");
return I->second;
}
- unsigned getAttributeGroupID(AttributeSet PAL) const {
- if (PAL.isEmpty()) return 0; // Null maps to zero.
- AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(PAL);
+ unsigned getAttributeGroupID(IndexAndAttrSet Group) const {
+ if (!Group.second.hasAttributes())
+ return 0; // Null maps to zero.
+ AttributeGroupMapType::const_iterator I = AttributeGroupMap.find(Group);
assert(I != AttributeGroupMap.end() && "Attribute not in ValueEnumerator!");
return I->second;
}
@@ -206,10 +211,8 @@ public:
const std::vector<const BasicBlock*> &getBasicBlocks() const {
return BasicBlocks;
}
- const std::vector<AttributeSet> &getAttributes() const {
- return Attribute;
- }
- const std::vector<AttributeSet> &getAttributeGroups() const {
+ const std::vector<AttributeList> &getAttributeLists() const { return AttributeLists; }
+ const std::vector<IndexAndAttrSet> &getAttributeGroups() const {
return AttributeGroups;
}
@@ -283,7 +286,7 @@ private:
void EnumerateValue(const Value *V);
void EnumerateType(Type *T);
void EnumerateOperandType(const Value *V);
- void EnumerateAttributes(AttributeSet PAL);
+ void EnumerateAttributes(AttributeList PAL);
void EnumerateValueSymbolTable(const ValueSymbolTable &ST);
void EnumerateNamedMetadata(const Module &M);