sway_ir/
asm.rs

1//! An 'asm' block represents an opaque set of Fuel VM assembly instructions, embedded in place and
2//! intended to be inserted as is into the assembly code generation.
3//!
4//! An [`AsmBlock`] has symbols for arguments and an optional return name and contains a list of
5//! [`AsmInstruction`].
6//!
7//! The syntax in Sway for asm blocks is shown by this example, and [`AsmBlock`] represents it
8//! symbolically:
9//!
10//! ```text
11//! asm(r1: self, r2: other, r3) {
12//!     add r3 r2 r1;
13//!     r3: u64
14//! }
15//! ```
16
17use sway_types::ident::Ident;
18
19use crate::{
20    context::Context, irtype::Type, metadata::MetadataIndex, pretty::DebugWithContext, value::Value,
21};
22
23#[doc(hidden)]
24#[derive(Clone, Debug, DebugWithContext)]
25pub struct AsmBlock {
26    pub args_names: Vec<Ident>,
27    pub body: Vec<AsmInstruction>,
28    pub return_type: Type,
29    pub return_name: Option<Ident>,
30}
31
32#[derive(Clone, Debug)]
33pub struct AsmArg {
34    pub name: Ident,
35    pub initializer: Option<Value>,
36}
37
38#[derive(Clone, Debug)]
39pub struct AsmInstruction {
40    pub op_name: Ident,
41    pub args: Vec<Ident>,
42    pub immediate: Option<Ident>,
43    pub metadata: Option<MetadataIndex>,
44}
45
46impl AsmInstruction {
47    pub fn log_no_span(
48        ra: impl Into<String>,
49        rb: impl Into<String>,
50        rc: impl Into<String>,
51        rd: impl Into<String>,
52    ) -> Self {
53        AsmInstruction {
54            op_name: Ident::new(sway_types::Span::from_string("log".into())),
55            args: vec![
56                Ident::new_no_span(ra.into()),
57                Ident::new_no_span(rb.into()),
58                Ident::new_no_span(rc.into()),
59                Ident::new_no_span(rd.into()),
60            ],
61            immediate: None,
62            metadata: None,
63        }
64    }
65
66    pub fn lw_no_span(
67        dst: impl Into<String>,
68        src: impl Into<String>,
69        offset: impl Into<String>,
70    ) -> Self {
71        AsmInstruction {
72            op_name: Ident::new(sway_types::Span::from_string("lw".into())),
73            args: vec![
74                Ident::new_no_span(dst.into()),
75                Ident::new_no_span(src.into()),
76            ],
77            immediate: Some(Ident::new_no_span(offset.into())),
78            metadata: None,
79        }
80    }
81
82    pub fn mul_no_span(dst: impl Into<String>, a: impl Into<String>, b: impl Into<String>) -> Self {
83        AsmInstruction {
84            op_name: Ident::new(sway_types::Span::from_string("mul".into())),
85            args: vec![
86                Ident::new_no_span(dst.into()),
87                Ident::new_no_span(a.into()),
88                Ident::new_no_span(b.into()),
89            ],
90            immediate: None,
91            metadata: None,
92        }
93    }
94
95    pub fn add_no_span(dst: impl Into<String>, a: impl Into<String>, b: impl Into<String>) -> Self {
96        AsmInstruction {
97            op_name: Ident::new(sway_types::Span::from_string("add".into())),
98            args: vec![
99                Ident::new_no_span(dst.into()),
100                Ident::new_no_span(a.into()),
101                Ident::new_no_span(b.into()),
102            ],
103            immediate: None,
104            metadata: None,
105        }
106    }
107
108    pub fn sub_no_span(dst: impl Into<String>, a: impl Into<String>, b: impl Into<String>) -> Self {
109        AsmInstruction {
110            op_name: Ident::new(sway_types::Span::from_string("sub".into())),
111            args: vec![
112                Ident::new_no_span(dst.into()),
113                Ident::new_no_span(a.into()),
114                Ident::new_no_span(b.into()),
115            ],
116            immediate: None,
117            metadata: None,
118        }
119    }
120}
121
122impl AsmBlock {
123    /// Create a new [`AsmBlock`] in the passed context and return its handle.
124    pub fn new(
125        args_names: Vec<Ident>,
126        body: Vec<AsmInstruction>,
127        return_type: Type,
128        return_name: Option<Ident>,
129    ) -> Self {
130        AsmBlock {
131            args_names,
132            body,
133            return_type,
134            return_name,
135        }
136    }
137}