This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-tirx.git
The following commit(s) were added to refs/heads/main by this push:
new 503e143c [FEAT][RUST] Define IR types in Rust (#27)
503e143c is described below
commit 503e143c2eeb2982da0ba7769f391cc2bea94c32
Author: Linzhang Li <[email protected]>
AuthorDate: Thu Oct 22 22:07:47 2026 -0400
[FEAT][RUST] Define IR types in Rust (#27)
## Summary
Rust could build the IR types C++ defines, but not define a new type of
expressions, as
`PrimType` and `TupleType` are: a Rust type could not extend `ir.Type`
with fields that C++ and
Python see.
This bumps `3rdparty/tvm-ffi` to 8fd9303, the head of apache/tvm-ffi
main, which has the merged
apache/tvm-ffi#869 on top of apache/tvm-ffi#870. Its `#[rs_class]`
defines an object type from
its object struct, whose first field `base` is the parent's object, and
registers the reflection
of every other field; `def_object_ref!` defines the reference to it.
This PR also regenerates the
bindings with that stubgen:
- A complete type that is not final now has a public `<Name>Obj::new`
and implements
`ShallowCopy`, which `rs_class` needs of the parent. This covers
`ir.Type`, `ir.Expr`,
`ir.Stmt`, `ir.Attrs` and seven more types.
- The wrapper's `new` takes a scalar field as its own type and any other
as `impl Into<T>`, as
the `new` of an `rs_class` object does. The hand-written callers drop
the `.into()` they
applied to an argument, which the new parameter types make ambiguous.
- Under `custom-new`, the generated allocator is `from_fields` instead
of
`from_complete_fields` (apache/tvm-ffi#870), and the hand-written
constructors call it by that
name.
A Rust type can then extend `ir.Type`:
```rust
use tvm_tirx::ir::{Location, PrimType, Type, TypeObj};
use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_class};
/// The type of a pair of values.
#[rs_class("my_ext.PairType", final)]
pub struct PairTypeNode {
base: TypeObj,
pub first: Type,
pub second: Type,
/// Not part of structural equality or hashing.
#[reflect(seq_hash_ignore)]
pub note: tvm_ffi::String,
}
def_object_ref!(pub PairType, Type, PairTypeNode);
impl PairType {
pub fn new(first: impl Into<Type>, second: impl Into<Type>) -> Self {
PairTypeNode::new(TypeObj::new(Location::unknown()), first, second,
"").into()
}
}
let pair = PairType::new(PrimType::int(32), PrimType::float(32));
let ty: Type = pair.into(); // an `ir.Type` that C++ sees as
`my_ext.PairType`
```
The C++ structural equality and hashing, deep copy, `repr`, the
TVMScript printer and Python see
its fields as they see a C++ type's. `tests/ir/type.rs` checks this end
to end:
- it registers under `ir.Type` as a `TreeNode`, with each field's offset
and flags;
- the C ABI getters read its own fields and the inherited `loc`;
- the C++ engines compare and hash it, and skip a `seq_hash_ignore`
field;
- `repr` and TVMScript print it;
- C++ deep-copies it, also as the type of a `Var` inside an `Evaluate`;
- the Rust structural engine maps it, a copy-on-write edit keeps the
other fields, and it
converts through `Any` and the type hierarchy.
---
3rdparty/tvm-ffi | 2 +-
rust/src/backend/cuda/op.rs | 36 ++--
rust/src/ir/attrs.rs | 13 +-
rust/src/ir/base.rs | 4 +-
rust/src/ir/expr.rs | 225 ++++++++++++++++--------
rust/src/ir/function.rs | 13 +-
rust/src/ir/global_info.rs | 9 +-
rust/src/ir/location.rs | 26 ++-
rust/src/ir/module.rs | 15 +-
rust/src/ir/op.rs | 4 +-
rust/src/ir/prim/expr.rs | 266 +++++++++++++++++++++--------
rust/src/ir/prim/vector_expr.rs | 47 ++---
rust/src/ir/stmt.rs | 183 +++++++++++---------
rust/src/ir/transform/core.rs | 20 ++-
rust/src/ir/type.rs | 69 +++++---
rust/src/lib.rs | 54 +++++-
rust/src/sym/iter_affine_map.rs | 12 +-
rust/src/tirx/function.rs | 34 ++--
rust/src/tirx/index_map.rs | 12 +-
rust/src/tirx/layout.rs | 4 +-
rust/src/tirx/op.rs | 14 +-
rust/src/tirx/tensor.rs | 25 ++-
rust/src/tirx/tile/instruction.rs | 32 ++--
rust/src/tirx/type.rs | 4 +-
rust/tests/ir/transform.rs | 2 +-
rust/tests/ir/transform/core.rs | 2 +-
rust/tests/ir/type.rs | 234 ++++++++++++++++++++++++-
rust/tests/sym/int_set.rs | 2 +-
rust/tests/sym/iter_affine_map.rs | 2 +-
rust/tests/sym/main.rs | 2 +-
rust/tests/tirx/transform/function_pass.rs | 4 +-
31 files changed, 967 insertions(+), 404 deletions(-)
diff --git a/3rdparty/tvm-ffi b/3rdparty/tvm-ffi
index 6628c464..8fd93039 160000
--- a/3rdparty/tvm-ffi
+++ b/3rdparty/tvm-ffi
@@ -1 +1 @@
-Subproject commit 6628c464e3b824d09c9cf65ac0c6c24f973f6d56
+Subproject commit 8fd93039ff332d6262d1f6a47f626b6f91a84080
diff --git a/rust/src/backend/cuda/op.rs b/rust/src/backend/cuda/op.rs
index 1d2a118f..5352ded7 100644
--- a/rust/src/backend/cuda/op.rs
+++ b/rust/src/backend/cuda/op.rs
@@ -126,9 +126,9 @@ impl TCGen05InstrDescriptorAttrs {
/// Lossless complete-field allocation.
#[allow(non_snake_case)]
pub fn new(
- d_dtype: String,
- a_dtype: String,
- b_dtype: String,
+ d_dtype: impl Into<String>,
+ a_dtype: impl Into<String>,
+ b_dtype: impl Into<String>,
M: i64,
N: i64,
K: i64,
@@ -141,9 +141,9 @@ impl TCGen05InstrDescriptorAttrs {
is_sparse: bool,
) -> Self {
let obj = TCGen05InstrDescriptorAttrsObj::new(
- d_dtype,
- a_dtype,
- b_dtype,
+ d_dtype.into(),
+ a_dtype.into(),
+ b_dtype.into(),
M,
N,
K,
@@ -255,11 +255,11 @@ impl TCGen05InstrDescriptorBlockScaledAttrs {
/// Lossless complete-field allocation.
#[allow(non_snake_case)]
pub fn new(
- d_dtype: String,
- a_dtype: String,
- b_dtype: String,
- sfa_dtype: String,
- sfb_dtype: String,
+ d_dtype: impl Into<String>,
+ a_dtype: impl Into<String>,
+ b_dtype: impl Into<String>,
+ sfa_dtype: impl Into<String>,
+ sfb_dtype: impl Into<String>,
M: i64,
N: i64,
K: i64,
@@ -271,11 +271,11 @@ impl TCGen05InstrDescriptorBlockScaledAttrs {
is_sparse: bool,
) -> Self {
let obj = TCGen05InstrDescriptorBlockScaledAttrsObj::new(
- d_dtype,
- a_dtype,
- b_dtype,
- sfa_dtype,
- sfb_dtype,
+ d_dtype.into(),
+ a_dtype.into(),
+ b_dtype.into(),
+ sfa_dtype.into(),
+ sfb_dtype.into(),
M,
N,
K,
@@ -362,7 +362,7 @@ impl TensorMapEncodeTiledAttrObj {
impl TensorMapEncodeTiledAttr {
/// Lossless complete-field allocation.
pub fn new(
- descriptor_dtype: DLDataType,
+ descriptor_dtype: impl Into<DLDataType>,
rank: i64,
interleave: i64,
swizzle: i64,
@@ -371,7 +371,7 @@ impl TensorMapEncodeTiledAttr {
force_cu_dtype: i64,
) -> Self {
let obj = TensorMapEncodeTiledAttrObj::new(
- descriptor_dtype,
+ descriptor_dtype.into(),
rank,
interleave,
swizzle,
diff --git a/rust/src/ir/attrs.rs b/rust/src/ir/attrs.rs
index bc1c2b18..a63332cf 100644
--- a/rust/src/ir/attrs.rs
+++ b/rust/src/ir/attrs.rs
@@ -29,6 +29,7 @@ use tvm_ffi::Any;
use tvm_ffi::Map;
use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
+use tvm_ffi::ShallowCopy;
use tvm_ffi::String;
// tvm-ffi-stubgen(end)
@@ -60,7 +61,7 @@ impl Deref for Attrs {
}
impl AttrsObj {
- pub(crate) fn new() -> Self {
+ pub fn new() -> Self {
let base = Object::new();
Self { base }
}
@@ -73,6 +74,12 @@ impl Attrs {
Self { base: ObjectArc::new(obj) }
}
}
+
+impl ShallowCopy for AttrsObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base) }
+ }
+}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.DictAttrs
@@ -120,8 +127,8 @@ impl DictAttrsObj {
impl DictAttrs {
/// Lossless complete-field allocation.
- pub fn new(dict: Map<String, Any>) -> Self {
- let obj = DictAttrsObj::new(dict);
+ pub fn new(dict: impl Into<Map<String, Any>>) -> Self {
+ let obj = DictAttrsObj::new(dict.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/base.rs b/rust/src/ir/base.rs
index 2a7e0233..c1f8650e 100644
--- a/rust/src/ir/base.rs
+++ b/rust/src/ir/base.rs
@@ -70,8 +70,8 @@ impl EnvFuncObj {
impl EnvFunc {
/// Lossless complete-field allocation.
- pub fn new(name: String, func: Function) -> Self {
- let obj = EnvFuncObj::new(name, func);
+ pub fn new(name: impl Into<String>, func: impl Into<Function>) -> Self {
+ let obj = EnvFuncObj::new(name.into(), func.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/expr.rs b/rust/src/ir/expr.rs
index 1733df7d..4ca0b3cf 100644
--- a/rust/src/ir/expr.rs
+++ b/rust/src/ir/expr.rs
@@ -29,7 +29,7 @@
//! `i32`, `i64`, `bool`, `f32` or `f64` converts into an [`Expr`] as C++
converts it implicitly.
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(defaults, implicit
-// conversions, a derived type); the generated `from_complete_fields`
allocates the fields as given.
+// conversions, a derived type); the generated `from_fields` allocates the
fields as given.
// tvm-ffi-stubgen(custom-new): ir.GlobalVar
// tvm-ffi-stubgen(custom-new): ir.Tuple
// tvm-ffi-stubgen(custom-new): ir.TensorLoad
@@ -87,6 +87,7 @@ use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
use tvm_ffi::ObjectRefCore;
use tvm_ffi::Result;
+use tvm_ffi::ShallowCopy;
use tvm_ffi::String;
use tvm_ffi::tvm_ffi_sys::TVMFFITypeIndex;
// tvm-ffi-stubgen(end)
@@ -121,7 +122,7 @@ impl Deref for Expr {
}
impl ExprObj {
- pub(crate) fn new(loc: Location, ty: Type) -> Self {
+ pub fn new(loc: Location, ty: Type) -> Self {
let base = Object::new();
Self { base, loc, ty }
}
@@ -129,11 +130,21 @@ impl ExprObj {
impl Expr {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type) -> Self {
- let obj = ExprObj::new(loc, ty);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>) -> Self {
+ let obj = ExprObj::new(loc.into(), ty.into());
Self { base: ObjectArc::new(obj) }
}
}
+
+impl ShallowCopy for ExprObj {
+ fn shallow_copy(&self) -> Self {
+ Self {
+ base: ShallowCopy::shallow_copy(&self.base),
+ loc: Clone::clone(&self.loc),
+ ty: Clone::clone(&self.ty),
+ }
+ }
+}
// tvm-ffi-stubgen(end)
/// One index of [`Expr::subscript`]: an expression, or a `start:stop:step`
slice whose missing
@@ -209,7 +220,7 @@ impl Deref for StagingExprObj {
}
impl StagingExprObj {
- pub(crate) fn new(loc: Location, ty: Type) -> Self {
+ pub fn new(loc: Location, ty: Type) -> Self {
let base = ExprObj::new(loc, ty);
Self { base }
}
@@ -217,12 +228,18 @@ impl StagingExprObj {
impl StagingExpr {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type) -> Self {
- let obj = StagingExprObj::new(loc, ty);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>) -> Self {
+ let obj = StagingExprObj::new(loc.into(), ty.into());
Self { base: ObjectArc::new(obj) }
}
}
+impl ShallowCopy for StagingExprObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base) }
+ }
+}
+
tvm_ffi::impl_object_upcast!(StagingExpr => Expr);
// tvm-ffi-stubgen(end)
@@ -261,7 +278,7 @@ impl Deref for OpaqueExprObj {
}
impl OpaqueExprObj {
- pub(crate) fn new(loc: Location, ty: Type) -> Self {
+ pub fn new(loc: Location, ty: Type) -> Self {
let base = ExprObj::new(loc, ty);
Self { base }
}
@@ -269,12 +286,18 @@ impl OpaqueExprObj {
impl OpaqueExpr {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type) -> Self {
- let obj = OpaqueExprObj::new(loc, ty);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>) -> Self {
+ let obj = OpaqueExprObj::new(loc.into(), ty.into());
Self { base: ObjectArc::new(obj) }
}
}
+impl ShallowCopy for OpaqueExprObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base) }
+ }
+}
+
tvm_ffi::impl_object_upcast!(OpaqueExpr => Expr);
// tvm-ffi-stubgen(end)
@@ -323,8 +346,12 @@ impl GlobalVarObj {
impl GlobalVar {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, name_hint: String) ->
Self {
- let obj = GlobalVarObj::new(loc, ty, name_hint);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ name_hint: impl Into<String>,
+ ) -> Self {
+ let obj = GlobalVarObj::new(loc.into(), ty.into(), name_hint.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -335,8 +362,8 @@ tvm_ffi::impl_object_upcast!(GlobalVar => Expr);
impl GlobalVar {
/// The global variable `name_hint`, of a missing type (C++
`GlobalVar(name_hint, loc)`).
pub fn new(name_hint: &str, loc: impl Into<Location>) -> Self {
- let ty = MissingType::new().into();
- Self::from_complete_fields(loc.into(), ty, String::from(name_hint))
+ let ty = MissingType::new();
+ Self::from_fields(loc.into(), ty, String::from(name_hint))
}
}
@@ -385,8 +412,12 @@ impl TupleObj {
impl Tuple {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, fields: Array<Expr>)
-> Self {
- let obj = TupleObj::new(loc, ty, fields);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ fields: impl Into<Array<Expr>>,
+ ) -> Self {
+ let obj = TupleObj::new(loc.into(), ty.into(), fields.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -410,7 +441,7 @@ impl Tuple {
TupleType::new(field_types, UnknownLoc::new()).into()
}
};
- Self::from_complete_fields(loc.into(), ty, fields)
+ Self::from_fields(loc.into(), ty, fields)
}
}
@@ -460,8 +491,13 @@ impl TupleGetItemObj {
impl TupleGetItem {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, tuple_value: Expr, index: i32) -> Self
{
- let obj = TupleGetItemObj::new(loc, ty, tuple_value, index);
+ pub fn new(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ tuple_value: impl Into<Expr>,
+ index: i32,
+ ) -> Self {
+ let obj = TupleGetItemObj::new(loc.into(), ty.into(),
tuple_value.into(), index);
Self { base: ObjectArc::new(obj) }
}
}
@@ -564,13 +600,13 @@ impl TensorLoadObj {
impl TensorLoad {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- source: Expr,
- indices: Array<Expr>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ source: impl Into<Expr>,
+ indices: impl Into<Array<Expr>>,
) -> Self {
- let obj = TensorLoadObj::new(loc, ty, source, indices);
+ let obj = TensorLoadObj::new(loc.into(), ty.into(), source.into(),
indices.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -599,14 +635,9 @@ impl TensorLoad {
format!("Type {} does not support TensorLoad",
support::type_key(ty_index));
return Err(support::check_failed(tvm_ffi::TYPE_ERROR,
"infer.has_value()", &message));
};
- let load = Self::from_complete_fields(loc, MissingType::new().into(),
source, indices);
+ let load = Self::from_fields(loc, MissingType::new(), source, indices);
let ty: PrimType =
support::NativeHook::from_any(infer)?.call_as(&load)?;
- Ok(Self::from_complete_fields(
- load.loc.clone(),
- ty.into(),
- load.source.clone(),
- load.indices.clone(),
- ))
+ Ok(Self::from_fields(load.loc.clone(), ty, load.source.clone(),
load.indices.clone()))
}
}
@@ -645,7 +676,7 @@ impl Deref for ConstantObj {
}
impl ConstantObj {
- pub(crate) fn new(loc: Location, ty: Type) -> Self {
+ pub fn new(loc: Location, ty: Type) -> Self {
let base = ExprObj::new(loc, ty);
Self { base }
}
@@ -653,12 +684,18 @@ impl ConstantObj {
impl Constant {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type) -> Self {
- let obj = ConstantObj::new(loc, ty);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>) -> Self {
+ let obj = ConstantObj::new(loc.into(), ty.into());
Self { base: ObjectArc::new(obj) }
}
}
+impl ShallowCopy for ConstantObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base) }
+ }
+}
+
tvm_ffi::impl_object_upcast!(Constant => Expr);
// tvm-ffi-stubgen(end)
@@ -707,8 +744,8 @@ impl FloatImmObj {
impl FloatImm {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, value: f64) -> Self {
- let obj = FloatImmObj::new(loc, ty, value);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>, value: f64) ->
Self {
+ let obj = FloatImmObj::new(loc.into(), ty.into(), value);
Self { base: ObjectArc::new(obj) }
}
}
@@ -722,7 +759,7 @@ impl FloatImm {
pub fn from_dtype(dtype: DLDataType, value: f64, loc: impl Into<Location>)
-> Result<Self> {
let ty = PrimType::from_dtype(dtype)?;
check_float_imm(dtype, value)?;
- Ok(Self::new(loc.into(), ty.into(), value))
+ Ok(Self::new(loc.into(), ty, value))
}
/// The `float32` constant `value` at the unknown location, which every
`f32` is
@@ -931,8 +968,8 @@ impl IntImmObj {
impl IntImm {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, value: BigInt) -> Self {
- let obj = IntImmObj::new(loc, ty, value);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>, value: impl
Into<BigInt>) -> Self {
+ let obj = IntImmObj::new(loc.into(), ty.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -950,7 +987,7 @@ impl IntImm {
) -> Result<Self> {
let (value, ty) = (value.into(), PrimType::from_dtype(dtype)?);
check_int_imm(dtype, &value)?;
- Ok(Self::new(loc.into(), ty.into(), value))
+ Ok(Self::new(loc.into(), ty, value))
}
/// The `int32` constant `value` at the unknown location, which every
`i32` is
@@ -1134,8 +1171,8 @@ impl GenericConstObj {
impl GenericConst {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, value: Any) -> Self {
- let obj = GenericConstObj::new(loc, ty, value);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>, value: impl
Into<Any>) -> Self {
+ let obj = GenericConstObj::new(loc.into(), ty.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1218,8 +1255,12 @@ impl DataTypeImmObj {
impl DataTypeImm {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, value: DLDataType) -> Self {
- let obj = DataTypeImmObj::new(loc, ty, value);
+ pub fn new(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ value: impl Into<DLDataType>,
+ ) -> Self {
+ let obj = DataTypeImmObj::new(loc.into(), ty.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1231,7 +1272,7 @@ impl DataTypeImm {
/// The data type `value` as a constant of type [`AnyType`]
/// (C++ `DataTypeImm(value, loc)`).
pub fn from_dtype(value: DLDataType, loc: impl Into<Location>) -> Self {
- let ty = AnyType::new(UnknownLoc::new().into()).into();
+ let ty = AnyType::new(UnknownLoc::new());
Self::new(loc.into(), ty, value)
}
}
@@ -1281,8 +1322,12 @@ impl StringImmObj {
impl StringImm {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, value: String) ->
Self {
- let obj = StringImmObj::new(loc, ty, value);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ value: impl Into<String>,
+ ) -> Self {
+ let obj = StringImmObj::new(loc.into(), ty.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1294,8 +1339,8 @@ impl StringImm {
/// The string constant `value`, of type [`StringType`]
/// (C++ `StringImm(value, loc)`).
pub fn new(value: &str, loc: impl Into<Location>) -> Self {
- let ty = StringType::new(UnknownLoc::new().into()).into();
- Self::from_complete_fields(loc.into(), ty, String::from(value))
+ let ty = StringType::new(UnknownLoc::new());
+ Self::from_fields(loc.into(), ty, String::from(value))
}
}
@@ -1354,15 +1399,22 @@ impl CallObj {
impl Call {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- op: Expr,
- args: Array<Expr>,
- attrs: Option<Attrs>,
- ty_args: Array<Type>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ op: impl Into<Expr>,
+ args: impl Into<Array<Expr>>,
+ attrs: impl Into<Option<Attrs>>,
+ ty_args: impl Into<Array<Type>>,
) -> Self {
- let obj = CallObj::new(loc, ty, op, args, attrs, ty_args);
+ let obj = CallObj::new(
+ loc.into(),
+ ty.into(),
+ op.into(),
+ args.into(),
+ attrs.into(),
+ ty_args.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -1385,12 +1437,11 @@ impl Call {
let args = args.into_iter().map(Into::into).collect::<Array<Expr>>();
let ty_args =
ty_args.into_iter().map(Into::into).collect::<Array<Type>>();
if let Some(ty) = ty {
- return Ok(Self::from_complete_fields(loc, ty.clone(), op, args,
attrs, ty_args));
+ return Ok(Self::from_fields(loc, ty.clone(), op, args, attrs,
ty_args));
}
- let call =
- Self::from_complete_fields(loc, MissingType::new().into(), op,
args, attrs, ty_args);
+ let call = Self::from_fields(loc, MissingType::new(), op, args, attrs,
ty_args);
let ty = call.reinfer_type()?;
- Ok(Self::from_complete_fields(
+ Ok(Self::from_fields(
call.loc.clone(),
ty,
call.op.clone(),
@@ -1476,8 +1527,13 @@ impl TensorRegionObj {
impl TensorRegion {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, source: Expr, region: Array<Range>) ->
Self {
- let obj = TensorRegionObj::new(loc, ty, source, region);
+ pub fn new(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ source: impl Into<Expr>,
+ region: impl Into<Array<Range>>,
+ ) -> Self {
+ let obj = TensorRegionObj::new(loc.into(), ty.into(), source.into(),
region.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1523,7 +1579,7 @@ impl Deref for VarObj {
}
impl VarObj {
- pub(crate) fn new(loc: Location, ty: Type, name: String) -> Self {
+ pub fn new(loc: Location, ty: Type, name: String) -> Self {
let base = ExprObj::new(loc, ty);
Self { base, name }
}
@@ -1531,12 +1587,22 @@ impl VarObj {
impl Var {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, name: String) -> Self
{
- let obj = VarObj::new(loc, ty, name);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ name: impl Into<String>,
+ ) -> Self {
+ let obj = VarObj::new(loc.into(), ty.into(), name.into());
Self { base: ObjectArc::new(obj) }
}
}
+impl ShallowCopy for VarObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base), name:
Clone::clone(&self.name) }
+ }
+}
+
tvm_ffi::impl_object_upcast!(Var => Expr);
// tvm-ffi-stubgen(end)
@@ -1544,7 +1610,7 @@ impl Var {
/// The variable `name` of type `ty` (C++ `Var(name, ty, loc)`); a
variable whose type is not
/// known yet takes [`MissingType::new`].
pub fn new(name: &str, ty: impl Into<Type>, loc: impl Into<Location>) ->
Self {
- Self::from_complete_fields(loc.into(), ty.into(), String::from(name))
+ Self::from_fields(loc.into(), ty.into(), String::from(name))
}
}
@@ -1594,8 +1660,13 @@ impl LambdaExprObj {
impl LambdaExpr {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, vars: Array<Var>,
body: Expr) -> Self {
- let obj = LambdaExprObj::new(loc, ty, vars, body);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ vars: impl Into<Array<Var>>,
+ body: impl Into<Expr>,
+ ) -> Self {
+ let obj = LambdaExprObj::new(loc.into(), ty.into(), vars.into(),
body.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1614,7 +1685,7 @@ impl LambdaExpr {
let (vars, body) =
(vars.into_iter().map(Into::into).collect::<Array<Var>>(), body.into());
let arg_types = vars.iter().map(|var|
var.ty.clone()).collect::<Vec<Type>>();
let ty = FuncType::new(arg_types, body.ty.clone());
- Self::from_complete_fields(loc.into(), ty.into(), vars, body)
+ Self::from_fields(loc.into(), ty, vars, body)
}
/// The body with `arguments` substituted for the variables
(`ir.LambdaExprApply`).
@@ -1666,8 +1737,12 @@ impl RangeObj {
impl Range {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(begin: Expr, extent: Expr, loc: Location) ->
Self {
- let obj = RangeObj::new(begin, extent, loc);
+ pub fn from_fields(
+ begin: impl Into<Expr>,
+ extent: impl Into<Expr>,
+ loc: impl Into<Location>,
+ ) -> Self {
+ let obj = RangeObj::new(begin.into(), extent.into(), loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1683,7 +1758,7 @@ impl Range {
) -> Result<Self> {
let (begin, end) = (begin.into(), end.into());
let extent = Self::get_extent_from_begin_end(begin.clone(), end)?;
- Ok(Self::from_complete_fields(begin, extent, loc.into()))
+ Ok(Self::from_fields(begin, extent, loc.into()))
}
/// The range of `extent` values from `min_value` (C++
`Range::FromMinExtent`).
@@ -1695,7 +1770,7 @@ impl Range {
let (min_value, extent) = (min_value.into(), extent.into());
support::prim_dtype(&min_value)?;
support::prim_dtype(&extent)?;
- Ok(Self::from_complete_fields(min_value, extent, loc.into()))
+ Ok(Self::from_fields(min_value, extent, loc.into()))
}
/// The extent `end - begin` of the range `[begin, end)`: the other
operand when `end` adds
diff --git a/rust/src/ir/function.rs b/rust/src/ir/function.rs
index 55894fba..3d30d098 100644
--- a/rust/src/ir/function.rs
+++ b/rust/src/ir/function.rs
@@ -45,6 +45,7 @@ use tvm_ffi::Map;
use tvm_ffi::ObjectArc;
use tvm_ffi::RValueRef;
use tvm_ffi::Result;
+use tvm_ffi::ShallowCopy;
use tvm_ffi::String;
// tvm-ffi-stubgen(end)
@@ -84,7 +85,7 @@ impl Deref for BaseFuncObj {
}
impl BaseFuncObj {
- pub(crate) fn new(loc: Location, ty: Type, attrs: DictAttrs) -> Self {
+ pub fn new(loc: Location, ty: Type, attrs: DictAttrs) -> Self {
let base = ExprObj::new(loc, ty);
Self { base, attrs }
}
@@ -92,12 +93,18 @@ impl BaseFuncObj {
impl BaseFunc {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, ty: Type, attrs: DictAttrs) -> Self {
- let obj = BaseFuncObj::new(loc, ty, attrs);
+ pub fn new(loc: impl Into<Location>, ty: impl Into<Type>, attrs: impl
Into<DictAttrs>) -> Self {
+ let obj = BaseFuncObj::new(loc.into(), ty.into(), attrs.into());
Self { base: ObjectArc::new(obj) }
}
}
+impl ShallowCopy for BaseFuncObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base), attrs:
Clone::clone(&self.attrs) }
+ }
+}
+
tvm_ffi::impl_object_upcast!(BaseFunc => Expr);
// tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/global_info.rs b/rust/src/ir/global_info.rs
index d7d74e99..60b088f8 100644
--- a/rust/src/ir/global_info.rs
+++ b/rust/src/ir/global_info.rs
@@ -27,6 +27,7 @@
use std::ops::Deref;
use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
+use tvm_ffi::ShallowCopy;
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.GlobalInfo
@@ -57,7 +58,7 @@ impl Deref for GlobalInfo {
}
impl GlobalInfoObj {
- pub(crate) fn new() -> Self {
+ pub fn new() -> Self {
let base = Object::new();
Self { base }
}
@@ -70,4 +71,10 @@ impl GlobalInfo {
Self { base: ObjectArc::new(obj) }
}
}
+
+impl ShallowCopy for GlobalInfoObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base) }
+ }
+}
// tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/location.rs b/rust/src/ir/location.rs
index 18ed01ce..a75917c7 100644
--- a/rust/src/ir/location.rs
+++ b/rust/src/ir/location.rs
@@ -25,7 +25,7 @@
//! caller). [`Location::unknown`] and [`SourceName::get`] wrap the native
constructors.
// `custom-new` reserves `new` for a constructor with the native one's
semantics (the shared
-// `UnknownLoc` instance); the generated `from_complete_fields` allocates the
fields as given.
+// `UnknownLoc` instance); the generated `from_fields` allocates the fields as
given.
// tvm-ffi-stubgen(custom-new): ir.UnknownLoc
// Names the hand-written wrappers use: the import section keeps them even
when no generated block
// does.
@@ -38,6 +38,7 @@ use std::ops::Deref;
use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
use tvm_ffi::Result;
+use tvm_ffi::ShallowCopy;
use tvm_ffi::String;
// tvm-ffi-stubgen(end)
@@ -79,8 +80,8 @@ impl SourceNameObj {
impl SourceName {
/// Lossless complete-field allocation.
- pub fn new(name: String) -> Self {
- let obj = SourceNameObj::new(name);
+ pub fn new(name: impl Into<String>) -> Self {
+ let obj = SourceNameObj::new(name.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -121,7 +122,7 @@ impl Deref for Location {
}
impl LocationObj {
- pub(crate) fn new() -> Self {
+ pub fn new() -> Self {
let base = Object::new();
Self { base }
}
@@ -134,6 +135,12 @@ impl Location {
Self { base: ObjectArc::new(obj) }
}
}
+
+impl ShallowCopy for LocationObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base) }
+ }
+}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.UnknownLoc
@@ -180,7 +187,7 @@ impl UnknownLocObj {
impl UnknownLoc {
/// Lossless complete-field allocation.
- pub fn from_complete_fields() -> Self {
+ pub fn from_fields() -> Self {
let obj = UnknownLocObj::new();
Self { base: ObjectArc::new(obj) }
}
@@ -281,13 +288,14 @@ impl SourceLocObj {
impl SourceLoc {
/// Lossless complete-field allocation.
pub fn new(
- source_name: SourceName,
+ source_name: impl Into<SourceName>,
start_line: i32,
start_column: i32,
end_line: i32,
end_column: i32,
) -> Self {
- let obj = SourceLocObj::new(source_name, start_line, start_column,
end_line, end_column);
+ let obj =
+ SourceLocObj::new(source_name.into(), start_line, start_column,
end_line, end_column);
Self { base: ObjectArc::new(obj) }
}
}
@@ -343,8 +351,8 @@ impl CallSiteLocObj {
impl CallSiteLoc {
/// Lossless complete-field allocation.
- pub fn new(callee: Location, caller: Location) -> Self {
- let obj = CallSiteLocObj::new(callee, caller);
+ pub fn new(callee: impl Into<Location>, caller: impl Into<Location>) ->
Self {
+ let obj = CallSiteLocObj::new(callee.into(), caller.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/module.rs b/rust/src/ir/module.rs
index 70a18c6b..5b5dc150 100644
--- a/rust/src/ir/module.rs
+++ b/rust/src/ir/module.rs
@@ -98,12 +98,17 @@ impl IRModuleObj {
impl IRModule {
/// Lossless complete-field allocation.
pub fn new(
- functions: Map<GlobalVar, BaseFunc>,
- attrs: DictAttrs,
- global_infos: Map<String, Array<GlobalInfo>>,
- global_var_map: Map<String, GlobalVar>,
+ functions: impl Into<Map<GlobalVar, BaseFunc>>,
+ attrs: impl Into<DictAttrs>,
+ global_infos: impl Into<Map<String, Array<GlobalInfo>>>,
+ global_var_map: impl Into<Map<String, GlobalVar>>,
) -> Self {
- let obj = IRModuleObj::new(functions, attrs, global_infos,
global_var_map);
+ let obj = IRModuleObj::new(
+ functions.into(),
+ attrs.into(),
+ global_infos.into(),
+ global_var_map.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/op.rs b/rust/src/ir/op.rs
index dd3e696c..5cf0d53f 100644
--- a/rust/src/ir/op.rs
+++ b/rust/src/ir/op.rs
@@ -88,8 +88,8 @@ impl ArgumentInfoObj {
impl ArgumentInfo {
/// Lossless complete-field allocation.
- pub fn new(name: String, doc: String) -> Self {
- let obj = ArgumentInfoObj::new(name, doc);
+ pub fn new(name: impl Into<String>, doc: impl Into<String>) -> Self {
+ let obj = ArgumentInfoObj::new(name.into(), doc.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/prim/expr.rs b/rust/src/ir/prim/expr.rs
index c5ee15ce..9280ce1a 100644
--- a/rust/src/ir/prim/expr.rs
+++ b/rust/src/ir/prim/expr.rs
@@ -27,7 +27,7 @@
//! [`super::op`].
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(operand type checks
-// and the derived result type); the generated `from_complete_fields`
allocates the fields as given.
+// and the derived result type); the generated `from_fields` allocates the
fields as given.
// tvm-ffi-stubgen(custom-new): prim.Cast
// tvm-ffi-stubgen(custom-new): prim.LShift
// tvm-ffi-stubgen(custom-new): prim.RShift
@@ -127,8 +127,12 @@ impl CastObj {
impl Cast {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, value: Expr) -> Self {
- let obj = CastObj::new(loc, ty, value);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ value: impl Into<Expr>,
+ ) -> Self {
+ let obj = CastObj::new(loc.into(), ty.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -182,8 +186,13 @@ impl LShiftObj {
impl LShift {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = LShiftObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = LShiftObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -237,8 +246,13 @@ impl RShiftObj {
impl RShift {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = RShiftObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = RShiftObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -292,8 +306,13 @@ impl BitwiseAndObj {
impl BitwiseAnd {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = BitwiseAndObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = BitwiseAndObj::new(loc.into(), ty.into(), a.into(),
b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -347,8 +366,13 @@ impl BitwiseOrObj {
impl BitwiseOr {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = BitwiseOrObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = BitwiseOrObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -402,8 +426,13 @@ impl BitwiseXorObj {
impl BitwiseXor {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = BitwiseXorObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = BitwiseXorObj::new(loc.into(), ty.into(), a.into(),
b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -456,8 +485,8 @@ impl BitwiseNotObj {
impl BitwiseNot {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr) -> Self {
- let obj = BitwiseNotObj::new(loc, ty, a);
+ pub fn from_fields(loc: impl Into<Location>, ty: impl Into<Type>, a: impl
Into<Expr>) -> Self {
+ let obj = BitwiseNotObj::new(loc.into(), ty.into(), a.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -511,8 +540,13 @@ impl AddObj {
impl Add {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = AddObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = AddObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -566,8 +600,13 @@ impl SubObj {
impl Sub {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = SubObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = SubObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -621,8 +660,13 @@ impl MulObj {
impl Mul {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = MulObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = MulObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -676,8 +720,13 @@ impl DivObj {
impl Div {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = DivObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = DivObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -731,8 +780,13 @@ impl ModObj {
impl Mod {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = ModObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = ModObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -786,8 +840,13 @@ impl FloorDivObj {
impl FloorDiv {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = FloorDivObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = FloorDivObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -841,8 +900,13 @@ impl FloorModObj {
impl FloorMod {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = FloorModObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = FloorModObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -896,8 +960,13 @@ impl MinObj {
impl Min {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = MinObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = MinObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -951,8 +1020,13 @@ impl MaxObj {
impl Max {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = MaxObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = MaxObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1006,8 +1080,13 @@ impl EQObj {
impl EQ {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = EQObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = EQObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1061,8 +1140,13 @@ impl NEObj {
impl NE {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = NEObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = NEObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1116,8 +1200,13 @@ impl LTObj {
impl LT {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = LTObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = LTObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1171,8 +1260,13 @@ impl LEObj {
impl LE {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = LEObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = LEObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1226,8 +1320,13 @@ impl GTObj {
impl GT {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = GTObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = GTObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1281,8 +1380,13 @@ impl GEObj {
impl GE {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = GEObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = GEObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1336,8 +1440,13 @@ impl AndObj {
impl And {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = AndObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = AndObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1391,8 +1500,13 @@ impl OrObj {
impl Or {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr, b: Expr) ->
Self {
- let obj = OrObj::new(loc, ty, a, b);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ a: impl Into<Expr>,
+ b: impl Into<Expr>,
+ ) -> Self {
+ let obj = OrObj::new(loc.into(), ty.into(), a.into(), b.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1445,8 +1559,8 @@ impl NotObj {
impl Not {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, a: Expr) -> Self {
- let obj = NotObj::new(loc, ty, a);
+ pub fn from_fields(loc: impl Into<Location>, ty: impl Into<Type>, a: impl
Into<Expr>) -> Self {
+ let obj = NotObj::new(loc.into(), ty.into(), a.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1507,14 +1621,20 @@ impl SelectObj {
impl Select {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- condition: Expr,
- true_value: Expr,
- false_value: Expr,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ condition: impl Into<Expr>,
+ true_value: impl Into<Expr>,
+ false_value: impl Into<Expr>,
) -> Self {
- let obj = SelectObj::new(loc, ty, condition, true_value, false_value);
+ let obj = SelectObj::new(
+ loc.into(),
+ ty.into(),
+ condition.into(),
+ true_value.into(),
+ false_value.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -1569,14 +1689,14 @@ impl LetObj {
impl Let {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- var: Var,
- value: Expr,
- body: Expr,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ var: impl Into<Var>,
+ value: impl Into<Expr>,
+ body: impl Into<Expr>,
) -> Self {
- let obj = LetObj::new(loc, ty, var, value, body);
+ let obj = LetObj::new(loc.into(), ty.into(), var.into(), value.into(),
body.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1599,7 +1719,7 @@ impl Cast {
let (lhs, rhs) = (ty.dtype.lanes, value_dtype.lanes);
return Err(support::compare_failed(tvm_ffi::INTERNAL_ERROR,
condition, lhs, rhs, ""));
}
- Ok(Self::from_complete_fields(loc.into(), ty.into(), value))
+ Ok(Self::from_fields(loc.into(), ty, value))
}
}
@@ -1667,7 +1787,7 @@ macro_rules! binary_new {
) -> Result<Self> {
let (a, b) = (a.into(), b.into());
let ty = binary_type(stringify!($node), $operands, &a,
&b)?;
- Ok(Self::from_complete_fields(loc.into(), ty, a, b))
+ Ok(Self::from_fields(loc.into(), ty, a, b))
}
}
)+
@@ -1738,7 +1858,7 @@ impl And {
pub fn new(a: impl Into<Expr>, b: impl Into<Expr>, loc: impl
Into<Location>) -> Result<Self> {
let (a, b) = (a.into(), b.into());
let ty = logical_type(&a, &b)?;
- Ok(Self::from_complete_fields(loc.into(), ty, a, b))
+ Ok(Self::from_fields(loc.into(), ty, a, b))
}
}
@@ -1747,7 +1867,7 @@ impl Or {
pub fn new(a: impl Into<Expr>, b: impl Into<Expr>, loc: impl
Into<Location>) -> Result<Self> {
let (a, b) = (a.into(), b.into());
let ty = logical_type(&a, &b)?;
- Ok(Self::from_complete_fields(loc.into(), ty, a, b))
+ Ok(Self::from_fields(loc.into(), ty, a, b))
}
}
@@ -1761,7 +1881,7 @@ impl BitwiseNot {
let message = "BitwiseNot requires an integer or boolean operand";
return Err(support::check_failed(tvm_ffi::TYPE_ERROR, condition,
message));
}
- Ok(Self::from_complete_fields(loc.into(), a.ty.clone(), a))
+ Ok(Self::from_fields(loc.into(), a.ty.clone(), a))
}
}
@@ -1774,7 +1894,7 @@ impl Not {
let condition = "a_ty.MatchesCode(DLDataTypeCode::kDLBool)";
return Err(support::check_failed(tvm_ffi::INTERNAL_ERROR,
condition, ""));
}
- Ok(Self::from_complete_fields(loc.into(), bool_type(a_dtype)?.into(),
a))
+ Ok(Self::from_fields(loc.into(), bool_type(a_dtype)?, a))
}
}
@@ -1823,7 +1943,7 @@ impl Select {
));
}
let ty = true_value.ty.clone();
- Ok(Self::from_complete_fields(loc.into(), ty, condition, true_value,
false_value))
+ Ok(Self::from_fields(loc.into(), ty, condition, true_value,
false_value))
}
}
@@ -1851,6 +1971,6 @@ impl Let {
return Err(support::check_failed(tvm_ffi::INTERNAL_ERROR,
condition, ""));
}
let ty = body.ty.clone();
- Ok(Self::from_complete_fields(loc.into(), ty, var, value, body))
+ Ok(Self::from_fields(loc.into(), ty, var, value, body))
}
}
diff --git a/rust/src/ir/prim/vector_expr.rs b/rust/src/ir/prim/vector_expr.rs
index 651d35ee..d2b31b94 100644
--- a/rust/src/ir/prim/vector_expr.rs
+++ b/rust/src/ir/prim/vector_expr.rs
@@ -26,7 +26,7 @@
//! checks the operands and derives the vector type.
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(operand checks and the
-// derived vector type); the generated `from_complete_fields` allocates the
fields as given.
+// derived vector type); the generated `from_fields` allocates the fields as
given.
// tvm-ffi-stubgen(custom-new): prim.Ramp
// tvm-ffi-stubgen(custom-new): prim.Broadcast
// tvm-ffi-stubgen(custom-new): prim.Shuffle
@@ -125,14 +125,14 @@ impl RampObj {
impl Ramp {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- base_: Expr,
- stride: Expr,
- lanes: Expr,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ base_: impl Into<Expr>,
+ stride: impl Into<Expr>,
+ lanes: impl Into<Expr>,
) -> Self {
- let obj = RampObj::new(loc, ty, base_, stride, lanes);
+ let obj = RampObj::new(loc.into(), ty.into(), base_.into(),
stride.into(), lanes.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -186,8 +186,13 @@ impl BroadcastObj {
impl Broadcast {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, ty: Type, value: Expr, lanes:
Expr) -> Self {
- let obj = BroadcastObj::new(loc, ty, value, lanes);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ value: impl Into<Expr>,
+ lanes: impl Into<Expr>,
+ ) -> Self {
+ let obj = BroadcastObj::new(loc.into(), ty.into(), value.into(),
lanes.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -241,13 +246,13 @@ impl ShuffleObj {
impl Shuffle {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- vectors: Array<Expr>,
- indices: Array<Expr>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ vectors: impl Into<Array<Expr>>,
+ indices: impl Into<Array<Expr>>,
) -> Self {
- let obj = ShuffleObj::new(loc, ty, vectors, indices);
+ let obj = ShuffleObj::new(loc.into(), ty.into(), vectors.into(),
indices.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -279,8 +284,8 @@ impl Ramp {
false => cast_scalar(stride, base_dtype)?,
};
let (dtype, lanes) = vector_lanes(base_dtype, lanes)?;
- let ty = PrimType::from_dtype(dtype)?.into();
- Ok(Self::from_complete_fields(loc.into(), ty, base, stride, lanes))
+ let ty = PrimType::from_dtype(dtype)?;
+ Ok(Self::from_fields(loc.into(), ty, base, stride, lanes))
}
}
@@ -298,8 +303,8 @@ impl Broadcast {
return Err(support::check_failed(tvm_ffi::INTERNAL_ERROR,
"value_ty.IsScalar()", ""));
}
let (dtype, lanes) = vector_lanes(value_dtype, lanes)?;
- let ty = PrimType::from_dtype(dtype)?.into();
- Ok(Self::from_complete_fields(loc.into(), ty, value, lanes))
+ let ty = PrimType::from_dtype(dtype)?;
+ Ok(Self::from_fields(loc.into(), ty, value, lanes))
}
}
@@ -347,7 +352,7 @@ impl Shuffle {
));
}
let ty = PrimType::from_dtype(with_lanes(base_dtype, indices.len() as
u16))?;
- Ok(Self::from_complete_fields(loc.into(), ty.into(), vectors, indices))
+ Ok(Self::from_fields(loc.into(), ty, vectors, indices))
}
}
diff --git a/rust/src/ir/stmt.rs b/rust/src/ir/stmt.rs
index 2cf2f2be..41944db0 100644
--- a/rust/src/ir/stmt.rs
+++ b/rust/src/ir/stmt.rs
@@ -26,7 +26,7 @@
//! as C++ converts it.
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(defaults, implicit
-// conversions, validation); the generated `from_complete_fields` allocates
the fields as given.
+// conversions, validation); the generated `from_fields` allocates the fields
as given.
// tvm-ffi-stubgen(custom-new): ir.Bind
// tvm-ffi-stubgen(custom-new): ir.AssertStmt
// tvm-ffi-stubgen(custom-new): ir.For
@@ -81,6 +81,7 @@ use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
use tvm_ffi::ObjectRefCore;
use tvm_ffi::Result;
+use tvm_ffi::ShallowCopy;
use tvm_ffi::String;
use tvm_ffi::tvm_ffi_sys::TVMFFITypeIndex;
// tvm-ffi-stubgen(end)
@@ -114,7 +115,7 @@ impl Deref for Stmt {
}
impl StmtObj {
- pub(crate) fn new(loc: Location) -> Self {
+ pub fn new(loc: Location) -> Self {
let base = Object::new();
Self { base, loc }
}
@@ -122,11 +123,17 @@ impl StmtObj {
impl Stmt {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = StmtObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = StmtObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
+
+impl ShallowCopy for StmtObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base), loc:
Clone::clone(&self.loc) }
+ }
+}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.Bind
@@ -175,8 +182,12 @@ impl BindObj {
impl Bind {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, var: Var, value: Expr) -> Self {
- let obj = BindObj::new(loc, var, value);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ var: impl Into<Var>,
+ value: impl Into<Expr>,
+ ) -> Self {
+ let obj = BindObj::new(loc.into(), var.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -197,7 +208,7 @@ impl Bind {
let condition = "ffi::StructuralEqual()(value->ty, var->ty)";
return Err(support::check_failed(tvm_ffi::INTERNAL_ERROR,
condition, ""));
}
- Ok(Self::from_complete_fields(loc.into(), var, value))
+ Ok(Self::from_fields(loc.into(), var, value))
}
}
@@ -253,13 +264,18 @@ impl AssertStmtObj {
impl AssertStmt {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- condition: Expr,
- error_kind: StringImm,
- message_parts: Array<StringImm>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ condition: impl Into<Expr>,
+ error_kind: impl Into<StringImm>,
+ message_parts: impl Into<Array<StringImm>>,
) -> Self {
- let obj = AssertStmtObj::new(loc, condition, error_kind,
message_parts);
+ let obj = AssertStmtObj::new(
+ loc.into(),
+ condition.into(),
+ error_kind.into(),
+ message_parts.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -288,7 +304,7 @@ impl AssertStmt {
let check = "condition_ty.MatchesCode(DLDataTypeCode::kDLBool)";
return Err(support::check_failed(tvm_ffi::INTERNAL_ERROR, check,
&message));
}
- Ok(Self::from_complete_fields(loc.into(), condition, error_kind,
message_parts))
+ Ok(Self::from_fields(loc.into(), condition, error_kind, message_parts))
}
}
@@ -352,17 +368,26 @@ impl ForObj {
impl For {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- var: Var,
- begin: Expr,
- end: Expr,
- step: Expr,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ var: impl Into<Var>,
+ begin: impl Into<Expr>,
+ end: impl Into<Expr>,
+ step: impl Into<Expr>,
kind: i32,
- body: SeqStmt,
- annotations: Map<String, Any>,
+ body: impl Into<SeqStmt>,
+ annotations: impl Into<Map<String, Any>>,
) -> Self {
- let obj = ForObj::new(loc, var, begin, end, step, kind, body,
annotations);
+ let obj = ForObj::new(
+ loc.into(),
+ var.into(),
+ begin.into(),
+ end.into(),
+ step.into(),
+ kind,
+ body.into(),
+ annotations.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -472,16 +497,7 @@ impl For {
same_type(&end, "var.ty() == end.ty()")?;
let step = promote(step)?;
same_type(&step, "var.ty() == step.ty()")?;
- Ok(Self::from_complete_fields(
- loc.into(),
- var,
- begin,
- end,
- step,
- kind as i32,
- body,
- annotations,
- ))
+ Ok(Self::from_fields(loc.into(), var, begin, end, step, kind as i32,
body, annotations))
}
}
@@ -542,8 +558,12 @@ impl WhileObj {
impl While {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, condition: Expr, body: SeqStmt) -> Self {
- let obj = WhileObj::new(loc, condition, body);
+ pub fn new(
+ loc: impl Into<Location>,
+ condition: impl Into<Expr>,
+ body: impl Into<SeqStmt>,
+ ) -> Self {
+ let obj = WhileObj::new(loc.into(), condition.into(), body.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -617,13 +637,13 @@ impl TensorStoreObj {
impl TensorStore {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- dest: Expr,
- indices: Array<Expr>,
- value: Expr,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ dest: impl Into<Expr>,
+ indices: impl Into<Array<Expr>>,
+ value: impl Into<Expr>,
) -> Self {
- let obj = TensorStoreObj::new(loc, dest, indices, value);
+ let obj = TensorStoreObj::new(loc.into(), dest.into(), indices.into(),
value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -663,7 +683,7 @@ impl TensorStore {
let message = "Packed hook result type mismatch";
return Err(tvm_ffi::Error::new(tvm_ffi::TYPE_ERROR, message, ""));
}
- Ok(Self::from_complete_fields(loc.into(), dest, indices, value))
+ Ok(Self::from_fields(loc.into(), dest, indices, value))
}
}
@@ -725,16 +745,24 @@ impl RegionStmtObj {
impl RegionStmt {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- op: Op,
- args: Array<Expr>,
- body_params: Array<Var>,
- attrs: DictAttrs,
- body: SeqStmt,
- result_vars: Array<Var>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ op: impl Into<Op>,
+ args: impl Into<Array<Expr>>,
+ body_params: impl Into<Array<Var>>,
+ attrs: impl Into<DictAttrs>,
+ body: impl Into<SeqStmt>,
+ result_vars: impl Into<Array<Var>>,
) -> Self {
- let obj = RegionStmtObj::new(loc, op, args, body_params, attrs, body,
result_vars);
+ let obj = RegionStmtObj::new(
+ loc.into(),
+ op.into(),
+ args.into(),
+ body_params.into(),
+ attrs.into(),
+ body.into(),
+ result_vars.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -790,8 +818,7 @@ impl RegionStmt {
return Err(support::check_failed(tvm_ffi::VALUE_ERROR,
condition, message));
}
}
- let region =
- Self::from_complete_fields(loc.into(), op, args, body_params,
attrs, body, result_vars);
+ let region = Self::from_fields(loc.into(), op, args, body_params,
attrs, body, result_vars);
if let Some(validate) = support::NativeHook::of_op(®ion.op,
"FRegionValidate")? {
validate.call_void(®ion)?;
}
@@ -810,10 +837,10 @@ fn region_body_params(op: &Op, args: &Array<Expr>, attrs:
&DictAttrs) -> Result<
);
return Err(support::check_failed(tvm_ffi::VALUE_ERROR,
"IsRegionOp(op)", &message));
};
- let signature = Call::from_complete_fields(
- UnknownLoc::new().into(),
- MissingType::new().into(),
- op.clone().into(),
+ let signature = Call::from_fields(
+ UnknownLoc::new(),
+ MissingType::new(),
+ op.clone(),
args.clone(),
Some(attrs.clone().into()),
Array::new(vec![]),
@@ -888,8 +915,8 @@ impl SeqStmtObj {
impl SeqStmt {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, seq: Array<Stmt>) -> Self {
- let obj = SeqStmtObj::new(loc, seq);
+ pub fn from_fields(loc: impl Into<Location>, seq: impl Into<Array<Stmt>>)
-> Self {
+ let obj = SeqStmtObj::new(loc.into(), seq.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -902,7 +929,7 @@ impl SeqStmt {
/// (C++ `SeqStmt(seq, loc)`).
pub fn new(seq: impl IntoIterator<Item = impl Into<Stmt>>, loc: impl
Into<Location>) -> Self {
let seq = seq.into_iter().map(Into::into).collect::<Array<Stmt>>();
- Self::from_complete_fields(loc.into(), flatten(seq))
+ Self::from_fields(loc.into(), flatten(seq))
}
}
@@ -938,7 +965,7 @@ fn into_body(stmt: Stmt) -> Result<SeqStmt> {
return Ok(tvm_ffi::ObjectRefCast::try_cast(stmt).expect("a SeqStmt"));
}
let loc = stmt.loc.clone();
- Ok(SeqStmt::from_complete_fields(loc, flatten(Array::new(vec![stmt]))))
+ Ok(SeqStmt::from_fields(loc, flatten(Array::new(vec![stmt]))))
}
// tvm-ffi-stubgen(begin): object/ir.If
@@ -993,13 +1020,13 @@ impl IfObj {
impl If {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- condition: Expr,
- then_case: SeqStmt,
- else_case: Option<SeqStmt>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ condition: impl Into<Expr>,
+ then_case: impl Into<SeqStmt>,
+ else_case: impl Into<Option<SeqStmt>>,
) -> Self {
- let obj = IfObj::new(loc, condition, then_case, else_case);
+ let obj = IfObj::new(loc.into(), condition.into(), then_case.into(),
else_case.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1020,7 +1047,7 @@ impl If {
support::prim_dtype(&condition)?;
let then_case = into_body(then_case.into())?;
let else_case = else_case.map(|stmt|
into_body(stmt.clone())).transpose()?;
- Ok(Self::from_complete_fields(loc.into(), condition, then_case,
else_case))
+ Ok(Self::from_fields(loc.into(), condition, then_case, else_case))
}
}
@@ -1069,8 +1096,8 @@ impl EvaluateObj {
impl Evaluate {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, value: Expr) -> Self {
- let obj = EvaluateObj::new(loc, value);
+ pub fn from_fields(loc: impl Into<Location>, value: impl Into<Expr>) ->
Self {
+ let obj = EvaluateObj::new(loc.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1081,7 +1108,7 @@ tvm_ffi::impl_object_upcast!(Evaluate => Stmt);
impl Evaluate {
/// Evaluate `value` for its side effects (C++ `Evaluate(value, loc)`).
pub fn new(value: impl Into<Expr>, loc: impl Into<Location>) -> Self {
- Self::from_complete_fields(loc.into(), value.into())
+ Self::from_fields(loc.into(), value.into())
}
}
@@ -1129,8 +1156,8 @@ impl BreakObj {
impl Break {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = BreakObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = BreakObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1185,8 +1212,8 @@ impl ReturnObj {
impl Return {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, value: Expr) -> Self {
- let obj = ReturnObj::new(loc, value);
+ pub fn from_fields(loc: impl Into<Location>, value: impl Into<Expr>) ->
Self {
+ let obj = ReturnObj::new(loc.into(), value.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -1197,7 +1224,7 @@ tvm_ffi::impl_object_upcast!(Return => Stmt);
impl Return {
/// Return `value` from the enclosing function (C++ `Return(value, loc)`).
pub fn new(value: impl Into<Expr>, loc: impl Into<Location>) -> Self {
- Self::from_complete_fields(loc.into(), value.into())
+ Self::from_fields(loc.into(), value.into())
}
}
@@ -1245,8 +1272,8 @@ impl ContinueObj {
impl Continue {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = ContinueObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = ContinueObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/transform/core.rs b/rust/src/ir/transform/core.rs
index b46b11a9..ccab94df 100644
--- a/rust/src/ir/transform/core.rs
+++ b/rust/src/ir/transform/core.rs
@@ -84,8 +84,8 @@ impl PassInfoObj {
impl PassInfo {
/// Lossless complete-field allocation.
- pub fn new(opt_level: i32, name: String) -> Self {
- let obj = PassInfoObj::new(opt_level, name);
+ pub fn new(opt_level: i32, name: impl Into<String>) -> Self {
+ let obj = PassInfoObj::new(opt_level, name.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -170,12 +170,18 @@ impl PassContext {
/// Lossless complete-field allocation.
pub fn new(
opt_level: i32,
- required_pass: Array<String>,
- disabled_pass: Array<String>,
- config: Map<String, Any>,
- instruments: Array<PassInstrument>,
+ required_pass: impl Into<Array<String>>,
+ disabled_pass: impl Into<Array<String>>,
+ config: impl Into<Map<String, Any>>,
+ instruments: impl Into<Array<PassInstrument>>,
) -> Self {
- let obj = PassContextObj::new(opt_level, required_pass, disabled_pass,
config, instruments);
+ let obj = PassContextObj::new(
+ opt_level,
+ required_pass.into(),
+ disabled_pass.into(),
+ config.into(),
+ instruments.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/ir/type.rs b/rust/src/ir/type.rs
index 09ec21ae..e3968d56 100644
--- a/rust/src/ir/type.rs
+++ b/rust/src/ir/type.rs
@@ -29,7 +29,7 @@
//! siblings, as C++ writes `PrimType::Int(32)`.
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(defaults, the shared
-// `MissingType`, `NoneType` and `TensorRegionType` nodes); the generated
`from_complete_fields`
+// `MissingType`, `NoneType` and `TensorRegionType` nodes); the generated
`from_fields`
// allocates the fields as given.
// tvm-ffi-stubgen(custom-new): ir.MissingType
// tvm-ffi-stubgen(custom-new): ir.NoneType
@@ -61,6 +61,7 @@ use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
use tvm_ffi::ObjectRefCore;
use tvm_ffi::Result;
+use tvm_ffi::ShallowCopy;
use tvm_ffi::VALUE_ERROR;
// tvm-ffi-stubgen(end)
@@ -93,7 +94,7 @@ impl Deref for Type {
}
impl TypeObj {
- pub(crate) fn new(loc: Location) -> Self {
+ pub fn new(loc: Location) -> Self {
let base = Object::new();
Self { base, loc }
}
@@ -101,11 +102,17 @@ impl TypeObj {
impl Type {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = TypeObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = TypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
+
+impl ShallowCopy for TypeObj {
+ fn shallow_copy(&self) -> Self {
+ Self { base: ShallowCopy::shallow_copy(&self.base), loc:
Clone::clone(&self.loc) }
+ }
+}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.MissingType
@@ -152,8 +159,8 @@ impl MissingTypeObj {
impl MissingType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location) -> Self {
- let obj = MissingTypeObj::new(loc);
+ pub fn from_fields(loc: impl Into<Location>) -> Self {
+ let obj = MissingTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -218,8 +225,8 @@ impl NoneTypeObj {
impl NoneType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location) -> Self {
- let obj = NoneTypeObj::new(loc);
+ pub fn from_fields(loc: impl Into<Location>) -> Self {
+ let obj = NoneTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -283,8 +290,8 @@ impl AnyTypeObj {
impl AnyType {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = AnyTypeObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = AnyTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -338,8 +345,8 @@ impl TensorRegionTypeObj {
impl TensorRegionType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location) -> Self {
- let obj = TensorRegionTypeObj::new(loc);
+ pub fn from_fields(loc: impl Into<Location>) -> Self {
+ let obj = TensorRegionTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -404,8 +411,8 @@ impl OpaqueTypeObj {
impl OpaqueType {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = OpaqueTypeObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = OpaqueTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -461,8 +468,8 @@ impl PrimTypeObj {
impl PrimType {
/// Lossless complete-field allocation.
- pub fn new(loc: Location, dtype: DLDataType) -> Self {
- let obj = PrimTypeObj::new(loc, dtype);
+ pub fn new(loc: impl Into<Location>, dtype: impl Into<DLDataType>) -> Self
{
+ let obj = PrimTypeObj::new(loc.into(), dtype.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -588,8 +595,8 @@ impl StringTypeObj {
impl StringType {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = StringTypeObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = StringTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -646,8 +653,12 @@ impl PtrTypeObj {
impl PtrType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, element_type: Type, scope:
MemoryScope) -> Self {
- let obj = PtrTypeObj::new(loc, element_type, scope);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ element_type: impl Into<Type>,
+ scope: impl Into<MemoryScope>,
+ ) -> Self {
+ let obj = PtrTypeObj::new(loc.into(), element_type.into(),
scope.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -665,7 +676,7 @@ impl PtrType {
let message = "PtrType element_type cannot be Type::Missing()";
return Err(support::check_failed(tvm_ffi::INTERNAL_ERROR,
condition, message));
}
- Ok(Self::from_complete_fields(UnknownLoc::new().into(), element_type,
scope.clone()))
+ Ok(Self::from_fields(UnknownLoc::new(), element_type, scope.clone()))
}
}
@@ -714,8 +725,8 @@ impl TupleTypeObj {
impl TupleType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, fields: Array<Type>) -> Self {
- let obj = TupleTypeObj::new(loc, fields);
+ pub fn from_fields(loc: impl Into<Location>, fields: impl
Into<Array<Type>>) -> Self {
+ let obj = TupleTypeObj::new(loc.into(), fields.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -730,7 +741,7 @@ impl TupleType {
loc: impl Into<Location>,
) -> Self {
let fields =
fields.into_iter().map(Into::into).collect::<Array<Type>>();
- Self::from_complete_fields(loc.into(), fields)
+ Self::from_fields(loc.into(), fields)
}
}
@@ -780,8 +791,12 @@ impl FuncTypeObj {
impl FuncType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(loc: Location, arg_types: Array<Type>,
ret_type: Type) -> Self {
- let obj = FuncTypeObj::new(loc, arg_types, ret_type);
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ arg_types: impl Into<Array<Type>>,
+ ret_type: impl Into<Type>,
+ ) -> Self {
+ let obj = FuncTypeObj::new(loc.into(), arg_types.into(),
ret_type.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -796,6 +811,6 @@ impl FuncType {
ret_type: impl Into<Type>,
) -> Self {
let arg_types =
arg_types.into_iter().map(Into::into).collect::<Array<Type>>();
- Self::from_complete_fields(UnknownLoc::new().into(), arg_types,
ret_type.into())
+ Self::from_fields(UnknownLoc::new(), arg_types, ret_type.into())
}
}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 019877c4..521650fd 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -72,7 +72,7 @@
//! as given, without the checks, defaults or derived fields of the native
constructor. Where the
//! native constructor does more than that (`ir::prim::Add` checks its operand
types,
//! `tirx::Function` derives its type from the signature), `new` is reserved
for a constructor with
-//! those semantics, and the allocation of the fields as given is
`from_complete_fields`. The IR
+//! those semantics, and the allocation of the fields as given is
`from_fields`. The IR
//! constructors are written in Rust after the C++ ones, with the same checks,
defaults, derived
//! fields and errors; they call into C++ only for the nodes C++ shares
(`UnknownLoc`,
//! `MissingType` and the `PrimType` of each dtype, fetched once per thread),
for the hooks an
@@ -91,6 +91,50 @@
//! The unknown location is [`ir::UNKNOWN_LOC`] as a constructor argument and
//! [`ir::Location::unknown`] as a value.
//!
+//! # Defining a type in Rust
+//!
+//! [`tvm_ffi::rs_class`] defines a new IR type, a type of expressions as
[`ir::PrimType`] and
+//! [`ir::TupleType`] are, from its object struct, whose first field `base` is
the [`ir::TypeObj`]
+//! it extends, which holds the location. It registers the type under
`ir.Type` with the
+//! reflection of every other field, so that the C++ structural equality and
hashing, deep copy,
+//! `repr`, the TVMScript printer and Python see the fields as they see a C++
type's.
+//! [`tvm_ffi::def_object_ref`] defines the reference, which converts into
[`ir::Type`]. The
+//! object's `new` takes the `TypeObj`, then the fields in order:
+//!
+//! ```no_run
+//! use tvm_tirx::ir::{Location, PrimType, Type, TypeObj};
+//! use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_class, ObjectRefCore};
+//!
+//! /// The type of a pair of values.
+//! #[rs_class("my_ext.PairType", final)]
+//! pub struct PairTypeNode {
+//! base: TypeObj,
+//! pub first: Type,
+//! pub second: Type,
+//! /// Not part of structural equality or hashing.
+//! #[reflect(seq_hash_ignore)]
+//! pub note: tvm_ffi::String,
+//! }
+//!
+//! def_object_ref!(pub PairType, Type, PairTypeNode);
+//!
+//! impl PairType {
+//! pub fn new(first: impl Into<Type>, second: impl Into<Type>) -> Self {
+//! PairTypeNode::new(TypeObj::new(Location::unknown()), first,
second, "").into()
+//! }
+//! }
+//!
+//! fn main() {
+//! let pair = PairType::new(PrimType::int(32), PrimType::float(32));
+//! let ty: Type = pair.into(); // an `ir.Type` that C++ sees as
`my_ext.PairType`
+//! assert!(ty.as_node::<PairTypeNode>().is_some());
+//! }
+//! ```
+//!
+//! The generated code names `tvm_ffi`, which `use tvm_tirx::tvm_ffi` brings
into scope in a crate
+//! that depends only on `tvm-tirx`. The parent's object must have a public
`new` and implement
+//! `ShallowCopy`; the bindings generate both for a complete type that is not
final, as `ir.Type`.
+//!
//! # Generated and hand-written code
//!
//! The code between a `// tvm-ffi-stubgen(begin)` and its `//
tvm-ffi-stubgen(end)` is generated
@@ -114,11 +158,9 @@
//! tvm-ffi-stubgen rust/src --target rust --dlls
build/lib/libtvm_tirx_compiler.so
//! ```
//!
-//! `tvm-ffi-stubgen` comes with the `tvm_ffi` Python package, which must be
tvm-ffi `f45854e` or
-//! later: that stubgen names a generated type by the module of its file
(`crate::ir::expr::Expr`).
-//! The older one of `3rdparty/tvm-ffi`, and of the `.venv` it installs, names
it by its type key
-//! and reports the files that use another module as stale. The blocks are
formatted as rustfmt
-//! formats them, so `cargo fmt --check` and `tvm-ffi-stubgen --check` agree.
+//! `tvm-ffi-stubgen` comes with the `tvm_ffi` Python package, which must be
the one of
+//! `3rdparty/tvm-ffi`: the blocks are what its generator emits. The blocks
are formatted as
+//! rustfmt formats them, so `cargo fmt --check` and `tvm-ffi-stubgen --check`
agree.
//!
//! # Tests
//!
diff --git a/rust/src/sym/iter_affine_map.rs b/rust/src/sym/iter_affine_map.rs
index c88e8c3c..7ababb3a 100644
--- a/rust/src/sym/iter_affine_map.rs
+++ b/rust/src/sym/iter_affine_map.rs
@@ -131,11 +131,11 @@ impl IterMapResultObj {
impl IterMapResult {
/// Lossless complete-field allocation.
pub fn new(
- indices: Array<IterSumExpr>,
- errors: Array<String>,
- padding_predicate: Option<Expr>,
+ indices: impl Into<Array<IterSumExpr>>,
+ errors: impl Into<Array<String>>,
+ padding_predicate: impl Into<Option<Expr>>,
) -> Self {
- let obj = IterMapResultObj::new(indices, errors, padding_predicate);
+ let obj = IterMapResultObj::new(indices.into(), errors.into(),
padding_predicate.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -180,8 +180,8 @@ impl IterMarkObj {
impl IterMark {
/// Lossless complete-field allocation.
- pub fn new(source: Expr, extent: Expr) -> Self {
- let obj = IterMarkObj::new(source, extent);
+ pub fn new(source: impl Into<Expr>, extent: impl Into<Expr>) -> Self {
+ let obj = IterMarkObj::new(source.into(), extent.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/tirx/function.rs b/rust/src/tirx/function.rs
index 7a76549c..289e4628 100644
--- a/rust/src/tirx/function.rs
+++ b/rust/src/tirx/function.rs
@@ -25,7 +25,7 @@
//! [`renew_def`] gives its variables fresh definitions.
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(`ty` derived from the
-// signature); the generated `from_complete_fields` allocates the fields as
given.
+// signature); the generated `from_fields` allocates the fields as given.
// tvm-ffi-stubgen(custom-new): tirx.Function
// Names the hand-written wrappers use: the import section keeps them even
when no generated block
@@ -111,15 +111,22 @@ impl FunctionObj {
impl Function {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- ty: Type,
- attrs: DictAttrs,
- params: Array<Var>,
- ret_type: Type,
- body: Option<SeqStmt>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ ty: impl Into<Type>,
+ attrs: impl Into<DictAttrs>,
+ params: impl Into<Array<Var>>,
+ ret_type: impl Into<Type>,
+ body: impl Into<Option<SeqStmt>>,
) -> Self {
- let obj = FunctionObj::new(loc, ty, attrs, params, ret_type, body);
+ let obj = FunctionObj::new(
+ loc.into(),
+ ty.into(),
+ attrs.into(),
+ params.into(),
+ ret_type.into(),
+ body.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -146,14 +153,7 @@ impl Function {
};
let param_types = params.iter().map(|param|
param.ty.clone()).collect::<Vec<Type>>();
let ty = FuncType::new(param_types, ret_type.clone());
- Self::from_complete_fields(
- loc.into(),
- ty.into(),
- attrs.into(),
- params,
- ret_type,
- body.cloned(),
- )
+ Self::from_fields(loc.into(), ty, attrs.into(), params, ret_type,
body.cloned())
}
}
diff --git a/rust/src/tirx/index_map.rs b/rust/src/tirx/index_map.rs
index d80a5f55..21d4ad1d 100644
--- a/rust/src/tirx/index_map.rs
+++ b/rust/src/tirx/index_map.rs
@@ -92,11 +92,15 @@ impl IndexMapObj {
impl IndexMap {
/// Lossless complete-field allocation.
pub fn new(
- initial_indices: Array<Var>,
- final_indices: Array<Expr>,
- inverse_index_map: Option<ObjectRef>,
+ initial_indices: impl Into<Array<Var>>,
+ final_indices: impl Into<Array<Expr>>,
+ inverse_index_map: impl Into<Option<ObjectRef>>,
) -> Self {
- let obj = IndexMapObj::new(initial_indices, final_indices,
inverse_index_map);
+ let obj = IndexMapObj::new(
+ initial_indices.into(),
+ final_indices.into(),
+ inverse_index_map.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/tirx/layout.rs b/rust/src/tirx/layout.rs
index d72490ef..5debdc77 100644
--- a/rust/src/tirx/layout.rs
+++ b/rust/src/tirx/layout.rs
@@ -156,8 +156,8 @@ impl IterObj {
impl Iter {
/// Lossless complete-field allocation.
- pub fn new(extent: Expr, stride: Expr, axis: Axis) -> Self {
- let obj = IterObj::new(extent, stride, axis);
+ pub fn new(extent: impl Into<Expr>, stride: impl Into<Expr>, axis: impl
Into<Axis>) -> Self {
+ let obj = IterObj::new(extent.into(), stride.into(), axis.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/tirx/op.rs b/rust/src/tirx/op.rs
index 3e910e04..3fd11a44 100644
--- a/rust/src/tirx/op.rs
+++ b/rust/src/tirx/op.rs
@@ -100,13 +100,17 @@ impl CallFFIKernelAttrObj {
impl CallFFIKernelAttr {
/// Lossless complete-field allocation.
pub fn new(
- launch_params: Array<String>,
- launch_fields: Array<String>,
+ launch_params: impl Into<Array<String>>,
+ launch_fields: impl Into<Array<String>>,
num_kernel_args: i64,
- kernel_attrs: Map<String, i64>,
+ kernel_attrs: impl Into<Map<String, i64>>,
) -> Self {
- let obj =
- CallFFIKernelAttrObj::new(launch_params, launch_fields,
num_kernel_args, kernel_attrs);
+ let obj = CallFFIKernelAttrObj::new(
+ launch_params.into(),
+ launch_fields.into(),
+ num_kernel_args,
+ kernel_attrs.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/src/tirx/tensor.rs b/rust/src/tirx/tensor.rs
index ed1d56b7..d7d5b7d9 100644
--- a/rust/src/tirx/tensor.rs
+++ b/rust/src/tirx/tensor.rs
@@ -25,7 +25,7 @@
//! [`TensorType::new`].
// `custom-new` reserves `new` for a constructor with the C++ one's semantics
(defaults); the
-// generated `from_complete_fields` allocates the fields as given.
+// generated `from_fields` allocates the fields as given.
// tvm-ffi-stubgen(custom-new): tirx.TensorType
// Names the hand-written wrappers use: the import section keeps them even
when no generated block
@@ -112,15 +112,22 @@ impl TensorTypeObj {
impl TensorType {
/// Lossless complete-field allocation.
- pub fn from_complete_fields(
- loc: Location,
- dtype: PrimType,
- scope: MemoryScope,
- shape: Array<Expr>,
+ pub fn from_fields(
+ loc: impl Into<Location>,
+ dtype: impl Into<PrimType>,
+ scope: impl Into<MemoryScope>,
+ shape: impl Into<Array<Expr>>,
data_alignment: i32,
- layout: Option<Layout>,
+ layout: impl Into<Option<Layout>>,
) -> Self {
- let obj = TensorTypeObj::new(loc, dtype, scope, shape, data_alignment,
layout);
+ let obj = TensorTypeObj::new(
+ loc.into(),
+ dtype.into(),
+ scope.into(),
+ shape.into(),
+ data_alignment,
+ layout.into(),
+ );
Self { base: ObjectArc::new(obj) }
}
}
@@ -166,7 +173,7 @@ impl TensorType {
true => alloc_alignment()?,
false => data_alignment,
};
- Ok(Self::from_complete_fields(
+ Ok(Self::from_fields(
loc.into(),
dtype.into(),
scope.into(),
diff --git a/rust/src/tirx/tile/instruction.rs
b/rust/src/tirx/tile/instruction.rs
index 8db80ad5..8a0bd9ff 100644
--- a/rust/src/tirx/tile/instruction.rs
+++ b/rust/src/tirx/tile/instruction.rs
@@ -97,8 +97,8 @@ impl ScopeAttrsObj {
impl ScopeAttrs {
/// Lossless complete-field allocation.
- pub fn new(scope: ThreadScope) -> Self {
- let obj = ScopeAttrsObj::new(scope);
+ pub fn new(scope: impl Into<ThreadScope>) -> Self {
+ let obj = ScopeAttrsObj::new(scope.into());
Self { base: ObjectArc::new(obj) }
}
}
@@ -170,24 +170,24 @@ impl TrnAttrsObj {
impl TrnAttrs {
/// Lossless complete-field allocation.
pub fn new(
- scope: ThreadScope,
- max_inst_size: Optional<i64>,
- opcode: String,
- reduce_op: String,
- op0: String,
- op1: String,
- axes: Array<i64>,
+ scope: impl Into<ThreadScope>,
+ max_inst_size: impl Into<Optional<i64>>,
+ opcode: impl Into<String>,
+ reduce_op: impl Into<String>,
+ op0: impl Into<String>,
+ op1: impl Into<String>,
+ axes: impl Into<Array<i64>>,
negate: bool,
reverse1: bool,
) -> Self {
let obj = TrnAttrsObj::new(
- scope,
- max_inst_size,
- opcode,
- reduce_op,
- op0,
- op1,
- axes,
+ scope.into(),
+ max_inst_size.into(),
+ opcode.into(),
+ reduce_op.into(),
+ op0.into(),
+ op1.into(),
+ axes.into(),
negate,
reverse1,
);
diff --git a/rust/src/tirx/type.rs b/rust/src/tirx/type.rs
index f2a05686..a874198c 100644
--- a/rust/src/tirx/type.rs
+++ b/rust/src/tirx/type.rs
@@ -75,8 +75,8 @@ impl TensorMapTypeObj {
impl TensorMapType {
/// Lossless complete-field allocation.
- pub fn new(loc: Location) -> Self {
- let obj = TensorMapTypeObj::new(loc);
+ pub fn new(loc: impl Into<Location>) -> Self {
+ let obj = TensorMapTypeObj::new(loc.into());
Self { base: ObjectArc::new(obj) }
}
}
diff --git a/rust/tests/ir/transform.rs b/rust/tests/ir/transform.rs
index d115599a..964ae6ca 100644
--- a/rust/tests/ir/transform.rs
+++ b/rust/tests/ir/transform.rs
@@ -41,6 +41,6 @@ fn logging_pass(name: &str, log: &Log) -> ModulePass {
log.lock().unwrap().push(entry.clone());
Ok(module)
},
- PassInfo::new(0, name.into()),
+ PassInfo::new(0, name),
)
}
diff --git a/rust/tests/ir/transform/core.rs b/rust/tests/ir/transform/core.rs
index b6ef7b9f..496c4b89 100644
--- a/rust/tests/ir/transform/core.rs
+++ b/rust/tests/ir/transform/core.rs
@@ -67,7 +67,7 @@ fn module_and_sequential_passes() {
|_module, _ctx| {
Err(tvm_tirx::tvm_ffi::Error::new(tvm_tirx::tvm_ffi::VALUE_ERROR,
"refused", ""))
},
- PassInfo::new(0, "failing".into()),
+ PassInfo::new(0, "failing"),
);
assert!(Pass::from(&failing).run(empty_module()).is_err());
diff --git a/rust/tests/ir/type.rs b/rust/tests/ir/type.rs
index f1f4b124..0ef08433 100644
--- a/rust/tests/ir/type.rs
+++ b/rust/tests/ir/type.rs
@@ -17,16 +17,26 @@
* under the License.
*/
-//! Tests of `ir::type`.
+//! Tests of `ir::type`, and of an `ir.Type` defined in Rust with `rs_class`
over the generated
+//! `TypeObj`: seen through the FFI type table, the C++ engines (structural
equality and hashing,
+//! deep copy, `repr`, TVMScript), the Rust engines and the IR that uses it.
+
+use std::mem::offset_of;
use tvm_tirx::ir::{
- UNKNOWN_LOC, Location, dtype, FuncType, MissingType, NoneType, PrimType,
PtrType,
- TensorRegionType, TupleType, Type,
+ UNKNOWN_LOC, Location, dtype, Evaluate, FuncType, MissingType, NoneType,
PrimType, PtrType,
+ TensorRegionType, TupleType, Type, TypeObj, Var, VarObj,
+};
+use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_class, structural_map};
+use tvm_tirx::tvm_ffi::{
+ Any, AnyView, Array, DLDataType, DLDataTypeExt, DefRegionKind,
FieldGetter, MapDispatch,
+ ObjectCore, ObjectRefCore, Result, ShallowCopy, String as FfiString,
StructuralView, WalkOrder,
};
-use tvm_tirx::tvm_ffi::{Array, DLDataType, DLDataTypeExt, ObjectRefCore};
use super::{scope};
-use crate::common::{agree, native, serial, structural_equal};
+use crate::common::{
+ agree, assert_type_contract, global, native, runtime_type_info, serial,
structural_equal,
+};
#[test]
fn types() {
@@ -104,3 +114,217 @@ fn types_agree_with_cpp() {
let region: Type = native("ir.TensorRegionType",
&[]).unwrap().try_into().unwrap();
assert!(TensorRegionType::new().same_as(®ion));
}
+
+/// A pair of types with a tag, defined in Rust.
+#[rs_class("testing.rust.PairType", final)]
+pub struct PairTypeNode {
+ base: TypeObj,
+ /// The first element.
+ pub lhs: Type,
+ /// The second element.
+ pub rhs: Type,
+ pub tag: i64,
+ /// Not part of structural equality or hashing.
+ #[reflect(seq_hash_ignore)]
+ pub note: FfiString,
+}
+
+def_object_ref!(pub PairType, Type, PairTypeNode);
+
+impl PairType {
+ /// A copy with the fields `edit` assigns replaced (C++ `CopyOnWrite()`).
+ fn with(&self, edit: impl FnOnce(&mut PairTypeNode)) -> Self {
+ let mut node = self.shallow_copy();
+ edit(&mut node);
+ node.into()
+ }
+}
+
+fn pair(lhs: Type, rhs: Type, tag: i64, note: &str) -> PairType {
+ PairTypeNode::new(TypeObj::new(Location::unknown()), lhs, rhs, tag,
note).into()
+}
+
+fn int_float_pair(tag: i64, note: &str) -> PairType {
+ pair(PrimType::int(32).into(), PrimType::float(32).into(), tag, note)
+}
+
+/// How C++ prints a node (`ffi.ReprPrint`).
+fn repr<T>(value: &T) -> String
+where
+ for<'a> AnyView<'a>: From<&'a T>,
+{
+ let text =
global("ffi.ReprPrint").call_packed(&[AnyView::from(value)]).unwrap();
+ FfiString::try_from(text).unwrap().as_str().to_string()
+}
+
+/// C++ `ffi::StructuralHash()(value)`.
+fn structural_hash<T>(value: &T) -> Result<i64>
+where
+ for<'a> AnyView<'a>: From<&'a T>,
+{
+ let flag = <AnyView as From<&bool>>::from;
+ global("ffi.StructuralHash")
+ .call_packed(&[AnyView::from(value), flag(&false), flag(&false)])?
+ .try_into()
+}
+
+#[test]
+fn rust_type_registers_under_ir_type_with_its_fields_reflected() {
+ let _serial = serial();
+ // The first use registers the type and its reflection.
+ assert_type_contract::<PairTypeNode, TypeObj>(true);
+
+ let info = runtime_type_info::<PairTypeNode>();
+ let metadata = unsafe { &*info.metadata };
+ assert_eq!(metadata.structural_eq_hash_kind, 1, "TreeNode, as every
ir.Type");
+ let fields: Vec<(String, i64, i64)> = (0..info.num_fields as usize)
+ .map(|index| {
+ let field = unsafe { &*info.fields.add(index) };
+ (field.name.as_str().to_string(), field.offset, field.flags)
+ })
+ .collect();
+ assert_eq!(
+ fields,
+ vec![
+ ("lhs".to_string(), offset_of!(PairTypeNode, lhs) as i64, 0),
+ ("rhs".to_string(), offset_of!(PairTypeNode, rhs) as i64, 0),
+ ("tag".to_string(), offset_of!(PairTypeNode, tag) as i64, 0),
+ ("note".to_string(), offset_of!(PairTypeNode, note) as i64, 1 <<
3),
+ ]
+ );
+}
+
+#[test]
+fn rust_type_reflection_reads_own_and_inherited_fields() {
+ let _serial = serial();
+ let value = int_float_pair(7, "seven");
+ let get = |field: &str| -> Any {
+ FieldGetter::new(PairTypeNode::type_index(),
field).unwrap().get_any(&*value).unwrap()
+ };
+ assert!(Type::try_from(get("lhs")).unwrap().same_as(&value.lhs));
+ assert!(Type::try_from(get("rhs")).unwrap().same_as(&value.rhs));
+ assert_eq!(i64::try_from(get("tag")).unwrap(), 7);
+ assert_eq!(FfiString::try_from(get("note")).unwrap().as_str(), "seven");
+ // `loc` belongs to the parent `ir.Type`.
+ assert!(Location::try_from(get("loc")).unwrap().same_as(&value.loc));
+}
+
+#[test]
+fn rust_type_cpp_structural_equal_and_hash_walk_the_fields() {
+ let _serial = serial();
+ let a = int_float_pair(7, "a");
+ let b = int_float_pair(7, "b");
+ let c = int_float_pair(8, "a");
+ assert!(structural_equal(&a, &b), "the note is ignored");
+ assert!(!structural_equal(&a, &c));
+ assert_eq!(structural_hash(&a).unwrap(), structural_hash(&b).unwrap());
+ assert_ne!(structural_hash(&a).unwrap(), structural_hash(&c).unwrap());
+
+ // Nested in itself, as any type.
+ let int32: Type = PrimType::int(32).into();
+ let outer_a = pair(a.clone().into(), int32.clone(), 0, "");
+ let outer_b = pair(b.into(), int32.clone(), 0, "");
+ let outer_c = pair(c.into(), int32, 0, "");
+ assert!(structural_equal(&outer_a, &outer_b));
+ assert!(!structural_equal(&outer_a, &outer_c));
+ assert_eq!(structural_hash(&outer_a).unwrap(),
structural_hash(&outer_b).unwrap());
+}
+
+#[test]
+fn rust_type_cpp_repr_and_tvmscript_print_the_node() {
+ let _serial = serial();
+ let value = int_float_pair(7, "seven");
+ let text = repr(&value);
+ assert!(text.contains("testing.rust.PairType"), "{text}");
+ assert!(text.contains("tag=7"), "{text}");
+ assert!(text.contains("seven"), "{text}");
+
+ let script = global("script.printer.Script")
+ .call_packed(&[AnyView::from(&value), AnyView::new()])
+ .unwrap();
+ let script = FfiString::try_from(script).unwrap();
+ assert!(script.as_str().contains("testing.rust.Pair("), "{}",
script.as_str());
+ assert!(script.as_str().contains("\"seven\""), "{}", script.as_str());
+}
+
+#[test]
+fn rust_type_cpp_deep_copy_goes_through_the_shallow_copy_and_the_setters() {
+ let _serial = serial();
+ let value = int_float_pair(7, "seven");
+ let copy =
global("ffi.DeepCopy").call_packed(&[AnyView::from(&value)]).unwrap();
+ let copy = PairType::try_from(copy).unwrap();
+ assert!(!copy.same_as(&value));
+ assert!(structural_equal(©, &value));
+ assert_eq!(copy.tag, 7);
+ assert_eq!(copy.note.as_str(), "seven");
+}
+
+/// Adds one to every integer leaf.
+struct IncrementIntegers;
+
+impl MapDispatch for IncrementIntegers {
+ fn dispatch_map(&mut self, value: &StructuralView, _: DefRegionKind) ->
Option<Result<Any>> {
+ value.cast::<i64>().map(|integer| Ok(Any::from(integer + 1)))
+ }
+}
+
+#[test]
+fn rust_type_rust_engines_descend_through_the_fields() {
+ let _serial = serial();
+ let value = int_float_pair(7, "seven");
+ // Shared with `value`, so the engine copies the node through
`__ffi_shallow_copy__`.
+ let mapped =
+ structural_map(value.clone(), &mut IncrementIntegers,
WalkOrder::PostOrder).unwrap();
+ let mapped = PairType::try_from(mapped).unwrap();
+ assert!(!mapped.same_as(&value));
+ assert_eq!(mapped.tag, 8);
+ assert_eq!(mapped.note.as_str(), "seven");
+ assert!(mapped.lhs.same_as(&value.lhs));
+ assert_eq!(value.tag, 7);
+}
+
+#[test]
+fn rust_type_with_is_copy_on_write() {
+ let _serial = serial();
+ let value = int_float_pair(7, "seven");
+ let edited = value.with(|node| node.tag = 9);
+ assert!(!edited.same_as(&value));
+ assert_eq!(edited.tag, 9);
+ assert_eq!(value.tag, 7);
+ assert!(edited.lhs.same_as(&value.lhs));
+ assert!(edited.rhs.same_as(&value.rhs));
+ // The generated `ShallowCopy` of `TypeObj` keeps the location.
+ assert!(edited.loc.same_as(&value.loc));
+ assert_eq!(edited.note.as_str(), "seven");
+}
+
+#[test]
+fn rust_type_converts_through_any_and_the_type_hierarchy() {
+ let _serial = serial();
+ let value = int_float_pair(1, "");
+ let as_type: Type = value.clone().into();
+ assert!(as_type.as_node::<PairTypeNode>().is_some());
+ let any = Any::from(as_type);
+ assert_eq!(any.type_index(), PairTypeNode::type_index());
+ let back = PairType::try_from(any).unwrap();
+ assert!(back.same_as(&value));
+}
+
+#[test]
+fn rust_type_of_a_variable_takes_part_in_ir() {
+ let _serial = serial();
+ // The type of a variable, as `PrimType` or `TupleType` is one.
+ let x = Var::new("x", int_float_pair(7, "seven"), UNKNOWN_LOC);
+ assert_eq!(x.ty.as_node::<PairTypeNode>().unwrap().tag, 7);
+ assert!(structural_equal(&x.ty, &int_float_pair(7, "other")));
+ assert!(!structural_equal(&x.ty, &int_float_pair(8, "seven")));
+
+ // Inside IR, which C++ deep-copies through the shallow copy and the
setters.
+ let stmt = Evaluate::new(x.clone(), UNKNOWN_LOC);
+ let copy =
global("ffi.DeepCopy").call_packed(&[AnyView::from(&stmt)]).unwrap();
+ let copy = Evaluate::try_from(copy).unwrap();
+ let copied = copy.value.as_node::<VarObj>().unwrap();
+ let ty = copied.ty.as_node::<PairTypeNode>().unwrap();
+ assert_eq!((ty.tag, ty.note.as_str()), (7, "seven"));
+ assert!(structural_equal(&copied.ty, &x.ty));
+}
diff --git a/rust/tests/sym/int_set.rs b/rust/tests/sym/int_set.rs
index 4871f0cb..33719c6f 100644
--- a/rust/tests/sym/int_set.rs
+++ b/rust/tests/sym/int_set.rs
@@ -93,7 +93,7 @@ fn int_sets() {
fn region_bounds() {
let x = var("x");
let var_dom = Map::from_iter([(x.clone(), range(0, 16))]);
- let region = [Range::from_complete_fields(x.clone().into(), int32(1),
Location::unknown())];
+ let region = [Range::from_fields(x.clone(), int32(1),
Location::unknown())];
let predicate = Expr::from(true);
let lower = estimate_region_lower_bound(region.clone(), &var_dom,
&predicate, None).unwrap();
diff --git a/rust/tests/sym/iter_affine_map.rs
b/rust/tests/sym/iter_affine_map.rs
index 6362c72f..206dbeca 100644
--- a/rust/tests/sym/iter_affine_map.rs
+++ b/rust/tests/sym/iter_affine_map.rs
@@ -127,7 +127,7 @@ fn iter_maps() {
let inverse = inverse_affine_iter_map([detected_index], [output]).unwrap();
assert_eq!(inverse.len(), 2);
- let mark = IterMark::new(x.clone().into(), int32(4));
+ let mark = IterMark::new(x.clone(), int32(4));
let split = IterSplitExpr::new(mark, int32(1), int32(4),
int32(1)).unwrap();
assert!(analyzer.can_prove_equal(split.scale().unwrap(),
int32(1)).unwrap());
let sum = IterSumExpr::new([split], int32(0));
diff --git a/rust/tests/sym/main.rs b/rust/tests/sym/main.rs
index f636ab73..faed540a 100644
--- a/rust/tests/sym/main.rs
+++ b/rust/tests/sym/main.rs
@@ -50,7 +50,7 @@ fn var(name: &str) -> Var {
}
fn range(begin: i64, extent: i64) -> Range {
- Range::from_complete_fields(int32(begin), int32(extent),
Location::unknown())
+ Range::from_fields(int32(begin), int32(extent), Location::unknown())
}
struct Fixture {
diff --git a/rust/tests/tirx/transform/function_pass.rs
b/rust/tests/tirx/transform/function_pass.rs
index 6f5dc871..7c0355a7 100644
--- a/rust/tests/tirx/transform/function_pass.rs
+++ b/rust/tests/tirx/transform/function_pass.rs
@@ -39,13 +39,13 @@ fn function_passes() {
counter.fetch_add(1, Ordering::Relaxed);
Ok(Some(func))
},
- PassInfo::new(0, "rust.Count".into()),
+ PassInfo::new(0, "rust.Count"),
);
let out = Pass::from(&counting).run(module_of("main", &func)).unwrap();
assert_eq!(runs.load(Ordering::Relaxed), 1);
assert!(out.contains("main").unwrap());
let dropping =
- FunctionPass::new(|_func, _module, _ctx| Ok(None), PassInfo::new(0,
"rust.Drop".into()));
+ FunctionPass::new(|_func, _module, _ctx| Ok(None), PassInfo::new(0,
"rust.Drop"));
assert!(!Pass::from(&dropping)
.run(module_of("main", &func))
.unwrap()