Partially revert r91626. Materializing extra functions to determine whether

they're available_externally broke VMKit, which was relying on the fact that
functions would only be materialized when they were first called.  We'll have
to wait for http://llvm.org/PR5737 to really fix this.

I also added a test for one of the F->isDeclaration() calls which wasn't
covered by anything else in the test suite.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91943 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jeffrey Yasskin
2009-12-22 23:47:23 +00:00
parent 3dbcb55b40
commit c5818fb837
3 changed files with 106 additions and 23 deletions

View File

@ -12,6 +12,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/BasicBlock.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
@ -24,6 +25,7 @@
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TypeBuilder.h"
#include "llvm/Target/TargetSelect.h"
@ -177,6 +179,17 @@ public:
}
};
bool LoadAssemblyInto(Module *M, const char *assembly) {
SMDiagnostic Error;
bool success =
NULL != ParseAssemblyString(assembly, M, Error, M->getContext());
std::string errMsg;
raw_string_ostream os(errMsg);
Error.Print("", os);
EXPECT_TRUE(success) << os.str();
return success;
}
class JITTest : public testing::Test {
protected:
virtual void SetUp() {
@ -192,12 +205,7 @@ class JITTest : public testing::Test {
}
void LoadAssembly(const char *assembly) {
SMDiagnostic Error;
bool success = NULL != ParseAssemblyString(assembly, M, Error, Context);
std::string errMsg;
raw_string_ostream os(errMsg);
Error.Print("", os);
ASSERT_TRUE(success) << os.str();
LoadAssemblyInto(M, assembly);
}
LLVMContext Context;
@ -619,6 +627,88 @@ TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) {
<< " not 7 from the IR version.";
}
// Converts the LLVM assembly to bitcode and returns it in a std::string. An
// empty string indicates an error.
std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) {
Module TempModule("TempModule", Context);
if (!LoadAssemblyInto(&TempModule, Assembly)) {
return "";
}
std::string Result;
raw_string_ostream OS(Result);
WriteBitcodeToFile(&TempModule, OS);
OS.flush();
return Result;
}
// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode'
// lazily. The associated ModuleProvider (owned by the ExecutionEngine) is
// returned in MP. Both will be NULL on an error. Bitcode must live at least
// as long as the ExecutionEngine.
ExecutionEngine *getJITFromBitcode(
LLVMContext &Context, const std::string &Bitcode, ModuleProvider *&MP) {
// c_str() is null-terminated like MemoryBuffer::getMemBuffer requires.
MemoryBuffer *BitcodeBuffer =
MemoryBuffer::getMemBuffer(Bitcode.c_str(),
Bitcode.c_str() + Bitcode.size(),
"Bitcode for test");
std::string errMsg;
MP = getBitcodeModuleProvider(BitcodeBuffer, Context, &errMsg);
if (MP == NULL) {
ADD_FAILURE() << errMsg;
delete BitcodeBuffer;
return NULL;
}
ExecutionEngine *TheJIT = EngineBuilder(MP)
.setEngineKind(EngineKind::JIT)
.setErrorStr(&errMsg)
.create();
if (TheJIT == NULL) {
ADD_FAILURE() << errMsg;
delete MP;
MP = NULL;
return NULL;
}
return TheJIT;
}
TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) {
LLVMContext Context;
const std::string Bitcode =
AssembleToBitcode(Context,
"define i32 @recur1(i32 %a) { "
" %zero = icmp eq i32 %a, 0 "
" br i1 %zero, label %done, label %notdone "
"done: "
" ret i32 3 "
"notdone: "
" %am1 = sub i32 %a, 1 "
" %result = call i32 @recur2(i32 %am1) "
" ret i32 %result "
"} "
" "
"define i32 @recur2(i32 %b) { "
" %result = call i32 @recur1(i32 %b) "
" ret i32 %result "
"} ");
ASSERT_FALSE(Bitcode.empty()) << "Assembling failed";
ModuleProvider *MP;
OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, MP));
ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT.";
TheJIT->DisableLazyCompilation(true);
Module *M = MP->getModule();
Function *recur1IR = M->getFunction("recur1");
Function *recur2IR = M->getFunction("recur2");
EXPECT_TRUE(recur1IR->hasNotBeenReadFromBitcode());
EXPECT_TRUE(recur2IR->hasNotBeenReadFromBitcode());
int32_t (*recur1)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>(
(intptr_t)TheJIT->getPointerToFunction(recur1IR));
EXPECT_EQ(3, recur1(4));
}
// This code is copied from JITEventListenerTest, but it only runs once for all
// the tests in this directory. Everything seems fine, but that's strange
// behavior.