Home | History | Annotate | Download | only in MCJIT
      1 //===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This test suite verifies basic MCJIT functionality when invoked form the C
     11 // API.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm-c/Analysis.h"
     16 #include "llvm-c/Core.h"
     17 #include "llvm-c/ExecutionEngine.h"
     18 #include "llvm-c/Target.h"
     19 #include "llvm-c/Transforms/Scalar.h"
     20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
     21 #include "llvm/Support/Host.h"
     22 #include "MCJITTestAPICommon.h"
     23 #include "gtest/gtest.h"
     24 
     25 using namespace llvm;
     26 
     27 static bool didCallAllocateCodeSection;
     28 
     29 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
     30                                              unsigned alignment,
     31                                              unsigned sectionID) {
     32   didCallAllocateCodeSection = true;
     33   return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
     34     size, alignment, sectionID);
     35 }
     36 
     37 static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
     38                                              unsigned alignment,
     39                                              unsigned sectionID,
     40                                              LLVMBool isReadOnly) {
     41   return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
     42     size, alignment, sectionID, isReadOnly);
     43 }
     44 
     45 static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
     46   std::string errMsgString;
     47   bool result =
     48     static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
     49   if (result) {
     50     *errMsg = LLVMCreateMessage(errMsgString.c_str());
     51     return 1;
     52   }
     53   return 0;
     54 }
     55 
     56 static void roundTripDestroy(void *object) {
     57   delete static_cast<SectionMemoryManager*>(object);
     58 }
     59 
     60 class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
     61 protected:
     62   MCJITCAPITest() {
     63     // The architectures below are known to be compatible with MCJIT as they
     64     // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
     65     // kept in sync.
     66     SupportedArchs.push_back(Triple::aarch64);
     67     SupportedArchs.push_back(Triple::arm);
     68     SupportedArchs.push_back(Triple::mips);
     69     SupportedArchs.push_back(Triple::x86);
     70     SupportedArchs.push_back(Triple::x86_64);
     71 
     72     // Some architectures have sub-architectures in which tests will fail, like
     73     // ARM. These two vectors will define if they do have sub-archs (to avoid
     74     // extra work for those who don't), and if so, if they are listed to work
     75     HasSubArchs.push_back(Triple::arm);
     76     SupportedSubArchs.push_back("armv6");
     77     SupportedSubArchs.push_back("armv7");
     78 
     79     // The operating systems below are known to be sufficiently incompatible
     80     // that they will fail the MCJIT C API tests.
     81     UnsupportedOSs.push_back(Triple::Cygwin);
     82   }
     83 
     84   virtual void SetUp() {
     85     didCallAllocateCodeSection = false;
     86     Module = 0;
     87     Function = 0;
     88     Engine = 0;
     89     Error = 0;
     90   }
     91 
     92   virtual void TearDown() {
     93     if (Engine)
     94       LLVMDisposeExecutionEngine(Engine);
     95     else if (Module)
     96       LLVMDisposeModule(Module);
     97   }
     98 
     99   void buildSimpleFunction() {
    100     Module = LLVMModuleCreateWithName("simple_module");
    101 
    102     LLVMSetTarget(Module, HostTriple.c_str());
    103 
    104     Function = LLVMAddFunction(
    105       Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
    106     LLVMSetFunctionCallConv(Function, LLVMCCallConv);
    107 
    108     LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
    109     LLVMBuilderRef builder = LLVMCreateBuilder();
    110     LLVMPositionBuilderAtEnd(builder, entry);
    111     LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
    112 
    113     LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
    114     LLVMDisposeMessage(Error);
    115 
    116     LLVMDisposeBuilder(builder);
    117   }
    118 
    119   void buildMCJITOptions() {
    120     LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
    121     Options.OptLevel = 2;
    122 
    123     // Just ensure that this field still exists.
    124     Options.NoFramePointerElim = false;
    125   }
    126 
    127   void useRoundTripSectionMemoryManager() {
    128     Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
    129       new SectionMemoryManager(),
    130       roundTripAllocateCodeSection,
    131       roundTripAllocateDataSection,
    132       roundTripFinalizeMemory,
    133       roundTripDestroy);
    134   }
    135 
    136   void buildMCJITEngine() {
    137     ASSERT_EQ(
    138       0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
    139                                           sizeof(Options), &Error));
    140   }
    141 
    142   void buildAndRunPasses() {
    143     LLVMPassManagerRef pass = LLVMCreatePassManager();
    144     LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
    145     LLVMAddConstantPropagationPass(pass);
    146     LLVMAddInstructionCombiningPass(pass);
    147     LLVMRunPassManager(pass, Module);
    148     LLVMDisposePassManager(pass);
    149   }
    150 
    151   LLVMModuleRef Module;
    152   LLVMValueRef Function;
    153   LLVMMCJITCompilerOptions Options;
    154   LLVMExecutionEngineRef Engine;
    155   char *Error;
    156 };
    157 
    158 TEST_F(MCJITCAPITest, simple_function) {
    159   SKIP_UNSUPPORTED_PLATFORM;
    160 
    161   buildSimpleFunction();
    162   buildMCJITOptions();
    163   buildMCJITEngine();
    164   buildAndRunPasses();
    165 
    166   union {
    167     void *raw;
    168     int (*usable)();
    169   } functionPointer;
    170   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
    171 
    172   EXPECT_EQ(42, functionPointer.usable());
    173 }
    174 
    175 TEST_F(MCJITCAPITest, custom_memory_manager) {
    176   SKIP_UNSUPPORTED_PLATFORM;
    177 
    178   buildSimpleFunction();
    179   buildMCJITOptions();
    180   useRoundTripSectionMemoryManager();
    181   buildMCJITEngine();
    182   buildAndRunPasses();
    183 
    184   union {
    185     void *raw;
    186     int (*usable)();
    187   } functionPointer;
    188   functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
    189 
    190   EXPECT_EQ(42, functionPointer.usable());
    191   EXPECT_TRUE(didCallAllocateCodeSection);
    192 }
    193