Bitcode: Move version and global value module code parsers to separate functions. NFCI.

This will make it easier to teach this code about the string table.

Differential Revision: https://reviews.llvm.org/D31828

llvm-svn: 300099
This commit is contained in:
Peter Collingbourne
2017-04-12 20:02:09 +00:00
parent 2bb94cd0dd
commit ce24a2aa93

View File

@@ -379,6 +379,8 @@ protected:
BitstreamBlockInfo BlockInfo;
BitstreamCursor Stream;
Expected<unsigned> parseVersionRecord(ArrayRef<uint64_t> Record);
bool readBlockInfo();
// Contains an arbitrary and optional string identifying the bitcode producer
@@ -395,6 +397,16 @@ 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 > 1)
return error("Invalid value");
return ModuleVersion;
}
class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
LLVMContext &Context;
Module *TheModule = nullptr;
@@ -405,6 +417,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;
@@ -598,6 +613,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();
@@ -2603,6 +2625,246 @@ bool BitcodeReaderBase::readBlockInfo() {
return false;
}
Error BitcodeReader::parseComdatRecord(ArrayRef<uint64_t> Record) {
// [selection_kind, name]
if (Record.size() < 2)
return error("Invalid record");
Comdat::SelectionKind SK = getDecodedComdatSelectionKind(Record[0]);
std::string Name;
unsigned ComdatNameSize = Record[1];
Name.reserve(ComdatNameSize);
for (unsigned i = 0; i != ComdatNameSize; ++i)
Name += (char)Record[2 + i];
Comdat *C = TheModule->getOrInsertComdat(Name);
C->setSelectionKind(SK);
ComdatList.push_back(C);
return Error::success();
}
Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
// [pointer type, isconst, initid, linkage, alignment, section,
// visibility, threadlocal, unnamed_addr, externally_initialized,
// dllstorageclass, comdat]
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, "",
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) {
// [type, callingconv, isproto, linkage, paramattr, alignment, section,
// visibility, gc, unnamed_addr, prologuedata, dllstorageclass, comdat,
// prefixdata]
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))
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) {
// ALIAS_OLD: [alias type, aliasee val#, linkage]
// ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,
// dllstorageclass]
// IFUNC: [alias type, addrspace, aliasee val#, linkage,
// visibility, dllstorageclass]
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));
return Error::success();
}
Error BitcodeReader::parseModule(uint64_t ResumeBit,
bool ShouldLazyLoadMetadata) {
if (ResumeBit)
@@ -2611,8 +2873,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) {
@@ -2758,21 +3018,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]
@@ -2818,240 +3068,26 @@ 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);
case bitc::MODULE_CODE_COMDAT: {
if (Error Err = parseComdatRecord(Record))
return Err;
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");
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));
if (Error Err = parseGlobalIndirectSymbolRecord(BitCode, Record))
return Err;
break;
}
/// MODULE_CODE_VSTOFFSET: [offset]