1
1
import cllvm
2
2
3
+ /// A `PhiNode` object represents a PHI node.
4
+ ///
5
+ /// Because all instructions in LLVM IR are in SSA (Single Static Assignment)
6
+ /// form, a PHI node is necessary when the value of a variable assignment
7
+ /// depends on the path the flow of control takes through the program. For
8
+ /// example:
9
+ ///
10
+ /// ```swift
11
+ /// var a = 1
12
+ /// if c == 42 {
13
+ /// a = 2
14
+ /// }
15
+ /// let b = a
16
+ /// ```
17
+ ///
18
+ /// The value of `b` in this program depends on the value of the condition
19
+ /// involving the variable `c`. Because `b` must be assigned to once, a PHI
20
+ /// node is created and the program effectively is transformed into the
21
+ /// following:
22
+ ///
23
+ /// ```swift
24
+ /// let aNoCond = 1
25
+ /// if c == 42 {
26
+ /// let aCondTrue = 2
27
+ /// }
28
+ /// let b = PHI(aNoCond, aCondTrue)
29
+ /// ```
30
+ ///
31
+ /// If the flow of control reaches `aCondTrue`, the value of `b` is `2`, else it
32
+ /// is `1` and SSA semantics are preserved.
3
33
public struct PhiNode : IRValue {
4
34
internal let llvm : LLVMValueRef
5
-
35
+
36
+ /// Adds a list of incoming value and their associated basic blocks to the end
37
+ /// of the list of incoming values for this PHI node.
38
+ ///
39
+ /// - parameter valueMap: A list of incoming values and their associated basic
40
+ /// blocks.
6
41
public func addIncoming( _ valueMap: [ ( IRValue , BasicBlock ) ] ) {
7
42
var values = valueMap. map { $0. 0 . asLLVM ( ) as Optional }
8
43
var blocks = valueMap. map { $0. 1 . asLLVM ( ) as Optional }
9
-
44
+
10
45
values. withUnsafeMutableBufferPointer { valueBuf in
11
46
blocks. withUnsafeMutableBufferPointer { blockBuf in
12
47
LLVMAddIncoming ( llvm,
@@ -16,27 +51,44 @@ public struct PhiNode: IRValue {
16
51
}
17
52
}
18
53
}
19
-
54
+
55
+ /// Obtain the incoming values and their associated basic blocks for this PHI
56
+ /// node.
20
57
public var incoming : [ ( IRValue , BasicBlock ) ] {
21
58
let count = Int ( LLVMCountIncoming ( llvm) )
22
59
var values = [ ( IRValue, BasicBlock) ] ( )
23
60
for i in 0 ..< count {
24
61
guard let value = incomingValue ( at: i) ,
25
- let block = incomingBlock ( at: i) else { continue }
62
+ let block = incomingBlock ( at: i) else { continue }
26
63
values. append ( ( value, block) )
27
64
}
28
65
return values
29
66
}
30
-
67
+
68
+ /// Retrieves the incoming value for the given index for this PHI node, if it
69
+ /// exists.
70
+ ///
71
+ /// - parameter index: The index of the incoming value to retrieve.
72
+ ///
73
+ /// - returns: A value representing the incoming value to this PHI node at
74
+ /// the given index, if it exists.
31
75
public func incomingValue( at index: Int ) -> IRValue ? {
32
76
return LLVMGetIncomingValue ( llvm, UInt32 ( index) )
33
77
}
34
-
78
+
79
+ /// Retrieves the incoming basic block for the given index for this PHI node,
80
+ /// if it exists.
81
+ ///
82
+ /// - parameter index: The index of the incoming basic block to retrieve.
83
+ ///
84
+ /// - returns: A value representing the incoming basic block to this PHI node
85
+ /// at the given index, if it exists.
35
86
public func incomingBlock( at index: Int ) -> BasicBlock ? {
36
87
guard let blockRef = LLVMGetIncomingBlock ( llvm, UInt32 ( index) ) else { return nil }
37
88
return BasicBlock ( llvm: blockRef)
38
89
}
39
-
90
+
91
+ /// Retrieves the underlying LLVM value object.
40
92
public func asLLVM( ) -> LLVMValueRef {
41
93
return llvm
42
94
}
0 commit comments