Provide a fast "get me the target triple from the module" API. This can

drastically reduce the linking time during LTO.

Patch by Shantonu Sen!

llvm-svn: 115728
This commit is contained in:
Bill Wendling 2010-10-06 01:22:42 +00:00
parent 5b3e46bd6b
commit ef718b99d4
4 changed files with 142 additions and 10 deletions

View File

@ -33,6 +33,15 @@ namespace llvm {
LLVMContext& Context,
std::string *ErrMsg = 0);
/// getBitcodeTargetTriple - Read the header of the specified bitcode
/// buffer and extract just the triple information. If successful,
/// this returns a string and *does not* take ownership
/// of 'buffer'. On error, this returns "", and fills in *ErrMsg
/// if ErrMsg is non-null.
std::string getBitcodeTargetTriple(MemoryBuffer *Buffer,
LLVMContext& Context,
std::string *ErrMsg = 0);
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, this returns null and fills in *ErrMsg if it is
/// non-null. This method *never* takes ownership of Buffer.

View File

@ -1600,6 +1600,112 @@ bool BitcodeReader::ParseBitcodeInto(Module *M) {
return false;
}
bool BitcodeReader::ParseModuleTriple(std::string &Triple) {
if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code == bitc::END_BLOCK) {
if (Stream.ReadBlockEnd())
return Error("Error at end of module block");
return false;
}
if (Code == bitc::ENTER_SUBBLOCK) {
switch (Stream.ReadSubBlockID()) {
default: // Skip unknown content.
if (Stream.SkipBlock())
return Error("Malformed block record");
break;
}
continue;
}
if (Code == bitc::DEFINE_ABBREV) {
Stream.ReadAbbrevRecord();
continue;
}
// Read a record.
switch (Stream.ReadRecord(Code, Record)) {
default: break; // Default behavior, ignore unknown content.
case bitc::MODULE_CODE_VERSION: // VERSION: [version#]
if (Record.size() < 1)
return Error("Malformed MODULE_CODE_VERSION");
// Only version #0 is supported so far.
if (Record[0] != 0)
return Error("Unknown bitstream version!");
break;
case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
std::string S;
if (ConvertToString(Record, 0, S))
return Error("Invalid MODULE_CODE_TRIPLE record");
Triple = S;
break;
}
}
Record.clear();
}
return Error("Premature end of bitstream");
}
bool BitcodeReader::ParseTriple(std::string &Triple) {
if (Buffer->getBufferSize() & 3)
return Error("Bitcode stream should be a multiple of 4 bytes in length");
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
// 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 (isBitcodeWrapper(BufPtr, BufEnd))
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd))
return Error("Invalid bitcode wrapper header");
StreamFile.init(BufPtr, BufEnd);
Stream.init(StreamFile);
// Sniff for the signature.
if (Stream.Read(8) != 'B' ||
Stream.Read(8) != 'C' ||
Stream.Read(4) != 0x0 ||
Stream.Read(4) != 0xC ||
Stream.Read(4) != 0xE ||
Stream.Read(4) != 0xD)
return Error("Invalid bitcode signature");
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code != bitc::ENTER_SUBBLOCK)
return Error("Invalid record at top-level");
unsigned BlockID = Stream.ReadSubBlockID();
// We only know the MODULE subblock ID.
switch (BlockID) {
case bitc::MODULE_BLOCK_ID:
if (ParseModuleTriple(Triple))
return true;
break;
default:
if (Stream.SkipBlock())
return Error("Malformed block record");
break;
}
}
return false;
}
/// ParseMetadataAttachment - Parse metadata attachments.
bool BitcodeReader::ParseMetadataAttachment() {
if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
@ -2537,7 +2643,24 @@ Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
// Read in the entire module, and destroy the BitcodeReader.
if (M->MaterializeAllPermanently(ErrMsg)) {
delete M;
return NULL;
return 0;
}
return M;
}
std::string llvm::getBitcodeTargetTriple(MemoryBuffer *Buffer,
LLVMContext& Context,
std::string *ErrMsg) {
BitcodeReader *R = new BitcodeReader(Buffer, Context);
// Don't let the BitcodeReader dtor delete 'Buffer'.
R->setBufferOwned(false);
std::string Triple("");
if (R->ParseTriple(Triple))
if (ErrMsg)
*ErrMsg = R->getErrorString();
delete R;
return Triple;
}

View File

@ -212,6 +212,10 @@ public:
/// @brief Main interface to parsing a bitcode buffer.
/// @returns true if an error occurred.
bool ParseBitcodeInto(Module *M);
/// @brief Cheap mechanism to just extract module triple
/// @returns true if an error occurred.
bool ParseTriple(std::string &Triple);
private:
const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
Value *getFnValueByID(unsigned ID, const Type *Ty) {
@ -270,6 +274,7 @@ private:
bool ResolveGlobalAndAliasInits();
bool ParseMetadata();
bool ParseMetadataAttachment();
bool ParseModuleTriple(std::string &Triple);
};
} // End llvm namespace

View File

@ -64,15 +64,10 @@ bool LTOModule::isBitcodeFileForTarget(const char *path,
// Takes ownership of buffer.
bool LTOModule::isTargetMatch(MemoryBuffer *buffer, const char *triplePrefix) {
OwningPtr<Module> m(getLazyBitcodeModule(buffer, getGlobalContext()));
// On success, m owns buffer and both are deleted at end of this method.
if (!m) {
delete buffer;
return false;
}
std::string actualTarget = m->getTargetTriple();
return (strncmp(actualTarget.c_str(), triplePrefix,
strlen(triplePrefix)) == 0);
std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext());
delete buffer;
return (strncmp(Triple.c_str(), triplePrefix,
strlen(triplePrefix)) == 0);
}