Index: lib/Bitcode/Reader/BitcodeReader.cpp |
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp |
index fa1290c9246e45110f748d8a1bab7f67ca569d12..7535fcf5255782b231134e6668a0c20d82b3aed1 100644 |
--- a/lib/Bitcode/Reader/BitcodeReader.cpp |
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp |
@@ -1528,6 +1528,7 @@ bool BitcodeReader::RememberAndSkipFunctionBody() { |
Function *Fn = FunctionsWithBodies.back(); |
FunctionsWithBodies.pop_back(); |
+ fprintf(stderr, "skipping %p\n", Fn); |
// Save the current stream state. |
uint64_t CurBit = Stream.GetCurrentBitNo(); |
@@ -1539,10 +1540,47 @@ bool BitcodeReader::RememberAndSkipFunctionBody() { |
return false; |
} |
-bool BitcodeReader::ParseModule() { |
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) |
+bool BitcodeReader::SuspendModuleParse() { |
+ // save our current position |
+ NextUnreadBit = Stream.GetCurrentBitNo(); |
+ // Patch the initializers for globals and aliases up. |
+ // TODO(dschuff) this probably only needs to be done once as well |
+ ResolveGlobalAndAliasInits(); |
+ if (!GlobalInits.empty() || !AliasInits.empty()) |
+ return Error("Malformed global initializer set"); |
+ |
+ // Look for intrinsic functions which need to be upgraded at some point |
+ // TODO(dschuff): do these intrinsics have bodies? if not, this can be |
+ // done only once, before we start dealing with function bodies. if so, |
+ // this can probably still be done incrementally instead of this copy/paste |
+ // hack |
+ for (Module::iterator FI = TheModule->begin(), FE = TheModule->end(); |
+ FI != FE; ++FI) { |
+ Function* NewFn; |
+ if (UpgradeIntrinsicFunction(FI, NewFn)) |
+ UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn)); |
+ } |
+ |
+ // TODO(dschuff) this probably only needs to be done once (currently it's a |
jasonwkim
2011/11/03 17:54:09
I think upstream guys dont like TODO(username) -
(google.com) Derek Schuff
2011/11/03 18:01:27
These will go away before I upstream it.
On 2011/
|
+ // noop anyway). find the right place to put it |
+ // Look for global variables which need to be renamed. |
+ for (Module::global_iterator |
+ GI = TheModule->global_begin(), GE = TheModule->global_end(); |
+ GI != GE; ++GI) |
+ UpgradeGlobalVariable(GI); |
+ // Force deallocation of memory for these vectors to favor the client that |
+ // want lazy deserialization. |
+ std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits); |
+ std::vector<std::pair<GlobalAlias*, unsigned> >().swap(AliasInits); |
+ return false; |
+} |
+ |
+bool BitcodeReader::ParseModule(bool Resume) { |
+ if (Resume) |
+ Stream.JumpToBit(NextUnreadBit); |
+ else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) |
return Error("Malformed block record"); |
-fprintf(stderr, "module at byte %d\n", Stream.GetCurrentBitNo()*8); |
+fprintf(stderr, "module at byte %lu\n", Stream.GetCurrentBitNo()/8); |
SmallVector<uint64_t, 64> Record; |
std::vector<std::string> SectionTable; |
std::vector<std::string> GCTable; |
@@ -1631,6 +1669,7 @@ fprintf(stderr, "module at byte %d\n", Stream.GetCurrentBitNo()*8); |
if (RememberAndSkipFunctionBody()) |
return true; |
+ if (LazyStreamer) return SuspendModuleParse(); |
break; |
} |
continue; |
@@ -1775,6 +1814,7 @@ fprintf(stderr, "module at byte %d\n", Stream.GetCurrentBitNo()*8); |
Func->setCallingConv(static_cast<CallingConv::ID>(Record[1])); |
bool isProto = Record[2]; |
+ fprintf(stderr, "func record %p isProto %d\n", Func, isProto); |
Func->setLinkage(GetDecodedLinkage(Record[3])); |
Func->setAttributes(getAttributes(Record[4])); |
@@ -1798,8 +1838,10 @@ fprintf(stderr, "module at byte %d\n", Stream.GetCurrentBitNo()*8); |
// 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) |
+ if (!isProto) { |
FunctionsWithBodies.push_back(Func); |
+ if (LazyStreamer) DeferredFunctionInfo[Func] = 0; |
+ } |
break; |
} |
// ALIAS: [alias type, aliasee val#, linkage] |
@@ -1880,8 +1922,9 @@ fprintf(stderr, "ParseBitcodeInto code %d\n", Code); |
if (TheModule) |
return Error("Multiple MODULE_BLOCKs in same stream"); |
TheModule = M; |
- if (ParseModule()) |
+ if (ParseModule(false)) |
return true; |
+ if (LazyStreamer) return false; |
break; |
default: |
if (Stream.SkipBlock()) |
@@ -2843,17 +2886,32 @@ bool BitcodeReader::isMaterializable(const GlobalValue *GV) const { |
return false; |
} |
+bool BitcodeReader::FindFunctionInStream(Function *F, |
+ DenseMap<Function*, uint64_t>::iterator DFII) { |
+ //Stream.JumpToBit(NextUnreadBit); |
+ while (DFII->second == 0) { |
+ if (Stream.AtEndOfStream()) |
+ return Error("Could not find Function in stream"); |
+ if(ParseModule(true)) return true; |
+ } |
+ return false; |
+} |
+ |
bool BitcodeReader::Materialize(GlobalValue *GV, std::string *ErrInfo) { |
Function *F = dyn_cast<Function>(GV); |
+ fprintf(stderr, "Materialize %p (%s)\n", F, F->getName().str().c_str()); |
// If it's not a function or is already material, ignore the request. |
if (!F || !F->isMaterializable()) return false; |
DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F); |
assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!"); |
+ if(DFII->second == 0) { |
+ if (LazyStreamer && FindFunctionInStream(F, DFII)) return true; |
+ } |
// Move the bit stream to the saved position of the deferred function body. |
Stream.JumpToBit(DFII->second); |
- fprintf(stderr, "Materialize %s\n", F->getName().str().c_str()); |
+ |
if (ParseFunctionBody(F)) { |
if (ErrInfo) *ErrInfo = ErrorString; |
return true; |