Skip to content

Top of the pops #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Sources/LLVM/BasicBlock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,20 @@ public struct BasicBlock: IRValue {
LLVMMoveBasicBlockAfter(llvm, block.llvm)
}
}

extension BasicBlock {
/// An `Address` represents a function-relative address of a basic block for
/// use with the `indirectbr` instruction.
public struct Address: IRValue {
internal let llvm: LLVMValueRef

internal init(llvm: LLVMValueRef) {
self.llvm = llvm
}

/// Retrieves the underlying LLVM value object.
public func asLLVM() -> LLVMValueRef {
return llvm
}
}
}
28 changes: 28 additions & 0 deletions Sources/LLVM/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,34 @@ public class Function: IRGlobal {
}
}

/// Computes the address of the specified basic block in this function.
///
/// Taking the address of the entry block is illegal.
///
/// This value only has defined behavior when used as an operand to the
/// `indirectbr` instruction, or for comparisons against null. Pointer
/// equality tests between labels addresses results in undefined behavior.
/// Though, again, comparison against null is ok, and no label is equal to
/// the null pointer. This may be passed around as an opaque pointer sized
/// value as long as the bits are not inspected. This allows `ptrtoint` and
/// arithmetic to be performed on these values so long as the original value
/// is reconstituted before the indirectbr instruction.
///
/// Finally, some targets may provide defined semantics when using the value
/// as the operand to an inline assembly, but that is target specific.
///
/// - parameter block: The basic block to compute the address of.
///
/// - returns: An IRValue representing the address of the given basic block
/// in this function, else nil if the address cannot be computed or the
/// basic block does not reside in this function.
public func address(of block: BasicBlock) -> BasicBlock.Address? {
guard let addr = LLVMBlockAddress(llvm, block.llvm) else {
return nil
}
return BasicBlock.Address(llvm: addr)
}

/// Retrieves the previous function in the module, if there is one.
public func previous() -> Function? {
guard let previous = LLVMGetPreviousFunction(llvm) else { return nil }
Expand Down
64 changes: 64 additions & 0 deletions Sources/LLVM/IRBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,25 @@ public class IRBuilder {
return LLVMBuildCondBr(llvm, condition.asLLVM(), then.asLLVM(), `else`.asLLVM())
}

/// Build an indirect branch to a label within the current function.
///
/// - parameter address: The address of the label to branch to.
/// - parameter destinations: The set of possible destinations the address may
/// point to. The same block may appear multiple times in this list, though
/// this isn't particularly useful.
///
/// - returns: An IRValue representing `void`.
@discardableResult
public func buildIndirectBr(address: BasicBlock.Address, destinations: [BasicBlock]) -> IRValue {
guard let ret = LLVMBuildIndirectBr(llvm, address.asLLVM(), UInt32(destinations.count)) else {
fatalError("Unable to build indirect branch to address \(address)")
}
for dest in destinations {
LLVMAddDestination(ret, dest.llvm)
}
return ret
}

/// Builds a return from the current function back to the calling function
/// with the given value.
///
Expand Down Expand Up @@ -891,6 +910,20 @@ public class IRBuilder {
return LLVMBuildUnreachable(llvm)
}

/// Build a return from the current function back to the calling function with
/// the given array of values as members of an aggregate.
///
/// - parameter values: The values to insert as members of the returned aggregate.
///
/// - returns: A value representing `void`.
@discardableResult
public func buildRetAggregate(of values: [IRValue]) -> IRValue {
var values = values.map { $0.asLLVM() as Optional }
return values.withUnsafeMutableBufferPointer { buf in
return LLVMBuildAggregateRet(llvm, buf.baseAddress!, UInt32(buf.count))
}
}

/// Build a call to the given function with the given arguments to transfer
/// control to that function.
///
Expand Down Expand Up @@ -1088,6 +1121,15 @@ public class IRBuilder {
return LLVMBuildFPCast(llvm, val.asLLVM(), type.asLLVM(), name)
}

/// Builds an address space cast instruction that converts a pointer value
/// to a given type in a different address space.
///
/// The address spaces of the value and the destination pointer types must
/// be distinct.
public func buildAddrSpaceCast(_ val: IRValue, type: IRType, name: String = "") -> IRValue {
return LLVMBuildAddrSpaceCast(llvm, val.asLLVM(), type.asLLVM(), name)
}

/// Builds a truncate instruction to truncate the given value to the given
/// type with a shorter width.
///
Expand Down Expand Up @@ -1211,6 +1253,27 @@ public class IRBuilder {
return LLVMSizeOf(val.asLLVM())
}

/// Builds an expression that returns the difference between two pointer
/// values, dividing out the size of the pointed-to objects.
///
/// This is intended to implement C-style pointer subtraction. As such, the
/// pointers must be appropriately aligned for their element types and
/// pointing into the same object.
///
/// - parameter lhs: The first pointer (the minuend).
/// - parameter rhs: The second pointer (the subtrahend).
/// - parameter name: The name for the newly inserted instruction.
///
/// - returns: A IRValue representing a 64-bit integer value of the difference
/// of the two pointer values modulo the size of the pointed-to objects.
public func buildPointerDifference(_ lhs: IRValue, _ rhs: IRValue, name: String = "") -> IRValue {
precondition(
lhs.type is PointerType && rhs.type is PointerType,
"Cannot take pointer diff of \(lhs.type) and \(rhs.type)."
)
return LLVMBuildPtrDiff(llvm, lhs.asLLVM(), rhs.asLLVM(), name)
}

// MARK: Atomic Instructions

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