├── .gitignore ├── Makefile ├── README.md └── hello_llvm.swift /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | llvm 3 | hello_llvm 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | xcrun -sdk macosx swiftc hello_llvm.swift \ 3 | -module-link-name LLVM_C \ 4 | `./build/bin/llvm-config --libs mcjit native` \ 5 | -L ./build/lib \ 6 | -lc++ -lcurses -lz \ 7 | -I ./llvm/include -I ./build/include \ 8 | -Xcc -D__STDC_CONSTANT_MACROS \ 9 | -Xcc -D__STDC_LIMIT_MACROS \ 10 | -Xcc -D__STDC_FORMAT_MACROS 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Using LLVM C API with Swift 2 | 3 | Example code for corresponding article - [How to use LLVM with Swift](http://lowlevelbits.com/how-to-use-llvm-api-with-swift/) 4 | 5 | How to use LLVM MCJIT execution engine - [How to use LLVM with Swift. Addendum](http://lowlevelbits.com/how-to-use-llvm-api-with-swift-addendum/) 6 | 7 | -------------------------------------------------------------------------------- /hello_llvm.swift: -------------------------------------------------------------------------------- 1 | import LLVM_C 2 | 3 | let module = LLVMModuleCreateWithName("Hello") 4 | 5 | let int32 = LLVMInt32Type() 6 | 7 | let paramTypes = [int32, int32] 8 | 9 | // need to convert paramTypes into UnsafeMutablePointer because of API requirements 10 | var paramTypesRef = UnsafeMutablePointer.alloc(paramTypes.count) 11 | paramTypesRef.initializeFrom(paramTypes) 12 | 13 | let returnType = int32 14 | let functionType = LLVMFunctionType(returnType, paramTypesRef, UInt32(paramTypes.count), 0) 15 | 16 | let sumFunction = LLVMAddFunction(module, "sum", functionType) 17 | 18 | let entryBlock = LLVMAppendBasicBlock(sumFunction, "entry") 19 | 20 | let builder = LLVMCreateBuilder() 21 | LLVMPositionBuilderAtEnd(builder, entryBlock) 22 | 23 | let a = LLVMGetParam(sumFunction, 0) 24 | let b = LLVMGetParam(sumFunction, 1) 25 | let temp = LLVMBuildAdd(builder, a, b, "temp") 26 | LLVMBuildRet(builder, temp) 27 | 28 | LLVMLinkInMCJIT() 29 | LLVMInitializeNativeTarget() 30 | LLVMInitializeNativeAsmPrinter() 31 | 32 | func runSumFunction(a: Int, _ b: Int) -> Int { 33 | let functionType = LLVMFunctionType(returnType, nil, 0, 0) 34 | let wrapperFunction = LLVMAddFunction(module, "", functionType) 35 | defer { 36 | LLVMDeleteFunction(wrapperFunction) 37 | } 38 | 39 | let entryBlock = LLVMAppendBasicBlock(wrapperFunction, "entry") 40 | 41 | let builder = LLVMCreateBuilder() 42 | LLVMPositionBuilderAtEnd(builder, entryBlock) 43 | 44 | let argumentsCount = 2 45 | var argumentValues = [LLVMValueRef]() 46 | 47 | argumentValues.append(LLVMConstInt(int32, UInt64(a), 0)) 48 | argumentValues.append(LLVMConstInt(int32, UInt64(b), 0)) 49 | 50 | let argumentsPointer = UnsafeMutablePointer.alloc(strideof(LLVMValueRef) * argumentsCount) 51 | defer { 52 | argumentsPointer.dealloc(strideof(LLVMValueRef) * argumentsCount) 53 | } 54 | argumentsPointer.initializeFrom(argumentValues) 55 | 56 | let callTemp = LLVMBuildCall(builder, 57 | sumFunction, 58 | argumentsPointer, 59 | UInt32(argumentsCount), "sum_temp") 60 | LLVMBuildRet(builder, callTemp) 61 | 62 | let executionEngine = UnsafeMutablePointer.alloc(strideof(LLVMExecutionEngineRef)) 63 | let error = UnsafeMutablePointer>.alloc(strideof(UnsafeMutablePointer)) 64 | 65 | defer { 66 | error.dealloc(strideof(UnsafeMutablePointer)) 67 | executionEngine.dealloc(strideof(LLVMExecutionEngineRef)) 68 | } 69 | 70 | let res = LLVMCreateExecutionEngineForModule(executionEngine, module, error) 71 | if res != 0 { 72 | let msg = String.fromCString(error.memory) 73 | print("\(msg)") 74 | exit(1) 75 | } 76 | 77 | let value = LLVMRunFunction(executionEngine.memory, wrapperFunction, 0, nil) 78 | let result = LLVMGenericValueToInt(value, 0) 79 | return Int(result) 80 | } 81 | 82 | print("\(runFunction(5, 6))") 83 | print("\(runFunction(7, 142))") 84 | print("\(runFunction(557, 1024))") 85 | 86 | LLVMDisposeModule(module) 87 | 88 | --------------------------------------------------------------------------------