@@ -9,12 +9,22 @@ public protocol RealConstantRepresentation: ConstantRepresentation {}
9
9
public enum Signed : IntegralConstantRepresentation { }
10
10
public enum Floating : RealConstantRepresentation { }
11
11
12
+ // FIXME: When upgrading to Swift 3.1, move this into `Constant`.
12
13
internal enum InternalConstantRepresentation {
13
14
case unsigned
14
15
case signed
15
16
case floating
16
17
}
17
18
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.
18
28
public struct Constant < Repr: ConstantRepresentation > : IRValue {
19
29
internal let llvm : LLVMValueRef
20
30
internal let repr : InternalConstantRepresentation
@@ -39,6 +49,48 @@ public struct Constant<Repr: ConstantRepresentation>: IRValue {
39
49
}
40
50
}
41
51
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
+
42
94
// MARK: Arithmetic Operations
43
95
44
96
public static func neg( _ lhs: Constant < Signed > , overflowBehavior: OverflowBehavior = . default) -> Constant < Signed > {
0 commit comments