brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · c63a72f Raw
300 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 <assert.h>17#include <stdio.h>18#include <string.h>19 20int handleError(LLVMErrorRef Err) {21  char *ErrMsg = LLVMGetErrorMessage(Err);22  fprintf(stderr, "Error: %s\n", ErrMsg);23  LLVMDisposeErrorMessage(ErrMsg);24  return 1;25}26 27// Example IR modules.28//29// Note that in the conditionally compiled modules, FooMod and BarMod, functions30// have been given an _body suffix. This is to ensure that their names do not31// clash with their lazy-reexports.32// For clients who do not wish to rename function bodies (e.g. because they want33// to re-use cached objects between static and JIT compiles) techniques exist to34// avoid renaming. See the lazy-reexports section of the ORCv2 design doc.35 36const char FooMod[] = "  define i32 @foo_body() { \n"37                      "  entry:                   \n"38                      "    ret i32 1              \n"39                      "  }                        \n";40 41const char BarMod[] = "  define i32 @bar_body() { \n"42                      "  entry:                   \n"43                      "    ret i32 2              \n"44                      "  }                        \n";45 46const char MainMod[] =47    "  define i32 @entry(i32 %argc) {                                 \n"48    "  entry:                                                         \n"49    "    %and = and i32 %argc, 1                                      \n"50    "    %tobool = icmp eq i32 %and, 0                                \n"51    "    br i1 %tobool, label %if.end, label %if.then                 \n"52    "                                                                 \n"53    "  if.then:                                                       \n"54    "    %call = tail call i32 @foo()                                 \n"55    "    br label %return                                             \n"56    "                                                                 \n"57    "  if.end:                                                        \n"58    "    %call1 = tail call i32 @bar()                                \n"59    "    br label %return                                             \n"60    "                                                                 \n"61    "  return:                                                        \n"62    "    %retval.0 = phi i32 [ %call, %if.then ], [ %call1, %if.end ] \n"63    "    ret i32 %retval.0                                            \n"64    "  }                                                              \n"65    "                                                                 \n"66    "  declare i32 @foo()                                             \n"67    "  declare i32 @bar()                                             \n";68 69LLVMErrorRef applyDataLayout(void *Ctx, LLVMModuleRef M) {70  LLVMSetDataLayout(M, LLVMOrcLLJITGetDataLayoutStr((LLVMOrcLLJITRef)Ctx));71  return LLVMErrorSuccess;72}73 74LLVMErrorRef parseExampleModule(const char *Source, size_t Len,75                                const char *Name,76                                LLVMOrcThreadSafeModuleRef *TSM) {77  // Create an LLVMContext.78  LLVMContextRef Ctx = LLVMContextCreate();79 80  // Wrap Source in a MemoryBuffer81  LLVMMemoryBufferRef MB =82      LLVMCreateMemoryBufferWithMemoryRange(Source, Len, Name, 1);83 84  // Parse the LLVM module.85  LLVMModuleRef M;86  char *ErrMsg;87  if (LLVMParseIRInContext(Ctx, MB, &M, &ErrMsg)) {88    LLVMErrorRef Err = LLVMCreateStringError(ErrMsg);89    LLVMDisposeMessage(ErrMsg);90    return Err;91  }92 93  // Create a new ThreadSafeContext to hold the context.94  LLVMOrcThreadSafeContextRef TSCtx =95      LLVMOrcCreateNewThreadSafeContextFromLLVMContext(Ctx);96 97  // Our module is now complete. Wrap it and our ThreadSafeContext in a98  // ThreadSafeModule.99  *TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);100 101  // Dispose of our local ThreadSafeContext value. The underlying LLVMContext102  // will be kept alive by our ThreadSafeModule, TSM.103  LLVMOrcDisposeThreadSafeContext(TSCtx);104 105  return LLVMErrorSuccess;106}107 108void Destroy(void *Ctx) {}109 110void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) {111  int MainResult = 0;112 113  size_t NumSymbols;114  LLVMOrcSymbolStringPoolEntryRef *Symbols =115      LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols);116 117  assert(NumSymbols == 1);118 119  LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx;120  LLVMOrcSymbolStringPoolEntryRef Sym = Symbols[0];121 122  LLVMOrcThreadSafeModuleRef TSM = 0;123  LLVMErrorRef Err;124 125  LLVMOrcSymbolStringPoolEntryRef FooBody =126      LLVMOrcLLJITMangleAndIntern(J, "foo_body");127  LLVMOrcSymbolStringPoolEntryRef BarBody =128      LLVMOrcLLJITMangleAndIntern(J, "bar_body");129 130  if (Sym == FooBody) {131    if ((Err = parseExampleModule(FooMod, strlen(FooMod), "foo-mod", &TSM))) {132      MainResult = handleError(Err);133      goto cleanup;134    }135  } else if (Sym == BarBody) {136    if ((Err = parseExampleModule(BarMod, strlen(BarMod), "bar-mod", &TSM))) {137      MainResult = handleError(Err);138      goto cleanup;139    }140  } else {141    MainResult = 1;142    goto cleanup;143  }144  assert(TSM);145 146  if ((Err = LLVMOrcThreadSafeModuleWithModuleDo(TSM, &applyDataLayout, Ctx))) {147    MainResult = handleError(Err);148    goto cleanup;149  }150 151cleanup:152  LLVMOrcReleaseSymbolStringPoolEntry(BarBody);153  LLVMOrcReleaseSymbolStringPoolEntry(FooBody);154  LLVMOrcDisposeSymbols(Symbols);155  if (MainResult == 1) {156    LLVMOrcMaterializationResponsibilityFailMaterialization(MR);157    LLVMOrcDisposeMaterializationResponsibility(MR);158  } else {159    LLVMOrcIRTransformLayerRef IRLayer = LLVMOrcLLJITGetIRTransformLayer(J);160    LLVMOrcIRTransformLayerEmit(IRLayer, MR, TSM);161  }162}163 164int main(int argc, const char *argv[]) {165 166  int MainResult = 0;167 168  // Parse command line arguments and initialize LLVM Core.169  LLVMParseCommandLineOptions(argc, argv, "");170 171  // Initialize native target codegen and asm printer.172  LLVMInitializeNativeTarget();173  LLVMInitializeNativeAsmPrinter();174 175  // Set up a JIT instance.176  LLVMOrcLLJITRef J;177  const char *TargetTriple;178  {179    LLVMErrorRef Err;180    if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {181      MainResult = handleError(Err);182      goto llvm_shutdown;183    }184    TargetTriple = LLVMOrcLLJITGetTripleString(J);185  }186 187  // Add our main module to the JIT.188  {189    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);190    LLVMErrorRef Err;191 192    LLVMOrcThreadSafeModuleRef MainTSM;193    if ((Err = parseExampleModule(MainMod, strlen(MainMod), "main-mod",194                                  &MainTSM))) {195      MainResult = handleError(Err);196      goto jit_cleanup;197    }198 199    if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, MainTSM))) {200      LLVMOrcDisposeThreadSafeModule(MainTSM);201      MainResult = handleError(Err);202      goto jit_cleanup;203    }204  }205 206  LLVMJITSymbolFlags Flags = {207      LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0};208  LLVMOrcCSymbolFlagsMapPair FooSym = {209      LLVMOrcLLJITMangleAndIntern(J, "foo_body"), Flags};210  LLVMOrcCSymbolFlagsMapPair BarSym = {211      LLVMOrcLLJITMangleAndIntern(J, "bar_body"), Flags};212 213  // add custom MaterializationUnit214  {215    LLVMOrcMaterializationUnitRef FooMU =216        LLVMOrcCreateCustomMaterializationUnit("FooMU", J, &FooSym, 1, NULL,217                                               &Materialize, NULL, &Destroy);218 219    LLVMOrcMaterializationUnitRef BarMU =220        LLVMOrcCreateCustomMaterializationUnit("BarMU", J, &BarSym, 1, NULL,221                                               &Materialize, NULL, &Destroy);222 223    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);224    LLVMOrcJITDylibDefine(MainJD, FooMU);225    LLVMOrcJITDylibDefine(MainJD, BarMU);226  }227 228  // add lazy reexports229  LLVMOrcIndirectStubsManagerRef ISM =230      LLVMOrcCreateLocalIndirectStubsManager(TargetTriple);231 232  LLVMOrcLazyCallThroughManagerRef LCTM;233  {234    LLVMErrorRef Err;235    LLVMOrcExecutionSessionRef ES = LLVMOrcLLJITGetExecutionSession(J);236    if ((Err = LLVMOrcCreateLocalLazyCallThroughManager(TargetTriple, ES, 0,237                                                        &LCTM))) {238      LLVMOrcDisposeIndirectStubsManager(ISM);239      MainResult = handleError(Err);240      goto jit_cleanup;241    }242  }243 244  LLVMOrcCSymbolAliasMapPair ReExports[2] = {245      {LLVMOrcLLJITMangleAndIntern(J, "foo"),246       {LLVMOrcLLJITMangleAndIntern(J, "foo_body"), Flags}},247      {LLVMOrcLLJITMangleAndIntern(J, "bar"),248       {LLVMOrcLLJITMangleAndIntern(J, "bar_body"), Flags}},249  };250 251  {252    LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);253    LLVMOrcMaterializationUnitRef MU =254        LLVMOrcLazyReexports(LCTM, ISM, MainJD, ReExports, 2);255    LLVMOrcJITDylibDefine(MainJD, MU);256  }257 258  // Look up the address of our demo entry point.259  LLVMOrcJITTargetAddress EntryAddr;260  {261    LLVMErrorRef Err;262    if ((Err = LLVMOrcLLJITLookup(J, &EntryAddr, "entry"))) {263      MainResult = handleError(Err);264      goto cleanup;265    }266  }267 268  // If we made it here then everything succeeded. Execute our JIT'd code.269  int32_t (*Entry)(int32_t) = (int32_t(*)(int32_t))EntryAddr;270  int32_t Result = Entry(argc);271 272  printf("--- Result ---\n");273  printf("entry(%i) = %i\n", argc, Result);274 275cleanup : {276  LLVMOrcDisposeIndirectStubsManager(ISM);277  LLVMOrcDisposeLazyCallThroughManager(LCTM);278}279 280jit_cleanup:281  // Destroy our JIT instance. This will clean up any memory that the JIT has282  // taken ownership of. This operation is non-trivial (e.g. it may need to283  // JIT static destructors) and may also fail. In that case we want to render284  // the error to stderr, but not overwrite any existing return value.285  {286    LLVMErrorRef Err;287    if ((Err = LLVMOrcDisposeLLJIT(J))) {288      int NewFailureResult = handleError(Err);289      if (MainResult == 0)290        MainResult = NewFailureResult;291    }292  }293 294llvm_shutdown:295  // Shut down LLVM.296  LLVMShutdown();297 298  return MainResult;299}300