brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · 9c31f93 Raw
245 lines · c
1//===-------- BasicOrcV2CBindings.c - Basic OrcV2 C Bindings Demo ---------===//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#include "llvm-c/Core.h"10#include "llvm-c/Error.h"11#include "llvm-c/IRReader.h"12#include "llvm-c/LLJIT.h"13#include "llvm-c/Support.h"14#include "llvm-c/Target.h"15 16#include <stdio.h>17 18int handleError(LLVMErrorRef Err) {19  char *ErrMsg = LLVMGetErrorMessage(Err);20  fprintf(stderr, "Error: %s\n", ErrMsg);21  LLVMDisposeErrorMessage(ErrMsg);22  return 1;23}24 25// Example IR modules.26//27// Note that in the conditionally compiled modules, FooMod and BarMod, functions28// have been given an _body suffix. This is to ensure that their names do not29// clash with their lazy-reexports.30// For clients who do not wish to rename function bodies (e.g. because they want31// to re-use cached objects between static and JIT compiles) techniques exist to32// avoid renaming. See the lazy-reexports section of the ORCv2 design doc.33 34const char FooMod[] = "  define i32 @foo_body() { \n"35                      "  entry:                   \n"36                      "    ret i32 1              \n"37                      "  }                        \n";38 39const char BarMod[] = "  define i32 @bar_body() { \n"40                      "  entry:                   \n"41                      "    ret i32 2              \n"42                      "  }                        \n";43 44const char MainMod[] =45    "  define i32 @entry(i32 %argc) {                                 \n"46    "  entry:                                                         \n"47    "    %and = and i32 %argc, 1                                      \n"48    "    %tobool = icmp eq i32 %and, 0                                \n"49    "    br i1 %tobool, label %if.end, label %if.then                 \n"50    "                                                                 \n"51    "  if.then:                                                       \n"52    "    %call = tail call i32 @foo()                                 \n"53    "    br label %return                                             \n"54    "                                                                 \n"55    "  if.end:                                                        \n"56    "    %call1 = tail call i32 @bar()                                \n"57    "    br label %return                                             \n"58    "                                                                 \n"59    "  return:                                                        \n"60    "    %retval.0 = phi i32 [ %call, %if.then ], [ %call1, %if.end ] \n"61    "    ret i32 %retval.0                                            \n"62    "  }                                                              \n"63    "                                                                 \n"64    "  declare i32 @foo()                                             \n"65    "  declare i32 @bar()                                             \n";66 67LLVMErrorRef parseExampleModule(const char *Source, size_t Len,68                                const char *Name,69                                LLVMOrcThreadSafeModuleRef *TSM) {70 71  // Create an LLVMContext for the Module.72  LLVMContextRef Ctx = LLVMContextCreate();73 74  // Wrap Source in a MemoryBuffer75  LLVMMemoryBufferRef MB =76      LLVMCreateMemoryBufferWithMemoryRange(Source, Len, Name, 0);77 78  // Parse the LLVM module.79  LLVMModuleRef M;80  char *ErrMsg;81  if (LLVMParseIRInContext(Ctx, MB, &M, &ErrMsg)) {82    return LLVMCreateStringError(ErrMsg);83    // TODO: LLVMDisposeMessage(ErrMsg);84  }85 86  // Create a new ThreadSafeContext to hold the context.87  LLVMOrcThreadSafeContextRef TSCtx =88      LLVMOrcCreateNewThreadSafeContextFromLLVMContext(Ctx);89 90  // Our module is now complete. Wrap it and our ThreadSafeContext in a91  // ThreadSafeModule.92  *TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);93 94  // Dispose of our local ThreadSafeContext value. The underlying LLVMContext95  // will be kept alive by our ThreadSafeModule, TSM.96  LLVMOrcDisposeThreadSafeContext(TSCtx);97 98  return LLVMErrorSuccess;99}100 101int main(int argc, const char *argv[]) {102 103  int MainResult = 0;104 105  // Parse command line arguments and initialize LLVM Core.106  LLVMParseCommandLineOptions(argc, argv, "");107 108  // Initialize native target codegen and asm printer.109  LLVMInitializeNativeTarget();110  LLVMInitializeNativeAsmPrinter();111 112  // Set up a JIT instance.113  LLVMOrcLLJITRef J;114  const char *TargetTriple;115  {116    LLVMErrorRef Err;117    if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {118      MainResult = handleError(Err);119      goto llvm_shutdown;120    }121    TargetTriple = LLVMOrcLLJITGetTripleString(J);122  }123 124  // Add our demo modules to the JIT.125  {126    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);127    LLVMErrorRef Err;128 129    LLVMOrcThreadSafeModuleRef FooTSM;130    if ((Err = parseExampleModule(FooMod, sizeof(FooMod) - 1, "foo-mod",131                                  &FooTSM))) {132      MainResult = handleError(Err);133      goto jit_cleanup;134    }135 136    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, FooTSM))) {137      // If adding the ThreadSafeModule fails then we need to clean it up138      // ourselves. If adding it succeeds the JIT will manage the memory.139      LLVMOrcDisposeThreadSafeModule(FooTSM);140      MainResult = handleError(Err);141      goto jit_cleanup;142    }143 144    LLVMOrcThreadSafeModuleRef BarTSM;145    if ((Err = parseExampleModule(BarMod, sizeof(BarMod) - 1, "bar-mod",146                                  &BarTSM))) {147      MainResult = handleError(Err);148      goto jit_cleanup;149    }150 151    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, BarTSM))) {152      LLVMOrcDisposeThreadSafeModule(BarTSM);153      MainResult = handleError(Err);154      goto jit_cleanup;155    }156 157    LLVMOrcThreadSafeModuleRef MainTSM;158    if ((Err = parseExampleModule(MainMod, sizeof(MainMod) - 1, "main-mod",159                                  &MainTSM))) {160      MainResult = handleError(Err);161      goto jit_cleanup;162    }163 164    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, MainTSM))) {165      LLVMOrcDisposeThreadSafeModule(MainTSM);166      MainResult = handleError(Err);167      goto jit_cleanup;168    }169  }170 171  // add lazy reexports172  LLVMOrcIndirectStubsManagerRef ISM =173      LLVMOrcCreateLocalIndirectStubsManager(TargetTriple);174 175  LLVMOrcLazyCallThroughManagerRef LCTM;176  {177    LLVMErrorRef Err;178    LLVMOrcExecutionSessionRef ES = LLVMOrcLLJITGetExecutionSession(J);179    if ((Err = LLVMOrcCreateLocalLazyCallThroughManager(TargetTriple, ES, 0,180                                                        &LCTM))) {181      LLVMOrcDisposeIndirectStubsManager(ISM);182      MainResult = handleError(Err);183      goto jit_cleanup;184    }185  }186 187  LLVMJITSymbolFlags flag = {188      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};189  LLVMOrcCSymbolAliasMapPair ReExports[2] = {190      {LLVMOrcLLJITMangleAndIntern(J, "foo"),191       {LLVMOrcLLJITMangleAndIntern(J, "foo_body"), flag}},192      {LLVMOrcLLJITMangleAndIntern(J, "bar"),193       {LLVMOrcLLJITMangleAndIntern(J, "bar_body"), flag}},194  };195 196  {197    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);198    LLVMOrcMaterializationUnitRef MU =199        LLVMOrcLazyReexports(LCTM, ISM, MainJD, ReExports, 2);200    LLVMOrcJITDylibDefine(MainJD, MU);201  }202 203  // Look up the address of our demo entry point.204  LLVMOrcJITTargetAddress EntryAddr;205  {206    LLVMErrorRef Err;207    if ((Err = LLVMOrcLLJITLookup(J, &EntryAddr, "entry"))) {208      MainResult = handleError(Err);209      goto cleanup;210    }211  }212 213  // If we made it here then everything succeeded. Execute our JIT'd code.214  int32_t (*Entry)(int32_t) = (int32_t(*)(int32_t))EntryAddr;215  int32_t Result = Entry(argc);216 217  printf("--- Result ---\n");218  printf("entry(%i) = %i\n", argc, Result);219 220cleanup : {221  LLVMOrcDisposeIndirectStubsManager(ISM);222  LLVMOrcDisposeLazyCallThroughManager(LCTM);223}224 225jit_cleanup:226  // Destroy our JIT instance. This will clean up any memory that the JIT has227  // taken ownership of. This operation is non-trivial (e.g. it may need to228  // JIT static destructors) and may also fail. In that case we want to render229  // the error to stderr, but not overwrite any existing return value.230  {231    LLVMErrorRef Err;232    if ((Err = LLVMOrcDisposeLLJIT(J))) {233      int NewFailureResult = handleError(Err);234      if (MainResult == 0)235        MainResult = NewFailureResult;236    }237  }238 239llvm_shutdown:240  // Shut down LLVM.241  LLVMShutdown();242 243  return MainResult;244}245