//===- MCJITTest.cpp - Unit tests for the MCJIT -----------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This test suite verifies basic MCJIT functionality such as making function // calls, using global variables, and compiling multpile modules. // //===----------------------------------------------------------------------===// #include "MCJITTestBase.h" #include "llvm/Support/DynamicLibrary.h" #include "gtest/gtest.h" usingnamespacellvm; namespace { class MCJITTest : public testing::Test, public MCJITTestBase { … }; // FIXME: Ensure creating an execution engine does not crash when constructed // with a null module. /* TEST_F(MCJITTest, null_module) { createJIT(0); } */ // FIXME: In order to JIT an empty module, there needs to be // an interface to ExecutionEngine that forces compilation but // does not require retrieval of a pointer to a function/global. /* TEST_F(MCJITTest, empty_module) { createJIT(M.take()); //EXPECT_NE(0, TheJIT->getObjectImage()) // << "Unable to generate executable loaded object image"; } */ TEST_F(MCJITTest, global_variable) { … } TEST_F(MCJITTest, add_function) { … } TEST_F(MCJITTest, run_main) { … } TEST_F(MCJITTest, return_global) { … } // FIXME: This case fails due to a bug with getPointerToGlobal(). // The bug is due to MCJIT not having an implementation of getPointerToGlobal() // which results in falling back on the ExecutionEngine implementation that // allocates a new memory block for the global instead of using the same // global variable that is emitted by MCJIT. Hence, the pointer (gvPtr below) // has the correct initial value, but updates to the real global (accessed by // JITted code) are not propagated. Instead, getPointerToGlobal() should return // a pointer into the loaded ObjectImage to reference the emitted global. /* TEST_F(MCJITTest, increment_global) { SKIP_UNSUPPORTED_PLATFORM; int32_t initialNum = 5; Function *IncrementGlobal = startFunction( M.get(), FunctionType::get(Builder.getInt32Ty(), {}, false), "IncrementGlobal"); GlobalVariable *GV = insertGlobalInt32(M.get(), "my_global", initialNum); Value *DerefGV = Builder.CreateLoad(GV); Value *AddResult = Builder.CreateAdd(DerefGV, ConstantInt::get(Context, APInt(32, 1))); Builder.CreateStore(AddResult, GV); endFunctionWithRet(IncrementGlobal, AddResult); createJIT(M.take()); void *gvPtr = TheJIT->getPointerToGlobal(GV); EXPECT_EQ(initialNum, *(int32_t*)gvPtr); void *vPtr = TheJIT->getFunctionAddress(IncrementGlobal->getName().str()); EXPECT_TRUE(0 != vPtr) << "Unable to get pointer to main() from JIT"; int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)vPtr; for(int i = 1; i < 3; ++i) { int32_t result = FuncPtr(); EXPECT_EQ(initialNum + i, result); // OK EXPECT_EQ(initialNum + i, *(int32_t*)gvPtr); // FAILS } } */ // PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations. #if !defined(__arm__) TEST_F(MCJITTest, multiple_functions) { … } #endif /*!defined(__arm__)*/ TEST_F(MCJITTest, multiple_decl_lookups) { … } FunctionHandlerPtr; TEST_F(MCJITTest, lazy_function_creator_pointer) { … } TEST_F(MCJITTest, lazy_function_creator_lambda) { … } } // end anonymous namespace