Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
35233 views
//===-- ExecutionEngineBindings.cpp - C bindings for EEs ------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the C bindings for the ExecutionEngine library.9//10//===----------------------------------------------------------------------===//1112#include "llvm-c/ExecutionEngine.h"13#include "llvm/ExecutionEngine/ExecutionEngine.h"14#include "llvm/ExecutionEngine/GenericValue.h"15#include "llvm/ExecutionEngine/JITEventListener.h"16#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"17#include "llvm/IR/DerivedTypes.h"18#include "llvm/IR/Module.h"19#include "llvm/Support/ErrorHandling.h"20#include "llvm/Target/CodeGenCWrappers.h"21#include "llvm/Target/TargetOptions.h"22#include <cstring>23#include <optional>2425using namespace llvm;2627#define DEBUG_TYPE "jit"2829// Wrapping the C bindings types.30DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef)313233static LLVMTargetMachineRef wrap(const TargetMachine *P) {34return35reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));36}3738/*===-- Operations on generic values --------------------------------------===*/3940LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty,41unsigned long long N,42LLVMBool IsSigned) {43GenericValue *GenVal = new GenericValue();44GenVal->IntVal = APInt(unwrap<IntegerType>(Ty)->getBitWidth(), N, IsSigned);45return wrap(GenVal);46}4748LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) {49GenericValue *GenVal = new GenericValue();50GenVal->PointerVal = P;51return wrap(GenVal);52}5354LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) {55GenericValue *GenVal = new GenericValue();56switch (unwrap(TyRef)->getTypeID()) {57case Type::FloatTyID:58GenVal->FloatVal = N;59break;60case Type::DoubleTyID:61GenVal->DoubleVal = N;62break;63default:64llvm_unreachable("LLVMGenericValueToFloat supports only float and double.");65}66return wrap(GenVal);67}6869unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) {70return unwrap(GenValRef)->IntVal.getBitWidth();71}7273unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef,74LLVMBool IsSigned) {75GenericValue *GenVal = unwrap(GenValRef);76if (IsSigned)77return GenVal->IntVal.getSExtValue();78else79return GenVal->IntVal.getZExtValue();80}8182void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) {83return unwrap(GenVal)->PointerVal;84}8586double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) {87switch (unwrap(TyRef)->getTypeID()) {88case Type::FloatTyID:89return unwrap(GenVal)->FloatVal;90case Type::DoubleTyID:91return unwrap(GenVal)->DoubleVal;92default:93llvm_unreachable("LLVMGenericValueToFloat supports only float and double.");94}95}9697void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) {98delete unwrap(GenVal);99}100101/*===-- Operations on execution engines -----------------------------------===*/102103LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE,104LLVMModuleRef M,105char **OutError) {106std::string Error;107EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));108builder.setEngineKind(EngineKind::Either)109.setErrorStr(&Error);110if (ExecutionEngine *EE = builder.create()){111*OutEE = wrap(EE);112return 0;113}114*OutError = strdup(Error.c_str());115return 1;116}117118LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp,119LLVMModuleRef M,120char **OutError) {121std::string Error;122EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));123builder.setEngineKind(EngineKind::Interpreter)124.setErrorStr(&Error);125if (ExecutionEngine *Interp = builder.create()) {126*OutInterp = wrap(Interp);127return 0;128}129*OutError = strdup(Error.c_str());130return 1;131}132133LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,134LLVMModuleRef M,135unsigned OptLevel,136char **OutError) {137std::string Error;138EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));139builder.setEngineKind(EngineKind::JIT)140.setErrorStr(&Error)141.setOptLevel((CodeGenOptLevel)OptLevel);142if (ExecutionEngine *JIT = builder.create()) {143*OutJIT = wrap(JIT);144return 0;145}146*OutError = strdup(Error.c_str());147return 1;148}149150void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions,151size_t SizeOfPassedOptions) {152LLVMMCJITCompilerOptions options;153memset(&options, 0, sizeof(options)); // Most fields are zero by default.154options.CodeModel = LLVMCodeModelJITDefault;155156memcpy(PassedOptions, &options,157std::min(sizeof(options), SizeOfPassedOptions));158}159160LLVMBool LLVMCreateMCJITCompilerForModule(161LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M,162LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions,163char **OutError) {164LLVMMCJITCompilerOptions options;165// If the user passed a larger sized options struct, then they were compiled166// against a newer LLVM. Tell them that something is wrong.167if (SizeOfPassedOptions > sizeof(options)) {168*OutError = strdup(169"Refusing to use options struct that is larger than my own; assuming "170"LLVM library mismatch.");171return 1;172}173174// Defend against the user having an old version of the API by ensuring that175// any fields they didn't see are cleared. We must defend against fields being176// set to the bitwise equivalent of zero, and assume that this means "do the177// default" as if that option hadn't been available.178LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));179memcpy(&options, PassedOptions, SizeOfPassedOptions);180181TargetOptions targetOptions;182targetOptions.EnableFastISel = options.EnableFastISel;183std::unique_ptr<Module> Mod(unwrap(M));184185if (Mod)186// Set function attribute "frame-pointer" based on187// NoFramePointerElim.188for (auto &F : *Mod) {189auto Attrs = F.getAttributes();190StringRef Value = options.NoFramePointerElim ? "all" : "none";191Attrs = Attrs.addFnAttribute(F.getContext(), "frame-pointer", Value);192F.setAttributes(Attrs);193}194195std::string Error;196EngineBuilder builder(std::move(Mod));197builder.setEngineKind(EngineKind::JIT)198.setErrorStr(&Error)199.setOptLevel((CodeGenOptLevel)options.OptLevel)200.setTargetOptions(targetOptions);201bool JIT;202if (std::optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))203builder.setCodeModel(*CM);204if (options.MCJMM)205builder.setMCJITMemoryManager(206std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));207if (ExecutionEngine *JIT = builder.create()) {208*OutJIT = wrap(JIT);209return 0;210}211*OutError = strdup(Error.c_str());212return 1;213}214215void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) {216delete unwrap(EE);217}218219void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) {220unwrap(EE)->finalizeObject();221unwrap(EE)->runStaticConstructorsDestructors(false);222}223224void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) {225unwrap(EE)->finalizeObject();226unwrap(EE)->runStaticConstructorsDestructors(true);227}228229int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F,230unsigned ArgC, const char * const *ArgV,231const char * const *EnvP) {232unwrap(EE)->finalizeObject();233234std::vector<std::string> ArgVec(ArgV, ArgV + ArgC);235return unwrap(EE)->runFunctionAsMain(unwrap<Function>(F), ArgVec, EnvP);236}237238LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F,239unsigned NumArgs,240LLVMGenericValueRef *Args) {241unwrap(EE)->finalizeObject();242243std::vector<GenericValue> ArgVec;244ArgVec.reserve(NumArgs);245for (unsigned I = 0; I != NumArgs; ++I)246ArgVec.push_back(*unwrap(Args[I]));247248GenericValue *Result = new GenericValue();249*Result = unwrap(EE)->runFunction(unwrap<Function>(F), ArgVec);250return wrap(Result);251}252253void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) {254}255256void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){257unwrap(EE)->addModule(std::unique_ptr<Module>(unwrap(M)));258}259260LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M,261LLVMModuleRef *OutMod, char **OutError) {262Module *Mod = unwrap(M);263unwrap(EE)->removeModule(Mod);264*OutMod = wrap(Mod);265return 0;266}267268LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name,269LLVMValueRef *OutFn) {270if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) {271*OutFn = wrap(F);272return 0;273}274return 1;275}276277void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE,278LLVMValueRef Fn) {279return nullptr;280}281282LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) {283return wrap(&unwrap(EE)->getDataLayout());284}285286LLVMTargetMachineRef287LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) {288return wrap(unwrap(EE)->getTargetMachine());289}290291void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,292void* Addr) {293unwrap(EE)->addGlobalMapping(unwrap<GlobalValue>(Global), Addr);294}295296void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) {297unwrap(EE)->finalizeObject();298299return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global));300}301302uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) {303return unwrap(EE)->getGlobalValueAddress(Name);304}305306uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) {307return unwrap(EE)->getFunctionAddress(Name);308}309310LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE,311char **OutError) {312assert(OutError && "OutError must be non-null");313auto *ExecEngine = unwrap(EE);314if (ExecEngine->hasError()) {315*OutError = strdup(ExecEngine->getErrorMessage().c_str());316ExecEngine->clearErrorMessage();317return true;318}319return false;320}321322/*===-- Operations on memory managers -------------------------------------===*/323324namespace {325326struct SimpleBindingMMFunctions {327LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection;328LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection;329LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory;330LLVMMemoryManagerDestroyCallback Destroy;331};332333class SimpleBindingMemoryManager : public RTDyldMemoryManager {334public:335SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions,336void *Opaque);337~SimpleBindingMemoryManager() override;338339uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,340unsigned SectionID,341StringRef SectionName) override;342343uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,344unsigned SectionID, StringRef SectionName,345bool isReadOnly) override;346347bool finalizeMemory(std::string *ErrMsg) override;348349private:350SimpleBindingMMFunctions Functions;351void *Opaque;352};353354SimpleBindingMemoryManager::SimpleBindingMemoryManager(355const SimpleBindingMMFunctions& Functions,356void *Opaque)357: Functions(Functions), Opaque(Opaque) {358assert(Functions.AllocateCodeSection &&359"No AllocateCodeSection function provided!");360assert(Functions.AllocateDataSection &&361"No AllocateDataSection function provided!");362assert(Functions.FinalizeMemory &&363"No FinalizeMemory function provided!");364assert(Functions.Destroy &&365"No Destroy function provided!");366}367368SimpleBindingMemoryManager::~SimpleBindingMemoryManager() {369Functions.Destroy(Opaque);370}371372uint8_t *SimpleBindingMemoryManager::allocateCodeSection(373uintptr_t Size, unsigned Alignment, unsigned SectionID,374StringRef SectionName) {375return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID,376SectionName.str().c_str());377}378379uint8_t *SimpleBindingMemoryManager::allocateDataSection(380uintptr_t Size, unsigned Alignment, unsigned SectionID,381StringRef SectionName, bool isReadOnly) {382return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID,383SectionName.str().c_str(),384isReadOnly);385}386387bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) {388char *errMsgCString = nullptr;389bool result = Functions.FinalizeMemory(Opaque, &errMsgCString);390assert((result || !errMsgCString) &&391"Did not expect an error message if FinalizeMemory succeeded");392if (errMsgCString) {393if (ErrMsg)394*ErrMsg = errMsgCString;395free(errMsgCString);396}397return result;398}399400} // anonymous namespace401402LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager(403void *Opaque,404LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection,405LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection,406LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory,407LLVMMemoryManagerDestroyCallback Destroy) {408409if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory ||410!Destroy)411return nullptr;412413SimpleBindingMMFunctions functions;414functions.AllocateCodeSection = AllocateCodeSection;415functions.AllocateDataSection = AllocateDataSection;416functions.FinalizeMemory = FinalizeMemory;417functions.Destroy = Destroy;418return wrap(new SimpleBindingMemoryManager(functions, Opaque));419}420421void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) {422delete unwrap(MM);423}424425/*===-- JIT Event Listener functions -------------------------------------===*/426427428#if !LLVM_USE_INTEL_JITEVENTS429LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void)430{431return nullptr;432}433#endif434435#if !LLVM_USE_OPROFILE436LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void)437{438return nullptr;439}440#endif441442#if !LLVM_USE_PERF443LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void)444{445return nullptr;446}447#endif448449450