2013-04-30 01:49:40 +08:00
|
|
|
//===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This test suite verifies basic MCJIT functionality when invoked form the C
|
|
|
|
// API.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm-c/Analysis.h"
|
|
|
|
#include "llvm-c/Core.h"
|
|
|
|
#include "llvm-c/ExecutionEngine.h"
|
|
|
|
#include "llvm-c/Target.h"
|
|
|
|
#include "llvm-c/Transforms/Scalar.h"
|
2013-05-22 10:46:43 +08:00
|
|
|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
2013-04-30 01:49:40 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
|
|
|
#include "MCJITTestAPICommon.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
static bool didCallAllocateCodeSection;
|
|
|
|
|
|
|
|
static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
|
|
|
|
unsigned alignment,
|
|
|
|
unsigned sectionID) {
|
|
|
|
didCallAllocateCodeSection = true;
|
|
|
|
return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
|
|
|
|
size, alignment, sectionID);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
|
|
|
|
unsigned alignment,
|
|
|
|
unsigned sectionID,
|
|
|
|
LLVMBool isReadOnly) {
|
|
|
|
return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
|
|
|
|
size, alignment, sectionID, isReadOnly);
|
|
|
|
}
|
|
|
|
|
|
|
|
static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
|
|
|
|
std::string errMsgString;
|
|
|
|
bool result =
|
|
|
|
static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
|
|
|
|
if (result) {
|
|
|
|
*errMsg = LLVMCreateMessage(errMsgString.c_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void roundTripDestroy(void *object) {
|
|
|
|
delete static_cast<SectionMemoryManager*>(object);
|
|
|
|
}
|
|
|
|
|
2013-04-30 01:49:40 +08:00
|
|
|
class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
|
|
|
|
protected:
|
|
|
|
MCJITCAPITest() {
|
|
|
|
// The architectures below are known to be compatible with MCJIT as they
|
|
|
|
// are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
|
|
|
|
// kept in sync.
|
2013-05-20 03:44:56 +08:00
|
|
|
SupportedArchs.push_back(Triple::aarch64);
|
2013-04-30 01:49:40 +08:00
|
|
|
SupportedArchs.push_back(Triple::arm);
|
|
|
|
SupportedArchs.push_back(Triple::mips);
|
|
|
|
SupportedArchs.push_back(Triple::x86);
|
|
|
|
SupportedArchs.push_back(Triple::x86_64);
|
|
|
|
|
2013-05-20 04:10:10 +08:00
|
|
|
// Some architectures have sub-architectures in which tests will fail, like
|
|
|
|
// ARM. These two vectors will define if they do have sub-archs (to avoid
|
|
|
|
// extra work for those who don't), and if so, if they are listed to work
|
|
|
|
HasSubArchs.push_back(Triple::arm);
|
|
|
|
SupportedSubArchs.push_back("armv6");
|
|
|
|
SupportedSubArchs.push_back("armv7");
|
|
|
|
|
2013-04-30 01:49:40 +08:00
|
|
|
// The operating systems below are known to be sufficiently incompatible
|
|
|
|
// that they will fail the MCJIT C API tests.
|
|
|
|
UnsupportedOSs.push_back(Triple::Cygwin);
|
|
|
|
}
|
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
virtual void SetUp() {
|
|
|
|
didCallAllocateCodeSection = false;
|
|
|
|
Module = 0;
|
|
|
|
Function = 0;
|
|
|
|
Engine = 0;
|
|
|
|
Error = 0;
|
|
|
|
}
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
virtual void TearDown() {
|
|
|
|
if (Engine)
|
|
|
|
LLVMDisposeExecutionEngine(Engine);
|
|
|
|
else if (Module)
|
|
|
|
LLVMDisposeModule(Module);
|
|
|
|
}
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
void buildSimpleFunction() {
|
|
|
|
Module = LLVMModuleCreateWithName("simple_module");
|
|
|
|
|
|
|
|
LLVMSetTarget(Module, HostTriple.c_str());
|
|
|
|
|
|
|
|
Function = LLVMAddFunction(
|
|
|
|
Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
|
|
|
|
LLVMSetFunctionCallConv(Function, LLVMCCallConv);
|
|
|
|
|
|
|
|
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
|
|
|
|
LLVMBuilderRef builder = LLVMCreateBuilder();
|
|
|
|
LLVMPositionBuilderAtEnd(builder, entry);
|
|
|
|
LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
|
|
|
|
|
|
|
|
LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
|
|
|
|
LLVMDisposeMessage(Error);
|
|
|
|
|
|
|
|
LLVMDisposeBuilder(builder);
|
|
|
|
}
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
void buildMCJITOptions() {
|
|
|
|
LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
|
|
|
|
Options.OptLevel = 2;
|
|
|
|
|
|
|
|
// Just ensure that this field still exists.
|
|
|
|
Options.NoFramePointerElim = false;
|
|
|
|
}
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
void useRoundTripSectionMemoryManager() {
|
|
|
|
Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
|
|
|
|
new SectionMemoryManager(),
|
|
|
|
roundTripAllocateCodeSection,
|
|
|
|
roundTripAllocateDataSection,
|
|
|
|
roundTripFinalizeMemory,
|
|
|
|
roundTripDestroy);
|
|
|
|
}
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
void buildMCJITEngine() {
|
|
|
|
ASSERT_EQ(
|
|
|
|
0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
|
|
|
|
sizeof(Options), &Error));
|
|
|
|
}
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
void buildAndRunPasses() {
|
|
|
|
LLVMPassManagerRef pass = LLVMCreatePassManager();
|
|
|
|
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
|
|
|
|
LLVMAddConstantPropagationPass(pass);
|
|
|
|
LLVMAddInstructionCombiningPass(pass);
|
|
|
|
LLVMRunPassManager(pass, Module);
|
|
|
|
LLVMDisposePassManager(pass);
|
|
|
|
}
|
2013-05-01 14:46:59 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
LLVMModuleRef Module;
|
|
|
|
LLVMValueRef Function;
|
|
|
|
LLVMMCJITCompilerOptions Options;
|
|
|
|
LLVMExecutionEngineRef Engine;
|
|
|
|
char *Error;
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(MCJITCAPITest, simple_function) {
|
|
|
|
SKIP_UNSUPPORTED_PLATFORM;
|
2013-05-22 04:00:56 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
buildSimpleFunction();
|
|
|
|
buildMCJITOptions();
|
|
|
|
buildMCJITEngine();
|
|
|
|
buildAndRunPasses();
|
|
|
|
|
|
|
|
union {
|
|
|
|
void *raw;
|
|
|
|
int (*usable)();
|
|
|
|
} functionPointer;
|
|
|
|
functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
EXPECT_EQ(42, functionPointer.usable());
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(MCJITCAPITest, custom_memory_manager) {
|
|
|
|
SKIP_UNSUPPORTED_PLATFORM;
|
2013-04-30 01:49:40 +08:00
|
|
|
|
2013-05-22 10:46:43 +08:00
|
|
|
buildSimpleFunction();
|
|
|
|
buildMCJITOptions();
|
|
|
|
useRoundTripSectionMemoryManager();
|
|
|
|
buildMCJITEngine();
|
|
|
|
buildAndRunPasses();
|
2013-04-30 01:49:40 +08:00
|
|
|
|
|
|
|
union {
|
|
|
|
void *raw;
|
|
|
|
int (*usable)();
|
|
|
|
} functionPointer;
|
2013-05-22 10:46:43 +08:00
|
|
|
functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
|
2013-04-30 01:49:40 +08:00
|
|
|
|
|
|
|
EXPECT_EQ(42, functionPointer.usable());
|
2013-05-22 10:46:43 +08:00
|
|
|
EXPECT_TRUE(didCallAllocateCodeSection);
|
2013-04-30 01:49:40 +08:00
|
|
|
}
|