{"id":13872082,"url":"https://github.com/llvm-swift/LLVMSwift","last_synced_at":"2025-07-16T01:32:46.845Z","repository":{"id":15530168,"uuid":"78325183","full_name":"llvm-swift/LLVMSwift","owner":"llvm-swift","description":"A Swift wrapper for the LLVM C API (version 11.0)","archived":false,"fork":false,"pushed_at":"2024-10-26T16:42:28.000Z","size":7833,"stargazers_count":747,"open_issues_count":8,"forks_count":56,"subscribers_count":21,"default_branch":"main","last_synced_at":"2024-11-16T17:16:21.924Z","etag":null,"topics":["compiler","llvm","swift","swiftpm"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/llvm-swift.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-08T06:10:37.000Z","updated_at":"2024-11-16T11:09:27.000Z","dependencies_parsed_at":"2024-08-06T00:34:30.518Z","dependency_job_id":"bb17c9bc-52fc-4361-9a0c-3abee553586d","html_url":"https://github.com/llvm-swift/LLVMSwift","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llvm-swift%2FLLVMSwift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llvm-swift%2FLLVMSwift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llvm-swift%2FLLVMSwift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/llvm-swift%2FLLVMSwift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/llvm-swift","download_url":"https://codeload.github.com/llvm-swift/LLVMSwift/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226090030,"owners_count":17572114,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compiler","llvm","swift","swiftpm"],"created_at":"2024-08-05T23:00:33.397Z","updated_at":"2024-11-23T19:31:35.382Z","avatar_url":"https://github.com/llvm-swift.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# LLVMSwift\n[![Build Status](https://travis-ci.org/llvm-swift/LLVMSwift.svg?branch=master)](https://travis-ci.org/llvm-swift/LLVMSwift) [![Documentation](https://cdn.rawgit.com/llvm-swift/LLVMSwift/master/docs/badge.svg)](https://llvm-swift.github.io/LLVMSwift) [![Slack Invite](https://llvmswift-slack.herokuapp.com/badge.svg)](https://llvmswift-slack.herokuapp.com)\n\nLLVMSwift is a pure Swift interface to the [LLVM](http://llvm.org) API and its associated libraries. It provides native, easy-to-use components to make compiler development fun.\n\n## Introduction\n\n### LLVM IR\n\nThe root unit of organization of an LLVM IR program is a `Module`\n\n```swift\nlet module = Module(name: \"main\")\n```\n\nLLVM IR construction is handled by `IRBuilder` objects.  An `IRBuilder` is a cursor pointed inside a context, and as such has ways of extending that context and moving around inside of it.\n\nDefining a function and moving the cursor to a point where we can begin inserting instructions is done like so:\n\n```swift\nlet builder = IRBuilder(module: module)\n\nlet main = builder.addFunction(\"main\",\n                               type: FunctionType([], IntType.int64))\nlet entry = main.appendBasicBlock(named: \"entry\")\nbuilder.positionAtEnd(of: entry)\n```\n\nInserting instructions creates native `IRValue` placeholder objects that allow us to structure LLVM IR programs just like Swift programs:\n\n```swift\nlet constant = IntType.int64.constant(21)\nlet sum = builder.buildAdd(constant, constant)\nbuilder.buildRet(sum)\n```\n\nThis simple program generates the following IR:\n\n```llvm\n// module.dump()\n\ndefine i64 @main() {\nentry:\n  ret i64 42\n}\n```\n\n### Types\n\nLLVM IR is a strong, statically typed language.  As such, values and functions\nare tagged with their types, and conversions between them must be explicit (see\n[Conversion Operators](http://llvm.org/docs/LangRef.html#conversion-operations)).\nLLVMSwift represents this with values conforming to the `IRType` protocol and defines\nthe following types:\n\n|**Type** | **Represents** |\n|:---:|:---:|\n| VoidType | Nothing; Has no size |\n| IntType | Integer and Boolean values (`i1`) |\n| FloatType | Floating-point values |\n| FunctionType | Function values |\n| LabelType | Code labels |\n| TokenType | Values paired with instructions |\n| MetadataType | Embedded metadata |\n| X86MMXType | X86 MMX values |\n| PointerType | Pointer values |\n| VectorType | SIMD data |\n| ArrayType | Homogeneous values |\n| Structure Type | Heterogeneous values |\n\n\n### Control Flow\n\nControl flow is changed through the unconditional and conditional `br` instruction.\n\nLLVM is also famous for a control-flow specific IR construct called a [PHI node](http://llvm.org/docs/LangRef.html#phi-instruction).  Because all instructions in LLVM IR are in SSA (Single Static Assignment) form, a PHI node is necessary when the value of a variable assignment depends on the path the flow of control takes through the program.  For example, let's try to build the following Swift program in IR:\n\n```swift\nfunc calculateFibs(_ backward : Bool) -\u003e Double {\n  let retVal : Double\n  if !backward {\n    // the fibonacci series (sort of)\n    retVal = 1/89\n  } else {\n    // the fibonacci series (sort of) backwards\n    retVal = 1/109\n  }\n  return retVal\n}\n```\n\nNotice that the value of `retVal` depends on the path the flow of control takes through this program, so we must emit a PHI node to properly initialize it:\n\n```swift\nlet function = builder.addFunction(\"calculateFibs\", \n                                   type: FunctionType([IntType.int1], \n                                                      FloatType.double))\nlet entryBB = function.appendBasicBlock(named: \"entry\")\nbuilder.positionAtEnd(of: entryBB)\n\n// allocate space for a local value\t\t\nlet local = builder.buildAlloca(type: FloatType.double, name: \"local\")\n\n// Compare to the condition\nlet test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .equal)\n\n// Create basic blocks for \"then\", \"else\", and \"merge\"\nlet thenBB = function.appendBasicBlock(named: \"then\")\nlet elseBB = function.appendBasicBlock(named: \"else\")\nlet mergeBB = function.appendBasicBlock(named: \"merge\")\n\nbuilder.buildCondBr(condition: test, then: thenBB, else: elseBB)\n\n// MARK: Then Block\nbuilder.positionAtEnd(of: thenBB)\n// local = 1/89, the fibonacci series (sort of)\nlet thenVal = FloatType.double.constant(1/89)\n// Branch to the merge block\nbuilder.buildBr(mergeBB)\n\n// MARK: Else Block\nbuilder.positionAtEnd(of: elseBB)\n// local = 1/109, the fibonacci series (sort of) backwards\nlet elseVal = FloatType.double.constant(1/109)\n// Branch to the merge block\nbuilder.buildBr(mergeBB)\n\n// MARK: Merge Block\nbuilder.positionAtEnd(of: mergeBB)\nlet phi = builder.buildPhi(FloatType.double, name: \"phi_example\")\nphi.addIncoming([\n  (thenVal, thenBB),\n  (elseVal, elseBB),\n])\nbuilder.buildStore(phi, to: local)\nlet ret = builder.buildLoad(local, type: FloatType.double, name: \"ret\")\nbuilder.buildRet(ret)\n```\n\nThis program generates the following IR:\n\n```llvm\ndefine double @calculateFibs(i1) {\nentry:\n  %local = alloca double\n  %1 = icmp ne i1 %0, false\n  br i1 %1, label %then, label %else\n\nthen:                                             ; preds = %entry\n  br label %merge\n\nelse:                                             ; preds = %entry\n  br label %merge\n\nmerge:                                            ; preds = %else, %then\n  %phi_example = phi double [ 0x3F8702E05C0B8170, %then ], [ 0x3F82C9FB4D812CA0, %else ]\n  store double %phi_example, double* %local\n  %ret = load double, double* %local\n  ret double %ret\n}\n```\n\n### JIT\n\nLLVMSwift provides a JIT abstraction to make executing code in LLVM modules quick and easy.  Let's execute the PHI node example from before:\n\n```swift\n// Setup the JIT\nlet jit = try JIT(machine: TargetMachine())\ntypealias FnPtr = @convention(c) (Bool) -\u003e Double\n_ = try jit.addEagerlyCompiledIR(module) { (name) -\u003e JIT.TargetAddress in\n  return JIT.TargetAddress()\n}\n// Retrieve a handle to the function we're going to invoke\nlet addr = try jit.address(of: \"calculateFibs\")\nlet fn = unsafeBitCast(addr, to: FnPtr.self)\n// Call the function!\nprint(fn(true)) // 0.00917431192660551...\nprint(fn(false)) // 0.0112359550561798...\n```\n\n## Installation\n\nThere are a couple annoying steps you need to accomplish before building\nLLVMSwift:\n\n- Install LLVM 11.0+ using your favorite package manager. For example:\n  - `brew install llvm@11`\n- Ensure `llvm-config` is in your `PATH`\n  - That will reside in the `/bin` folder wherever your package manager\n    installed LLVM.\n- Create a pkg-config file for your specific LLVM installation.\n  - We have a utility for this: `swift utils/make-pkgconfig.swift`\n\nOnce you do that, you can add LLVMSwift as a dependency for your own Swift\ncompiler projects!\n\n### Installation with Swift Package Manager\n\n```swift\n.package(url: \"https://github.com/llvm-swift/LLVMSwift.git\", from: \"0.8.0\")\n```\n\n### Installation without Swift Package Manager\n\nWe really recommend using SwiftPM with LLVMSwift, but if your project is\nstructured in such a way that makes using SwiftPM impractical or impossible,\nuse the following instructions: \n\n- Xcode:\n  - Add this repository as a git submodule\n  - Add the files in `Sources/` to your Xcode project.\n  - Under `Library Search Paths` add the output of `llvm-config --libdir`\n  - Under `Header Search Paths` add the output of `llvm-config --includedir`\n  - Under `Link Target with Libraries` drag in\n    `/path/to/your/llvm/lib/libLLVM.dylib`\n\nThis project is used by [Trill](https://github.com/harlanhaskins/trill) for\nall its code generation.\n\n## Authors\n\n- Harlan Haskins ([@harlanhaskins](https://github.com/harlanhaskins))\n- Robert Widmann ([@CodaFi](https://github.com/CodaFi))\n\n## License\n\nThis project is released under the MIT license, a copy of which is available\nin this repo.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllvm-swift%2FLLVMSwift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fllvm-swift%2FLLVMSwift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllvm-swift%2FLLVMSwift/lists"}