Skip to content

Commit 7dfc371

Browse files
authored
Merge pull request #64 from CodaFi/top-of-the-pops
Top of the pops
2 parents a539cee + a64062a commit 7dfc371

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

Sources/LLVM/BasicBlock.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,20 @@ public struct BasicBlock: IRValue {
8686
LLVMMoveBasicBlockAfter(llvm, block.llvm)
8787
}
8888
}
89+
90+
extension BasicBlock {
91+
/// An `Address` represents a function-relative address of a basic block for
92+
/// use with the `indirectbr` instruction.
93+
public struct Address: IRValue {
94+
internal let llvm: LLVMValueRef
95+
96+
internal init(llvm: LLVMValueRef) {
97+
self.llvm = llvm
98+
}
99+
100+
/// Retrieves the underlying LLVM value object.
101+
public func asLLVM() -> LLVMValueRef {
102+
return llvm
103+
}
104+
}
105+
}

Sources/LLVM/Function.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,34 @@ public class Function: IRGlobal {
9090
}
9191
}
9292

93+
/// Computes the address of the specified basic block in this function.
94+
///
95+
/// Taking the address of the entry block is illegal.
96+
///
97+
/// This value only has defined behavior when used as an operand to the
98+
/// `indirectbr` instruction, or for comparisons against null. Pointer
99+
/// equality tests between labels addresses results in undefined behavior.
100+
/// Though, again, comparison against null is ok, and no label is equal to
101+
/// the null pointer. This may be passed around as an opaque pointer sized
102+
/// value as long as the bits are not inspected. This allows `ptrtoint` and
103+
/// arithmetic to be performed on these values so long as the original value
104+
/// is reconstituted before the indirectbr instruction.
105+
///
106+
/// Finally, some targets may provide defined semantics when using the value
107+
/// as the operand to an inline assembly, but that is target specific.
108+
///
109+
/// - parameter block: The basic block to compute the address of.
110+
///
111+
/// - returns: An IRValue representing the address of the given basic block
112+
/// in this function, else nil if the address cannot be computed or the
113+
/// basic block does not reside in this function.
114+
public func address(of block: BasicBlock) -> BasicBlock.Address? {
115+
guard let addr = LLVMBlockAddress(llvm, block.llvm) else {
116+
return nil
117+
}
118+
return BasicBlock.Address(llvm: addr)
119+
}
120+
93121
/// Retrieves the previous function in the module, if there is one.
94122
public func previous() -> Function? {
95123
guard let previous = LLVMGetPreviousFunction(llvm) else { return nil }

Sources/LLVM/IRBuilder.swift

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,25 @@ public class IRBuilder {
864864
return LLVMBuildCondBr(llvm, condition.asLLVM(), then.asLLVM(), `else`.asLLVM())
865865
}
866866

867+
/// Build an indirect branch to a label within the current function.
868+
///
869+
/// - parameter address: The address of the label to branch to.
870+
/// - parameter destinations: The set of possible destinations the address may
871+
/// point to. The same block may appear multiple times in this list, though
872+
/// this isn't particularly useful.
873+
///
874+
/// - returns: An IRValue representing `void`.
875+
@discardableResult
876+
public func buildIndirectBr(address: BasicBlock.Address, destinations: [BasicBlock]) -> IRValue {
877+
guard let ret = LLVMBuildIndirectBr(llvm, address.asLLVM(), UInt32(destinations.count)) else {
878+
fatalError("Unable to build indirect branch to address \(address)")
879+
}
880+
for dest in destinations {
881+
LLVMAddDestination(ret, dest.llvm)
882+
}
883+
return ret
884+
}
885+
867886
/// Builds a return from the current function back to the calling function
868887
/// with the given value.
869888
///
@@ -891,6 +910,20 @@ public class IRBuilder {
891910
return LLVMBuildUnreachable(llvm)
892911
}
893912

913+
/// Build a return from the current function back to the calling function with
914+
/// the given array of values as members of an aggregate.
915+
///
916+
/// - parameter values: The values to insert as members of the returned aggregate.
917+
///
918+
/// - returns: A value representing `void`.
919+
@discardableResult
920+
public func buildRetAggregate(of values: [IRValue]) -> IRValue {
921+
var values = values.map { $0.asLLVM() as Optional }
922+
return values.withUnsafeMutableBufferPointer { buf in
923+
return LLVMBuildAggregateRet(llvm, buf.baseAddress!, UInt32(buf.count))
924+
}
925+
}
926+
894927
/// Build a call to the given function with the given arguments to transfer
895928
/// control to that function.
896929
///
@@ -1088,6 +1121,15 @@ public class IRBuilder {
10881121
return LLVMBuildFPCast(llvm, val.asLLVM(), type.asLLVM(), name)
10891122
}
10901123

1124+
/// Builds an address space cast instruction that converts a pointer value
1125+
/// to a given type in a different address space.
1126+
///
1127+
/// The address spaces of the value and the destination pointer types must
1128+
/// be distinct.
1129+
public func buildAddrSpaceCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue {
1130+
return LLVMBuildAddrSpaceCast(llvm, val.asLLVM(), type.asLLVM(), name)
1131+
}
1132+
10911133
/// Builds a truncate instruction to truncate the given value to the given
10921134
/// type with a shorter width.
10931135
///
@@ -1211,6 +1253,27 @@ public class IRBuilder {
12111253
return LLVMSizeOf(val.asLLVM())
12121254
}
12131255

1256+
/// Builds an expression that returns the difference between two pointer
1257+
/// values, dividing out the size of the pointed-to objects.
1258+
///
1259+
/// This is intended to implement C-style pointer subtraction. As such, the
1260+
/// pointers must be appropriately aligned for their element types and
1261+
/// pointing into the same object.
1262+
///
1263+
/// - parameter lhs: The first pointer (the minuend).
1264+
/// - parameter rhs: The second pointer (the subtrahend).
1265+
/// - parameter name: The name for the newly inserted instruction.
1266+
///
1267+
/// - returns: A IRValue representing a 64-bit integer value of the difference
1268+
/// of the two pointer values modulo the size of the pointed-to objects.
1269+
public func buildPointerDifference(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue {
1270+
precondition(
1271+
lhs.type is PointerType && rhs.type is PointerType,
1272+
"Cannot take pointer diff of \(lhs.type) and \(rhs.type)."
1273+
)
1274+
return LLVMBuildPtrDiff(llvm, lhs.asLLVM(), rhs.asLLVM(), name)
1275+
}
1276+
12141277
// MARK: Atomic Instructions
12151278

12161279
/// Builds a fence instruction that introduces "happens-before" edges between
@@ -1222,6 +1285,7 @@ public class IRBuilder {
12221285
/// with other atomics in the same thread. (This is useful for interacting
12231286
/// with signal handlers.) Otherwise this fence is atomic with respect to
12241287
/// all other code in the system.
1288+
/// - parameter name: The name for the newly inserted instruction.
12251289
///
12261290
/// - returns: A value representing `void`.
12271291
public func buildFence(ordering: AtomicOrdering, singleThreaded: Bool = false, name: String = "") -> IRValue {

0 commit comments

Comments
 (0)