448 lines · cpp
1//===-- ExecutionEngineBindings.cpp - C bindings for EEs ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the C bindings for the ExecutionEngine library.10//11//===----------------------------------------------------------------------===//12 13#include "llvm-c/ExecutionEngine.h"14#include "llvm/ExecutionEngine/ExecutionEngine.h"15#include "llvm/ExecutionEngine/GenericValue.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>24 25using namespace llvm;26 27#define DEBUG_TYPE "jit"28 29// Wrapping the C bindings types.30DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef)31 32 33static LLVMTargetMachineRef wrap(const TargetMachine *P) {34 return35 reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));36}37 38/*===-- Operations on generic values --------------------------------------===*/39 40LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty,41 unsigned long long N,42 LLVMBool IsSigned) {43 GenericValue *GenVal = new GenericValue();44 GenVal->IntVal = APInt(unwrap<IntegerType>(Ty)->getBitWidth(), N, IsSigned);45 return wrap(GenVal);46}47 48LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) {49 GenericValue *GenVal = new GenericValue();50 GenVal->PointerVal = P;51 return wrap(GenVal);52}53 54LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) {55 GenericValue *GenVal = new GenericValue();56 switch (unwrap(TyRef)->getTypeID()) {57 case Type::FloatTyID:58 GenVal->FloatVal = N;59 break;60 case Type::DoubleTyID:61 GenVal->DoubleVal = N;62 break;63 default:64 llvm_unreachable("LLVMGenericValueToFloat supports only float and double.");65 }66 return wrap(GenVal);67}68 69unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) {70 return unwrap(GenValRef)->IntVal.getBitWidth();71}72 73unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef,74 LLVMBool IsSigned) {75 GenericValue *GenVal = unwrap(GenValRef);76 if (IsSigned)77 return GenVal->IntVal.getSExtValue();78 else79 return GenVal->IntVal.getZExtValue();80}81 82void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) {83 return unwrap(GenVal)->PointerVal;84}85 86double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) {87 switch (unwrap(TyRef)->getTypeID()) {88 case Type::FloatTyID:89 return unwrap(GenVal)->FloatVal;90 case Type::DoubleTyID:91 return unwrap(GenVal)->DoubleVal;92 default:93 llvm_unreachable("LLVMGenericValueToFloat supports only float and double.");94 }95}96 97void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) {98 delete unwrap(GenVal);99}100 101/*===-- Operations on execution engines -----------------------------------===*/102 103LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE,104 LLVMModuleRef M,105 char **OutError) {106 std::string Error;107 EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));108 builder.setEngineKind(EngineKind::Either)109 .setErrorStr(&Error);110 if (ExecutionEngine *EE = builder.create()){111 *OutEE = wrap(EE);112 return 0;113 }114 *OutError = strdup(Error.c_str());115 return 1;116}117 118LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp,119 LLVMModuleRef M,120 char **OutError) {121 std::string Error;122 EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));123 builder.setEngineKind(EngineKind::Interpreter)124 .setErrorStr(&Error);125 if (ExecutionEngine *Interp = builder.create()) {126 *OutInterp = wrap(Interp);127 return 0;128 }129 *OutError = strdup(Error.c_str());130 return 1;131}132 133LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,134 LLVMModuleRef M,135 unsigned OptLevel,136 char **OutError) {137 std::string Error;138 EngineBuilder builder(std::unique_ptr<Module>(unwrap(M)));139 builder.setEngineKind(EngineKind::JIT)140 .setErrorStr(&Error)141 .setOptLevel((CodeGenOptLevel)OptLevel);142 if (ExecutionEngine *JIT = builder.create()) {143 *OutJIT = wrap(JIT);144 return 0;145 }146 *OutError = strdup(Error.c_str());147 return 1;148}149 150void LLVMInitializeMCJITCompilerOptions(LLVMMCJITCompilerOptions *PassedOptions,151 size_t SizeOfPassedOptions) {152 LLVMMCJITCompilerOptions options;153 memset(&options, 0, sizeof(options)); // Most fields are zero by default.154 options.CodeModel = LLVMCodeModelJITDefault;155 156 memcpy(PassedOptions, &options,157 std::min(sizeof(options), SizeOfPassedOptions));158}159 160LLVMBool LLVMCreateMCJITCompilerForModule(161 LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M,162 LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions,163 char **OutError) {164 LLVMMCJITCompilerOptions 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.167 if (SizeOfPassedOptions > sizeof(options)) {168 *OutError = strdup(169 "Refusing to use options struct that is larger than my own; assuming "170 "LLVM library mismatch.");171 return 1;172 }173 174 // 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.178 LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));179 memcpy(&options, PassedOptions, SizeOfPassedOptions);180 181 TargetOptions targetOptions;182 targetOptions.EnableFastISel = options.EnableFastISel;183 std::unique_ptr<Module> Mod(unwrap(M));184 185 if (Mod)186 // Set function attribute "frame-pointer" based on187 // NoFramePointerElim.188 for (auto &F : *Mod) {189 auto Attrs = F.getAttributes();190 StringRef Value = options.NoFramePointerElim ? "all" : "none";191 Attrs = Attrs.addFnAttribute(F.getContext(), "frame-pointer", Value);192 F.setAttributes(Attrs);193 }194 195 std::string Error;196 EngineBuilder builder(std::move(Mod));197 builder.setEngineKind(EngineKind::JIT)198 .setErrorStr(&Error)199 .setOptLevel((CodeGenOptLevel)options.OptLevel)200 .setTargetOptions(targetOptions);201 bool JIT;202 if (std::optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))203 builder.setCodeModel(*CM);204 if (options.MCJMM)205 builder.setMCJITMemoryManager(206 std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));207 if (ExecutionEngine *JIT = builder.create()) {208 *OutJIT = wrap(JIT);209 return 0;210 }211 *OutError = strdup(Error.c_str());212 return 1;213}214 215void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) {216 delete unwrap(EE);217}218 219void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) {220 unwrap(EE)->finalizeObject();221 unwrap(EE)->runStaticConstructorsDestructors(false);222}223 224void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) {225 unwrap(EE)->finalizeObject();226 unwrap(EE)->runStaticConstructorsDestructors(true);227}228 229int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F,230 unsigned ArgC, const char * const *ArgV,231 const char * const *EnvP) {232 unwrap(EE)->finalizeObject();233 234 std::vector<std::string> ArgVec(ArgV, ArgV + ArgC);235 return unwrap(EE)->runFunctionAsMain(unwrap<Function>(F), ArgVec, EnvP);236}237 238LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F,239 unsigned NumArgs,240 LLVMGenericValueRef *Args) {241 unwrap(EE)->finalizeObject();242 243 std::vector<GenericValue> ArgVec;244 ArgVec.reserve(NumArgs);245 for (unsigned I = 0; I != NumArgs; ++I)246 ArgVec.push_back(*unwrap(Args[I]));247 248 GenericValue *Result = new GenericValue();249 *Result = unwrap(EE)->runFunction(unwrap<Function>(F), ArgVec);250 return wrap(Result);251}252 253void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) {254}255 256void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){257 unwrap(EE)->addModule(std::unique_ptr<Module>(unwrap(M)));258}259 260LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M,261 LLVMModuleRef *OutMod, char **OutError) {262 Module *Mod = unwrap(M);263 unwrap(EE)->removeModule(Mod);264 *OutMod = wrap(Mod);265 return 0;266}267 268LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name,269 LLVMValueRef *OutFn) {270 if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) {271 *OutFn = wrap(F);272 return 0;273 }274 return 1;275}276 277void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE,278 LLVMValueRef Fn) {279 return nullptr;280}281 282LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) {283 return wrap(&unwrap(EE)->getDataLayout());284}285 286LLVMTargetMachineRef287LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE) {288 return wrap(unwrap(EE)->getTargetMachine());289}290 291void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,292 void* Addr) {293 unwrap(EE)->addGlobalMapping(unwrap<GlobalValue>(Global), Addr);294}295 296void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) {297 unwrap(EE)->finalizeObject();298 299 return unwrap(EE)->getPointerToGlobal(unwrap<GlobalValue>(Global));300}301 302uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) {303 return unwrap(EE)->getGlobalValueAddress(Name);304}305 306uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) {307 return unwrap(EE)->getFunctionAddress(Name);308}309 310LLVMBool LLVMExecutionEngineGetErrMsg(LLVMExecutionEngineRef EE,311 char **OutError) {312 assert(OutError && "OutError must be non-null");313 auto *ExecEngine = unwrap(EE);314 if (ExecEngine->hasError()) {315 *OutError = strdup(ExecEngine->getErrorMessage().c_str());316 ExecEngine->clearErrorMessage();317 return true;318 }319 return false;320}321 322/*===-- Operations on memory managers -------------------------------------===*/323 324namespace {325 326struct SimpleBindingMMFunctions {327 LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection;328 LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection;329 LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory;330 LLVMMemoryManagerDestroyCallback Destroy;331};332 333class SimpleBindingMemoryManager : public RTDyldMemoryManager {334public:335 SimpleBindingMemoryManager(const SimpleBindingMMFunctions& Functions,336 void *Opaque);337 ~SimpleBindingMemoryManager() override;338 339 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,340 unsigned SectionID,341 StringRef SectionName) override;342 343 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,344 unsigned SectionID, StringRef SectionName,345 bool isReadOnly) override;346 347 bool finalizeMemory(std::string *ErrMsg) override;348 349private:350 SimpleBindingMMFunctions Functions;351 void *Opaque;352};353 354SimpleBindingMemoryManager::SimpleBindingMemoryManager(355 const SimpleBindingMMFunctions& Functions,356 void *Opaque)357 : Functions(Functions), Opaque(Opaque) {358 assert(Functions.AllocateCodeSection &&359 "No AllocateCodeSection function provided!");360 assert(Functions.AllocateDataSection &&361 "No AllocateDataSection function provided!");362 assert(Functions.FinalizeMemory &&363 "No FinalizeMemory function provided!");364 assert(Functions.Destroy &&365 "No Destroy function provided!");366}367 368SimpleBindingMemoryManager::~SimpleBindingMemoryManager() {369 Functions.Destroy(Opaque);370}371 372uint8_t *SimpleBindingMemoryManager::allocateCodeSection(373 uintptr_t Size, unsigned Alignment, unsigned SectionID,374 StringRef SectionName) {375 return Functions.AllocateCodeSection(Opaque, Size, Alignment, SectionID,376 SectionName.str().c_str());377}378 379uint8_t *SimpleBindingMemoryManager::allocateDataSection(380 uintptr_t Size, unsigned Alignment, unsigned SectionID,381 StringRef SectionName, bool isReadOnly) {382 return Functions.AllocateDataSection(Opaque, Size, Alignment, SectionID,383 SectionName.str().c_str(),384 isReadOnly);385}386 387bool SimpleBindingMemoryManager::finalizeMemory(std::string *ErrMsg) {388 char *errMsgCString = nullptr;389 bool result = Functions.FinalizeMemory(Opaque, &errMsgCString);390 assert((result || !errMsgCString) &&391 "Did not expect an error message if FinalizeMemory succeeded");392 if (errMsgCString) {393 if (ErrMsg)394 *ErrMsg = errMsgCString;395 free(errMsgCString);396 }397 return result;398}399 400} // anonymous namespace401 402LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager(403 void *Opaque,404 LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection,405 LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection,406 LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory,407 LLVMMemoryManagerDestroyCallback Destroy) {408 409 if (!AllocateCodeSection || !AllocateDataSection || !FinalizeMemory ||410 !Destroy)411 return nullptr;412 413 SimpleBindingMMFunctions functions;414 functions.AllocateCodeSection = AllocateCodeSection;415 functions.AllocateDataSection = AllocateDataSection;416 functions.FinalizeMemory = FinalizeMemory;417 functions.Destroy = Destroy;418 return wrap(new SimpleBindingMemoryManager(functions, Opaque));419}420 421void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM) {422 delete unwrap(MM);423}424 425/*===-- JIT Event Listener functions -------------------------------------===*/426 427 428#if !LLVM_USE_INTEL_JITEVENTS429LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void)430{431 return nullptr;432}433#endif434 435#if !LLVM_USE_OPROFILE436LLVMJITEventListenerRef LLVMCreateOProfileJITEventListener(void)437{438 return nullptr;439}440#endif441 442#if !LLVM_USE_PERF443LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void)444{445 return nullptr;446}447#endif448