mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-23 12:08:25 +00:00
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. llvm-svn: 91943
This commit is contained in:
parent
68e8f657a2
commit
0c46d96fd0
@ -59,6 +59,12 @@ STATISTIC(NumRetries, "Number of retries with more memory");
|
||||
static JIT *TheJIT = 0;
|
||||
|
||||
|
||||
// A declaration may stop being a declaration once it's fully read from bitcode.
|
||||
// This function returns true if F is fully read and is still a declaration.
|
||||
static bool isNonGhostDeclaration(const Function *F) {
|
||||
return F->isDeclaration() && !F->hasNotBeenReadFromBitcode();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// JIT lazy compilation code.
|
||||
//
|
||||
@ -517,15 +523,9 @@ void *JITResolver::getLazyFunctionStub(Function *F) {
|
||||
void *Actual = TheJIT->isCompilingLazily()
|
||||
? (void *)(intptr_t)LazyResolverFn : (void *)0;
|
||||
|
||||
// TODO: Delete this when PR5737 is fixed.
|
||||
std::string ErrorMsg;
|
||||
if (TheJIT->materializeFunction(F, &ErrorMsg)) {
|
||||
llvm_report_error("Error reading function '" + F->getName()+
|
||||
"' from bitcode file: " + ErrorMsg);
|
||||
}
|
||||
// If this is an external declaration, attempt to resolve the address now
|
||||
// to place in the stub.
|
||||
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
|
||||
if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage()) {
|
||||
Actual = TheJIT->getPointerToFunction(F);
|
||||
|
||||
// If we resolved the symbol to a null address (eg. a weak external)
|
||||
@ -558,7 +558,7 @@ void *JITResolver::getLazyFunctionStub(Function *F) {
|
||||
// exist yet, add it to the JIT's work list so that we can fill in the stub
|
||||
// address later.
|
||||
if (!Actual && !TheJIT->isCompilingLazily())
|
||||
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage())
|
||||
if (!isNonGhostDeclaration(F) && !F->hasAvailableExternallyLinkage())
|
||||
TheJIT->addPendingFunction(F);
|
||||
|
||||
return Stub;
|
||||
@ -761,16 +761,9 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
|
||||
void *ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F);
|
||||
if (ResultPtr) return ResultPtr;
|
||||
|
||||
// TODO: Delete this when PR5737 is fixed.
|
||||
std::string ErrorMsg;
|
||||
if (TheJIT->materializeFunction(F, &ErrorMsg)) {
|
||||
llvm_report_error("Error reading function '" + F->getName()+
|
||||
"' from bitcode file: " + ErrorMsg);
|
||||
}
|
||||
|
||||
// If this is an external function pointer, we can force the JIT to
|
||||
// 'compile' it, which really just adds it to the map.
|
||||
if (F->isDeclaration() || F->hasAvailableExternallyLinkage())
|
||||
if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage())
|
||||
return TheJIT->getPointerToFunction(F);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
LEVEL = ../../..
|
||||
TESTNAME = JIT
|
||||
LINK_COMPONENTS := asmparser core support jit native
|
||||
LINK_COMPONENTS := asmparser bitreader bitwriter core jit native support
|
||||
|
||||
include $(LEVEL)/Makefile.config
|
||||
include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
|
||||
|
Loading…
Reference in New Issue
Block a user