use super::{Node, NodeExtension};
use crate::ir_inner::model::expr::{Expr, Ident};
use crate::memory_model::MemoryOrdering;
use std::sync::Arc;
impl Node {
#[must_use]
#[inline]
pub fn let_bind(name: impl Into<Ident>, value: Expr) -> Self {
Self::Let {
name: name.into(),
value,
}
}
#[must_use]
#[inline]
pub fn assign(name: impl Into<Ident>, value: Expr) -> Self {
Self::Assign {
name: name.into(),
value,
}
}
#[must_use]
#[inline]
pub fn store(buffer: impl Into<Ident>, index: Expr, value: Expr) -> Self {
Self::Store {
buffer: buffer.into(),
index,
value,
}
}
#[must_use]
#[inline]
pub fn if_then_else(cond: Expr, then: Vec<Self>, otherwise: Vec<Self>) -> Self {
Self::If {
cond,
then,
otherwise,
}
}
#[must_use]
#[inline]
pub fn if_then(cond: Expr, then: Vec<Self>) -> Self {
Self::If {
cond,
then,
otherwise: Vec::new(),
}
}
#[must_use]
#[inline]
pub fn loop_for(var: impl Into<Ident>, from: Expr, to: Expr, body: Vec<Self>) -> Self {
Self::Loop {
var: var.into(),
from,
to,
body,
}
}
#[must_use]
#[inline]
pub fn loop_(var: impl Into<Ident>, from: Expr, to: Expr, body: Vec<Self>) -> Self {
Self::loop_for(var, from, to, body)
}
#[must_use]
#[inline]
pub fn forever(body: Vec<Self>) -> Self {
Self::loop_for("__forever__", Expr::u32(0), Expr::u32(u32::MAX), body)
}
#[must_use]
#[inline]
pub fn block(nodes: Vec<Self>) -> Self {
Self::Block(nodes)
}
#[must_use]
pub const fn return_() -> Self {
Self::Return
}
#[must_use]
pub const fn barrier() -> Self {
Self::Barrier {
ordering: MemoryOrdering::SeqCst,
}
}
#[must_use]
pub const fn barrier_with_ordering(ordering: MemoryOrdering) -> Self {
Self::Barrier { ordering }
}
#[must_use]
pub fn call(op_id: impl Into<Ident>, args: Vec<Expr>) -> Self {
let body: Vec<Node> = args
.into_iter()
.enumerate()
.map(|(idx, expr)| Node::let_bind(format!("arg{idx}"), expr))
.collect();
Self::Region {
generator: op_id.into(),
source_region: None,
body: Arc::new(body),
}
}
#[must_use]
#[inline]
pub fn indirect_dispatch(count_buffer: impl Into<Ident>, count_offset: u64) -> Self {
Self::IndirectDispatch {
count_buffer: count_buffer.into(),
count_offset,
}
}
#[must_use]
#[inline]
pub fn async_load_ext(
source: impl Into<Ident>,
destination: impl Into<Ident>,
offset: Expr,
size: Expr,
tag: impl Into<Ident>,
) -> Self {
Self::AsyncLoad {
source: source.into(),
destination: destination.into(),
offset: Box::new(offset),
size: Box::new(size),
tag: tag.into(),
}
}
#[must_use]
#[inline]
pub fn async_load(tag: impl Into<Ident>) -> Self {
Self::async_load_ext(
"__legacy_src__",
"__legacy_dst__",
Expr::u32(0),
Expr::u32(0),
tag,
)
}
#[must_use]
#[inline]
pub fn async_store(
source: impl Into<Ident>,
destination: impl Into<Ident>,
offset: Expr,
size: Expr,
tag: impl Into<Ident>,
) -> Self {
Self::AsyncStore {
source: source.into(),
destination: destination.into(),
offset: Box::new(offset),
size: Box::new(size),
tag: tag.into(),
}
}
#[must_use]
#[inline]
pub fn async_wait(tag: impl Into<Ident>) -> Self {
Self::AsyncWait { tag: tag.into() }
}
#[must_use]
#[inline]
pub fn trap(address: Expr, tag: impl Into<Ident>) -> Self {
Self::Trap {
address: Box::new(address),
tag: tag.into(),
}
}
#[must_use]
#[inline]
pub fn resume(tag: impl Into<Ident>) -> Self {
Self::Resume { tag: tag.into() }
}
#[must_use]
#[inline]
pub fn opaque(node: impl NodeExtension) -> Self {
Self::Opaque(Arc::new(node))
}
#[must_use]
#[inline]
pub fn opaque_arc(node: Arc<dyn NodeExtension>) -> Self {
Self::Opaque(node)
}
}