1d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//===- MCJITTest.cpp - Unit tests for the MCJIT ---------------------------===//
2d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//
3d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//                     The LLVM Compiler Infrastructure
4d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//
5d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor// This file is distributed under the University of Illinois Open Source
6d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor// License. See LICENSE.TXT for details.
7d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//
8d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//===----------------------------------------------------------------------===//
9d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//
10d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor// This test suite verifies basic MCJIT functionality when invoked form the C
11d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor// API.
12d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//
13d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor//===----------------------------------------------------------------------===//
14d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
15d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "llvm-c/Analysis.h"
16d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "llvm-c/Core.h"
17d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "llvm-c/ExecutionEngine.h"
18d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "llvm-c/Target.h"
19d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "llvm-c/Transforms/Scalar.h"
206cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo#include "llvm/ExecutionEngine/SectionMemoryManager.h"
21d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "llvm/Support/Host.h"
22d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "MCJITTestAPICommon.h"
23d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor#include "gtest/gtest.h"
24d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
25d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylorusing namespace llvm;
26d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
276cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlostatic bool didCallAllocateCodeSection;
286cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
296cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlostatic uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
306cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo                                             unsigned alignment,
316cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo                                             unsigned sectionID) {
326cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  didCallAllocateCodeSection = true;
336cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
346cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    size, alignment, sectionID);
356cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo}
366cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
376cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlostatic uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
386cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo                                             unsigned alignment,
396cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo                                             unsigned sectionID,
406cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo                                             LLVMBool isReadOnly) {
416cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
426cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    size, alignment, sectionID, isReadOnly);
436cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo}
446cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
456cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlostatic LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
466cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  std::string errMsgString;
476cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  bool result =
486cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
496cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  if (result) {
506cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    *errMsg = LLVMCreateMessage(errMsgString.c_str());
516cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    return 1;
526cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
536cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  return 0;
546cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo}
556cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
566cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlostatic void roundTripDestroy(void *object) {
576cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  delete static_cast<SectionMemoryManager*>(object);
586cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo}
596cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
60d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylorclass MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
61d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylorprotected:
62d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor  MCJITCAPITest() {
63d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    // The architectures below are known to be compatible with MCJIT as they
64d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
65d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    // kept in sync.
66233a4d7124ecf9611804e3c75102cdcf7d2fd074Tim Northover    SupportedArchs.push_back(Triple::aarch64);
67d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    SupportedArchs.push_back(Triple::arm);
68d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    SupportedArchs.push_back(Triple::mips);
69d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    SupportedArchs.push_back(Triple::x86);
70d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    SupportedArchs.push_back(Triple::x86_64);
71d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
724e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin    // Some architectures have sub-architectures in which tests will fail, like
734e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin    // ARM. These two vectors will define if they do have sub-archs (to avoid
744e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin    // extra work for those who don't), and if so, if they are listed to work
754e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin    HasSubArchs.push_back(Triple::arm);
764e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin    SupportedSubArchs.push_back("armv6");
774e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin    SupportedSubArchs.push_back("armv7");
784e4464bf744030ae4a775bf49a30e9e4ea625682Renato Golin
79d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    // The operating systems below are known to be sufficiently incompatible
80d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    // that they will fail the MCJIT C API tests.
81d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    UnsupportedOSs.push_back(Triple::Cygwin);
82d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor  }
83d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
846cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  virtual void SetUp() {
856cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    didCallAllocateCodeSection = false;
866cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Module = 0;
876cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Function = 0;
886cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Engine = 0;
896cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Error = 0;
906cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
91d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
926cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  virtual void TearDown() {
936cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    if (Engine)
946cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      LLVMDisposeExecutionEngine(Engine);
956cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    else if (Module)
966cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      LLVMDisposeModule(Module);
976cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
98d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
996cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  void buildSimpleFunction() {
1006cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Module = LLVMModuleCreateWithName("simple_module");
1016cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1026cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMSetTarget(Module, HostTriple.c_str());
1036cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1046cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Function = LLVMAddFunction(
1056cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
1066cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMSetFunctionCallConv(Function, LLVMCCallConv);
1076cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1086cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
1096cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMBuilderRef builder = LLVMCreateBuilder();
1106cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMPositionBuilderAtEnd(builder, entry);
1116cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
1126cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1136cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
1146cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMDisposeMessage(Error);
1156cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1166cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMDisposeBuilder(builder);
1176cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
118d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
1196cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  void buildMCJITOptions() {
1206cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
1216cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Options.OptLevel = 2;
1226cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1236cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    // Just ensure that this field still exists.
1246cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Options.NoFramePointerElim = false;
1256cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
126d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
1276cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  void useRoundTripSectionMemoryManager() {
1286cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
1296cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      new SectionMemoryManager(),
1306cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      roundTripAllocateCodeSection,
1316cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      roundTripAllocateDataSection,
1326cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      roundTripFinalizeMemory,
1336cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      roundTripDestroy);
1346cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
135d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
1366cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  void buildMCJITEngine() {
1376cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    ASSERT_EQ(
1386cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo      0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
1396cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo                                          sizeof(Options), &Error));
1406cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
141d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
1426cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  void buildAndRunPasses() {
1436cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMPassManagerRef pass = LLVMCreatePassManager();
1446cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
1456cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMAddConstantPropagationPass(pass);
1466cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMAddInstructionCombiningPass(pass);
1476cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMRunPassManager(pass, Module);
1486cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    LLVMDisposePassManager(pass);
1496cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  }
150a4fa74e38163ec3dc652f31ddac2c08e4a05889cFilip Pizlo
1516cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  LLVMModuleRef Module;
1526cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  LLVMValueRef Function;
1536cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  LLVMMCJITCompilerOptions Options;
1546cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  LLVMExecutionEngineRef Engine;
1556cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  char *Error;
1566cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo};
1576cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1586cfed36338d7728076ddbc1331908b887a4302d3Filip PizloTEST_F(MCJITCAPITest, simple_function) {
1596cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  SKIP_UNSUPPORTED_PLATFORM;
16052755c472a738e48a9687240368e4c1f78c45711Filip Pizlo
1616cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildSimpleFunction();
1626cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildMCJITOptions();
1636cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildMCJITEngine();
1646cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildAndRunPasses();
1656cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1666cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  union {
1676cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    void *raw;
1686cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo    int (*usable)();
1696cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  } functionPointer;
1706cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
171d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
1726cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  EXPECT_EQ(42, functionPointer.usable());
1736cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo}
1746cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo
1756cfed36338d7728076ddbc1331908b887a4302d3Filip PizloTEST_F(MCJITCAPITest, custom_memory_manager) {
1766cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  SKIP_UNSUPPORTED_PLATFORM;
177d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
1786cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildSimpleFunction();
1796cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildMCJITOptions();
1806cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  useRoundTripSectionMemoryManager();
1816cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildMCJITEngine();
1826cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  buildAndRunPasses();
183d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
184d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor  union {
185d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    void *raw;
186d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor    int (*usable)();
187d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor  } functionPointer;
1886cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
189d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor
190d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor  EXPECT_EQ(42, functionPointer.usable());
1916cfed36338d7728076ddbc1331908b887a4302d3Filip Pizlo  EXPECT_TRUE(didCallAllocateCodeSection);
192d2755af8bda2e0fd80efb46556485c4cdbe8704aAndrew Kaylor}
193