Skip to content

Commit 6d83474

Browse files
authored
Merge pull request #118 from CodaFi/boilerplate-your-scraps
Remove `JIT.runFunction`
2 parents e223097 + 4e53572 commit 6d83474

File tree

4 files changed

+87
-17
lines changed

4 files changed

+87
-17
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ builder.positionAtEnd(of: entryBB)
107107
let local = builder.buildAlloca(type: FloatType.double, name: "local")
108108

109109
// Compare to the condition
110-
let test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .notEqual)
110+
let test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .equal)
111111

112112
// Create basic blocks for "then", "else", and "merge"
113113
let thenBB = function.appendBasicBlock(named: "then")

Sources/LLVM/JIT.swift

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public final class JIT {
3232
/// The underlying LLVMExecutionEngineRef backing this JIT.
3333
internal let llvm: LLVMExecutionEngineRef
3434

35+
private static var linkOnce: () = {
36+
return LLVMLinkInMCJIT()
37+
}()
38+
3539
/// Creates a Just In Time compiler that will compile the code in the
3640
/// provided `Module` to the architecture of the provided `TargetMachine`,
3741
/// and execute it.
@@ -41,6 +45,8 @@ public final class JIT {
4145
/// - machine: The target machine which you're compiling for
4246
/// - throws: JITError
4347
public init(module: Module, machine: TargetMachine) throws {
48+
_ = JIT.linkOnce
49+
4450
var jit: LLVMExecutionEngineRef?
4551
var error: UnsafeMutablePointer<Int8>?
4652
if LLVMCreateExecutionEngineForModule(&jit, module.llvm, &error) != 0 {
@@ -54,22 +60,6 @@ public final class JIT {
5460
LLVMRunStaticConstructors(self.llvm)
5561
}
5662

57-
/// Runs the specified function with the provided arguments by compiling
58-
/// it to machine code for the target architecture used to initialize this
59-
/// JIT.
60-
///
61-
/// - parameters:
62-
/// - function: The function you wish to execute
63-
/// - args: The arguments you wish to pass to the function
64-
/// - returns: The LLVM value that the function returned
65-
public func runFunction(_ function: Function, args: [IRValue]) -> IRValue {
66-
var irArgs = args.map { $0.asLLVM() as Optional }
67-
return irArgs.withUnsafeMutableBufferPointer { buf in
68-
return LLVMRunFunction(llvm, function.asLLVM(),
69-
UInt32(buf.count), buf.baseAddress)
70-
}
71-
}
72-
7363
/// Retrieves a pointer to the function compiled by this JIT.
7464
/// - parameter name: The name of the function you wish to look up.
7565
/// - returns: A pointer to the result of compiling the specified function.

Tests/LLVMTests/JITSpec.swift

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import LLVM
2+
import XCTest
3+
import FileCheck
4+
import Foundation
5+
6+
class JITSpec : XCTestCase {
7+
func testFibonacci() {
8+
XCTAssert(fileCheckOutput(withPrefixes: ["JIT"]) {
9+
let module = Module(name: "Fibonacci")
10+
let builder = IRBuilder(module: module)
11+
12+
let function = builder.addFunction(
13+
"calculateFibs",
14+
type: FunctionType(argTypes: [IntType.int1],
15+
returnType: FloatType.double)
16+
)
17+
let entryBB = function.appendBasicBlock(named: "entry")
18+
builder.positionAtEnd(of: entryBB)
19+
20+
// allocate space for a local value
21+
let local = builder.buildAlloca(type: FloatType.double, name: "local")
22+
23+
// Compare to the condition
24+
let test = builder.buildICmp(function.parameters[0], IntType.int1.zero(), .equal)
25+
26+
// Create basic blocks for "then", "else", and "merge"
27+
let thenBB = function.appendBasicBlock(named: "then")
28+
let elseBB = function.appendBasicBlock(named: "else")
29+
let mergeBB = function.appendBasicBlock(named: "merge")
30+
31+
builder.buildCondBr(condition: test, then: thenBB, else: elseBB)
32+
33+
// MARK: Then Block
34+
35+
builder.positionAtEnd(of: thenBB)
36+
// local = 1/89, the fibonacci series (sort of)
37+
let thenVal = FloatType.double.constant(1/89)
38+
// Branch to the merge block
39+
builder.buildBr(mergeBB)
40+
41+
// MARK: Else Block
42+
builder.positionAtEnd(of: elseBB)
43+
// local = 1/109, the fibonacci series (sort of) backwards
44+
let elseVal = FloatType.double.constant(1/109)
45+
// Branch to the merge block
46+
builder.buildBr(mergeBB)
47+
48+
// MARK: Merge Block
49+
50+
builder.positionAtEnd(of: mergeBB)
51+
let phi = builder.buildPhi(FloatType.double, name: "phi_example")
52+
phi.addIncoming([
53+
(thenVal, thenBB),
54+
(elseVal, elseBB),
55+
])
56+
builder.buildStore(phi, to: local)
57+
let ret = builder.buildLoad(local, name: "ret")
58+
builder.buildRet(ret)
59+
60+
// Setup the JIT
61+
let jit = try! JIT(module: module, machine: TargetMachine())
62+
typealias FnPtr = @convention(c) (Bool) -> Double
63+
// Retrieve a handle to the function we're going to invoke
64+
let fnAddr = jit.addressOfFunction(name: "calculateFibs")
65+
let fn = unsafeBitCast(fnAddr, to: FnPtr.self)
66+
// JIT: 0.00917431192660551
67+
print(fn(true))
68+
// JIT-NEXT: 0.0112359550561798
69+
print(fn(false))
70+
})
71+
}
72+
73+
#if !os(macOS)
74+
static var allTests = testCase([
75+
("testFibonacci", testFibonacci),
76+
])
77+
#endif
78+
}
79+

Tests/LinuxMain.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ XCTMain([
99
IRExceptionSpec.allTests,
1010
IROperationSpec.allTests,
1111
FileCheckSpec.allTests,
12+
JITSpec.allTests,
1213
])
1314
#endif

0 commit comments

Comments
 (0)