Skip to content

Commit 0e588dc

Browse files
committed
Add Casting operators
1 parent bbe4b40 commit 0e588dc

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

Sources/LLVM/Constant.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,22 @@ public protocol RealConstantRepresentation: ConstantRepresentation {}
99
public enum Signed: IntegralConstantRepresentation {}
1010
public enum Floating: RealConstantRepresentation {}
1111

12+
// FIXME: When upgrading to Swift 3.1, move this into `Constant`.
1213
internal enum InternalConstantRepresentation {
1314
case unsigned
1415
case signed
1516
case floating
1617
}
1718

19+
/// A `Constant` represents a value initialized to a constant. Constant values
20+
/// may be manipulated with standard Swift arithmetic operations and used with
21+
/// standard IR Builder instructions like any other operand. The difference
22+
/// being any instructions acting solely on constants and any arithmetic
23+
/// performed on constants is evaluated at compile-time only.
24+
///
25+
/// `Constant`s keep track of the values they represent at the type level to
26+
/// disallow mixed-type arithmetic. Use the `cast` family of operations to
27+
/// safely convert constants to other representations.
1828
public struct Constant<Repr: ConstantRepresentation>: IRValue {
1929
internal let llvm: LLVMValueRef
2030
internal let repr: InternalConstantRepresentation
@@ -39,6 +49,48 @@ public struct Constant<Repr: ConstantRepresentation>: IRValue {
3949
}
4050
}
4151

52+
// MARK: Casting
53+
54+
public func cast<T: IntegralConstantRepresentation>(to type: IntType) -> Constant<T> {
55+
let reprID = ObjectIdentifier(T.self)
56+
let val = self.asLLVM()
57+
if reprID == ObjectIdentifier(Unsigned.self) {
58+
switch self.repr {
59+
case .unsigned: fallthrough
60+
case .signed:
61+
return Constant<T>(llvm: LLVMConstIntCast(val, type.asLLVM(), /*signed:*/ false.llvm))
62+
case .floating:
63+
return Constant<T>(llvm: LLVMConstFPToUI(val, type.asLLVM()))
64+
}
65+
} else if reprID == ObjectIdentifier(Signed.self) {
66+
switch self.repr {
67+
case .unsigned: fallthrough
68+
case .signed:
69+
return Constant<T>(llvm: LLVMConstIntCast(val, type.asLLVM(), /*signed:*/ true.llvm))
70+
case .floating:
71+
return Constant<T>(llvm: LLVMConstFPToSI(val, type.asLLVM()))
72+
}
73+
} else {
74+
fatalError("Invalid representation \(type(of: T.self))")
75+
}
76+
}
77+
78+
public func cast<T: RealConstantRepresentation>(to type: FloatType) -> Constant<T> {
79+
guard ObjectIdentifier(T.self) == ObjectIdentifier(Floating.self) else {
80+
fatalError("Invalid representation \(type(of: T.self))")
81+
}
82+
83+
let val = self.asLLVM()
84+
switch self.repr {
85+
case .unsigned:
86+
return Constant<T>(llvm: LLVMConstUIToFP(val, type.asLLVM()))
87+
case .signed:
88+
return Constant<T>(llvm: LLVMConstSIToFP(val, type.asLLVM()))
89+
case .floating:
90+
return Constant<T>(llvm: LLVMConstFPCast(val, type.asLLVM()))
91+
}
92+
}
93+
4294
// MARK: Arithmetic Operations
4395

4496
public static func neg(_ lhs: Constant<Signed>, overflowBehavior: OverflowBehavior = .default) -> Constant<Signed> {

0 commit comments

Comments
 (0)