Skip to content

Commit 4bd90b8

Browse files
authored
Add insert_after to Builder class (#327)
This adds the ability to set the insertion point for a builder to after the given instruction.
1 parent c0bd9cc commit 4bd90b8

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

pyqir/pyqir/_native.pyi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@ class Builder:
151151
"""
152152
...
153153

154+
def insert_after(self, instr: Instruction) -> None:
155+
"""
156+
Tells the builder to insert subsequent instructions after the given instruction.
157+
158+
:param inst: The instruction to insert after.
159+
"""
160+
...
161+
154162
def instr(self, instr: Instruction) -> None:
155163
"""
156164
Inserts an instruction into the current block.

pyqir/src/builder.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,31 @@ impl Builder {
7777
Ok(())
7878
}
7979

80+
/// Tells this builder to insert subsequent instructions after the given instruction.
81+
///
82+
/// :param Value instr: The instruction to insert after.
83+
/// :rtype: None
84+
#[pyo3(text_signature = "(instr)")]
85+
fn insert_after(&mut self, py: Python, instr: &Value) -> PyResult<()> {
86+
let owner = Owner::merge(py, [&self.owner, instr.owner()])?;
87+
if *owner.context(py).borrow(py) != *self.owner.context(py).borrow(py) {
88+
Err(PyValueError::new_err(
89+
"Instruction is not from the same context as builder.",
90+
))?;
91+
}
92+
93+
unsafe {
94+
let next_instr = LLVMGetNextInstruction(instr.cast().as_ptr());
95+
if next_instr.is_null() {
96+
let block = LLVMGetInstructionParent(instr.cast().as_ptr());
97+
LLVMPositionBuilderAtEnd(self.cast().as_ptr(), block);
98+
} else {
99+
LLVMPositionBuilderBefore(self.cast().as_ptr(), next_instr);
100+
}
101+
}
102+
Ok(())
103+
}
104+
80105
/// Inserts the given instruction.
81106
fn instr(&mut self, py: Python, instr: &Value) -> PyResult<()> {
82107
let owner = Owner::merge(py, [&self.owner, instr.owner()])?;

pyqir/tests/test_transform.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ def test_reordering_instrs() -> None:
2828
x_instr = module.entry_block.instructions[0]
2929
y_instr = module.entry_block.instructions[1]
3030
z_instr = module.entry_block.instructions[2]
31-
builder.insert_before(x_instr)
32-
y_instr.remove()
33-
builder.instr(y_instr)
3431
builder.insert_before(y_instr)
3532
z_instr.remove()
3633
builder.instr(z_instr)
37-
builder.insert_at_end(module.entry_block)
34+
builder.insert_after(y_instr)
35+
x_instr.remove()
36+
builder.instr(x_instr)
37+
# Inserting after the last instruction will be equivalent to `insert_at_end` on the block.
38+
builder.insert_after(x_instr)
3839
after_ir = module.ir()
3940
file = os.path.join(os.path.dirname(__file__), "resources/test_reordering_after.ll")
4041
expected = Path(file).read_text()

0 commit comments

Comments
 (0)