/* Copyright (c) 2022 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Siddharth Bhat This file contains bare bones bindings to the LLVM C FFI. This enables `src/Lean/Compiler/IR/EmitLLVM.lean` to produce LLVM bitcode from Lean's IR. */ #include #include #include "runtime/array_ref.h" #include "runtime/debug.h" #include "runtime/string_ref.h" #ifdef LEAN_LLVM #include "llvm-c/BitReader.h" #include "llvm-c/BitWriter.h" #include "llvm-c/Core.h" #include "llvm-c/Linker.h" #include "llvm-c/Target.h" #include "llvm-c/TargetMachine.h" #include "llvm-c/Types.h" #include "llvm-c/Transforms/PassBuilder.h" #include "llvm-c/Transforms/PassManagerBuilder.h" #endif // This is mostly boilerplate, suppress warnings #if defined(__clang__) #pragma clang diagnostic ignored "-Wunused-parameter" #elif defined(__GNUC__) && !defined(__CLANG__) #pragma GCC diagnostic ignored "-Wunused-parameter" #endif extern "C" LEAN_EXPORT lean_object* lean_llvm_initialize_target_info(lean_object * /* w */) { #ifdef LEAN_LLVM LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmParsers(); LLVMInitializeAllAsmPrinters(); #endif return lean_io_result_mk_ok(lean_box(0)); } #ifdef LEAN_LLVM // == LLVM <-> Lean: Target == static inline size_t Target_to_lean(LLVMTargetRef s) { return reinterpret_cast(s); } static inline LLVMTargetRef lean_to_Target(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: TargetMachine == static inline size_t TargetMachine_to_lean(LLVMTargetMachineRef s) { return reinterpret_cast(s); } static inline LLVMTargetMachineRef lean_to_TargetMachine(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: MemoryBuffer == static inline size_t MemoryBuffer_to_lean(LLVMMemoryBufferRef s) { return reinterpret_cast(s); } static inline LLVMMemoryBufferRef lean_to_MemoryBuffer(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: ModuleRef == static inline size_t Module_to_lean(LLVMModuleRef s) { return reinterpret_cast(s); } static inline LLVMModuleRef lean_to_Module(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: ContextRef == static inline size_t Context_to_lean(LLVMContextRef s) { return reinterpret_cast(s); } static inline LLVMContextRef lean_to_Context(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: TypeRef == static inline size_t Type_to_lean(LLVMTypeRef s) { return reinterpret_cast(s); } static inline LLVMTypeRef lean_to_Type(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: ValueRef == static inline size_t Value_to_lean(LLVMValueRef s) { return reinterpret_cast(s); } static inline LLVMValueRef lean_to_Value(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: BuilderRef == static inline size_t Builder_to_lean(LLVMBuilderRef s) { return reinterpret_cast(s); } static inline LLVMBuilderRef lean_to_Builder(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: BasicBlockRef == static inline size_t BasicBlock_to_lean(LLVMBasicBlockRef s) { return reinterpret_cast(s); } static inline LLVMBasicBlockRef lean_to_BasicBlock(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: PassManagerRef == static inline size_t PassManager_to_lean(LLVMPassManagerRef s) { return reinterpret_cast(s); } static inline LLVMPassManagerRef lean_to_PassManager(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: PassManagerRef == static inline size_t PassManagerBuilder_to_lean(LLVMPassManagerBuilderRef s) { return reinterpret_cast(s); } static inline LLVMPassManagerBuilderRef lean_to_PassManagerBuilder(size_t s) { return reinterpret_cast(s); } // == LLVM <-> Lean: AttributeRef == static inline size_t Attribute_to_lean(LLVMAttributeRef s) { return reinterpret_cast(s); } static inline LLVMAttributeRef lean_to_Attribute(size_t s) { return reinterpret_cast(s); } #else typedef int LLVMBasicBlockRef; typedef int LLVMContextRef; typedef int LLVMBuilderRef; typedef int LLVMTargetRef; typedef int LLVMTargetMachineRef; typedef int LLVMTypeRef; typedef int LLVMValueRef; typedef int LLVMModuleRef; typedef int LLVMPassManagerRef; typedef int LLVMPassManagerBuilderRef; #endif // LEAN_LLVM // == Array Type <-> C array of types == // There is redundancy here, but I am loath to clean it up with templates, // because we will somehow dispatch to the correct `lean_to_*` function. I can't // think of an immediate, clean way to achieve this (plenty of unclean ways. eg: // create a templated function that we partial template specialize that tells us // what the correct `lean_to_*` is. // Concretely: // leanToFn = lean_to_LLVMType; // leanToFn = lean_to_LLVMValue). LLVMTypeRef *array_ref_to_ArrayLLVMType( const lean::array_ref &arr) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else const int nargs = arr.size(); // lean::array_size(args); // bollu: ouch, this is expensive! There must be a cheaper way? LLVMTypeRef *tys = (LLVMTypeRef *)malloc(sizeof(LLVMTypeRef) * nargs); for (int i = 0; i < nargs; ++i) { tys[i] = lean_to_Type(lean_unbox_usize(arr[i])); } return tys; #endif // LEAN_LLVM } // TODO: Is there a nicer way to do this? LLVMValueRef *array_ref_to_ArrayLLVMValue( const lean::array_ref &arr) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else const int nargs = arr.size(); // lean::array_size(args); // bollu: ouch, this is expensive! There must be a cheaper way? LLVMValueRef *vals = (LLVMValueRef *)malloc(sizeof(LLVMValueRef) * nargs); lean_always_assert(vals && "unable to allocate array"); for (int i = 0; i < nargs; ++i) { lean_inc(arr[i]); // TODO: do I need this? vals[i] = lean_to_Value(lean_unbox_usize(arr[i])); } return vals; #endif // LEAN_LLVM } // == FFI == extern "C" LEAN_EXPORT lean_object *lean_llvm_create_context( lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMContextRef ctx = LLVMContextCreate(); return lean_io_result_mk_ok(lean_box_usize(Context_to_lean(ctx))); #endif // LEAN_LLVM }; extern "C" LEAN_EXPORT lean_object *lean_llvm_create_module( size_t ctx, lean_object *str, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMModuleRef mod = LLVMModuleCreateWithNameInContext(lean_string_cstr(str), lean_to_Context(ctx)); return lean_io_result_mk_ok(lean_box_usize(Module_to_lean(mod))); #endif // LEAN_LLVM }; extern "C" LEAN_EXPORT lean_object *lean_llvm_write_bitcode_to_file(size_t ctx, size_t mod, lean_object *filepath, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else const int err = LLVMWriteBitcodeToFile(lean_to_Module(mod), lean_string_cstr(filepath)); lean_always_assert(!err && "unable to write bitcode"); return lean_io_result_mk_ok(lean_box(0)); // IO Unit #endif // LEAN_LLVM }; extern "C" LEAN_EXPORT lean_object *lean_llvm_module_to_string( size_t ctx, size_t mod, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else char *str = LLVMPrintModuleToString(lean_to_Module(mod)); lean_object *out = lean_io_result_mk_ok(lean_mk_string(str)); free(str); return out; #endif // LEAN_LLVM }; extern "C" LEAN_EXPORT lean_object *lean_llvm_add_function( size_t ctx, size_t mod, lean_object *name, size_t type, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMAddFunction( lean_to_Module(mod), lean_string_cstr(name), lean_to_Type(type)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_named_function( size_t ctx, size_t mod, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef f = LLVMGetNamedFunction(lean_to_Module(mod), lean_string_cstr(name)); return lean_io_result_mk_ok( f ? lean::mk_option_some(lean_box_usize(Value_to_lean(f))) : lean::mk_option_none()); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_add_global( size_t ctx, size_t mod, lean_object *name, size_t type, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMAddGlobal(lean_to_Module(mod), lean_to_Type(type), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_named_global( size_t ctx, size_t mod, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef g = LLVMGetNamedGlobal(lean_to_Module(mod), lean_string_cstr(name)); return lean_io_result_mk_ok( g ? lean::mk_option_some(lean_box_usize(Value_to_lean(g))) : lean::mk_option_none()); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_global_string( size_t ctx, size_t builder, lean_object *str, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else lean::string_ref sref = lean::string_ref(str, true); lean::string_ref nameref = lean::string_ref(name, true); LLVMValueRef out = LLVMBuildGlobalString(lean_to_Builder(builder), sref.data(), nameref.data()); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_undef(size_t ctx, size_t ty, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetUndef(lean_to_Type(ty)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_set_initializer( size_t ctx, size_t global, size_t initializer, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMSetInitializer(lean_to_Value(global), lean_to_Value(initializer)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_function_type( size_t ctx, size_t retty, lean_object *argtys, uint8_t isvararg, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else lean::array_ref arr(argtys, true); // TODO, this is expensive! Is there a cheaper way? LLVMTypeRef *tys = array_ref_to_ArrayLLVMType(arr); LLVMTypeRef out = LLVMFunctionType(lean_to_Type(retty), tys, arr.size(), isvararg); free(tys); return lean_io_result_mk_ok(lean_box_usize(Type_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_opaque_pointer_type_in_context( size_t ctx, uint64_t addrspace, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize( Type_to_lean(LLVMPointerTypeInContext(lean_to_Context(ctx), addrspace)))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_int_type_in_context( size_t ctx, uint64_t width, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize( Type_to_lean(LLVMIntTypeInContext(lean_to_Context(ctx), width)))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_float_type_in_context( size_t ctx, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize( Type_to_lean(LLVMFloatTypeInContext(lean_to_Context(ctx))))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_void_type_in_context( size_t ctx, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize( Type_to_lean(LLVMVoidTypeInContext(lean_to_Context(ctx))))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_double_type_in_context( size_t ctx, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize( Type_to_lean(LLVMDoubleTypeInContext(lean_to_Context(ctx))))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_pointer_type( size_t ctx, size_t base, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMTypeRef out = LLVMPointerType(lean_to_Type(base), /*addrspace=*/0); return lean_io_result_mk_ok(lean_box_usize(Type_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_array_type( size_t ctx, size_t base, uint64_t nelem, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMTypeRef out = LLVMArrayType(lean_to_Type(base), /*nelem=*/nelem); return lean_io_result_mk_ok(lean_box_usize(Type_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_create_builder_in_context( size_t ctx, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize( Builder_to_lean(LLVMCreateBuilderInContext(lean_to_Context(ctx))))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_append_basic_block_in_context( size_t ctx, size_t fn, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMBasicBlockRef bb = LLVMAppendBasicBlockInContext( lean_to_Context(ctx), lean_to_Value(fn), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(BasicBlock_to_lean(bb))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_position_builder_at_end( size_t ctx, size_t builder, size_t bb, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMPositionBuilderAtEnd(lean_to_Builder(builder), lean_to_BasicBlock(bb)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_clear_insertion_position(size_t ctx, size_t builder, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMClearInsertionPosition(lean_to_Builder(builder)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_call2( size_t ctx, size_t builder, size_t fnty, size_t fnval, lean_object *args, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else lean::array_ref arr(args, true); LLVMValueRef *arrArgVals = array_ref_to_ArrayLLVMValue(arr); LLVMValueRef out = LLVMBuildCall2( lean_to_Builder(builder), lean_to_Type(fnty), lean_to_Value(fnval), arrArgVals, arr.size(), lean_string_cstr(name)); free(arrArgVals); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_cond_br( size_t ctx, size_t builder, size_t if_, size_t thenbb, size_t elsebb, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildCondBr(lean_to_Builder(builder), lean_to_Value(if_), lean_to_BasicBlock(thenbb), lean_to_BasicBlock(elsebb)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_br(size_t ctx, size_t builder, size_t bb, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildBr(lean_to_Builder(builder), lean_to_BasicBlock(bb)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_store(size_t ctx, size_t builder, size_t v, size_t slot, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildStore(lean_to_Builder(builder), lean_to_Value(v), lean_to_Value(slot)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_load2(size_t ctx, size_t builder, size_t ty, size_t slot, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildLoad2( lean_to_Builder(builder), lean_to_Type(ty), lean_to_Value(slot), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_alloca(size_t ctx, size_t builder, size_t type, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildAlloca( lean_to_Builder(builder), lean_to_Type(type), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_ret(size_t ctx, size_t builder, size_t v, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildRet(lean_to_Builder(builder), lean_to_Value(v)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_ret_void( size_t builder, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildRetVoid(lean_to_Builder(builder)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_unreachable(size_t ctx, size_t builder, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildUnreachable(lean_to_Builder(builder)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_inbounds_gep2(size_t ctx, size_t builder, size_t ty, size_t pointer, lean_object *indices, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else lean::array_ref indices_array_ref(indices, true); LLVMValueRef *indices_carr = array_ref_to_ArrayLLVMValue(indices_array_ref); lean::string_ref name_ref(name, true); LLVMValueRef out = LLVMBuildInBoundsGEP2( lean_to_Builder(builder), lean_to_Type(ty), lean_to_Value(pointer), indices_carr, indices_array_ref.size(), name_ref.data()); free(indices_carr); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_gep2(size_t ctx, size_t builder, size_t ty, size_t pointer, lean_object *indices, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else lean::array_ref indices_array_ref(indices, true); LLVMValueRef *indices_carr = array_ref_to_ArrayLLVMValue(indices_array_ref); lean::string_ref name_ref(name, true); LLVMValueRef out = LLVMBuildGEP2(lean_to_Builder(builder), lean_to_Type(ty), lean_to_Value(pointer), indices_carr, indices_array_ref.size(), name_ref.data()); free(indices_carr); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_sext(size_t ctx, size_t builder, size_t val, size_t destty, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildSExt(lean_to_Builder(builder), lean_to_Value(val), lean_to_Type(destty), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_zext(size_t ctx, size_t builder, size_t val, size_t destty, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildZExt(lean_to_Builder(builder), lean_to_Value(val), lean_to_Type(destty), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_sext_or_trunc(size_t ctx, size_t builder, size_t val, size_t destty, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMTypeRef valType = LLVMTypeOf(lean_to_Value(val)); LLVMValueRef out; if (LLVMGetIntTypeWidth(valType) == LLVMGetIntTypeWidth(lean_to_Type(destty))) { out = lean_to_Value(val); } else if (LLVMGetIntTypeWidth(valType) < LLVMGetIntTypeWidth(lean_to_Type(destty))) { out = LLVMBuildSExt(lean_to_Builder(builder), lean_to_Value(val), lean_to_Type(destty), lean_string_cstr(name)); } else { out = LLVMBuildTrunc(lean_to_Builder(builder), lean_to_Value(val), lean_to_Type(destty), lean_string_cstr(name)); } return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_switch(size_t ctx, size_t builder, size_t val, size_t elsebb, uint64_t numCases, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildSwitch(lean_to_Builder(builder), lean_to_Value(val), lean_to_BasicBlock(elsebb), numCases); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_ptr_to_int(size_t ctx, size_t builder, size_t ptr, size_t destty, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildPtrToInt(lean_to_Builder(builder), lean_to_Value(ptr), lean_to_Type(destty), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_mul(size_t ctx, size_t builder, size_t lhs, size_t rhs, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildMul(lean_to_Builder(builder), lean_to_Value(lhs), lean_to_Value(rhs), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_add(size_t ctx, size_t builder, size_t lhs, size_t rhs, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildAdd(lean_to_Builder(builder), lean_to_Value(lhs), lean_to_Value(rhs), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_sub(size_t ctx, size_t builder, size_t lhs, size_t rhs, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildSub(lean_to_Builder(builder), lean_to_Value(lhs), lean_to_Value(rhs), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_not(size_t ctx, size_t builder, size_t v, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildNot(lean_to_Builder(builder), lean_to_Value(v), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_build_icmp(size_t ctx, size_t builder, uint64_t predicate, size_t x, size_t y, lean_object *name, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMBuildICmp( lean_to_Builder(builder), LLVMIntPredicate(predicate), lean_to_Value(x), lean_to_Value(y), lean_string_cstr(name)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_add_case(size_t ctx, size_t switch_, size_t onVal, size_t destbb, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMAddCase(lean_to_Value(switch_), lean_to_Value(onVal), lean_to_BasicBlock(destbb)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_basic_block_parent(size_t ctx, size_t bb, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetBasicBlockParent(lean_to_BasicBlock(bb)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_insert_block(size_t ctx, size_t builder, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMBasicBlockRef out = LLVMGetInsertBlock(lean_to_Builder(builder)); return lean_io_result_mk_ok(lean_box_usize(BasicBlock_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_type_of(size_t ctx, size_t val, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMTypeRef ty = LLVMTypeOf(lean_to_Value(val)); return lean_io_result_mk_ok(lean_box_usize(Type_to_lean(ty))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_print_module_to_string(size_t ctx, size_t mod, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else const char *s = LLVMPrintModuleToString(lean_to_Module(mod)); return lean_io_result_mk_ok(lean::mk_string(s)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_print_module_to_file(size_t ctx, size_t mod, lean_object *file, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else char *err_str = NULL; const char *file_cstr = lean_string_cstr(file); int is_error = LLVMPrintModuleToFile(lean_to_Module(mod), file_cstr, /*errorMessage=*/&err_str); if (is_error) { fprintf(stderr, "'%30s' file:%30s ERROR: %30s\n", __FUNCTION__, file_cstr, err_str); } lean_always_assert(!is_error && "failed to print module to file"); lean_always_assert (err_str == NULL); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_const_int(size_t ctx, size_t ty, uint64_t val, uint8_t sext, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMConstInt(lean_to_Type(ty), val, sext); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_const_array( size_t ctx, size_t elemty, lean_object *args, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else lean::array_ref args_array_ref(args, true); LLVMValueRef *args_carr = array_ref_to_ArrayLLVMValue(args_array_ref); LLVMValueRef out = LLVMConstArray(lean_to_Type(elemty), args_carr, args_array_ref.size()); free(args_carr); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_const_string( size_t ctx, lean_object *s, lean_object * /* w */) { lean::string_ref sref = lean::string_ref(s, true); #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMConstStringInContext(lean_to_Context(ctx), sref.data(), sref.length(), /*DontNullTerminate=*/false); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_const_pointer_null( size_t ctx, size_t elemty, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMConstPointerNull(lean_to_Type(elemty)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *llvm_get_param(size_t ctx, size_t f, uint64_t ix, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetParam(lean_to_Value(f), ix); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object * llvm_count_params(size_t ctx, size_t f, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else int n = LLVMCountParams(lean_to_Value(f)); return lean_io_result_mk_ok(lean_box_uint64(n)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_set_tail_call( size_t ctx, size_t fnval, uint8_t isTail, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMSetTailCall(lean_to_Value(fnval), isTail); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object * lean_llvm_create_memory_buffer_with_contents_of_file(size_t ctx, lean_object *path, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMMemoryBufferRef membuf; char *err_str = NULL; const char *path_cstr = lean_string_cstr(path); int is_error = LLVMCreateMemoryBufferWithContentsOfFile( path_cstr, &membuf, &err_str); if (is_error) { fprintf(stderr, "%20s file:%30s ERROR: %30s\n", __FUNCTION__, path_cstr, err_str); } lean_always_assert((is_error != 1) && "failed to create membuf from file"); lean_always_assert(err_str == NULL); return lean_io_result_mk_ok(lean_box_usize(MemoryBuffer_to_lean(membuf))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_parse_bitcode( size_t context, size_t membuf, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMModuleRef out_module; char *err_str = NULL; int is_error = LLVMParseBitcodeInContext(lean_to_Context(context), lean_to_MemoryBuffer(membuf), &out_module, &err_str); if (is_error) { fprintf(stderr, "%20s ERROR: %30s\n", __FUNCTION__, err_str); } lean_always_assert(!is_error && "failed to parse bitcode"); lean_always_assert(err_str == NULL); return lean_io_result_mk_ok(lean_box_usize(Module_to_lean(out_module))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_link_modules(size_t ctx, size_t dest_module, size_t src_module, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else int is_error = LLVMLinkModules2(lean_to_Module(dest_module), lean_to_Module(src_module)); if (is_error) { fprintf(stderr, "%20s ERROR: unable to link modules\n", __FUNCTION__); } lean_always_assert(!is_error && "failed to link modules"); return lean_io_result_mk_ok(lean_box(0)); #endif } extern "C" LEAN_EXPORT lean_object *lean_llvm_create_target_machine(size_t ctx, size_t target, lean_object *tripleStr, lean_object *cpuStr, lean_object *featuresStr, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else // TODO (bollu): expose this option const LLVMCodeGenOptLevel optLevel = LLVMCodeGenLevelAggressive; const LLVMRelocMode relocMode = LLVMRelocPIC; const LLVMCodeModel codeModel = LLVMCodeModelDefault; LLVMTargetMachineRef tm = LLVMCreateTargetMachine( lean_to_Target(target), lean_string_cstr(tripleStr), lean_string_cstr(cpuStr), lean_string_cstr(featuresStr), optLevel, relocMode, codeModel); return lean_io_result_mk_ok(lean_box_usize(TargetMachine_to_lean(tm))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_target_from_triple(size_t ctx, lean_object *triple, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMTargetRef t; char *errmsg = NULL; int is_error = LLVMGetTargetFromTriple(lean_string_cstr(triple), &t, &errmsg); if (is_error) { fprintf(stderr, "Unable to find target '%s'. Registered targets:\n", lean_string_cstr(triple)); for(LLVMTargetRef t = LLVMGetFirstTarget(); t != NULL; t = LLVMGetNextTarget(t)) { fprintf(stderr, " %-10s - %s\n", LLVMGetTargetName(t), LLVMGetTargetDescription(t)); } } lean_always_assert(!is_error && "failed to get target from triple"); return lean_io_result_mk_ok(lean_box_usize(Target_to_lean(t))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_default_target_triple(lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else char *triple = LLVMGetDefaultTargetTriple(); lean_object *out = lean::mk_string(triple); free(triple); return lean_io_result_mk_ok(out); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_target_machine_emit_to_file(size_t ctx, size_t target_machine, size_t module, lean_object *filepath, uint64_t codegenType, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else // TODO (bollu): figure out a story for cross-compilation. // We currently choose not to invoke LLVMInitializeAllTargetInfos() etc. // since our build system only enables certain backends. // LLVMInitializeNativeTargetInfo(); char *err_msg = NULL; char *filepath_c_str = const_cast(lean_string_cstr(filepath)); int is_error = LLVMTargetMachineEmitToFile( lean_to_TargetMachine(target_machine), lean_to_Module(module), filepath_c_str, LLVMCodeGenFileType(codegenType), &err_msg); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_create_pass_manager(size_t ctx, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize(PassManager_to_lean(LLVMCreatePassManager()))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_run_pass_manager(size_t ctx, size_t pm, size_t mod, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else int is_error = LLVMRunPassManager(lean_to_PassManager(pm), lean_to_Module(mod)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_dispose_pass_manager(size_t ctx, size_t pm, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMDisposePassManager(lean_to_PassManager(pm)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_create_pass_manager_builder(size_t ctx, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else return lean_io_result_mk_ok(lean_box_usize(PassManagerBuilder_to_lean(LLVMPassManagerBuilderCreate()))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_dispose_pass_manager_builder(size_t ctx, size_t pmb, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMPassManagerBuilderDispose(lean_to_PassManagerBuilder(pmb)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_pass_manager_builder_set_opt_level(size_t ctx, size_t pmb, unsigned opt_level, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMPassManagerBuilderSetOptLevel(lean_to_PassManagerBuilder(pmb), opt_level); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_pass_manager_builder_populate_module_pass_manager(size_t ctx, size_t pmb, size_t pm, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMPassManagerBuilderPopulateModulePassManager(lean_to_PassManagerBuilder(pmb), lean_to_PassManager(pm)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_dispose_target_machine(size_t ctx, size_t tm, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMDisposeTargetMachine(lean_to_TargetMachine(tm)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_dispose_module(size_t ctx, size_t mod, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMDisposeModule(lean_to_Module(mod)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_set_visibility(size_t ctx, size_t value, uint64_t vis, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMSetVisibility(lean_to_Value(value), LLVMVisibility(vis)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_set_dll_storage_class(size_t ctx, size_t value, uint64_t cls, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMSetDLLStorageClass(lean_to_Value(value), LLVMDLLStorageClass(cls)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_create_string_attribute(size_t ctx, lean_object* key, lean_object* value, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMAttributeRef attr = LLVMCreateStringAttribute(lean_to_Context(ctx), lean_string_cstr(key), lean_string_len(key), lean_string_cstr(value), lean_string_len(value)); return lean_io_result_mk_ok(lean_box_usize(Attribute_to_lean(attr))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_add_attribute_at_index(size_t ctx, size_t fn, uint64_t idx, size_t attr, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMAddAttributeAtIndex(lean_to_Value(fn), idx, lean_to_Attribute(attr)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_first_global(size_t ctx, size_t mod, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetFirstGlobal(lean_to_Module(mod)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_next_global(size_t ctx, size_t global, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetNextGlobal(lean_to_Value(global)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_first_function(size_t ctx, size_t mod, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetFirstFunction(lean_to_Module(mod)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_next_function(size_t ctx, size_t function, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMValueRef out = LLVMGetNextFunction(lean_to_Value(function)); return lean_io_result_mk_ok(lean_box_usize(Value_to_lean(out))); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_set_linkage(size_t ctx, size_t value, uint64_t linkage, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else LLVMSetLinkage(lean_to_Value(value), LLVMLinkage(linkage)); return lean_io_result_mk_ok(lean_box(0)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *lean_llvm_get_value_name2(size_t ctx, size_t value, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else size_t len; const char *name = LLVMGetValueName2(lean_to_Value(value), &len); return lean_io_result_mk_ok(lean::mk_string(name)); #endif // LEAN_LLVM } extern "C" LEAN_EXPORT lean_object *llvm_is_declaration(size_t ctx, size_t global, lean_object * /* w */) { #ifndef LEAN_LLVM lean_always_assert( false && ("Please build a version of Lean4 with -DLLVM=ON to invoke " "the LLVM backend function.")); #else uint8_t is_bool = LLVMIsDeclaration(lean_to_Value(global)); return lean_io_result_mk_ok(lean_box(is_bool)); #endif // LEAN_LLVM }