LLVM IR Iteration
STL-style refers to following the design patterns and conventions established by the Standard Template Library (STL), which is a fundamental part of the C++ standard library.
Core STL Design Patterns
1. Iterator Pattern
STL uses iterators as a uniform way to traverse containers:
// STL vector example
std::vector<int> vec = {1, 2, 3, 4, 5};
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
2. Common Interface Conventions
STL containers share consistent method names:
begin()
/end()
- start/end iteratorssize()
- number of elementsempty()
- check if container is emptyinsert()
/erase()
- add/remove elements
3. Template-Based Design
STL heavily uses templates for type safety and reusability:
template<typename T>
class vector { /* ... */ };
How LLVM Adopts STL-Style
LLVM IR classes follow these same patterns:
// LLVM follows STL conventions
Function* F = /* ... */;
// STL-style iteration
for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
// process instruction
}
}
// STL-style methods
if (!F->empty()) { // Like STL containers
size_t numBB = F->size(); // Like STL containers
}
STL Iterator Categories
STL defines different iterator types that LLVM also follows:
Iterator Type | Capabilities | Example |
---|---|---|
Input Iterator | Read-only, forward only | istream_iterator |
Output Iterator | Write-only, forward only | ostream_iterator |
Forward Iterator | Read/write, forward only | forward_list::iterator |
Bidirectional Iterator | Read/write, forward/backward | list::iterator |
Random Access Iterator | Read/write, jump to any position | vector::iterator |
STL-Style Benefits
1. Familiar Interface
C++ developers already know these patterns:
// This feels familiar to anyone who knows STL
for (Module::iterator F = M.begin(); F != M.end(); ++F) {
// process function
}
2. Generic Algorithms
Works with STL algorithms:
#include <algorithm>
// Count functions in a module
size_t funcCount = std::distance(M.begin(), M.end());
// Find a specific function
auto it = std::find_if(M.begin(), M.end(),
[](const Function& F) { return F.getName() == "main"; });
3. Range-Based For Loops (C++11+)
// Modern C++ range-based for loop works because of STL-style design
for (auto& F : M) {
for (auto& BB : F) {
for (auto& I : BB) {
// process instruction
}
}
}
Available Iterator Types in LLVM
From the document, LLVM provides these STL-style iterator types:
// Different iterator types for different LLVM structures
Module::iterator // Iterates over functions in a module
Function::iterator // Iterates over basic blocks in a function
BasicBlock::iterator // Iterates over instructions in a basic block
Value::use_iterator // Iterates over uses of a value
User::op_iterator // Iterates over operands of a user
Comparison: STL-Style vs Custom Approaches
// STL-style (what LLVM uses)
for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) {
// Standard, predictable interface
}
// Hypothetical custom approach (what LLVM could have done differently)
for (int i = 0; i < F->getBasicBlockCount(); ++i) {
BasicBlock* BB = F->getBasicBlock(i);
// Less familiar, inconsistent across different classes
}
The STL-style approach makes LLVM more approachable for C++ developers because they can leverage their existing knowledge of STL patterns and conventions. This design choice reduces the learning curve and makes the API more intuitive and consistent.