summaryrefslogtreecommitdiff
path: root/lib/Bitcode/Reader/BitcodeReader.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Bitcode/Reader/BitcodeReader.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp237
1 files changed, 204 insertions, 33 deletions
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index c45b441238bc..fe051e7a9125 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -876,6 +876,7 @@ static FunctionSummary::FFlags getDecodedFFlags(uint64_t RawFlags) {
Flags.ReadOnly = (RawFlags >> 1) & 0x1;
Flags.NoRecurse = (RawFlags >> 2) & 0x1;
Flags.ReturnDoesNotAlias = (RawFlags >> 3) & 0x1;
+ Flags.NoInline = (RawFlags >> 4) & 0x1;
return Flags;
}
@@ -897,6 +898,11 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags,
return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, Live, Local);
}
+// Decode the flags for GlobalVariable in the summary
+static GlobalVarSummary::GVarFlags getDecodedGVarFlags(uint64_t RawFlags) {
+ return GlobalVarSummary::GVarFlags((RawFlags & 0x1) ? true : false);
+}
+
static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) {
switch (Val) {
default: // Map unknown visibilities to default.
@@ -963,6 +969,20 @@ static int getDecodedCastOpcode(unsigned Val) {
}
}
+static int getDecodedUnaryOpcode(unsigned Val, Type *Ty) {
+ bool IsFP = Ty->isFPOrFPVectorTy();
+ // UnOps are only valid for int/fp or vector of int/fp types
+ if (!IsFP && !Ty->isIntOrIntVectorTy())
+ return -1;
+
+ switch (Val) {
+ default:
+ return -1;
+ case bitc::UNOP_NEG:
+ return IsFP ? Instruction::FNeg : -1;
+ }
+}
+
static int getDecodedBinaryOpcode(unsigned Val, Type *Ty) {
bool IsFP = Ty->isFPOrFPVectorTy();
// BinOps are only valid for int/fp or vector of int/fp types
@@ -1165,6 +1185,8 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
case Attribute::NoCfCheck: return 1ULL << 57;
case Attribute::OptForFuzzing: return 1ULL << 58;
case Attribute::ShadowCallStack: return 1ULL << 59;
+ case Attribute::SpeculativeLoadHardening:
+ return 1ULL << 60;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
@@ -1389,6 +1411,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::SanitizeThread;
case bitc::ATTR_KIND_SANITIZE_MEMORY:
return Attribute::SanitizeMemory;
+ case bitc::ATTR_KIND_SPECULATIVE_LOAD_HARDENING:
+ return Attribute::SpeculativeLoadHardening;
case bitc::ATTR_KIND_SWIFT_ERROR:
return Attribute::SwiftError;
case bitc::ATTR_KIND_SWIFT_SELF:
@@ -2312,6 +2336,19 @@ Error BitcodeReader::parseConstants() {
}
break;
}
+ case bitc::CST_CODE_CE_UNOP: { // CE_UNOP: [opcode, opval]
+ if (Record.size() < 2)
+ return error("Invalid record");
+ int Opc = getDecodedUnaryOpcode(Record[0], CurTy);
+ if (Opc < 0) {
+ V = UndefValue::get(CurTy); // Unknown unop.
+ } else {
+ Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
+ unsigned Flags = 0;
+ V = ConstantExpr::get(Opc, LHS, Flags);
+ }
+ break;
+ }
case bitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval]
if (Record.size() < 3)
return error("Invalid record");
@@ -2938,7 +2975,7 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
// v1: [type, callingconv, isproto, linkage, paramattr, alignment, section,
// visibility, gc, unnamed_addr, prologuedata, dllstorageclass, comdat,
- // prefixdata, personalityfn, preemption specifier] (name in VST)
+ // prefixdata, personalityfn, preemption specifier, addrspace] (name in VST)
// v2: [strtab_offset, strtab_size, v1]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(Record);
@@ -2957,8 +2994,12 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
if (CC & ~CallingConv::MaxID)
return error("Invalid calling convention ID");
- Function *Func =
- Function::Create(FTy, GlobalValue::ExternalLinkage, Name, TheModule);
+ unsigned AddrSpace = TheModule->getDataLayout().getProgramAddressSpace();
+ if (Record.size() > 16)
+ AddrSpace = Record[16];
+
+ Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
+ AddrSpace, Name, TheModule);
Func->setCallingConv(CC);
bool isProto = Record[2];
@@ -3508,24 +3549,47 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
unsigned Line = Record[0], Col = Record[1];
unsigned ScopeID = Record[2], IAID = Record[3];
+ bool isImplicitCode = Record.size() == 5 && Record[4];
MDNode *Scope = nullptr, *IA = nullptr;
if (ScopeID) {
- Scope = MDLoader->getMDNodeFwdRefOrNull(ScopeID - 1);
+ Scope = dyn_cast_or_null<MDNode>(
+ MDLoader->getMetadataFwdRefOrLoad(ScopeID - 1));
if (!Scope)
return error("Invalid record");
}
if (IAID) {
- IA = MDLoader->getMDNodeFwdRefOrNull(IAID - 1);
+ IA = dyn_cast_or_null<MDNode>(
+ MDLoader->getMetadataFwdRefOrLoad(IAID - 1));
if (!IA)
return error("Invalid record");
}
- LastLoc = DebugLoc::get(Line, Col, Scope, IA);
+ LastLoc = DebugLoc::get(Line, Col, Scope, IA, isImplicitCode);
I->setDebugLoc(LastLoc);
I = nullptr;
continue;
}
+ case bitc::FUNC_CODE_INST_UNOP: { // UNOP: [opval, ty, opcode]
+ unsigned OpNum = 0;
+ Value *LHS;
+ if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
+ OpNum+1 > Record.size())
+ return error("Invalid record");
+ int Opc = getDecodedUnaryOpcode(Record[OpNum++], LHS->getType());
+ if (Opc == -1)
+ return error("Invalid record");
+ I = UnaryOperator::Create((Instruction::UnaryOps)Opc, LHS);
+ InstructionList.push_back(I);
+ if (OpNum < Record.size()) {
+ if (isa<FPMathOperator>(I)) {
+ FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]);
+ if (FMF.any())
+ I->setFastMathFlags(FMF);
+ }
+ }
+ break;
+ }
case bitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode]
unsigned OpNum = 0;
Value *LHS, *RHS;
@@ -3656,16 +3720,16 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
return error("EXTRACTVAL: Invalid type");
if ((unsigned)Index != Index)
return error("Invalid value");
- if (IsStruct && Index >= CurTy->subtypes().size())
+ if (IsStruct && Index >= CurTy->getStructNumElements())
return error("EXTRACTVAL: Invalid struct index");
if (IsArray && Index >= CurTy->getArrayNumElements())
return error("EXTRACTVAL: Invalid array index");
EXTRACTVALIdx.push_back((unsigned)Index);
if (IsStruct)
- CurTy = CurTy->subtypes()[Index];
+ CurTy = CurTy->getStructElementType(Index);
else
- CurTy = CurTy->subtypes()[0];
+ CurTy = CurTy->getArrayElementType();
}
I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
@@ -3698,16 +3762,16 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
return error("INSERTVAL: Invalid type");
if ((unsigned)Index != Index)
return error("Invalid value");
- if (IsStruct && Index >= CurTy->subtypes().size())
+ if (IsStruct && Index >= CurTy->getStructNumElements())
return error("INSERTVAL: Invalid struct index");
if (IsArray && Index >= CurTy->getArrayNumElements())
return error("INSERTVAL: Invalid array index");
INSERTVALIdx.push_back((unsigned)Index);
if (IsStruct)
- CurTy = CurTy->subtypes()[Index];
+ CurTy = CurTy->getStructElementType(Index);
else
- CurTy = CurTy->subtypes()[0];
+ CurTy = CurTy->getArrayElementType();
}
if (CurTy != Val->getType())
@@ -4616,7 +4680,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
CurBB->getInstList().push_back(I);
// If this was a terminator instruction, move to the next block.
- if (isa<TerminatorInst>(I)) {
+ if (I->isTerminator()) {
++CurBBNo;
CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : nullptr;
}
@@ -4854,7 +4918,7 @@ void ModuleSummaryIndexBitcodeReader::setValueGUID(
ValueIdToValueInfoMap[ValueID] = std::make_pair(
TheIndex.getOrInsertValueInfo(
ValueGUID,
- UseStrtab ? ValueName : TheIndex.saveString(ValueName.str())),
+ UseStrtab ? ValueName : TheIndex.saveString(ValueName)),
OriginalNameID);
}
@@ -5160,6 +5224,12 @@ static void parseTypeIdSummaryRecord(ArrayRef<uint64_t> Record,
parseWholeProgramDevirtResolution(Record, Strtab, Slot, TypeId);
}
+static void setImmutableRefs(std::vector<ValueInfo> &Refs, unsigned Count) {
+ // Read-only refs are in the end of the refs list.
+ for (unsigned RefNo = Refs.size() - Count; RefNo < Refs.size(); ++RefNo)
+ Refs[RefNo].setReadOnly();
+}
+
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
@@ -5177,9 +5247,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
}
const uint64_t Version = Record[0];
const bool IsOldProfileFormat = Version == 1;
- if (Version < 1 || Version > 4)
+ if (Version < 1 || Version > 6)
return error("Invalid summary version " + Twine(Version) +
- ", 1, 2, 3 or 4 expected");
+ ". Version should be in the range [1-6].");
Record.clear();
// Keep around the last seen summary to be used when we see an optional
@@ -5224,15 +5294,30 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
break;
case bitc::FS_FLAGS: { // [flags]
uint64_t Flags = Record[0];
- // Scan flags (set only on the combined index).
- assert(Flags <= 0x3 && "Unexpected bits in flag");
+ // Scan flags.
+ assert(Flags <= 0x1f && "Unexpected bits in flag");
// 1 bit: WithGlobalValueDeadStripping flag.
+ // Set on combined index only.
if (Flags & 0x1)
TheIndex.setWithGlobalValueDeadStripping();
// 1 bit: SkipModuleByDistributedBackend flag.
+ // Set on combined index only.
if (Flags & 0x2)
TheIndex.setSkipModuleByDistributedBackend();
+ // 1 bit: HasSyntheticEntryCounts flag.
+ // Set on combined index only.
+ if (Flags & 0x4)
+ TheIndex.setHasSyntheticEntryCounts();
+ // 1 bit: DisableSplitLTOUnit flag.
+ // Set on per module indexes. It is up to the client to validate
+ // the consistency of this flag across modules being linked.
+ if (Flags & 0x8)
+ TheIndex.setEnableSplitLTOUnit();
+ // 1 bit: PartiallySplitLTOUnits flag.
+ // Set on combined index only.
+ if (Flags & 0x10)
+ TheIndex.setPartiallySplitLTOUnits();
break;
}
case bitc::FS_VALUE_GUID: { // [valueid, refguid]
@@ -5258,11 +5343,16 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
unsigned InstCount = Record[2];
uint64_t RawFunFlags = 0;
unsigned NumRefs = Record[3];
+ unsigned NumImmutableRefs = 0;
int RefListStartIndex = 4;
if (Version >= 4) {
RawFunFlags = Record[3];
NumRefs = Record[4];
RefListStartIndex = 5;
+ if (Version >= 5) {
+ NumImmutableRefs = Record[5];
+ RefListStartIndex = 6;
+ }
}
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
@@ -5281,9 +5371,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
std::vector<FunctionSummary::EdgeTy> Calls = makeCallList(
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile, HasRelBF);
+ setImmutableRefs(Refs, NumImmutableRefs);
auto FS = llvm::make_unique<FunctionSummary>(
- Flags, InstCount, getDecodedFFlags(RawFunFlags), std::move(Refs),
- std::move(Calls), std::move(PendingTypeTests),
+ Flags, InstCount, getDecodedFFlags(RawFunFlags), /*EntryCount=*/0,
+ std::move(Refs), std::move(Calls), std::move(PendingTypeTests),
std::move(PendingTypeTestAssumeVCalls),
std::move(PendingTypeCheckedLoadVCalls),
std::move(PendingTypeTestAssumeConstVCalls),
@@ -5329,14 +5420,21 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
TheIndex.addGlobalValueSummary(GUID.first, std::move(AS));
break;
}
- // FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, flags, n x valueid]
+ // FS_PERMODULE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags, n x valueid]
case bitc::FS_PERMODULE_GLOBALVAR_INIT_REFS: {
unsigned ValueID = Record[0];
uint64_t RawFlags = Record[1];
+ unsigned RefArrayStart = 2;
+ GlobalVarSummary::GVarFlags GVF;
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
+ if (Version >= 5) {
+ GVF = getDecodedGVarFlags(Record[2]);
+ RefArrayStart = 3;
+ }
std::vector<ValueInfo> Refs =
- makeRefList(ArrayRef<uint64_t>(Record).slice(2));
- auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
+ makeRefList(ArrayRef<uint64_t>(Record).slice(RefArrayStart));
+ auto FS =
+ llvm::make_unique<GlobalVarSummary>(Flags, GVF, std::move(Refs));
FS->setModulePath(getThisModule()->first());
auto GUID = getValueInfoFromValueId(ValueID);
FS->setOriginalName(GUID.second);
@@ -5354,13 +5452,25 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
uint64_t RawFlags = Record[2];
unsigned InstCount = Record[3];
uint64_t RawFunFlags = 0;
+ uint64_t EntryCount = 0;
unsigned NumRefs = Record[4];
+ unsigned NumImmutableRefs = 0;
int RefListStartIndex = 5;
if (Version >= 4) {
RawFunFlags = Record[4];
- NumRefs = Record[5];
RefListStartIndex = 6;
+ size_t NumRefsIndex = 5;
+ if (Version >= 5) {
+ RefListStartIndex = 7;
+ if (Version >= 6) {
+ NumRefsIndex = 6;
+ EntryCount = Record[5];
+ RefListStartIndex = 8;
+ }
+ NumImmutableRefs = Record[RefListStartIndex - 1];
+ }
+ NumRefs = Record[NumRefsIndex];
}
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
@@ -5374,9 +5484,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile, false);
ValueInfo VI = getValueInfoFromValueId(ValueID).first;
+ setImmutableRefs(Refs, NumImmutableRefs);
auto FS = llvm::make_unique<FunctionSummary>(
- Flags, InstCount, getDecodedFFlags(RawFunFlags), std::move(Refs),
- std::move(Edges), std::move(PendingTypeTests),
+ Flags, InstCount, getDecodedFFlags(RawFunFlags), EntryCount,
+ std::move(Refs), std::move(Edges), std::move(PendingTypeTests),
std::move(PendingTypeTestAssumeVCalls),
std::move(PendingTypeCheckedLoadVCalls),
std::move(PendingTypeTestAssumeConstVCalls),
@@ -5422,10 +5533,17 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
unsigned ValueID = Record[0];
uint64_t ModuleId = Record[1];
uint64_t RawFlags = Record[2];
+ unsigned RefArrayStart = 3;
+ GlobalVarSummary::GVarFlags GVF;
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
+ if (Version >= 5) {
+ GVF = getDecodedGVarFlags(Record[3]);
+ RefArrayStart = 4;
+ }
std::vector<ValueInfo> Refs =
- makeRefList(ArrayRef<uint64_t>(Record).slice(3));
- auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
+ makeRefList(ArrayRef<uint64_t>(Record).slice(RefArrayStart));
+ auto FS =
+ llvm::make_unique<GlobalVarSummary>(Flags, GVF, std::move(Refs));
LastSeenSummary = FS.get();
FS->setModulePath(ModuleIdMap[ModuleId]);
ValueInfo VI = getValueInfoFromValueId(ValueID).first;
@@ -5811,6 +5929,46 @@ Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
return std::move(Index);
}
+static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
+ unsigned ID) {
+ if (Stream.EnterSubBlock(ID))
+ return error("Invalid record");
+ SmallVector<uint64_t, 64> Record;
+
+ while (true) {
+ BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ // If no flags record found, conservatively return true to mimic
+ // behavior before this flag was added.
+ return true;
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Look for the FS_FLAGS record.
+ Record.clear();
+ auto BitCode = Stream.readRecord(Entry.ID, Record);
+ switch (BitCode) {
+ default: // Default behavior: ignore.
+ break;
+ case bitc::FS_FLAGS: { // [flags]
+ uint64_t Flags = Record[0];
+ // Scan flags.
+ assert(Flags <= 0x1f && "Unexpected bits in flag");
+
+ return Flags & 0x8;
+ }
+ }
+ }
+ llvm_unreachable("Exit infinite loop");
+}
+
// Check if the given bitcode buffer contains a global value summary block.
Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
BitstreamCursor Stream(Buffer);
@@ -5826,14 +5984,27 @@ Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::EndBlock:
- return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/false};
+ return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/false,
+ /*EnableSplitLTOUnit=*/false};
case BitstreamEntry::SubBlock:
- if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID)
- return BitcodeLTOInfo{/*IsThinLTO=*/true, /*HasSummary=*/true};
+ if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID) {
+ Expected<bool> EnableSplitLTOUnit =
+ getEnableSplitLTOUnitFlag(Stream, Entry.ID);
+ if (!EnableSplitLTOUnit)
+ return EnableSplitLTOUnit.takeError();
+ return BitcodeLTOInfo{/*IsThinLTO=*/true, /*HasSummary=*/true,
+ *EnableSplitLTOUnit};
+ }
- if (Entry.ID == bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID)
- return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/true};
+ if (Entry.ID == bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID) {
+ Expected<bool> EnableSplitLTOUnit =
+ getEnableSplitLTOUnitFlag(Stream, Entry.ID);
+ if (!EnableSplitLTOUnit)
+ return EnableSplitLTOUnit.takeError();
+ return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/true,
+ *EnableSplitLTOUnit};
+ }
// Ignore other sub-blocks.
if (Stream.SkipBlock())