summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-05-01 04:59:48 +0000
committerChris Lattner <sabre@nondot.org>2007-05-01 04:59:48 +0000
commit48f848716e80d01619b239111db48bfac77baad1 (patch)
tree8ba09ee34c732d5e0c4537fe7755c627ea0476c0
parent90a5c7dbc150af336b6e153427f21fb8a1d46d78 (diff)
downloadllvm-48f848716e80d01619b239111db48bfac77baad1.tar.gz
llvm-48f848716e80d01619b239111db48bfac77baad1.tar.bz2
llvm-48f848716e80d01619b239111db48bfac77baad1.tar.xz
implement scafolding for lazy deserialization of function bodies
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36614 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp65
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h27
2 files changed, 85 insertions, 7 deletions
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 07089a85af..81ba5d7f4e 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -13,7 +13,6 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "BitcodeReader.h"
-#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.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,
const std::string &ModuleID) {
// Reject multiple MODULE_BLOCK's in a single bitstream.
@@ -682,6 +705,8 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
ResolveGlobalAndAliasInits();
if (!GlobalInits.empty() || !AliasInits.empty())
return Error("Malformed global initializer set");
+ if (!FunctionsWithBodies.empty())
+ return Error("Too few function bodies found");
if (Stream.ReadBlockEnd())
return Error("Error at end of module block");
return false;
@@ -709,6 +734,17 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
if (ParseConstants(Stream) || ResolveGlobalAndAliasInits())
return true;
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;
}
@@ -819,6 +855,7 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
"", TheModule);
Func->setCallingConv(Record[1]);
+ bool isProto = Record[2];
Func->setLinkage(GetDecodedLinkage(Record[3]));
Func->setAlignment((1 << Record[4]) >> 1);
if (Record[5]) {
@@ -829,6 +866,11 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
Func->setVisibility(GetDecodedVisibility(Record[6]));
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;
}
// 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");
unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
- BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());
+ Stream.init(BufPtr, BufPtr+Buffer->getBufferSize());
// Sniff for the signature.
if (Stream.Read(8) != 'B' ||
@@ -900,6 +942,25 @@ bool BitcodeReader::ParseBitcode() {
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
//===----------------------------------------------------------------------===//
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index 0935c06f93..470758f0e5 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -17,7 +17,9 @@
#include "llvm/ModuleProvider.h"
#include "llvm/Type.h"
#include "llvm/User.h"
+#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/ADT/DenseMap.h"
#include <vector>
namespace llvm {
@@ -59,14 +61,31 @@ public:
class BitcodeReader : public ModuleProvider {
MemoryBuffer *Buffer;
+ BitstreamReader Stream;
+
const char *ErrorString;
std::vector<PATypeHolder> TypeList;
BitcodeReaderValueList ValueList;
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
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:
- BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) {}
+ BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) {
+ HasReversedFunctionsWithBodies = false;
+ }
~BitcodeReader();
@@ -77,10 +96,7 @@ public:
Buffer = 0;
}
- virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0) {
- // FIXME: TODO
- return false;
- }
+ virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0);
virtual Module *materializeModule(std::string *ErrInfo = 0) {
// FIXME: TODO
@@ -106,6 +122,7 @@ private:
bool ParseTypeSymbolTable(BitstreamReader &Stream);
bool ParseValueSymbolTable(BitstreamReader &Stream);
bool ParseConstants(BitstreamReader &Stream);
+ bool ParseFunction(BitstreamReader &Stream);
bool ResolveGlobalAndAliasInits();
};