mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
implement scafolding for lazy deserialization of function bodies
llvm-svn: 36614
This commit is contained in:
parent
eb2a5f5f99
commit
cfd5b13e25
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "llvm/Bitcode/ReaderWriter.h"
|
#include "llvm/Bitcode/ReaderWriter.h"
|
||||||
#include "BitcodeReader.h"
|
#include "BitcodeReader.h"
|
||||||
#include "llvm/Bitcode/BitstreamReader.h"
|
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
@ -660,6 +659,30 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ParseFunction - When we see the block for a function body, remember where it
|
||||||
|
/// is and then skip it. This lets us lazily deserialize the functions.
|
||||||
|
bool BitcodeReader::ParseFunction(BitstreamReader &Stream) {
|
||||||
|
// Get the function we are talking about.
|
||||||
|
if (FunctionsWithBodies.empty())
|
||||||
|
return Error("Insufficient function protos");
|
||||||
|
|
||||||
|
Function *Fn = FunctionsWithBodies.back();
|
||||||
|
FunctionsWithBodies.pop_back();
|
||||||
|
|
||||||
|
// Save the current stream state.
|
||||||
|
uint64_t CurBit = Stream.GetCurrentBitNo();
|
||||||
|
DeferredFunctionInfo[Fn] = std::make_pair(CurBit, Fn->getLinkage());
|
||||||
|
|
||||||
|
// Set the functions linkage to GhostLinkage so we know it is lazily
|
||||||
|
// deserialized.
|
||||||
|
Fn->setLinkage(GlobalValue::GhostLinkage);
|
||||||
|
|
||||||
|
// Skip over the function block for now.
|
||||||
|
if (Stream.SkipBlock())
|
||||||
|
return Error("Malformed block record");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool BitcodeReader::ParseModule(BitstreamReader &Stream,
|
bool BitcodeReader::ParseModule(BitstreamReader &Stream,
|
||||||
const std::string &ModuleID) {
|
const std::string &ModuleID) {
|
||||||
// Reject multiple MODULE_BLOCK's in a single bitstream.
|
// Reject multiple MODULE_BLOCK's in a single bitstream.
|
||||||
@ -682,6 +705,8 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
|
|||||||
ResolveGlobalAndAliasInits();
|
ResolveGlobalAndAliasInits();
|
||||||
if (!GlobalInits.empty() || !AliasInits.empty())
|
if (!GlobalInits.empty() || !AliasInits.empty())
|
||||||
return Error("Malformed global initializer set");
|
return Error("Malformed global initializer set");
|
||||||
|
if (!FunctionsWithBodies.empty())
|
||||||
|
return Error("Too few function bodies found");
|
||||||
if (Stream.ReadBlockEnd())
|
if (Stream.ReadBlockEnd())
|
||||||
return Error("Error at end of module block");
|
return Error("Error at end of module block");
|
||||||
return false;
|
return false;
|
||||||
@ -709,6 +734,17 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
|
|||||||
if (ParseConstants(Stream) || ResolveGlobalAndAliasInits())
|
if (ParseConstants(Stream) || ResolveGlobalAndAliasInits())
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
case bitc::FUNCTION_BLOCK_ID:
|
||||||
|
// If this is the first function body we've seen, reverse the
|
||||||
|
// FunctionsWithBodies list.
|
||||||
|
if (!HasReversedFunctionsWithBodies) {
|
||||||
|
std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
|
||||||
|
HasReversedFunctionsWithBodies = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParseFunction(Stream))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -819,6 +855,7 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
|
|||||||
"", TheModule);
|
"", TheModule);
|
||||||
|
|
||||||
Func->setCallingConv(Record[1]);
|
Func->setCallingConv(Record[1]);
|
||||||
|
bool isProto = Record[2];
|
||||||
Func->setLinkage(GetDecodedLinkage(Record[3]));
|
Func->setLinkage(GetDecodedLinkage(Record[3]));
|
||||||
Func->setAlignment((1 << Record[4]) >> 1);
|
Func->setAlignment((1 << Record[4]) >> 1);
|
||||||
if (Record[5]) {
|
if (Record[5]) {
|
||||||
@ -829,6 +866,11 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
|
|||||||
Func->setVisibility(GetDecodedVisibility(Record[6]));
|
Func->setVisibility(GetDecodedVisibility(Record[6]));
|
||||||
|
|
||||||
ValueList.push_back(Func);
|
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)
|
||||||
|
FunctionsWithBodies.push_back(Func);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// ALIAS: [alias type, aliasee val#, linkage]
|
// ALIAS: [alias type, aliasee val#, linkage]
|
||||||
@ -867,7 +909,7 @@ bool BitcodeReader::ParseBitcode() {
|
|||||||
return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
return Error("Bitcode stream should be a multiple of 4 bytes in length");
|
||||||
|
|
||||||
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
|
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
|
||||||
BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());
|
Stream.init(BufPtr, BufPtr+Buffer->getBufferSize());
|
||||||
|
|
||||||
// Sniff for the signature.
|
// Sniff for the signature.
|
||||||
if (Stream.Read(8) != 'B' ||
|
if (Stream.Read(8) != 'B' ||
|
||||||
@ -900,6 +942,25 @@ bool BitcodeReader::ParseBitcode() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool BitcodeReader::materializeFunction(Function *F, std::string *ErrInfo) {
|
||||||
|
// If it already is material, ignore the request.
|
||||||
|
if (!F->hasNotBeenReadFromBytecode()) return false;
|
||||||
|
|
||||||
|
DenseMap<Function*, std::pair<uint64_t, unsigned> >::iterator DFII =
|
||||||
|
DeferredFunctionInfo.find(F);
|
||||||
|
assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
|
||||||
|
|
||||||
|
// Move the bit stream to the saved position of the deferred function body and
|
||||||
|
// restore the real linkage type for the function.
|
||||||
|
Stream.JumpToBit(DFII->second.first);
|
||||||
|
F->setLinkage((GlobalValue::LinkageTypes)DFII->second.second);
|
||||||
|
DeferredFunctionInfo.erase(DFII);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// External interface
|
// External interface
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
#include "llvm/ModuleProvider.h"
|
#include "llvm/ModuleProvider.h"
|
||||||
#include "llvm/Type.h"
|
#include "llvm/Type.h"
|
||||||
#include "llvm/User.h"
|
#include "llvm/User.h"
|
||||||
|
#include "llvm/Bitcode/BitstreamReader.h"
|
||||||
#include "llvm/Bitcode/LLVMBitCodes.h"
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -59,14 +61,31 @@ public:
|
|||||||
|
|
||||||
class BitcodeReader : public ModuleProvider {
|
class BitcodeReader : public ModuleProvider {
|
||||||
MemoryBuffer *Buffer;
|
MemoryBuffer *Buffer;
|
||||||
|
BitstreamReader Stream;
|
||||||
|
|
||||||
const char *ErrorString;
|
const char *ErrorString;
|
||||||
|
|
||||||
std::vector<PATypeHolder> TypeList;
|
std::vector<PATypeHolder> TypeList;
|
||||||
BitcodeReaderValueList ValueList;
|
BitcodeReaderValueList ValueList;
|
||||||
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
||||||
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
|
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
|
||||||
|
|
||||||
|
// When reading the module header, this list is populated with functions that
|
||||||
|
// have bodies later in the file.
|
||||||
|
std::vector<Function*> FunctionsWithBodies;
|
||||||
|
|
||||||
|
// After the module header has been read, the FunctionsWithBodies list is
|
||||||
|
// reversed. This keeps track of whether we've done this yet.
|
||||||
|
bool HasReversedFunctionsWithBodies;
|
||||||
|
|
||||||
|
/// DeferredFunctionInfo - When function bodies are initially scanned, this
|
||||||
|
/// map contains info about where to find deferred function body (in the
|
||||||
|
/// stream) and what linkage the original function had.
|
||||||
|
DenseMap<Function*, std::pair<uint64_t, unsigned> > DeferredFunctionInfo;
|
||||||
public:
|
public:
|
||||||
BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) {}
|
BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) {
|
||||||
|
HasReversedFunctionsWithBodies = false;
|
||||||
|
}
|
||||||
~BitcodeReader();
|
~BitcodeReader();
|
||||||
|
|
||||||
|
|
||||||
@ -77,10 +96,7 @@ public:
|
|||||||
Buffer = 0;
|
Buffer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0) {
|
virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0);
|
||||||
// FIXME: TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Module *materializeModule(std::string *ErrInfo = 0) {
|
virtual Module *materializeModule(std::string *ErrInfo = 0) {
|
||||||
// FIXME: TODO
|
// FIXME: TODO
|
||||||
@ -106,6 +122,7 @@ private:
|
|||||||
bool ParseTypeSymbolTable(BitstreamReader &Stream);
|
bool ParseTypeSymbolTable(BitstreamReader &Stream);
|
||||||
bool ParseValueSymbolTable(BitstreamReader &Stream);
|
bool ParseValueSymbolTable(BitstreamReader &Stream);
|
||||||
bool ParseConstants(BitstreamReader &Stream);
|
bool ParseConstants(BitstreamReader &Stream);
|
||||||
|
bool ParseFunction(BitstreamReader &Stream);
|
||||||
bool ResolveGlobalAndAliasInits();
|
bool ResolveGlobalAndAliasInits();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user