#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ManagedStatic.h"
+
using namespace llvm;
enum {
return Error(BitcodeError::NeverResolvedFunctionFromBlockAddress);
// Try to materialize F.
- if (std::error_code EC = Materialize(F))
+ if (std::error_code EC = materialize(F))
return EC;
}
assert(BasicBlockFwdRefs.empty() && "Function missing from queue");
/// Provide fast operand accessors
- //DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
}
struct OperandTraits<ConstantPlaceHolder> :
public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
};
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
}
}
}
-void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) {
+void BitcodeReaderMDValueList::AssignValue(Metadata *MD, unsigned Idx) {
if (Idx == size()) {
- push_back(V);
+ push_back(MD);
return;
}
if (Idx >= size())
resize(Idx+1);
- WeakVH &OldV = MDValuePtrs[Idx];
- if (!OldV) {
- OldV = V;
+ TrackingMDRef &OldMD = MDValuePtrs[Idx];
+ if (!OldMD) {
+ OldMD.reset(MD);
return;
}
// If there was a forward reference to this value, replace it.
- MDNode *PrevVal = cast<MDNode>(OldV);
- OldV->replaceAllUsesWith(V);
- MDNode::deleteTemporary(PrevVal);
- // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new
- // value for Idx.
- MDValuePtrs[Idx] = V;
+ MDNodeFwdDecl *PrevMD = cast<MDNodeFwdDecl>(OldMD.get());
+ PrevMD->replaceAllUsesWith(MD);
+ MDNode::deleteTemporary(PrevMD);
+ --NumFwdRefs;
}
-Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
if (Idx >= size())
resize(Idx + 1);
- if (Value *V = MDValuePtrs[Idx]) {
- assert(V->getType()->isMetadataTy() && "Type mismatch in value table!");
- return V;
- }
+ if (Metadata *MD = MDValuePtrs[Idx])
+ return MD;
// Create and return a placeholder, which will later be RAUW'd.
- Value *V = MDNode::getTemporary(Context, None);
- MDValuePtrs[Idx] = V;
- return V;
+ AnyFwdRefs = true;
+ ++NumFwdRefs;
+ Metadata *MD = MDNode::getTemporary(Context, None);
+ MDValuePtrs[Idx].reset(MD);
+ return MD;
+}
+
+void BitcodeReaderMDValueList::tryToResolveCycles() {
+ if (!AnyFwdRefs)
+ // Nothing to do.
+ return;
+
+ if (NumFwdRefs)
+ // Still forward references... can't resolve cycles.
+ return;
+
+ // Resolve any cycles.
+ for (auto &MD : MDValuePtrs) {
+ assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Unexpected forward reference");
+ if (auto *G = dyn_cast_or_null<GenericMDNode>(MD))
+ G->resolveCycles();
+ }
}
Type *BitcodeReader::getTypeByID(unsigned ID) {
// If we have a forward reference, the only possible case is when it is to a
// named struct. Just create a placeholder for now.
- return TypeList[ID] = StructType::create(Context);
+ return TypeList[ID] = createIdentifiedStructType(Context);
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context,
+ StringRef Name) {
+ auto *Ret = StructType::create(Context, Name);
+ IdentifiedStructTypes.push_back(Ret);
+ return Ret;
+}
+
+StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context) {
+ auto *Ret = StructType::create(Context);
+ IdentifiedStructTypes.push_back(Ret);
+ return Ret;
}
Res->setName(TypeName);
TypeList[NumRecords] = nullptr;
} else // Otherwise, create a new struct.
- Res = StructType::create(Context, TypeName);
+ Res = createIdentifiedStructType(Context, TypeName);
TypeName.clear();
SmallVector<Type*, 8> EltTys;
Res->setName(TypeName);
TypeList[NumRecords] = nullptr;
} else // Otherwise, create a new struct with no body.
- Res = StructType::create(Context, TypeName);
+ Res = createIdentifiedStructType(Context, TypeName);
TypeName.clear();
ResultTy = Res;
break;
case BitstreamEntry::Error:
return Error(BitcodeError::MalformedBlock);
case BitstreamEntry::EndBlock:
+ MDValueList.tryToResolveCycles();
return std::error_code();
case BitstreamEntry::Record:
// The interesting case.
break;
}
- bool IsFunctionLocal = false;
// Read a record.
Record.clear();
unsigned Code = Stream.readRecord(Entry.ID, Record);
}
break;
}
- case bitc::METADATA_FN_NODE:
- IsFunctionLocal = true;
- // fall-through
- case bitc::METADATA_NODE: {
+ case bitc::METADATA_OLD_FN_NODE: {
+ // This is a LocalAsMetadata record, the only type of function-local
+ // metadata.
+ if (Record.size() % 2 == 1)
+ return Error(BitcodeError::InvalidRecord);
+
+ // If this isn't a LocalAsMetadata record, we're dropping it. This used
+ // to be legal, but there's no upgrade path.
+ auto dropRecord = [&] {
+ MDValueList.AssignValue(MDNode::get(Context, None), NextMDValueNo++);
+ };
+ if (Record.size() != 2) {
+ dropRecord();
+ break;
+ }
+
+ Type *Ty = getTypeByID(Record[0]);
+ if (Ty->isMetadataTy() || Ty->isVoidTy()) {
+ dropRecord();
+ break;
+ }
+
+ MDValueList.AssignValue(
+ LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
+ NextMDValueNo++);
+ break;
+ }
+ case bitc::METADATA_OLD_NODE: {
if (Record.size() % 2 == 1)
return Error(BitcodeError::InvalidRecord);
unsigned Size = Record.size();
- SmallVector<Value*, 8> Elts;
+ SmallVector<Metadata *, 8> Elts;
for (unsigned i = 0; i != Size; i += 2) {
Type *Ty = getTypeByID(Record[i]);
if (!Ty)
return Error(BitcodeError::InvalidRecord);
if (Ty->isMetadataTy())
Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
- else if (!Ty->isVoidTy())
- Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty));
- else
+ else if (!Ty->isVoidTy()) {
+ auto *MD =
+ ValueAsMetadata::get(ValueList.getValueFwdRef(Record[i + 1], Ty));
+ assert(isa<ConstantAsMetadata>(MD) &&
+ "Expected non-function-local metadata");
+ Elts.push_back(MD);
+ } else
Elts.push_back(nullptr);
}
- Value *V = MDNode::getWhenValsUnresolved(Context, Elts, IsFunctionLocal);
- IsFunctionLocal = false;
- MDValueList.AssignValue(V, NextMDValueNo++);
+ MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
+ break;
+ }
+ case bitc::METADATA_VALUE: {
+ if (Record.size() != 2)
+ return Error(BitcodeError::InvalidRecord);
+
+ Type *Ty = getTypeByID(Record[0]);
+ if (Ty->isMetadataTy() || Ty->isVoidTy())
+ return Error(BitcodeError::InvalidRecord);
+
+ MDValueList.AssignValue(
+ ValueAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
+ NextMDValueNo++);
+ break;
+ }
+ case bitc::METADATA_NODE: {
+ SmallVector<Metadata *, 8> Elts;
+ Elts.reserve(Record.size());
+ for (unsigned ID : Record)
+ Elts.push_back(ID ? MDValueList.getValueFwdRef(ID - 1) : nullptr);
+ MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
break;
}
case bitc::METADATA_STRING: {
std::string String(Record.begin(), Record.end());
llvm::UpgradeMDStringConstant(String);
- Value *V = MDString::get(Context, String);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ Metadata *MD = MDString::get(Context, String);
+ MDValueList.AssignValue(MD, NextMDValueNo++);
break;
}
case bitc::METADATA_KIND: {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
+ std::vector<std::pair<Function*, unsigned> > FunctionPrologueWorklist;
GlobalInitWorklist.swap(GlobalInits);
AliasInitWorklist.swap(AliasInits);
FunctionPrefixWorklist.swap(FunctionPrefixes);
+ FunctionPrologueWorklist.swap(FunctionPrologues);
while (!GlobalInitWorklist.empty()) {
unsigned ValID = GlobalInitWorklist.back().second;
FunctionPrefixWorklist.pop_back();
}
+ while (!FunctionPrologueWorklist.empty()) {
+ unsigned ValID = FunctionPrologueWorklist.back().second;
+ if (ValID >= ValueList.size()) {
+ FunctionPrologues.push_back(FunctionPrologueWorklist.back());
+ } else {
+ if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID]))
+ FunctionPrologueWorklist.back().first->setPrologueData(C);
+ else
+ return Error(BitcodeError::ExpectedConstant);
+ }
+ FunctionPrologueWorklist.pop_back();
+ }
+
return std::error_code();
}
}
// FUNCTION: [type, callingconv, isproto, linkage, paramattr,
// alignment, section, visibility, gc, unnamed_addr,
- // dllstorageclass]
+ // prologuedata, dllstorageclass, comdat, prefixdata]
case bitc::MODULE_CODE_FUNCTION: {
if (Record.size() < 8)
return Error(BitcodeError::InvalidRecord);
UnnamedAddr = Record[9];
Func->setUnnamedAddr(UnnamedAddr);
if (Record.size() > 10 && Record[10] != 0)
- FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1));
+ FunctionPrologues.push_back(std::make_pair(Func, Record[10]-1));
if (Record.size() > 11)
Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[11]));
Func->setComdat(ComdatList[ComdatID - 1]);
}
+ if (Record.size() > 13 && Record[13] != 0)
+ FunctionPrefixes.push_back(std::make_pair(Func, Record[13]-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);
- if (LazyStreamer) DeferredFunctionInfo[Func] = 0;
+ if (LazyStreamer)
+ DeferredFunctionInfo[Func] = 0;
}
break;
}
else
UpgradeDLLImportExportLinkage(NewGA, Record[2]);
if (Record.size() > 5)
- NewGA->setThreadLocalMode(GetDecodedThreadLocalMode(Record[5]));
+ NewGA->setThreadLocalMode(GetDecodedThreadLocalMode(Record[5]));
if (Record.size() > 6)
- NewGA->setUnnamedAddr(Record[6]);
+ NewGA->setUnnamedAddr(Record[6]);
ValueList.push_back(NewGA);
AliasInits.push_back(std::make_pair(NewGA, Record[1]));
break;
MDKindMap.find(Kind);
if (I == MDKindMap.end())
return Error(BitcodeError::InvalidID);
- Value *Node = MDValueList.getValueFwdRef(Record[i+1]);
+ Metadata *Node = MDValueList.getValueFwdRef(Record[i + 1]);
+ if (isa<LocalAsMetadata>(Node))
+ // Drop the attachment. This used to be legal, but there's no
+ // upgrade path.
+ break;
Inst->setMetadata(I->second, cast<MDNode>(Node));
if (I->second == LLVMContext::MD_tbaa)
InstsWithTBAATag.push_back(Inst);
void BitcodeReader::releaseBuffer() { Buffer.release(); }
-bool BitcodeReader::isMaterializable(const GlobalValue *GV) const {
- if (const Function *F = dyn_cast<Function>(GV)) {
- return F->isDeclaration() &&
- DeferredFunctionInfo.count(const_cast<Function*>(F));
- }
- return false;
-}
-
-std::error_code BitcodeReader::Materialize(GlobalValue *GV) {
+std::error_code BitcodeReader::materialize(GlobalValue *GV) {
Function *F = dyn_cast<Function>(GV);
// If it's not a function or is already material, ignore the request.
if (!F || !F->isMaterializable())
if (std::error_code EC = ParseFunctionBody(F))
return EC;
+ F->setIsMaterializable(false);
// Upgrade any old intrinsic calls in the function.
for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(),
assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
// Just forget the function body, we can remat it later.
- F->deleteBody();
+ F->dropAllReferences();
+ F->setIsMaterializable(true);
}
std::error_code BitcodeReader::MaterializeModule(Module *M) {
// disk.
for (Module::iterator F = TheModule->begin(), E = TheModule->end();
F != E; ++F) {
- if (F->isMaterializable()) {
- if (std::error_code EC = Materialize(F))
- return EC;
- }
+ 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
return std::error_code();
}
+std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
+ return IdentifiedStructTypes;
+}
+
std::error_code BitcodeReader::InitStream() {
if (LazyStreamer)
return InitLazyStream();
return Error(BitcodeError::InvalidBitcodeWrapperHeader);
StreamFile.reset(new BitstreamReader(BufPtr, BufEnd));
- Stream.init(*StreamFile);
+ Stream.init(&*StreamFile);
return std::error_code();
}
// see it.
StreamingMemoryObject *Bytes = new StreamingMemoryObject(LazyStreamer);
StreamFile.reset(new BitstreamReader(Bytes));
- Stream.init(*StreamFile);
+ Stream.init(&*StreamFile);
unsigned char buf[16];
- if (Bytes->readBytes(0, 16, buf) == -1)
+ if (Bytes->readBytes(buf, 16, 0) != 16)
return Error(BitcodeError::InvalidBitcodeSignature);
if (!isBitcode(buf, buf + 16))
};
}
+static ManagedStatic<BitcodeErrorCategoryType> ErrorCategory;
+
const std::error_category &llvm::BitcodeErrorCategory() {
- static BitcodeErrorCategoryType O;
- return O;
+ return *ErrorCategory;
}
//===----------------------------------------------------------------------===//