Skip to content

Commit 7dd5dbc

Browse files
authored
Merge pull request #98 from CodaFi/parody
A Hodge-Podge of Fixes and Features
2 parents fb715ee + 9aa43f3 commit 7dd5dbc

File tree

4 files changed

+77
-10
lines changed

4 files changed

+77
-10
lines changed

Sources/LLVM/Global.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public struct Global: IRGlobal {
111111

112112
/// Accesses the model of reference for this global variable if it is
113113
/// thread-local.
114-
public var threadLocalMode: ThreadLocalModel {
114+
public var threadLocalModel: ThreadLocalModel {
115115
get { return ThreadLocalModel(llvm: LLVMGetThreadLocalMode(asLLVM())) }
116116
set { LLVMSetThreadLocalMode(asLLVM(), newValue.llvm) }
117117
}

Sources/LLVM/IRBuilder.swift

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,8 @@ public enum AtomicOrdering: Comparable {
200200
.sequentiallyConsistent: LLVMAtomicOrderingSequentiallyConsistent,
201201
]
202202

203-
public static func ==(lhs: AtomicOrdering, rhs: AtomicOrdering) -> Bool {
204-
return lhs.llvm == rhs.llvm
205-
}
206-
203+
/// Returns whether the left atomic ordering is strictly weaker than the
204+
/// right atomic order.
207205
public static func <(lhs: AtomicOrdering, rhs: AtomicOrdering) -> Bool {
208206
return lhs.llvm.rawValue < rhs.llvm.rawValue
209207
}
@@ -1094,25 +1092,40 @@ public class IRBuilder {
10941092
return LLVMBuildAlloca(llvm, type.asLLVM(), name)
10951093
}
10961094

1097-
/// Build a store instruction that stores the first value into the location
1095+
/// Builds a store instruction that stores the first value into the location
10981096
/// given in the second value.
10991097
///
1098+
/// - parameter val: The source value.
1099+
/// - parameter ptr: The destination pointer to store into.
1100+
/// - parameter ordering: The ordering effect of the fence for this store,
1101+
/// if any. Defaults to a nonatomic store.
1102+
/// - parameter volatile: Whether this is a store to a volatile memory location.
1103+
///
11001104
/// - returns: A value representing `void`.
11011105
@discardableResult
1102-
public func buildStore(_ val: IRValue, to ptr: IRValue) -> IRValue {
1103-
return LLVMBuildStore(llvm, val.asLLVM(), ptr.asLLVM())
1106+
public func buildStore(_ val: IRValue, to ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false) -> IRValue {
1107+
let storeInst = LLVMBuildStore(llvm, val.asLLVM(), ptr.asLLVM())!
1108+
LLVMSetOrdering(storeInst, ordering.llvm)
1109+
LLVMSetVolatile(storeInst, volatile.llvm)
1110+
return storeInst
11041111
}
11051112

11061113
/// Builds a load instruction that loads a value from the location in the
11071114
/// given value.
11081115
///
11091116
/// - parameter ptr: The pointer value to load from.
1117+
/// - parameter ordering: The ordering effect of the fence for this load,
1118+
/// if any. Defaults to a nonatomic load.
1119+
/// - parameter volatile: Whether this is a load from a volatile memory location.
11101120
/// - parameter name: The name for the newly inserted instruction.
11111121
///
11121122
/// - returns: A value representing the result of a load from the given
11131123
/// pointer value.
1114-
public func buildLoad(_ ptr: IRValue, name: String = "") -> IRValue {
1115-
return LLVMBuildLoad(llvm, ptr.asLLVM(), name)
1124+
public func buildLoad(_ ptr: IRValue, ordering: AtomicOrdering = .notAtomic, volatile: Bool = false, name: String = "") -> IRValue {
1125+
let loadInst = LLVMBuildLoad(llvm, ptr.asLLVM(), name)!
1126+
LLVMSetOrdering(loadInst, ordering.llvm)
1127+
LLVMSetVolatile(loadInst, volatile.llvm)
1128+
return loadInst
11161129
}
11171130

11181131
/// Builds a `GEP` (Get Element Pointer) instruction with a resultant value
@@ -1706,6 +1719,48 @@ public class IRBuilder {
17061719
return Alias(llvm: LLVMAddAlias(module.llvm, type.asLLVM(), aliasee.asLLVM(), name))
17071720
}
17081721

1722+
// MARK: Inline Assembly
1723+
1724+
/// Builds a value representing an inline assembly expression (as opposed to
1725+
/// module-level inline assembly).
1726+
///
1727+
/// LLVM represents inline assembler as a template string (containing the
1728+
/// instructions to emit), a list of operand constraints (stored as a string),
1729+
/// and some flags.
1730+
///
1731+
/// The template string supports argument substitution of the operands using
1732+
/// "$" followed by a number, to indicate substitution of the given
1733+
/// register/memory location, as specified by the constraint string.
1734+
/// "${NUM:MODIFIER}" may also be used, where MODIFIER is a target-specific
1735+
/// annotation for how to print the operand (see [Asm Template Argument
1736+
/// Modifiers](https://llvm.org/docs/LangRef.html#inline-asm-modifiers)).
1737+
///
1738+
/// LLVM’s support for inline asm is modeled closely on the requirements of
1739+
/// Clang’s GCC-compatible inline-asm support. Thus, the feature-set and the
1740+
/// constraint and modifier codes are similar or identical to those in GCC’s
1741+
/// inline asm support.
1742+
///
1743+
/// However, the syntax of the template and constraint strings is not the
1744+
/// same as the syntax accepted by GCC and Clang, and, while most constraint
1745+
/// letters are passed through as-is by Clang, some get translated to other
1746+
/// codes when converting from the C source to the LLVM assembly.
1747+
///
1748+
/// - parameter asm: The inline assembly expression template string.
1749+
/// - parameter type: The type of the parameters and return value of the
1750+
/// assembly expression string.
1751+
/// - parameter constraints: A comma-separated string, each element containing
1752+
/// one or more constraint codes.
1753+
/// - parameter hasSideEffects: Whether this inline asm expression has
1754+
/// side effects. Defaults to `false`.
1755+
/// - parameter needsAlignedStack: Whether the function containing the
1756+
/// asm needs to align its stack conservatively. Defaults to `true`.
1757+
///
1758+
/// - returns: A representation of the newly created inline assembly
1759+
/// expression.
1760+
public func buildInlineAssembly(_ asm: String, type: FunctionType, constraints: String = "", hasSideEffects: Bool = true, needsAlignedStack: Bool = true) -> IRValue {
1761+
return LLVMConstInlineAsm(type.asLLVM(), asm, constraints, hasSideEffects.llvm, needsAlignedStack.llvm)
1762+
}
1763+
17091764
deinit {
17101765
LLVMDisposeBuilder(llvm)
17111766
}

Sources/LLVM/Switch.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public struct Switch: IRValue {
1919
LLVMAddCase(llvm, value.asLLVM(), block.asLLVM())
2020
}
2121

22+
/// Retrieves the basic block the flow of control reaches should a
23+
/// value not match any of the cases in the branch table.
24+
var defaultDestination: BasicBlock {
25+
return BasicBlock(llvm: LLVMGetSwitchDefaultDest(self.llvm))
26+
}
27+
2228
/// Retrieves the underlying LLVM value object.
2329
public func asLLVM() -> LLVMValueRef {
2430
return llvm

Tests/LLVMTests/IRBuilderSpec.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,12 @@ class IRBuilderSpec : XCTestCase {
223223
// CONTROLFLOW-NEXT: store i64 1, i64* %var
224224
builder.buildStore(IntType.int64.constant(1), to: variable)
225225

226+
// CONTROLFLOW-NEXT: store volatile i64 1, i64* %var
227+
builder.buildStore(IntType.int64.constant(1), to: variable, volatile: true)
228+
229+
// CONTROLFLOW-NEXT: store atomic i64 1, i64* %var
230+
builder.buildStore(IntType.int64.constant(1), to: variable, ordering: .sequentiallyConsistent)
231+
226232
// CONTROLFLOW-NEXT: %0 = load i64, i64* %var
227233
let load = builder.buildLoad(variable)
228234

0 commit comments

Comments
 (0)