mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	the C API to provide their own way of allocating JIT memory (both code and data) and finalizing memory permissions (page protections, cache flush). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182448 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			193 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===- 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"
 | 
						|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
 | 
						|
#include "llvm/Support/Host.h"
 | 
						|
#include "MCJITTestAPICommon.h"
 | 
						|
#include "gtest/gtest.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
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);
 | 
						|
}
 | 
						|
 | 
						|
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.
 | 
						|
    SupportedArchs.push_back(Triple::aarch64);
 | 
						|
    SupportedArchs.push_back(Triple::arm);
 | 
						|
    SupportedArchs.push_back(Triple::mips);
 | 
						|
    SupportedArchs.push_back(Triple::x86);
 | 
						|
    SupportedArchs.push_back(Triple::x86_64);
 | 
						|
 | 
						|
    // 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");
 | 
						|
 | 
						|
    // The operating systems below are known to be sufficiently incompatible
 | 
						|
    // that they will fail the MCJIT C API tests.
 | 
						|
    UnsupportedOSs.push_back(Triple::Cygwin);
 | 
						|
  }
 | 
						|
  
 | 
						|
  virtual void SetUp() {
 | 
						|
    didCallAllocateCodeSection = false;
 | 
						|
    Module = 0;
 | 
						|
    Function = 0;
 | 
						|
    Engine = 0;
 | 
						|
    Error = 0;
 | 
						|
  }
 | 
						|
  
 | 
						|
  virtual void TearDown() {
 | 
						|
    if (Engine)
 | 
						|
      LLVMDisposeExecutionEngine(Engine);
 | 
						|
    else if (Module)
 | 
						|
      LLVMDisposeModule(Module);
 | 
						|
  }
 | 
						|
  
 | 
						|
  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);
 | 
						|
  }
 | 
						|
  
 | 
						|
  void buildMCJITOptions() {
 | 
						|
    LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
 | 
						|
    Options.OptLevel = 2;
 | 
						|
    
 | 
						|
    // Just ensure that this field still exists.
 | 
						|
    Options.NoFramePointerElim = false;
 | 
						|
  }
 | 
						|
  
 | 
						|
  void useRoundTripSectionMemoryManager() {
 | 
						|
    Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
 | 
						|
      new SectionMemoryManager(),
 | 
						|
      roundTripAllocateCodeSection,
 | 
						|
      roundTripAllocateDataSection,
 | 
						|
      roundTripFinalizeMemory,
 | 
						|
      roundTripDestroy);
 | 
						|
  }
 | 
						|
  
 | 
						|
  void buildMCJITEngine() {
 | 
						|
    ASSERT_EQ(
 | 
						|
      0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
 | 
						|
                                          sizeof(Options), &Error));
 | 
						|
  }
 | 
						|
  
 | 
						|
  void buildAndRunPasses() {
 | 
						|
    LLVMPassManagerRef pass = LLVMCreatePassManager();
 | 
						|
    LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
 | 
						|
    LLVMAddConstantPropagationPass(pass);
 | 
						|
    LLVMAddInstructionCombiningPass(pass);
 | 
						|
    LLVMRunPassManager(pass, Module);
 | 
						|
    LLVMDisposePassManager(pass);
 | 
						|
  }
 | 
						|
  
 | 
						|
  LLVMModuleRef Module;
 | 
						|
  LLVMValueRef Function;
 | 
						|
  LLVMMCJITCompilerOptions Options;
 | 
						|
  LLVMExecutionEngineRef Engine;
 | 
						|
  char *Error;
 | 
						|
};
 | 
						|
 | 
						|
TEST_F(MCJITCAPITest, simple_function) {
 | 
						|
  SKIP_UNSUPPORTED_PLATFORM;
 | 
						|
  
 | 
						|
  buildSimpleFunction();
 | 
						|
  buildMCJITOptions();
 | 
						|
  buildMCJITEngine();
 | 
						|
  buildAndRunPasses();
 | 
						|
  
 | 
						|
  union {
 | 
						|
    void *raw;
 | 
						|
    int (*usable)();
 | 
						|
  } functionPointer;
 | 
						|
  functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
 | 
						|
  
 | 
						|
  EXPECT_EQ(42, functionPointer.usable());
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(MCJITCAPITest, custom_memory_manager) {
 | 
						|
  SKIP_UNSUPPORTED_PLATFORM;
 | 
						|
  
 | 
						|
  buildSimpleFunction();
 | 
						|
  buildMCJITOptions();
 | 
						|
  useRoundTripSectionMemoryManager();
 | 
						|
  buildMCJITEngine();
 | 
						|
  buildAndRunPasses();
 | 
						|
  
 | 
						|
  union {
 | 
						|
    void *raw;
 | 
						|
    int (*usable)();
 | 
						|
  } functionPointer;
 | 
						|
  functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
 | 
						|
  
 | 
						|
  EXPECT_EQ(42, functionPointer.usable());
 | 
						|
  EXPECT_TRUE(didCallAllocateCodeSection);
 | 
						|
}
 |