Skip to content

Commit 1ca4af8

Browse files
Added custom iterators for instructions, basic blocks, and uses of instructions. (#21)
Also split Instruction and OpCode into separate files
1 parent 2ae4e58 commit 1ca4af8

File tree

5 files changed

+230
-209
lines changed

5 files changed

+230
-209
lines changed

Sources/LLVM/BasicBlock.swift

Lines changed: 12 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import cllvm
1313
/// have predecessor basic blocks (i.e. there can not be any branches to the
1414
/// entry block of a function). Because the block can have no predecessors, it
1515
/// also cannot have any PHI nodes.
16-
public struct BasicBlock: IRValue, Sequence {
16+
public struct BasicBlock: IRValue {
1717
internal let llvm: LLVMBasicBlockRef
1818

1919
/// Creates a `BasicBlock` from an `LLVMBasicBlockRef` object.
@@ -50,6 +50,17 @@ public struct BasicBlock: IRValue, Sequence {
5050
return BasicBlock(llvm: blockRef)
5151
}
5252

53+
/// Returns a sequence of the Instructions that make up this basic block.
54+
public var instructions: AnySequence<Instruction> {
55+
var current = firstInstruction
56+
return AnySequence<Instruction> {
57+
return AnyIterator<Instruction> {
58+
defer { current = current?.next() }
59+
return current
60+
}
61+
}
62+
}
63+
5364
/// Deletes the basic block from its containing function.
5465
/// - note: This does not remove breaks to this block from the
5566
/// function. Ensure you have removed all insructions that reference
@@ -72,204 +83,4 @@ public struct BasicBlock: IRValue, Sequence {
7283
public func moveAfter(_ block: BasicBlock) {
7384
LLVMMoveBasicBlockAfter(llvm, block.llvm)
7485
}
75-
76-
/// Returns an iterator over the `Instruction`s that make up this basic block.
77-
public func makeIterator() -> AnyIterator<Instruction> {
78-
var current = firstInstruction
79-
return AnyIterator {
80-
defer { current = current?.next() }
81-
return current
82-
}
83-
}
8486
}
85-
86-
/// Enumerates the opcodes of instructions available in the LLVM IR language.
87-
///
88-
/// The raw values of this enumeration *must* match those in
89-
/// [llvm-c/Core.h](https://github.com/llvm-mirror/llvm/blob/master/include/llvm-c/Core.h).
90-
public enum OpCode: UInt32 {
91-
// MARK: Terminator Instructions
92-
93-
// The opcode for the `ret` instruction.
94-
case ret = 1
95-
// The opcode for the `br` instruction.
96-
case br = 2
97-
// The opcode for the `switch` instruction.
98-
case `switch` = 3
99-
// The opcode for the `indirectBr` instruction.
100-
case indirectBr = 4
101-
// The opcode for the `invoke` instruction.
102-
case invoke = 5
103-
// The opcode for the `unreachable` instruction.
104-
case unreachable = 7
105-
106-
// MARK: Standard Binary Operators
107-
108-
// The opcode for the `add` instruction.
109-
case add = 8
110-
// The opcode for the `fadd` instruction.
111-
case fadd = 9
112-
// The opcode for the `sub` instruction.
113-
case sub = 10
114-
// The opcode for the `fsub` instruction.
115-
case fsub = 11
116-
// The opcode for the `mul` instruction.
117-
case mul = 12
118-
// The opcode for the `fmul` instruction.
119-
case fmul = 13
120-
// The opcode for the `udiv` instruction.
121-
case udiv = 14
122-
// The opcode for the `sdiv` instruction.
123-
case sdiv = 15
124-
// The opcode for the `fdiv` instruction.
125-
case fdiv = 16
126-
// The opcode for the `urem` instruction.
127-
case urem = 17
128-
// The opcode for the `srem` instruction.
129-
case srem = 18
130-
// The opcode for the `frem` instruction.
131-
case frem = 19
132-
133-
// MARK: Logical Operators
134-
135-
// The opcode for the `shl` instruction.
136-
case shl = 20
137-
// The opcode for the `lshr` instruction.
138-
case lshr = 21
139-
// The opcode for the `ashr` instruction.
140-
case ashr = 22
141-
// The opcode for the `and` instruction.
142-
case and = 23
143-
// The opcode for the `or` instruction.
144-
case or = 24
145-
// The opcode for the `xor` instruction.
146-
case xor = 25
147-
148-
// MARK: Memory Operators
149-
150-
// The opcode for the `alloca` instruction.
151-
case alloca = 26
152-
// The opcode for the `load` instruction.
153-
case load = 27
154-
// The opcode for the `store` instruction.
155-
case store = 28
156-
// The opcode for the `getElementPtr` instruction.
157-
case getElementPtr = 29
158-
159-
// MARK: Cast Operators
160-
161-
// The opcode for the `trunc` instruction.
162-
case trunc = 30
163-
// The opcode for the `zext` instruction.
164-
case zext = 31
165-
// The opcode for the `sext` instruction.
166-
case sext = 32
167-
// The opcode for the `fpToUI` instruction.
168-
case fpToUI = 33
169-
// The opcode for the `fpToSI` instruction.
170-
case fpToSI = 34
171-
// The opcode for the `uiToFP` instruction.
172-
case uiToFP = 35
173-
// The opcode for the `siToFP` instruction.
174-
case siToFP = 36
175-
// The opcode for the `fpTrunc` instruction.
176-
case fpTrunc = 37
177-
// The opcode for the `fpExt` instruction.
178-
case fpExt = 38
179-
// The opcode for the `ptrToInt` instruction.
180-
case ptrToInt = 39
181-
// The opcode for the `intToPtr` instruction.
182-
case intToPtr = 40
183-
// The opcode for the `bitCast` instruction.
184-
case bitCast = 41
185-
// The opcode for the `addrSpaceCast` instruction.
186-
case addrSpaceCast = 60
187-
188-
// MARK: Other Operators
189-
190-
// The opcode for the `icmp` instruction.
191-
case icmp = 42
192-
// The opcode for the `fcmp` instruction.
193-
case fcmp = 43
194-
// The opcode for the `PHI` instruction.
195-
case PHI = 44
196-
// The opcode for the `call` instruction.
197-
case call = 45
198-
// The opcode for the `select` instruction.
199-
case select = 46
200-
// The opcode for the `userOp1` instruction.
201-
case userOp1 = 47
202-
// The opcode for the `userOp2` instruction.
203-
case userOp2 = 48
204-
// The opcode for the `vaArg` instruction.
205-
case vaArg = 49
206-
// The opcode for the `extractElement` instruction.
207-
case extractElement = 50
208-
// The opcode for the `insertElement` instruction.
209-
case insertElement = 51
210-
// The opcode for the `shuffleVector` instruction.
211-
case shuffleVector = 52
212-
// The opcode for the `extractValue` instruction.
213-
case extractValue = 53
214-
// The opcode for the `insertValue` instruction.
215-
case insertValue = 54
216-
217-
// MARK: Atomic operators
218-
219-
// The opcode for the `fence` instruction.
220-
case fence = 55
221-
// The opcode for the `atomicCmpXchg` instruction.
222-
case atomicCmpXchg = 56
223-
// The opcode for the `atomicRMW` instruction.
224-
case atomicRMW = 57
225-
226-
// MARK: Exception Handling Operators
227-
228-
// The opcode for the `resume` instruction.
229-
case resume = 58
230-
// The opcode for the `landingPad` instruction.
231-
case landingPad = 59
232-
// The opcode for the `cleanupRet` instruction.
233-
case cleanupRet = 61
234-
// The opcode for the `catchRet` instruction.
235-
case catchRet = 62
236-
// The opcode for the `catchPad` instruction.
237-
case catchPad = 63
238-
// The opcode for the `cleanupPad` instruction.
239-
case cleanupPad = 64
240-
// The opcode for the `catchSwitch` instruction.
241-
case catchSwitch = 65
242-
}
243-
244-
/// An `Instruction` represents an instruction residing in a basic block.
245-
public struct Instruction: IRValue {
246-
internal let llvm: LLVMValueRef
247-
248-
/// Creates an `Intruction` from an `LLVMValueRef` object.
249-
public init(llvm: LLVMValueRef) {
250-
self.llvm = llvm
251-
}
252-
253-
/// Retrieves the underlying LLVM value object.
254-
public func asLLVM() -> LLVMValueRef {
255-
return llvm
256-
}
257-
258-
/// Retrieves the opcode associated with this `Instruction`.
259-
public var opCode: OpCode {
260-
return OpCode(rawValue: LLVMGetInstructionOpcode(llvm).rawValue)!
261-
}
262-
263-
/// Obtain the instruction that occurs before this one, if it exists.
264-
public func previous() -> Instruction? {
265-
guard let val = LLVMGetPreviousInstruction(llvm) else { return nil }
266-
return Instruction(llvm: val)
267-
}
268-
269-
/// Obtain the instruction that occurs after this one, if it exists.
270-
public func next() -> Instruction? {
271-
guard let val = LLVMGetNextInstruction(llvm) else { return nil }
272-
return Instruction(llvm: val)
273-
}
274-
}
275-

Sources/LLVM/Function.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ public class Function: IRValue {
4040
}
4141

4242
/// Retrieves the sequence of basic blocks that make up this function's body.
43-
public var basicBlocks: [BasicBlock] {
44-
var blocks = [BasicBlock]()
43+
public var basicBlocks: AnySequence<BasicBlock> {
4544
var current = firstBlock
46-
while let block = current {
47-
blocks.append(block)
48-
current = block.next()
45+
return AnySequence<BasicBlock> {
46+
return AnyIterator<BasicBlock> {
47+
defer { current = current?.next() }
48+
return current
49+
}
4950
}
50-
return blocks
5151
}
5252

5353
/// Retrieves a parameter at the given index, if it exists.

Sources/LLVM/Instruction.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import cllvm
2+
3+
/// An `Instruction` represents an instruction residing in a basic block.
4+
public struct Instruction: IRValue {
5+
internal let llvm: LLVMValueRef
6+
7+
/// Creates an `Intruction` from an `LLVMValueRef` object.
8+
public init(llvm: LLVMValueRef) {
9+
self.llvm = llvm
10+
}
11+
12+
/// Retrieves the underlying LLVM value object.
13+
public func asLLVM() -> LLVMValueRef {
14+
return llvm
15+
}
16+
17+
/// Retrieves the opcode associated with this `Instruction`.
18+
public var opCode: OpCode {
19+
return OpCode(rawValue: LLVMGetInstructionOpcode(llvm).rawValue)!
20+
}
21+
22+
/// Obtain the instruction that occurs before this one, if it exists.
23+
public func previous() -> Instruction? {
24+
guard let val = LLVMGetPreviousInstruction(llvm) else { return nil }
25+
return Instruction(llvm: val)
26+
}
27+
28+
/// Obtain the instruction that occurs after this one, if it exists.
29+
public func next() -> Instruction? {
30+
guard let val = LLVMGetNextInstruction(llvm) else { return nil }
31+
return Instruction(llvm: val)
32+
}
33+
34+
public var firstUse: Use? {
35+
guard let use = LLVMGetFirstUse(llvm) else { return nil }
36+
return Use(llvm: use)
37+
}
38+
39+
40+
/// Retrieves the sequence of instructions that use the value from this
41+
/// instruction.
42+
public var uses: AnySequence<Use> {
43+
var current = firstUse
44+
return AnySequence<Use> {
45+
return AnyIterator<Use> {
46+
defer { current = current?.next() }
47+
return current
48+
}
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)