std::unique_ptr<MemoryBuffer> Buffer;
std::unique_ptr<BitstreamReader> StreamFile;
BitstreamCursor Stream;
+ // Next offset to start scanning for lazy parsing of function bodies.
uint64_t NextUnreadBit = 0;
+ // Last function offset found in the VST.
+ uint64_t LastFunctionBlockBit = 0;
bool SeenValueSymbolTable = false;
- unsigned VSTOffset = 0;
+ uint64_t VSTOffset = 0;
+ // Contains an arbitrary and optional string identifying the bitcode producer
+ std::string ProducerIdentification;
+ // Number of module level metadata records specified by the
+ // MODULE_CODE_METADATA_VALUES record.
+ unsigned NumModuleMDs = 0;
+ // Support older bitcode without the MODULE_CODE_METADATA_VALUES record.
+ bool SeenModuleValuesRecord = false;
std::vector<Type*> TypeList;
BitcodeReaderValueList ValueList;
bool StripDebugInfo = false;
+ /// Functions that need to be matched with subprograms when upgrading old
+ /// metadata.
+ SmallDenseMap<Function *, DISubprogram *, 16> FunctionsWithSPs;
+
std::vector<std::string> BundleTags;
public:
/// \returns true if an error occurred.
ErrorOr<std::string> parseTriple();
+ /// Cheap mechanism to just extract the identification block out of bitcode.
+ ErrorOr<std::string> parseIdentificationBlock();
+
static uint64_t decodeSignRotatedValue(uint64_t V);
/// Materialize any deferred Metadata block.
void setStripDebugInfo() override;
private:
+ /// Parse the "IDENTIFICATION_BLOCK_ID" block, populate the
+ // ProducerIdentification data member, and do some basic enforcement on the
+ // "epoch" encoded in the bitcode.
+ std::error_code parseBitcodeVersion();
+
std::vector<StructType *> IdentifiedStructTypes;
StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
StructType *createIdentifiedStructType(LLVMContext &Context);
/// a corresponding error code.
std::error_code parseAlignmentValue(uint64_t Exponent, unsigned &Alignment);
std::error_code parseAttrKind(uint64_t Code, Attribute::AttrKind *Kind);
- std::error_code parseModule(bool Resume, bool ShouldLazyLoadMetadata = false);
+ std::error_code parseModule(uint64_t ResumeBit,
+ bool ShouldLazyLoadMetadata = false);
std::error_code parseAttributeBlock();
std::error_code parseAttributeGroupBlock();
std::error_code parseTypeTable();
ErrorOr<Value *> recordValue(SmallVectorImpl<uint64_t> &Record,
unsigned NameIndex, Triple &TT);
- std::error_code parseValueSymbolTable(unsigned Offset = 0);
+ std::error_code parseValueSymbolTable(uint64_t Offset = 0);
std::error_code parseConstants();
+ std::error_code rememberAndSkipFunctionBodies();
std::error_code rememberAndSkipFunctionBody();
/// Save the positions of the Metadata blocks and skip parsing the blocks.
std::error_code rememberAndSkipMetadata();
std::error_code parseFunctionBody(Function *F);
std::error_code globalCleanup();
std::error_code resolveGlobalAndAliasInits();
- std::error_code parseMetadata();
+ std::error_code parseMetadata(bool ModuleLevel = false);
+ std::error_code parseMetadataKinds();
+ std::error_code parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
std::error_code parseMetadataAttachment(Function &F);
ErrorOr<std::string> parseModuleTriple();
std::error_code parseUseLists();
/// summary records.
DenseMap<uint64_t, StringRef> ModuleIdMap;
- public:
+public:
std::error_code error(BitcodeError E, const Twine &Message);
std::error_code error(BitcodeError E);
std::error_code error(const Twine &Message);
- FunctionIndexBitcodeReader(MemoryBuffer *Buffer, LLVMContext &Context,
+ FunctionIndexBitcodeReader(MemoryBuffer *Buffer,
DiagnosticHandlerFunction DiagnosticHandler,
bool IsLazy = false,
bool CheckFuncSummaryPresenceOnly = false);
- FunctionIndexBitcodeReader(LLVMContext &Context,
- DiagnosticHandlerFunction DiagnosticHandler,
+ FunctionIndexBitcodeReader(DiagnosticHandlerFunction DiagnosticHandler,
bool IsLazy = false,
bool CheckFuncSummaryPresenceOnly = false);
~FunctionIndexBitcodeReader() { freeState(); }
FunctionInfoIndex *I,
size_t FunctionSummaryOffset);
- private:
+private:
std::error_code parseModule();
std::error_code parseValueSymbolTable();
std::error_code parseEntireSummary();
}
std::error_code BitcodeReader::error(BitcodeError E, const Twine &Message) {
+ if (!ProducerIdentification.empty()) {
+ return ::error(DiagnosticHandler, make_error_code(E),
+ Message + " (Producer: '" + ProducerIdentification +
+ "' Reader: 'LLVM " + LLVM_VERSION_STRING "')");
+ }
return ::error(DiagnosticHandler, make_error_code(E), Message);
}
std::error_code BitcodeReader::error(const Twine &Message) {
+ if (!ProducerIdentification.empty()) {
+ return ::error(DiagnosticHandler,
+ make_error_code(BitcodeError::CorruptedBitcode),
+ Message + " (Producer: '" + ProducerIdentification +
+ "' Reader: 'LLVM " + LLVM_VERSION_STRING "')");
+ }
return ::error(DiagnosticHandler,
make_error_code(BitcodeError::CorruptedBitcode), Message);
}
return Attribute::NoImplicitFloat;
case bitc::ATTR_KIND_NO_INLINE:
return Attribute::NoInline;
+ case bitc::ATTR_KIND_NO_RECURSE:
+ return Attribute::NoRecurse;
case bitc::ATTR_KIND_NON_LAZY_BIND:
return Attribute::NonLazyBind;
case bitc::ATTR_KIND_NON_NULL:
return error("Invalid record");
Value *V = ValueList[ValueID];
- V->setName(StringRef(ValueName.data(), ValueName.size()));
+ StringRef NameStr(ValueName.data(), ValueName.size());
+ if (NameStr.find_first_of(0) != StringRef::npos)
+ return error("Invalid value name");
+ V->setName(NameStr);
auto *GO = dyn_cast<GlobalObject>(V);
if (GO) {
if (GO->getComdat() == reinterpret_cast<Comdat *>(1)) {
/// Parse the value symbol table at either the current parsing location or
/// at the given bit offset if provided.
-std::error_code BitcodeReader::parseValueSymbolTable(unsigned Offset) {
+std::error_code BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
uint64_t CurrentBit;
// 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
assert(F);
uint64_t FuncBitOffset = FuncWordOffset * 32;
DeferredFunctionInfo[F] = FuncBitOffset + FuncBitcodeOffsetDelta;
- // Set the NextUnreadBit to point to the last function block.
+ // 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 > NextUnreadBit)
- NextUnreadBit = FuncBitOffset;
+ if (FuncBitOffset > LastFunctionBlockBit)
+ LastFunctionBlockBit = FuncBitOffset;
break;
}
case bitc::VST_CODE_BBENTRY: {
}
}
+/// Parse a single METADATA_KIND record, inserting result in MDKindMap.
+std::error_code
+BitcodeReader::parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record) {
+ if (Record.size() < 2)
+ return error("Invalid record");
+
+ unsigned Kind = Record[0];
+ SmallString<8> Name(Record.begin() + 1, Record.end());
+
+ unsigned NewKind = TheModule->getMDKindID(Name.str());
+ if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
+ return error("Conflicting METADATA_KIND records");
+ return std::error_code();
+}
+
static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >> 1; }
-std::error_code BitcodeReader::parseMetadata() {
+/// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
+/// module level metadata.
+std::error_code BitcodeReader::parseMetadata(bool ModuleLevel) {
IsMetadataMaterialized = true;
unsigned NextMDValueNo = MDValueList.size();
+ if (ModuleLevel && SeenModuleValuesRecord) {
+ // Now that we are parsing the module level metadata, we want to restart
+ // the numbering of the MD values, and replace temp MD created earlier
+ // with their real values. If we saw a METADATA_VALUE record then we
+ // would have set the MDValueList size to the number specified in that
+ // record, to support parsing function-level metadata first, and we need
+ // to reset back to 0 to fill the MDValueList in with the parsed module
+ // The function-level metadata parsing should have reset the MDValueList
+ // size back to the value reported by the METADATA_VALUE record, saved in
+ // NumModuleMDs.
+ assert(NumModuleMDs == MDValueList.size() &&
+ "Expected MDValueList to only contain module level values");
+ NextMDValueNo = 0;
+ }
if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
return error("Invalid record");
return error("Malformed block");
case BitstreamEntry::EndBlock:
MDValueList.tryToResolveCycles();
+ assert((!(ModuleLevel && SeenModuleValuesRecord) ||
+ NumModuleMDs == MDValueList.size()) &&
+ "Inconsistent bitcode: METADATA_VALUES mismatch");
return std::error_code();
case BitstreamEntry::Record:
// The interesting case.
break;
}
case bitc::METADATA_SUBPROGRAM: {
- if (Record.size() != 19)
- return error("Invalid record");
-
- MDValueList.assignValue(
- GET_OR_DISTINCT(
- DISubprogram,
- Record[0] || Record[8], // All definitions should be distinct.
- (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
- getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
- getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
- getMDOrNull(Record[10]), Record[11], Record[12], Record[13],
- Record[14], getMDOrNull(Record[15]), getMDOrNull(Record[16]),
- getMDOrNull(Record[17]), getMDOrNull(Record[18]))),
- NextMDValueNo++);
+ if (Record.size() != 18 && Record.size() != 19)
+ return error("Invalid record");
+
+ bool HasFn = Record.size() == 19;
+ DISubprogram *SP = GET_OR_DISTINCT(
+ DISubprogram,
+ Record[0] || Record[8], // All definitions should be distinct.
+ (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
+ getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
+ getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
+ getMDOrNull(Record[10]), Record[11], Record[12], Record[13],
+ Record[14], getMDOrNull(Record[15 + HasFn]),
+ getMDOrNull(Record[16 + HasFn]), getMDOrNull(Record[17 + HasFn])));
+ MDValueList.assignValue(SP, NextMDValueNo++);
+
+ // Upgrade sp->function mapping to function->sp mapping.
+ if (HasFn && Record[15]) {
+ if (auto *CMD = dyn_cast<ConstantAsMetadata>(getMDOrNull(Record[15])))
+ if (auto *F = dyn_cast<Function>(CMD->getValue())) {
+ if (F->isMaterializable())
+ // Defer until materialized; unmaterialized functions may not have
+ // metadata.
+ FunctionsWithSPs[F] = SP;
+ else if (!F->empty())
+ F->setSubprogram(SP);
+ }
+ }
break;
}
case bitc::METADATA_LEXICAL_BLOCK: {
break;
}
case bitc::METADATA_KIND: {
- if (Record.size() < 2)
- return error("Invalid record");
+ // Support older bitcode files that had METADATA_KIND records in a
+ // block with METADATA_BLOCK_ID.
+ if (std::error_code EC = parseMetadataKindRecord(Record))
+ return EC;
+ break;
+ }
+ }
+ }
+#undef GET_OR_DISTINCT
+}
- unsigned Kind = Record[0];
- SmallString<8> Name(Record.begin()+1, Record.end());
+/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
+std::error_code BitcodeReader::parseMetadataKinds() {
+ if (Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
+ return error("Invalid record");
- unsigned NewKind = TheModule->getMDKindID(Name.str());
- if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
- return error("Conflicting METADATA_KIND records");
+ SmallVector<uint64_t, 64> Record;
+
+ // Read all the records.
+ while (1) {
+ BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ unsigned Code = Stream.readRecord(Entry.ID, Record);
+ switch (Code) {
+ default: // Default behavior: ignore.
+ break;
+ case bitc::METADATA_KIND: {
+ if (std::error_code EC = parseMetadataKindRecord(Record))
+ return EC;
break;
}
}
}
-#undef GET_OR_DISTINCT
}
/// Decode a signed value stored with the sign bit in the LSB for dense VBR
return error("Invalid ID");
++BBI;
}
- BB = BBI;
+ BB = &*BBI;
} else {
// Otherwise insert a placeholder and remember it so it can be inserted
// when the function is parsed.
for (uint64_t BitPos : DeferredMetadataInfo) {
// Move the bit stream to the saved position.
Stream.JumpToBit(BitPos);
- if (std::error_code EC = parseMetadata())
+ if (std::error_code EC = parseMetadata(true))
return EC;
}
DeferredMetadataInfo.clear();
// Save the current stream state.
uint64_t CurBit = Stream.GetCurrentBitNo();
+ assert(
+ (DeferredFunctionInfo[Fn] == 0 || DeferredFunctionInfo[Fn] == CurBit) &&
+ "Mismatch between VST and scanned function offsets");
DeferredFunctionInfo[Fn] = CurBit;
// Skip over the function block for now.
return std::error_code();
}
-std::error_code BitcodeReader::parseModule(bool Resume,
+/// Support for lazy parsing of function bodies. This is required if we
+/// either have an old bitcode file without a VST forward declaration record,
+/// or if we have an anonymous function being materialized, since anonymous
+/// functions do not have a name and are therefore not in the VST.
+std::error_code BitcodeReader::rememberAndSkipFunctionBodies() {
+ Stream.JumpToBit(NextUnreadBit);
+
+ if (Stream.AtEndOfStream())
+ return error("Could not find function in stream");
+
+ if (!SeenFirstFunctionBody)
+ return error("Trying to materialize functions before seeing function blocks");
+
+ // An old bitcode file with the symbol table at the end would have
+ // finished the parse greedily.
+ assert(SeenValueSymbolTable);
+
+ SmallVector<uint64_t, 64> Record;
+
+ while (1) {
+ BitstreamEntry Entry = Stream.advance();
+ switch (Entry.Kind) {
+ default:
+ return error("Expect SubBlock");
+ case BitstreamEntry::SubBlock:
+ switch (Entry.ID) {
+ default:
+ return error("Expect function block");
+ case bitc::FUNCTION_BLOCK_ID:
+ if (std::error_code EC = rememberAndSkipFunctionBody())
+ return EC;
+ NextUnreadBit = Stream.GetCurrentBitNo();
+ return std::error_code();
+ }
+ }
+ }
+}
+
+std::error_code BitcodeReader::parseBitcodeVersion() {
+ if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID))
+ return error("Invalid record");
+
+ // Read all the records.
+ SmallVector<uint64_t, 64> Record;
+ while (1) {
+ BitstreamEntry Entry = Stream.advance();
+
+ switch (Entry.Kind) {
+ default:
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ // Read a record.
+ Record.clear();
+ unsigned BitCode = Stream.readRecord(Entry.ID, Record);
+ switch (BitCode) {
+ default: // Default behavior: reject
+ return error("Invalid value");
+ case bitc::IDENTIFICATION_CODE_STRING: { // IDENTIFICATION: [strchr x
+ // N]
+ convertToString(Record, 0, ProducerIdentification);
+ break;
+ }
+ case bitc::IDENTIFICATION_CODE_EPOCH: { // EPOCH: [epoch#]
+ unsigned epoch = (unsigned)Record[0];
+ if (epoch != bitc::BITCODE_CURRENT_EPOCH) {
+ return error(
+ Twine("Incompatible epoch: Bitcode '") + Twine(epoch) +
+ "' vs current: '" + Twine(bitc::BITCODE_CURRENT_EPOCH) + "'");
+ }
+ }
+ }
+ }
+}
+
+std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
bool ShouldLazyLoadMetadata) {
- if (Resume)
- Stream.JumpToBit(NextUnreadBit);
+ if (ResumeBit)
+ Stream.JumpToBit(ResumeBit);
else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
return error("Invalid record");
break;
}
assert(DeferredMetadataInfo.empty() && "Unexpected deferred metadata");
- if (std::error_code EC = parseMetadata())
+ if (std::error_code EC = parseMetadata(true))
+ return EC;
+ break;
+ case bitc::METADATA_KIND_BLOCK_ID:
+ if (std::error_code EC = parseMetadataKinds())
return EC;
break;
case bitc::FUNCTION_BLOCK_ID:
BitcodeReader::parseValueSymbolTable(VSTOffset))
return EC;
SeenValueSymbolTable = true;
- return std::error_code();
+ // Fall through so that we record the NextUnreadBit below.
+ // This is necessary in case we have an anonymous function that
+ // is later materialized. Since it will not have a VST entry we
+ // need to fall back to the lazy parse to find its offset.
} else {
// If we have a VST forward declaration record, but have already
// parsed the VST (just above, when the first function body was
// encountered here), then we are resuming the parse after
- // materializing functions. The NextUnreadBit points to the start
- // of the last function block recorded in the VST (set when
- // parsing the VST function entries). Skip it.
+ // materializing functions. The ResumeBit points to the
+ // start of the last function block recorded in the
+ // DeferredFunctionInfo map. Skip it.
if (Stream.SkipBlock())
return error("Invalid record");
continue;
}
// Support older bitcode files that did not have the function
- // index in the VST, nor a VST forward declaration record.
+ // index in the VST, nor a VST forward declaration record, as
+ // well as anonymous functions that do not have VST entries.
// Build the DeferredFunctionInfo vector on the fly.
if (std::error_code EC = rememberAndSkipFunctionBody())
return EC;
+
// Suspend parsing when we reach the function bodies. Subsequent
// materialization calls will resume it when necessary. If the bitcode
// file is old, the symbol table will be at the end instead and will not
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(static_cast<CallingConv::ID>(Record[1]));
+ Func->setCallingConv(CC);
bool isProto = Record[2];
uint64_t RawLinkage = Record[3];
Func->setLinkage(getDecodedLinkage(RawLinkage));
return error("Invalid record");
VSTOffset = Record[0];
break;
+ /// MODULE_CODE_METADATA_VALUES: [numvals]
+ case bitc::MODULE_CODE_METADATA_VALUES:
+ if (Record.size() < 1)
+ return error("Invalid record");
+ assert(!IsMetadataMaterialized);
+ // This record contains the number of metadata values in the module-level
+ // METADATA_BLOCK. It is used to support lazy parsing of metadata as
+ // a postpass, where we will parse function-level metadata first.
+ // This is needed because the ids of metadata are assigned implicitly
+ // based on their ordering in the bitcode, with the function-level
+ // metadata ids starting after the module-level metadata ids. Otherwise,
+ // we would have to parse the module-level metadata block to prime the
+ // MDValueList when we are lazy loading metadata during function
+ // importing. Initialize the MDValueList size here based on the
+ // record value, regardless of whether we are doing lazy metadata
+ // loading, so that we have consistent handling and assertion
+ // checking in parseMetadata for module-level metadata.
+ NumModuleMDs = Record[0];
+ SeenModuleValuesRecord = true;
+ assert(MDValueList.size() == 0);
+ MDValueList.resize(NumModuleMDs);
+ break;
}
Record.clear();
}
return EC;
// Sniff for the signature.
- if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");
+ if (!hasValidBitcodeHeader(Stream))
+ return error("Invalid bitcode signature");
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
if (Entry.Kind != BitstreamEntry::SubBlock)
return error("Malformed block");
+ if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) {
+ parseBitcodeVersion();
+ continue;
+ }
+
if (Entry.ID == bitc::MODULE_BLOCK_ID)
- return parseModule(false, ShouldLazyLoadMetadata);
+ return parseModule(0, ShouldLazyLoadMetadata);
if (Stream.SkipBlock())
return error("Invalid record");
return EC;
// Sniff for the signature.
- if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");
+ if (!hasValidBitcodeHeader(Stream))
+ return error("Invalid bitcode signature");
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
}
}
+ErrorOr<std::string> BitcodeReader::parseIdentificationBlock() {
+ if (std::error_code EC = initStream(nullptr))
+ return EC;
+
+ // Sniff for the signature.
+ if (!hasValidBitcodeHeader(Stream))
+ return error("Invalid bitcode signature");
+
+ // We expect a number of well-defined blocks, though we don't necessarily
+ // need to understand them all.
+ while (1) {
+ BitstreamEntry Entry = Stream.advance();
+ switch (Entry.Kind) {
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+
+ case BitstreamEntry::SubBlock:
+ if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) {
+ if (std::error_code EC = parseBitcodeVersion())
+ return EC;
+ return ProducerIdentification;
+ }
+ // Ignore other sub-blocks.
+ if (Stream.SkipBlock())
+ return error("Malformed block");
+ continue;
+ case BitstreamEntry::Record:
+ Stream.skipRecord(Entry.ID);
+ continue;
+ }
+ }
+}
+
/// Parse metadata attachments.
std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
unsigned ModuleMDValueListSize = MDValueList.size();
// Add all the function arguments to the value table.
- for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
- ValueList.push_back(I);
+ for (Argument &I : F->args())
+ ValueList.push_back(&I);
unsigned NextValueNo = ValueList.size();
BasicBlock *CurBB = nullptr;
I = InvokeInst::Create(Callee, NormalBB, UnwindBB, Ops, OperandBundles);
OperandBundles.clear();
InstructionList.push_back(I);
- cast<InvokeInst>(I)
- ->setCallingConv(static_cast<CallingConv::ID>(~(1U << 13) & CCInfo));
+ cast<InvokeInst>(I)->setCallingConv(
+ static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));
cast<InvokeInst>(I)->setAttributes(PAL);
break;
}
unsigned CCInfo = Record[OpNum++];
FunctionType *FTy = nullptr;
- if (CCInfo >> 15 & 1 &&
+ if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 &&
!(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]))))
return error("Explicit call type is not a function type");
OperandBundles.clear();
InstructionList.push_back(I);
cast<CallInst>(I)->setCallingConv(
- static_cast<CallingConv::ID>((~(1U << 14) & CCInfo) >> 1));
+ static_cast<CallingConv::ID>((0x7ff & CCInfo) >> bitc::CALL_CCONV));
CallInst::TailCallKind TCK = CallInst::TCK_None;
- if (CCInfo & 1)
+ if (CCInfo & 1 << bitc::CALL_TAIL)
TCK = CallInst::TCK_Tail;
- if (CCInfo & (1 << 14))
+ if (CCInfo & (1 << bitc::CALL_MUSTTAIL))
TCK = CallInst::TCK_MustTail;
+ if (CCInfo & (1 << bitc::CALL_NOTAIL))
+ TCK = CallInst::TCK_NoTail;
cast<CallInst>(I)->setTailCallKind(TCK);
cast<CallInst>(I)->setAttributes(PAL);
break;
if (Record.size() < 1 || Record[0] >= BundleTags.size())
return error("Invalid record");
- OperandBundles.emplace_back();
- OperandBundles.back().Tag = BundleTags[Record[0]];
-
- std::vector<Value *> &Inputs = OperandBundles.back().Inputs;
+ std::vector<Value *> Inputs;
unsigned OpNum = 1;
while (OpNum != Record.size()) {
Inputs.push_back(Op);
}
+ OperandBundles.emplace_back(BundleTags[Record[0]], std::move(Inputs));
continue;
}
}
DenseMap<Function *, uint64_t>::iterator DeferredFunctionInfoIterator) {
while (DeferredFunctionInfoIterator->second == 0) {
// This is the fallback handling for the old format bitcode that
- // didn't contain the function index in the VST. Assert if we end up
- // here for the new format (which is the only time the VSTOffset would
- // be non-zero).
- assert(VSTOffset == 0);
- if (Stream.AtEndOfStream())
- return error("Could not find function in stream");
- // ParseModule will parse the next body in the stream and set its
- // position in the DeferredFunctionInfo map.
- if (std::error_code EC = parseModule(true))
+ // didn't contain the function index in the VST, or when we have
+ // an anonymous function which would not have a VST entry.
+ // Assert that we have one of those two cases.
+ assert(VSTOffset == 0 || !F->hasName());
+ // Parse the next body in the stream and set its position in the
+ // DeferredFunctionInfo map.
+ if (std::error_code EC = rememberAndSkipFunctionBodies())
return EC;
}
return std::error_code();
void BitcodeReader::releaseBuffer() { Buffer.release(); }
std::error_code BitcodeReader::materialize(GlobalValue *GV) {
- if (std::error_code EC = materializeMetadata())
- return EC;
+ // In older bitcode we must materialize the metadata before parsing
+ // any functions, in order to set up the MDValueList properly.
+ if (!SeenModuleValuesRecord) {
+ if (std::error_code EC = materializeMetadata())
+ return EC;
+ }
Function *F = dyn_cast<Function>(GV);
// If it's not a function or is already material, ignore the request.
}
}
+ // Finish fn->subprogram upgrade for materialized functions.
+ if (DISubprogram *SP = FunctionsWithSPs.lookup(F))
+ F->setSubprogram(SP);
+
// Bring in any functions that this function forward-referenced via
// blockaddresses.
return materializeForwardReferencedFunctions();
// Iterate over the module, deserializing any functions that are still on
// disk.
- for (Module::iterator F = TheModule->begin(), E = TheModule->end();
- F != E; ++F) {
- if (std::error_code EC = materialize(F))
+ for (Function &F : *TheModule) {
+ if (std::error_code EC = materialize(&F))
return EC;
}
- // At this point, if there are any function bodies, the current bit is
- // pointing to the END_BLOCK record after them. Now make sure the rest
- // of the bits in the module have been read.
- if (NextUnreadBit)
- parseModule(true);
+ // At this point, if there are any function bodies, parse the rest of
+ // the bits in the module past the last function block we have recorded
+ // through either lazy scanning or the VST.
+ if (LastFunctionBlockBit || NextUnreadBit)
+ parseModule(LastFunctionBlockBit > NextUnreadBit ? LastFunctionBlockBit
+ : NextUnreadBit);
// Check that all block address forward references got resolved (as we
// promised above).
}
FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(
- MemoryBuffer *Buffer, LLVMContext &Context,
- DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy,
- bool CheckFuncSummaryPresenceOnly)
- : DiagnosticHandler(getDiagHandler(DiagnosticHandler, Context)),
- Buffer(Buffer),
- IsLazy(IsLazy),
+ MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler,
+ bool IsLazy, bool CheckFuncSummaryPresenceOnly)
+ : DiagnosticHandler(DiagnosticHandler), Buffer(Buffer), IsLazy(IsLazy),
CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}
FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(
- LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy, bool CheckFuncSummaryPresenceOnly)
- : DiagnosticHandler(getDiagHandler(DiagnosticHandler, Context)),
- Buffer(nullptr),
- IsLazy(IsLazy),
+ DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy,
+ bool CheckFuncSummaryPresenceOnly)
+ : DiagnosticHandler(DiagnosticHandler), Buffer(nullptr), IsLazy(IsLazy),
CheckFuncSummaryPresenceOnly(CheckFuncSummaryPresenceOnly) {}
void FunctionIndexBitcodeReader::freeState() { Buffer = nullptr; }
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
- case BitstreamEntry::SubBlock: // Handled for us already.
- case BitstreamEntry::Error:
- return error("Malformed block");
- case BitstreamEntry::EndBlock:
- return std::error_code();
- case BitstreamEntry::Record:
- // The interesting case.
- break;
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
}
// Read a record.
Record.clear();
switch (Stream.readRecord(Entry.ID, Record)) {
- default: // Default behavior: ignore (e.g. VST_CODE_BBENTRY records).
- break;
- case bitc::VST_CODE_FNENTRY: {
- // VST_FNENTRY: [valueid, offset, namechar x N]
- if (convertToString(Record, 2, ValueName))
- return error("Invalid record");
- unsigned ValueID = Record[0];
- uint64_t FuncOffset = Record[1];
- std::unique_ptr<FunctionInfo> FuncInfo =
- llvm::make_unique<FunctionInfo>(FuncOffset);
- if (foundFuncSummary() && !IsLazy) {
- DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =
- SummaryMap.find(ValueID);
- assert(SMI != SummaryMap.end() && "Summary info not found");
- FuncInfo->setFunctionSummary(std::move(SMI->second));
- }
- TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));
-
- ValueName.clear();
- break;
+ default: // Default behavior: ignore (e.g. VST_CODE_BBENTRY records).
+ break;
+ case bitc::VST_CODE_FNENTRY: {
+ // VST_FNENTRY: [valueid, offset, namechar x N]
+ if (convertToString(Record, 2, ValueName))
+ return error("Invalid record");
+ unsigned ValueID = Record[0];
+ uint64_t FuncOffset = Record[1];
+ std::unique_ptr<FunctionInfo> FuncInfo =
+ llvm::make_unique<FunctionInfo>(FuncOffset);
+ if (foundFuncSummary() && !IsLazy) {
+ DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =
+ SummaryMap.find(ValueID);
+ assert(SMI != SummaryMap.end() && "Summary info not found");
+ FuncInfo->setFunctionSummary(std::move(SMI->second));
}
- case bitc::VST_CODE_COMBINED_FNENTRY: {
- // VST_FNENTRY: [offset, namechar x N]
- if (convertToString(Record, 1, ValueName))
- return error("Invalid record");
- uint64_t FuncSummaryOffset = Record[0];
- std::unique_ptr<FunctionInfo> FuncInfo =
- llvm::make_unique<FunctionInfo>(FuncSummaryOffset);
- if (foundFuncSummary() && !IsLazy) {
- DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =
- SummaryMap.find(FuncSummaryOffset);
- assert(SMI != SummaryMap.end() && "Summary info not found");
- FuncInfo->setFunctionSummary(std::move(SMI->second));
- }
- TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));
+ TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));
- ValueName.clear();
- break;
+ ValueName.clear();
+ break;
+ }
+ case bitc::VST_CODE_COMBINED_FNENTRY: {
+ // VST_FNENTRY: [offset, namechar x N]
+ if (convertToString(Record, 1, ValueName))
+ return error("Invalid record");
+ uint64_t FuncSummaryOffset = Record[0];
+ std::unique_ptr<FunctionInfo> FuncInfo =
+ llvm::make_unique<FunctionInfo>(FuncSummaryOffset);
+ if (foundFuncSummary() && !IsLazy) {
+ DenseMap<uint64_t, std::unique_ptr<FunctionSummary>>::iterator SMI =
+ SummaryMap.find(FuncSummaryOffset);
+ assert(SMI != SummaryMap.end() && "Summary info not found");
+ FuncInfo->setFunctionSummary(std::move(SMI->second));
}
+ TheIndex->addFunctionInfo(ValueName, std::move(FuncInfo));
+
+ ValueName.clear();
+ break;
+ }
}
}
}
BitstreamEntry Entry = Stream.advance();
switch (Entry.Kind) {
- case BitstreamEntry::Error:
- return error("Malformed block");
- case BitstreamEntry::EndBlock:
- return std::error_code();
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
- case BitstreamEntry::SubBlock:
- if (CheckFuncSummaryPresenceOnly) {
- if (Entry.ID == bitc::FUNCTION_SUMMARY_BLOCK_ID)
- SeenFuncSummary = true;
- if (Stream.SkipBlock()) return error("Invalid record");
- // No need to parse the rest since we found the summary.
- return std::error_code();
- }
- switch (Entry.ID) {
- default: // Skip unknown content.
- if (Stream.SkipBlock()) return error("Invalid record");
- break;
- case bitc::BLOCKINFO_BLOCK_ID:
- // Need to parse these to get abbrev ids (e.g. for VST)
- if (Stream.ReadBlockInfoBlock()) return error("Malformed block");
- break;
- case bitc::VALUE_SYMTAB_BLOCK_ID:
- if (std::error_code EC = parseValueSymbolTable()) return EC;
- break;
- case bitc::FUNCTION_SUMMARY_BLOCK_ID:
- SeenFuncSummary = true;
- if (IsLazy) {
- // Lazy parsing of summary info, skip it.
- if (Stream.SkipBlock()) return error("Invalid record");
- } else if (std::error_code EC = parseEntireSummary())
- return EC;
- break;
- case bitc::MODULE_STRTAB_BLOCK_ID:
- if (std::error_code EC = parseModuleStringTable()) return EC;
- break;
- }
- continue;
+ case BitstreamEntry::SubBlock:
+ if (CheckFuncSummaryPresenceOnly) {
+ if (Entry.ID == bitc::FUNCTION_SUMMARY_BLOCK_ID)
+ SeenFuncSummary = true;
+ if (Stream.SkipBlock())
+ return error("Invalid record");
+ // No need to parse the rest since we found the summary.
+ return std::error_code();
+ }
+ switch (Entry.ID) {
+ default: // Skip unknown content.
+ if (Stream.SkipBlock())
+ return error("Invalid record");
+ break;
+ case bitc::BLOCKINFO_BLOCK_ID:
+ // Need to parse these to get abbrev ids (e.g. for VST)
+ if (Stream.ReadBlockInfoBlock())
+ return error("Malformed block");
+ break;
+ case bitc::VALUE_SYMTAB_BLOCK_ID:
+ if (std::error_code EC = parseValueSymbolTable())
+ return EC;
+ break;
+ case bitc::FUNCTION_SUMMARY_BLOCK_ID:
+ SeenFuncSummary = true;
+ if (IsLazy) {
+ // Lazy parsing of summary info, skip it.
+ if (Stream.SkipBlock())
+ return error("Invalid record");
+ } else if (std::error_code EC = parseEntireSummary())
+ return EC;
+ break;
+ case bitc::MODULE_STRTAB_BLOCK_ID:
+ if (std::error_code EC = parseModuleStringTable())
+ return EC;
+ break;
+ }
+ continue;
- case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ case BitstreamEntry::Record:
+ Stream.skipRecord(Entry.ID);
+ continue;
}
}
}
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
- case BitstreamEntry::SubBlock: // Handled for us already.
- case BitstreamEntry::Error:
- return error("Malformed block");
- case BitstreamEntry::EndBlock:
- return std::error_code();
- case BitstreamEntry::Record:
- // The interesting case.
- break;
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
}
// Read a record. The record format depends on whether this
Record.clear();
uint64_t CurRecordBit = Stream.GetCurrentBitNo();
switch (Stream.readRecord(Entry.ID, Record)) {
- default: // Default behavior: ignore.
- break;
- // FS_PERMODULE_ENTRY: [valueid, islocal, instcount]
- case bitc::FS_CODE_PERMODULE_ENTRY: {
- unsigned ValueID = Record[0];
- bool IsLocal = Record[1];
- unsigned InstCount = Record[2];
- std::unique_ptr<FunctionSummary> FS =
- llvm::make_unique<FunctionSummary>(InstCount);
- FS->setLocalFunction(IsLocal);
- // The module path string ref set in the summary must be owned by the
- // index's module string table. Since we don't have a module path
- // string table section in the per-module index, we create a single
- // module path string table entry with an empty (0) ID to take
- // ownership.
- FS->setModulePath(
- TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0));
- SummaryMap[ValueID] = std::move(FS);
- }
- // FS_COMBINED_ENTRY: [modid, instcount]
- case bitc::FS_CODE_COMBINED_ENTRY: {
- uint64_t ModuleId = Record[0];
- unsigned InstCount = Record[1];
- std::unique_ptr<FunctionSummary> FS =
- llvm::make_unique<FunctionSummary>(InstCount);
- FS->setModulePath(ModuleIdMap[ModuleId]);
- SummaryMap[CurRecordBit] = std::move(FS);
- }
+ default: // Default behavior: ignore.
+ break;
+ // FS_PERMODULE_ENTRY: [valueid, islocal, instcount]
+ case bitc::FS_CODE_PERMODULE_ENTRY: {
+ unsigned ValueID = Record[0];
+ bool IsLocal = Record[1];
+ unsigned InstCount = Record[2];
+ std::unique_ptr<FunctionSummary> FS =
+ llvm::make_unique<FunctionSummary>(InstCount);
+ FS->setLocalFunction(IsLocal);
+ // The module path string ref set in the summary must be owned by the
+ // index's module string table. Since we don't have a module path
+ // string table section in the per-module index, we create a single
+ // module path string table entry with an empty (0) ID to take
+ // ownership.
+ FS->setModulePath(
+ TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0));
+ SummaryMap[ValueID] = std::move(FS);
+ }
+ // FS_COMBINED_ENTRY: [modid, instcount]
+ case bitc::FS_CODE_COMBINED_ENTRY: {
+ uint64_t ModuleId = Record[0];
+ unsigned InstCount = Record[1];
+ std::unique_ptr<FunctionSummary> FS =
+ llvm::make_unique<FunctionSummary>(InstCount);
+ FS->setModulePath(ModuleIdMap[ModuleId]);
+ SummaryMap[CurRecordBit] = std::move(FS);
+ }
}
}
llvm_unreachable("Exit infinite loop");
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
- case BitstreamEntry::SubBlock: // Handled for us already.
- case BitstreamEntry::Error:
- return error("Malformed block");
- case BitstreamEntry::EndBlock:
- return std::error_code();
- case BitstreamEntry::Record:
- // The interesting case.
- break;
+ case BitstreamEntry::SubBlock: // Handled for us already.
+ case BitstreamEntry::Error:
+ return error("Malformed block");
+ case BitstreamEntry::EndBlock:
+ return std::error_code();
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
}
Record.clear();
switch (Stream.readRecord(Entry.ID, Record)) {
- default: // Default behavior: ignore.
- break;
- case bitc::MST_CODE_ENTRY: {
- // MST_ENTRY: [modid, namechar x N]
- if (convertToString(Record, 1, ModulePath))
- return error("Invalid record");
- uint64_t ModuleId = Record[0];
- StringRef ModulePathInMap =
- TheIndex->addModulePath(ModulePath, ModuleId);
- ModuleIdMap[ModuleId] = ModulePathInMap;
- ModulePath.clear();
- break;
- }
+ default: // Default behavior: ignore.
+ break;
+ case bitc::MST_CODE_ENTRY: {
+ // MST_ENTRY: [modid, namechar x N]
+ if (convertToString(Record, 1, ModulePath))
+ return error("Invalid record");
+ uint64_t ModuleId = Record[0];
+ StringRef ModulePathInMap = TheIndex->addModulePath(ModulePath, ModuleId);
+ ModuleIdMap[ModuleId] = ModulePathInMap;
+ ModulePath.clear();
+ break;
+ }
}
}
llvm_unreachable("Exit infinite loop");
std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I) {
TheIndex = I;
- if (std::error_code EC = initStream(std::move(Streamer))) return EC;
+ if (std::error_code EC = initStream(std::move(Streamer)))
+ return EC;
// Sniff for the signature.
- if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");
+ if (!hasValidBitcodeHeader(Stream))
+ return error("Invalid bitcode signature");
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
BitstreamEntry Entry =
Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
- if (Entry.Kind != BitstreamEntry::SubBlock) return error("Malformed block");
+ if (Entry.Kind != BitstreamEntry::SubBlock)
+ return error("Malformed block");
// If we see a MODULE_BLOCK, parse it to find the blocks needed for
// building the function summary index.
- if (Entry.ID == bitc::MODULE_BLOCK_ID) return parseModule();
+ if (Entry.ID == bitc::MODULE_BLOCK_ID)
+ return parseModule();
- if (Stream.SkipBlock()) return error("Invalid record");
+ if (Stream.SkipBlock())
+ return error("Invalid record");
}
}
size_t FunctionSummaryOffset) {
TheIndex = I;
- if (std::error_code EC = initStream(std::move(Streamer))) return EC;
+ if (std::error_code EC = initStream(std::move(Streamer)))
+ return EC;
// Sniff for the signature.
- if (!hasValidBitcodeHeader(Stream)) return error("Invalid bitcode signature");
+ if (!hasValidBitcodeHeader(Stream))
+ return error("Invalid bitcode signature");
Stream.JumpToBit(FunctionSummaryOffset);
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
- default:
- return error("Malformed block");
- case BitstreamEntry::Record:
- // The expected case.
- break;
+ default:
+ return error("Malformed block");
+ case BitstreamEntry::Record:
+ // The expected case.
+ break;
}
// TODO: Read a record. This interface will be completed when ThinLTO
// importing is added so that it can be tested.
SmallVector<uint64_t, 64> Record;
switch (Stream.readRecord(Entry.ID, Record)) {
- default:
- return error("Invalid record");
+ case bitc::FS_CODE_COMBINED_ENTRY:
+ default:
+ return error("Invalid record");
}
return std::error_code();
}
-std::error_code FunctionIndexBitcodeReader::initStream(
- std::unique_ptr<DataStreamer> Streamer) {
- if (Streamer) return initLazyStream(std::move(Streamer));
+std::error_code
+FunctionIndexBitcodeReader::initStream(std::unique_ptr<DataStreamer> Streamer) {
+ if (Streamer)
+ return initLazyStream(std::move(Streamer));
return initStreamFromBuffer();
}
const unsigned char *BufPtr = (const unsigned char *)Buffer->getBufferStart();
const unsigned char *BufEnd = BufPtr + Buffer->getBufferSize();
- if (Buffer->getBufferSize() & 3) return error("Invalid bitcode signature");
+ if (Buffer->getBufferSize() & 3)
+ return error("Invalid bitcode signature");
// If we have a wrapper header, parse it and ignore the non-bc file contents.
// The magic number is 0x0B17C0DE stored in little endian.
if (Bytes.readBytes(buf, 16, 0) != 16)
return error("Invalid bitcode signature");
- if (!isBitcode(buf, buf + 16)) return error("Invalid bitcode signature");
+ if (!isBitcode(buf, buf + 16))
+ return error("Invalid bitcode signature");
if (isBitcodeWrapper(buf, buf + 4)) {
const unsigned char *bitcodeStart = buf;
return Triple.get();
}
+std::string
+llvm::getBitcodeProducerString(MemoryBufferRef Buffer, LLVMContext &Context,
+ DiagnosticHandlerFunction DiagnosticHandler) {
+ std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
+ BitcodeReader R(Buf.release(), Context, DiagnosticHandler);
+ ErrorOr<std::string> ProducerString = R.parseIdentificationBlock();
+ if (ProducerString.getError())
+ return "";
+ return ProducerString.get();
+}
+
// Parse the specified bitcode buffer, returning the function info index.
// If IsLazy is false, parse the entire function summary into
// the index. Otherwise skip the function summary section, and only create
// an index object with a map from function name to function summary offset.
// The index is used to perform lazy function summary reading later.
-ErrorOr<std::unique_ptr<FunctionInfoIndex>> llvm::getFunctionInfoIndex(
- MemoryBufferRef Buffer, LLVMContext &Context,
- DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy) {
+ErrorOr<std::unique_ptr<FunctionInfoIndex>>
+llvm::getFunctionInfoIndex(MemoryBufferRef Buffer,
+ DiagnosticHandlerFunction DiagnosticHandler,
+ const Module *ExportingModule, bool IsLazy) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
- FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler, IsLazy);
+ FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler, IsLazy);
std::unique_ptr<FunctionInfoIndex> Index =
- llvm::make_unique<FunctionInfoIndex>();
+ llvm::make_unique<FunctionInfoIndex>(ExportingModule);
auto cleanupOnError = [&](std::error_code EC) {
- R.releaseBuffer(); // Never take ownership on error.
+ R.releaseBuffer(); // Never take ownership on error.
return EC;
};
if (std::error_code EC = R.parseSummaryIndexInto(nullptr, Index.get()))
return cleanupOnError(EC);
- Buf.release(); // The FunctionIndexBitcodeReader owns it now.
+ Buf.release(); // The FunctionIndexBitcodeReader owns it now.
return std::move(Index);
}
// Check if the given bitcode buffer contains a function summary block.
-bool llvm::hasFunctionSummary(MemoryBufferRef Buffer, LLVMContext &Context,
+bool llvm::hasFunctionSummary(MemoryBufferRef Buffer,
DiagnosticHandlerFunction DiagnosticHandler) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
- FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler, false,
- true);
+ FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler, false, true);
auto cleanupOnError = [&](std::error_code EC) {
- R.releaseBuffer(); // Never take ownership on error.
+ R.releaseBuffer(); // Never take ownership on error.
return false;
};
if (std::error_code EC = R.parseSummaryIndexInto(nullptr, nullptr))
return cleanupOnError(EC);
- Buf.release(); // The FunctionIndexBitcodeReader owns it now.
+ Buf.release(); // The FunctionIndexBitcodeReader owns it now.
return R.foundFuncSummary();
}
// to parse the summary information for the given function name into
// the index.
std::error_code llvm::readFunctionSummary(
- MemoryBufferRef Buffer, LLVMContext &Context,
- DiagnosticHandlerFunction DiagnosticHandler, StringRef FunctionName,
- std::unique_ptr<FunctionInfoIndex> Index) {
+ MemoryBufferRef Buffer, DiagnosticHandlerFunction DiagnosticHandler,
+ StringRef FunctionName, std::unique_ptr<FunctionInfoIndex> Index) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
- FunctionIndexBitcodeReader R(Buf.get(), Context, DiagnosticHandler);
+ FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler);
auto cleanupOnError = [&](std::error_code EC) {
- R.releaseBuffer(); // Never take ownership on error.
+ R.releaseBuffer(); // Never take ownership on error.
return EC;
};
return cleanupOnError(EC);
}
- Buf.release(); // The FunctionIndexBitcodeReader owns it now.
+ Buf.release(); // The FunctionIndexBitcodeReader owns it now.
return std::error_code();
}