brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.4 KiB · 700fb03 Raw
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