Kill ModuleProvider and ghost linkage by inverting the relationship between
Modules and ModuleProviders. Because the "ModuleProvider" simply materializes
GlobalValues now, and doesn't provide modules, it's renamed to
"GVMaterializer". Code that used to need a ModuleProvider to materialize
Functions can now materialize the Functions directly. Functions no longer use a
magic linkage to record that they're materializable; they simply ask the
GVMaterializer.
Because the C ABI must never change, we can't remove LLVMModuleProviderRef or
the functions that refer to it. Instead, because Module now exposes the same
functionality ModuleProvider used to, we store a Module* in any
LLVMModuleProviderRef and translate in the wrapper methods. The bindings to
other languages still use the ModuleProvider concept. It would probably be
worth some time to update them to follow the C++ more closely, but I don't
intend to do it.
Fixes http://llvm.org/PR5737 and http://llvm.org/PR5735.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94686 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Bitcode/Reader/BitReader.cpp b/lib/Bitcode/Reader/BitReader.cpp
index 32b97e8..1facbc3 100644
--- a/lib/Bitcode/Reader/BitReader.cpp
+++ b/lib/Bitcode/Reader/BitReader.cpp
@@ -59,8 +59,8 @@
char **OutMessage) {
std::string Message;
- *OutMP = wrap(getBitcodeModuleProvider(unwrap(MemBuf), getGlobalContext(),
- &Message));
+ *OutMP = reinterpret_cast<LLVMModuleProviderRef>(
+ getLazyBitcodeModule(unwrap(MemBuf), getGlobalContext(), &Message));
if (!*OutMP) {
if (OutMessage)
@@ -77,8 +77,8 @@
char **OutMessage) {
std::string Message;
- *OutMP = wrap(getBitcodeModuleProvider(unwrap(MemBuf), *unwrap(ContextRef),
- &Message));
+ *OutMP = reinterpret_cast<LLVMModuleProviderRef>(
+ getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef), &Message));
if (!*OutMP) {
if (OutMessage)
*OutMessage = strdup(Message.c_str());
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 6dae45f..4dfc6ce 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -28,7 +28,8 @@
using namespace llvm;
void BitcodeReader::FreeState() {
- delete Buffer;
+ if (BufferOwned)
+ delete Buffer;
Buffer = 0;
std::vector<PATypeHolder>().swap(TypeList);
ValueList.clear();
@@ -1241,11 +1242,7 @@
// 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);
+ DeferredFunctionInfo[Fn] = CurBit;
// Skip over the function block for now.
if (Stream.SkipBlock())
@@ -1253,17 +1250,10 @@
return false;
}
-bool BitcodeReader::ParseModule(const std::string &ModuleID) {
- // Reject multiple MODULE_BLOCK's in a single bitstream.
- if (TheModule)
- return Error("Multiple MODULE_BLOCKs in same stream");
-
+bool BitcodeReader::ParseModule() {
if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
return Error("Malformed block record");
- // Otherwise, create the module.
- TheModule = new Module(ModuleID, Context);
-
SmallVector<uint64_t, 64> Record;
std::vector<std::string> SectionTable;
std::vector<std::string> GCTable;
@@ -1520,7 +1510,7 @@
return Error("Premature end of bitstream");
}
-bool BitcodeReader::ParseBitcode() {
+bool BitcodeReader::ParseBitcodeInto(Module *M) {
TheModule = 0;
if (Buffer->getBufferSize() & 3)
@@ -1564,7 +1554,11 @@
return Error("Malformed BlockInfoBlock");
break;
case bitc::MODULE_BLOCK_ID:
- if (ParseModule(Buffer->getBufferIdentifier()))
+ // Reject multiple MODULE_BLOCK's in a single bitstream.
+ if (TheModule)
+ return Error("Multiple MODULE_BLOCKs in same stream");
+ TheModule = M;
+ if (ParseModule())
return true;
break;
default:
@@ -2299,22 +2293,28 @@
}
//===----------------------------------------------------------------------===//
-// ModuleProvider implementation
+// GVMaterializer implementation
//===----------------------------------------------------------------------===//
-bool BitcodeReader::materializeFunction(Function *F, std::string *ErrInfo) {
- // If it already is material, ignore the request.
- if (!F->hasNotBeenReadFromBitcode()) return false;
+bool BitcodeReader::isMaterializable(const GlobalValue *GV) const {
+ if (const Function *F = dyn_cast<Function>(GV)) {
+ return F->isDeclaration() &&
+ DeferredFunctionInfo.count(const_cast<Function*>(F));
+ }
+ return false;
+}
- DenseMap<Function*, std::pair<uint64_t, unsigned> >::iterator DFII =
- DeferredFunctionInfo.find(F);
+bool BitcodeReader::Materialize(GlobalValue *GV, std::string *ErrInfo) {
+ Function *F = dyn_cast<Function>(GV);
+ // 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!");
- // 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);
+ // Move the bit stream to the saved position of the deferred function body.
+ Stream.JumpToBit(DFII->second);
if (ParseFunctionBody(F)) {
if (ErrInfo) *ErrInfo = ErrorString;
@@ -2336,27 +2336,36 @@
return false;
}
-void BitcodeReader::dematerializeFunction(Function *F) {
- // If this function isn't materialized, or if it is a proto, this is a noop.
- if (F->hasNotBeenReadFromBitcode() || F->isDeclaration())
+bool BitcodeReader::isDematerializable(const GlobalValue *GV) const {
+ const Function *F = dyn_cast<Function>(GV);
+ if (!F || F->isDeclaration())
+ return false;
+ return DeferredFunctionInfo.count(const_cast<Function*>(F));
+}
+
+void BitcodeReader::Dematerialize(GlobalValue *GV) {
+ Function *F = dyn_cast<Function>(GV);
+ // If this function isn't dematerializable, this is a noop.
+ if (!F || !isDematerializable(F))
return;
assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
// Just forget the function body, we can remat it later.
F->deleteBody();
- F->setLinkage(GlobalValue::GhostLinkage);
}
-Module *BitcodeReader::materializeModule(std::string *ErrInfo) {
+bool BitcodeReader::MaterializeModule(Module *M, std::string *ErrInfo) {
+ assert(M == TheModule &&
+ "Can only Materialize the Module this BitcodeReader is attached to.");
// Iterate over the module, deserializing any functions that are still on
// disk.
for (Module::iterator F = TheModule->begin(), E = TheModule->end();
F != E; ++F)
- if (F->hasNotBeenReadFromBitcode() &&
- materializeFunction(F, ErrInfo))
- return 0;
+ if (F->isMaterializable() &&
+ Materialize(F, ErrInfo))
+ return true;
// Upgrade any intrinsic calls that slipped through (should not happen!) and
// delete the old functions to clean up. We can't do this unless the entire
@@ -2380,19 +2389,7 @@
// Check debug info intrinsics.
CheckDebugInfoIntrinsics(TheModule);
- return TheModule;
-}
-
-
-/// This method is provided by the parent ModuleProvde class and overriden
-/// here. It simply releases the module from its provided and frees up our
-/// state.
-/// @brief Release our hold on the generated module
-Module *BitcodeReader::releaseModule(std::string *ErrInfo) {
- // Since we're losing control of this Module, we must hand it back complete
- Module *M = ModuleProvider::releaseModule(ErrInfo);
- FreeState();
- return M;
+ return false;
}
@@ -2400,45 +2397,41 @@
// External interface
//===----------------------------------------------------------------------===//
-/// getBitcodeModuleProvider - lazy function-at-a-time loading from a file.
+/// getLazyBitcodeModule - lazy function-at-a-time loading from a file.
///
-ModuleProvider *llvm::getBitcodeModuleProvider(MemoryBuffer *Buffer,
- LLVMContext& Context,
- std::string *ErrMsg) {
+Module *llvm::getLazyBitcodeModule(MemoryBuffer *Buffer,
+ LLVMContext& Context,
+ std::string *ErrMsg) {
+ Module *M = new Module(Buffer->getBufferIdentifier(), Context);
BitcodeReader *R = new BitcodeReader(Buffer, Context);
- if (R->ParseBitcode()) {
+ M->setMaterializer(R);
+ if (R->ParseBitcodeInto(M)) {
if (ErrMsg)
*ErrMsg = R->getErrorString();
- // Don't let the BitcodeReader dtor delete 'Buffer'.
- R->releaseMemoryBuffer();
- delete R;
+ delete M; // Also deletes R.
return 0;
}
- return R;
+ // Have the BitcodeReader dtor delete 'Buffer'.
+ R->setBufferOwned(true);
+ return M;
}
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, return null and fill in *ErrMsg if non-null.
Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
std::string *ErrMsg){
- BitcodeReader *R;
- R = static_cast<BitcodeReader*>(getBitcodeModuleProvider(Buffer, Context,
- ErrMsg));
- if (!R) return 0;
-
- // Read in the entire module.
- Module *M = R->materializeModule(ErrMsg);
+ Module *M = getLazyBitcodeModule(Buffer, Context, ErrMsg);
+ if (!M) return 0;
// Don't let the BitcodeReader dtor delete 'Buffer', regardless of whether
// there was an error.
- R->releaseMemoryBuffer();
+ static_cast<BitcodeReader*>(M->getMaterializer())->setBufferOwned(false);
- // If there was no error, tell ModuleProvider not to delete it when its dtor
- // is run.
- if (M)
- M = R->releaseModule(ErrMsg);
-
- delete R;
+ // Read in the entire module, and destroy the BitcodeReader.
+ if (M->MaterializeAllPermanently(ErrMsg)) {
+ delete M;
+ return NULL;
+ }
return M;
}
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index bb3961a..55c71f7 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -14,7 +14,7 @@
#ifndef BITCODE_READER_H
#define BITCODE_READER_H
-#include "llvm/ModuleProvider.h"
+#include "llvm/GVMaterializer.h"
#include "llvm/Attributes.h"
#include "llvm/Type.h"
#include "llvm/OperandTraits.h"
@@ -121,9 +121,11 @@
void AssignValue(Value *V, unsigned Idx);
};
-class BitcodeReader : public ModuleProvider {
+class BitcodeReader : public GVMaterializer {
LLVMContext &Context;
+ Module *TheModule;
MemoryBuffer *Buffer;
+ bool BufferOwned;
BitstreamReader StreamFile;
BitstreamCursor Stream;
@@ -160,9 +162,9 @@
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;
+ /// map contains info about where to find deferred function body in the
+ /// stream.
+ DenseMap<Function*, uint64_t> DeferredFunctionInfo;
/// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These
/// are resolved lazily when functions are loaded.
@@ -171,7 +173,8 @@
public:
explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C)
- : Context(C), Buffer(buffer), ErrorString(0), ValueList(C), MDValueList(C) {
+ : Context(C), TheModule(0), Buffer(buffer), BufferOwned(false),
+ ErrorString(0), ValueList(C), MDValueList(C) {
HasReversedFunctionsWithBodies = false;
}
~BitcodeReader() {
@@ -180,17 +183,15 @@
void FreeState();
- /// releaseMemoryBuffer - This causes the reader to completely forget about
- /// the memory buffer it contains, which prevents the buffer from being
- /// destroyed when it is deleted.
- void releaseMemoryBuffer() {
- Buffer = 0;
- }
+ /// setBufferOwned - If this is true, the reader will destroy the MemoryBuffer
+ /// when the reader is destroyed.
+ void setBufferOwned(bool Owned) { BufferOwned = Owned; }
- virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0);
- virtual Module *materializeModule(std::string *ErrInfo = 0);
- virtual void dematerializeFunction(Function *F);
- virtual Module *releaseModule(std::string *ErrInfo = 0);
+ virtual bool isMaterializable(const GlobalValue *GV) const;
+ virtual bool isDematerializable(const GlobalValue *GV) const;
+ virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0);
+ virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0);
+ virtual void Dematerialize(GlobalValue *GV);
bool Error(const char *Str) {
ErrorString = Str;
@@ -200,7 +201,7 @@
/// @brief Main interface to parsing a bitcode buffer.
/// @returns true if an error occurred.
- bool ParseBitcode();
+ bool ParseBitcodeInto(Module *M);
private:
const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
Value *getFnValueByID(unsigned ID, const Type *Ty) {
@@ -248,7 +249,7 @@
}
- bool ParseModule(const std::string &ModuleID);
+ bool ParseModule();
bool ParseAttributeBlock();
bool ParseTypeTable();
bool ParseTypeSymbolTable();
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 5a4a1b2..54f756f 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -280,7 +280,6 @@
static unsigned getEncodedLinkage(const GlobalValue *GV) {
switch (GV->getLinkage()) {
default: llvm_unreachable("Invalid linkage!");
- case GlobalValue::GhostLinkage: // Map ghost linkage onto external.
case GlobalValue::ExternalLinkage: return 0;
case GlobalValue::WeakAnyLinkage: return 1;
case GlobalValue::AppendingLinkage: return 2;