From 78265f41b799bd00dc21f5ab612a4b93b1a71e8a Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Sun, 15 Jan 2017 19:04:05 -0500 Subject: [PATCH 1/3] Added module-related functions to JIT --- Sources/LLVM/JIT.swift | 36 ++++++++++++++++++++++++++++++++++++ Sources/LLVM/Module.swift | 11 +++++++++++ 2 files changed, 47 insertions(+) diff --git a/Sources/LLVM/JIT.swift b/Sources/LLVM/JIT.swift index 6257344f..6639e82f 100644 --- a/Sources/LLVM/JIT.swift +++ b/Sources/LLVM/JIT.swift @@ -7,9 +7,15 @@ public enum JITError: Error, CustomStringConvertible { /// the failure. case couldNotInitialize(String) + /// The JIT was unable to remove the provided module. A message is provided + /// explaining the failure + case couldNotRemoveModule(Module, String) + /// A human-readable description of the error. public var description: String { switch self { + case .couldNotRemoveModule(let module, let message): + return "could not remove module '\(module.name)': \(message)" case .couldNotInitialize(let message): return "could not initialize JIT: \(message)" } @@ -61,6 +67,36 @@ public final class JIT { } } + /// Retrieves a pointer to the function compiled by this JIT. + /// - parameter name: The name of the function you wish to look up. + /// - returns: A pointer to the result of compiling the specified function. + /// - note: You will have to `unsafeBitCast` this pointer to + /// the appropriate `@convention(c)` function type to be + /// able to run it from Swift. + public func addressOfFunction(name: String) -> OpaquePointer? { + let addr = LLVMGetFunctionAddress(llvm, name) + guard addr != 0 else { return nil } + return OpaquePointer(bitPattern: UInt(addr)) + } + + /// Adds the provided module, and all top-level declarations into this JIT. + /// - parameter module: The module you wish to add. + public func addModule(_ module: Module) { + LLVMAddModule(llvm, module.llvm) + } + + /// Removes the provided module, and all top-level declarations, from this + /// JIT. + public func removeModule(_ module: Module) throws { + var outMod: LLVMModuleRef? = module.llvm + var outError: UnsafeMutablePointer? + LLVMRemoveModule(llvm, module.llvm, &outMod, &outError) + if let err = outError { + defer { LLVMDisposeMessage(err) } + throw JITError.couldNotRemoveModule(module, String(cString: err)) + } + } + /// Runs the specified function as if it were the `main` function in an /// executable. It takes an array of argument strings and passes them /// into the function as `argc` and `argv`. diff --git a/Sources/LLVM/Module.swift b/Sources/LLVM/Module.swift index 6faf926e..dbf93d98 100644 --- a/Sources/LLVM/Module.swift +++ b/Sources/LLVM/Module.swift @@ -72,6 +72,17 @@ public final class Module: CustomStringConvertible { return TargetData(llvm: LLVMGetModuleDataLayout(llvm)) } + /// The identifier of this module. + public var name: String { + get { + guard let id = LLVMGetModuleIdentifier(llvm, nil) else { return "" } + return String(cString: id) + } + set { + LLVMSetModuleIdentifier(llvm, newValue, newValue.utf8.count) + } + } + /// Print a representation of a module to a file at the given path. /// /// If the provided path is not suitable for writing, this function will throw From bca8dbcfffeb794832f2f074c13be6a5904be1cd Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Sun, 15 Jan 2017 19:07:16 -0500 Subject: [PATCH 2/3] Updated comment with example --- Sources/LLVM/JIT.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/LLVM/JIT.swift b/Sources/LLVM/JIT.swift index 6639e82f..eea8798c 100644 --- a/Sources/LLVM/JIT.swift +++ b/Sources/LLVM/JIT.swift @@ -73,6 +73,10 @@ public final class JIT { /// - note: You will have to `unsafeBitCast` this pointer to /// the appropriate `@convention(c)` function type to be /// able to run it from Swift. + /// + /// typealias FnPtr = @convention(c) () -> Double + /// let fnAddr = jit.addressOfFunction(name: "test") + /// let fn = unsafeBitCast(fnAddr, to: FnPtr.self) public func addressOfFunction(name: String) -> OpaquePointer? { let addr = LLVMGetFunctionAddress(llvm, name) guard addr != 0 else { return nil } From f3753e3c33e5074a3e00b2bd4543a5cb785c05a8 Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Sun, 15 Jan 2017 20:29:06 -0500 Subject: [PATCH 3/3] Extra code voice --- Sources/LLVM/JIT.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Sources/LLVM/JIT.swift b/Sources/LLVM/JIT.swift index eea8798c..3e130fd3 100644 --- a/Sources/LLVM/JIT.swift +++ b/Sources/LLVM/JIT.swift @@ -73,10 +73,12 @@ public final class JIT { /// - note: You will have to `unsafeBitCast` this pointer to /// the appropriate `@convention(c)` function type to be /// able to run it from Swift. - /// - /// typealias FnPtr = @convention(c) () -> Double - /// let fnAddr = jit.addressOfFunction(name: "test") - /// let fn = unsafeBitCast(fnAddr, to: FnPtr.self) + /// + /// ``` + /// typealias FnPtr = @convention(c) () -> Double + /// let fnAddr = jit.addressOfFunction(name: "test") + /// let fn = unsafeBitCast(fnAddr, to: FnPtr.self) + /// ``` public func addressOfFunction(name: String) -> OpaquePointer? { let addr = LLVMGetFunctionAddress(llvm, name) guard addr != 0 else { return nil }