@@ -115,24 +115,39 @@ end
115
115
116
116
export blocks
117
117
118
- struct FunctionBlockSet
118
+ struct FunctionBlockSet <: AbstractVector{BasicBlock}
119
119
f:: Function
120
+ cache:: Vector{API.LLVMValueRef}
121
+
122
+ FunctionBlockSet (f:: Function ) = new (f, BasicBlock[])
120
123
end
121
124
122
125
blocks (f:: Function ) = FunctionBlockSet (f)
123
126
124
- Base. eltype (:: FunctionBlockSet ) = BasicBlock
125
-
126
- function Base. iterate (iter:: FunctionBlockSet , state= API. LLVMGetFirstBasicBlock (iter. f))
127
- state == C_NULL ? nothing : (BasicBlock (state), API. LLVMGetNextBasicBlock (state))
128
- end
127
+ Base. size (iter:: FunctionBlockSet ) = (Int (API. LLVMCountBasicBlocks (iter. f)),)
129
128
130
129
Base. first (iter:: FunctionBlockSet ) = BasicBlock (API. LLVMGetFirstBasicBlock (iter. f))
131
130
Base. last (iter:: FunctionBlockSet ) = BasicBlock (API. LLVMGetLastBasicBlock (iter. f))
132
131
133
- Base. isempty (iter:: FunctionBlockSet ) = length (iter) == 0
132
+ function Base. iterate (iter:: FunctionBlockSet , state= API. LLVMGetFirstBasicBlock (iter. f))
133
+ state == C_NULL ? nothing : (BasicBlock (state), API. LLVMGetNextBasicBlock (state))
134
+ end
134
135
135
- Base. length (iter:: FunctionBlockSet ) = API. LLVMCountBasicBlocks (iter. f)
136
+ # provide a random access interface by maintaining a cache of blocks
137
+ function Base. getindex (iter:: FunctionBlockSet , i:: Int )
138
+ i <= 0 && throw (BoundsError (iter, i))
139
+ i == 1 && return first (iter)
140
+ while i > length (iter. cache)
141
+ next = if isempty (iter. cache)
142
+ iterate (iter)
143
+ else
144
+ iterate (iter, iter. cache[end ])
145
+ end
146
+ next === nothing && throw (BoundsError (iter, i))
147
+ push! (iter. cache, next[2 ])
148
+ end
149
+ return BasicBlock (iter. cache[i- 1 ])
150
+ end
136
151
137
152
# NOTE: optimized `collect`
138
153
function Base. collect (iter:: FunctionBlockSet )
0 commit comments