Skip to content

Commit

Permalink
add zext and trunc to builder (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
cqc-melf authored Aug 19, 2024
1 parent f1278c0 commit bc3a886
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 0 deletions.
20 changes: 20 additions & 0 deletions pyqir/pyqir/_native.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,26 @@ class Builder:
"""
...

def zext(self, value: Value, type: Type) -> Value:
"""
Inserts an zext instruction.
:param Value val: Value to be converted.
:param Type ty: Target type.
:returns: The result.
"""
...

def trunc(self, value: Value, type: Type) -> Value:
"""
Inserts an trunc instruction.
:param Value val: Value to be converted.
:param Type ty: Target type.
:returns: The result.
"""
...

class Call(Instruction):
"""A call instruction."""

Expand Down
30 changes: 30 additions & 0 deletions pyqir/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,36 @@ impl Builder {
};
unsafe { Value::from_raw(py, owner, value) }
}

/// The ‘zext’ instruction zero extends its operand to the given type.
///
/// :param Value val: Value to be converted.
/// :param Type ty: Target type.
/// :returns: The result.
/// :rtype: Value
#[pyo3(text_signature = "(self, val, ty)")]
fn zext(&self, py: Python, val: &Value, ty: &Type) -> PyResult<PyObject> {
let owner = Owner::merge(py, [&self.owner, val.owner()])?;
unsafe {
let value = LLVMBuildZExt(self.as_ptr(), val.as_ptr(), ty.as_ptr(), raw_cstr!(""));
Value::from_raw(py, owner, value)
}
}

/// The ‘trunc’ instruction truncates its operand to the given type.
///
/// :param Value val: Value to be converted.
/// :param Type ty: Target type.
/// :returns: The result.
/// :rtype: Value
#[pyo3(text_signature = "(self, val, ty)")]
fn trunc(&self, py: Python, val: &Value, ty: &Type) -> PyResult<PyObject> {
let owner = Owner::merge(py, [&self.owner, val.owner()])?;
unsafe {
let value = LLVMBuildTrunc(self.as_ptr(), val.as_ptr(), ty.as_ptr(), raw_cstr!(""));
Value::from_raw(py, owner, value)
}
}
}

impl Builder {
Expand Down
20 changes: 20 additions & 0 deletions pyqir/tests/resources/test_trunc.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; ModuleID = 'trunc'
source_filename = "trunc"

define void @main() #0 {
entry:
%0 = call i32 @random_int(i32 0)
%1 = trunc i32 %0 to i16
ret void
}

declare i32 @random_int(i32)

attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="custom" "required_num_qubits"="1" "required_num_results"="1" }

!llvm.module.flags = !{!0, !1, !2, !3}

!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
20 changes: 20 additions & 0 deletions pyqir/tests/resources/test_zext.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; ModuleID = 'zext'
source_filename = "zext"

define void @main() #0 {
entry:
%0 = call i16 @random_int(i16 0)
%1 = zext i16 %0 to i32
ret void
}

declare i16 @random_int(i16)

attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="custom" "required_num_qubits"="1" "required_num_results"="1" }

!llvm.module.flags = !{!0, !1, !2, !3}

!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
33 changes: 33 additions & 0 deletions pyqir/tests/test_trunc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import os

import pytest
from pathlib import Path

import pyqir


def test_trunc() -> None:
module = pyqir.SimpleModule("trunc", 1, 1)
context = module.context
builder = module.builder
entry = module.entry_block
builder.insert_at_end(entry)
i16 = pyqir.IntType(context, 16)
i32 = pyqir.IntType(context, 32)
random_int = module.add_external_function(
"random_int",
pyqir.FunctionType(
i32,
[i32],
),
)
const = builder.call(random_int, [pyqir.const(i32, 0)])
builder.trunc(const, i16)
ir = module.ir()

file = os.path.join(os.path.dirname(__file__), "resources/test_trunc.ll")
expected = Path(file).read_text()
assert ir == expected
33 changes: 33 additions & 0 deletions pyqir/tests/test_zext.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import os

import pytest
from pathlib import Path

import pyqir


def test_zext() -> None:
module = pyqir.SimpleModule("zext", 1, 1)
context = module.context
builder = module.builder
entry = module.entry_block
builder.insert_at_end(entry)
i16 = pyqir.IntType(context, 16)
i32 = pyqir.IntType(context, 32)
random_int = module.add_external_function(
"random_int",
pyqir.FunctionType(
i16,
[i16],
),
)
const1 = builder.call(random_int, [pyqir.const(i16, 0)])
builder.zext(const1, i32)
ir = module.ir()

file = os.path.join(os.path.dirname(__file__), "resources/test_zext.ll")
expected = Path(file).read_text()
assert ir == expected

0 comments on commit bc3a886

Please sign in to comment.