Skip to content

Commit 17cabc6

Browse files
Added module-related functions to JIT (#38)
* Added module-related functions to JIT * Updated comment with example * Extra code voice
1 parent f4ed12e commit 17cabc6

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

Diff for: Sources/LLVM/JIT.swift

+42
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ public enum JITError: Error, CustomStringConvertible {
77
/// the failure.
88
case couldNotInitialize(String)
99

10+
/// The JIT was unable to remove the provided module. A message is provided
11+
/// explaining the failure
12+
case couldNotRemoveModule(Module, String)
13+
1014
/// A human-readable description of the error.
1115
public var description: String {
1216
switch self {
17+
case .couldNotRemoveModule(let module, let message):
18+
return "could not remove module '\(module.name)': \(message)"
1319
case .couldNotInitialize(let message):
1420
return "could not initialize JIT: \(message)"
1521
}
@@ -61,6 +67,42 @@ public final class JIT {
6167
}
6268
}
6369

70+
/// Retrieves a pointer to the function compiled by this JIT.
71+
/// - parameter name: The name of the function you wish to look up.
72+
/// - returns: A pointer to the result of compiling the specified function.
73+
/// - note: You will have to `unsafeBitCast` this pointer to
74+
/// the appropriate `@convention(c)` function type to be
75+
/// able to run it from Swift.
76+
///
77+
/// ```
78+
/// typealias FnPtr = @convention(c) () -> Double
79+
/// let fnAddr = jit.addressOfFunction(name: "test")
80+
/// let fn = unsafeBitCast(fnAddr, to: FnPtr.self)
81+
/// ```
82+
public func addressOfFunction(name: String) -> OpaquePointer? {
83+
let addr = LLVMGetFunctionAddress(llvm, name)
84+
guard addr != 0 else { return nil }
85+
return OpaquePointer(bitPattern: UInt(addr))
86+
}
87+
88+
/// Adds the provided module, and all top-level declarations into this JIT.
89+
/// - parameter module: The module you wish to add.
90+
public func addModule(_ module: Module) {
91+
LLVMAddModule(llvm, module.llvm)
92+
}
93+
94+
/// Removes the provided module, and all top-level declarations, from this
95+
/// JIT.
96+
public func removeModule(_ module: Module) throws {
97+
var outMod: LLVMModuleRef? = module.llvm
98+
var outError: UnsafeMutablePointer<Int8>?
99+
LLVMRemoveModule(llvm, module.llvm, &outMod, &outError)
100+
if let err = outError {
101+
defer { LLVMDisposeMessage(err) }
102+
throw JITError.couldNotRemoveModule(module, String(cString: err))
103+
}
104+
}
105+
64106
/// Runs the specified function as if it were the `main` function in an
65107
/// executable. It takes an array of argument strings and passes them
66108
/// into the function as `argc` and `argv`.

Diff for: Sources/LLVM/Module.swift

+11
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ public final class Module: CustomStringConvertible {
7272
return TargetData(llvm: LLVMGetModuleDataLayout(llvm))
7373
}
7474

75+
/// The identifier of this module.
76+
public var name: String {
77+
get {
78+
guard let id = LLVMGetModuleIdentifier(llvm, nil) else { return "" }
79+
return String(cString: id)
80+
}
81+
set {
82+
LLVMSetModuleIdentifier(llvm, newValue, newValue.utf8.count)
83+
}
84+
}
85+
7586
/// Print a representation of a module to a file at the given path.
7687
///
7788
/// If the provided path is not suitable for writing, this function will throw

0 commit comments

Comments
 (0)