Skip to content

Commit 0f32b8a

Browse files
authored
Merge pull request #61 from CodaFi/a-select-many
Add (constant) Select
2 parents 00b72e2 + 4e9f1e7 commit 0f32b8a

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

Sources/LLVM/Constant.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,4 +487,37 @@ extension Constant where Repr: IntegralConstantRepresentation {
487487

488488
return Constant(llvm: LLVMConstXor(lhs.llvm, rhs.llvm))
489489
}
490+
491+
// MARK: Bitshifting Operations
492+
493+
/// A constant left-shift of the first value by the second amount.
494+
///
495+
/// - parameter lhs: The first operand.
496+
/// - parameter rhs: The second operand.
497+
///
498+
/// - returns: A constant value representing the value of the first operand
499+
/// shifted left by the number of bits specified in the second operand.
500+
public static func <<(lhs: Constant, rhs: Constant) -> Constant {
501+
precondition(lhs.repr == rhs.repr, "Mixed-representation constant operations are disallowed")
502+
503+
return Constant(llvm: LLVMConstShl(lhs.llvm, rhs.llvm))
504+
}
505+
506+
507+
// MARK: Conditional Operations
508+
509+
/// A constant select using the given condition to select among two values.
510+
///
511+
/// - parameter cond: The condition to evaluate. It must have type `i1` or
512+
/// be a vector of `i1`.
513+
/// - parameter then: The value to select if the given condition is true.
514+
/// - parameter else: The value to select if the given condition is false.
515+
///
516+
/// - returns: A constant value representing the constant value selected for
517+
/// by the condition.
518+
public static func select<T: ConstantRepresentation>(_ cond: Constant, then: Constant<T>, else: Constant<T>) -> Constant<T> {
519+
precondition(then.repr == `else`.repr, "Mixed-representation constant operations are disallowed")
520+
521+
return Constant<T>(llvm: LLVMConstSelect(cond.llvm, then.llvm, `else`.llvm))
522+
}
490523
}

Sources/LLVM/IRBuilder.swift

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ public class IRBuilder {
746746
}
747747
}
748748

749-
// MARK: Declaration Instructions
749+
// MARK: Conditional Instructions
750750

751751
/// Build a phi node with the given type acting as the result of any incoming
752752
/// basic blocks.
@@ -760,14 +760,26 @@ public class IRBuilder {
760760
return PhiNode(llvm: value)
761761
}
762762

763-
/// Build a named function body with the given type.
763+
/// Build a select instruction to choose a value based on a condition without
764+
/// IR-level branching.
764765
///
765-
/// - parameter name: The name of the newly defined function.
766-
/// - parameter type: The type of the newly defined function.
766+
/// - parameter cond: The condition to evaluate. It must have type `i1` or
767+
/// be a vector of `i1`.
768+
/// - parameter then: The value to select if the given condition is true.
769+
/// - parameter else: The value to select if the given condition is false.
770+
/// - parameter name: The name for the newly inserted instruction.
767771
///
768-
/// - returns: A value representing the newly inserted function definition.
769-
public func addFunction(_ name: String, type: FunctionType) -> Function {
770-
return Function(llvm: LLVMAddFunction(module.llvm, name, type.asLLVM()))
772+
/// - returns: A value representing the value selected for by the condition.
773+
public func buildSelect(_ cond: IRValue, then: IRValue, else: IRValue, name: String = "") -> IRValue {
774+
if let ty = cond.type as? IntType {
775+
precondition(ty.width == 1, "Switch statement condition must have bitwidth of 1, instead has bitwidth of \(ty.width)")
776+
return LLVMBuildSelect(llvm, cond.asLLVM(), then.asLLVM(), `else`.asLLVM(), name)
777+
} else if let ty = cond.type as? VectorType, let intTy = ty.elementType as? IntType {
778+
precondition(intTy.width == 1, "Switch statement condition must have bitwidth of 1, instead has bitwidth of \(intTy.width)")
779+
return LLVMBuildSelect(llvm, cond.asLLVM(), then.asLLVM(), `else`.asLLVM(), name)
780+
} else {
781+
fatalError("Condition must have type i1 or <i1 x N>")
782+
}
771783
}
772784

773785
/// Build a branch table that branches on the given value with the given
@@ -790,6 +802,18 @@ public class IRBuilder {
790802
UInt32(caseCount))!)
791803
}
792804

805+
// MARK: Declaration Instructions
806+
807+
/// Build a named function body with the given type.
808+
///
809+
/// - parameter name: The name of the newly defined function.
810+
/// - parameter type: The type of the newly defined function.
811+
///
812+
/// - returns: A value representing the newly inserted function definition.
813+
public func addFunction(_ name: String, type: FunctionType) -> Function {
814+
return Function(llvm: LLVMAddFunction(module.llvm, name, type.asLLVM()))
815+
}
816+
793817
/// Build a named structure definition.
794818
///
795819
/// - parameter name: The name of the structure.

0 commit comments

Comments
 (0)