1use std::fmt::{self, Write};
2
3use crate::{
4 db::MirDb,
5 ir::{function::BodyDataStore, inst::InstKind, InstId},
6};
7
8use super::PrettyPrint;
9
10impl PrettyPrint for InstId {
11 fn pretty_print<W: Write>(
12 &self,
13 db: &dyn MirDb,
14 store: &BodyDataStore,
15 w: &mut W,
16 ) -> fmt::Result {
17 if let Some(result) = store.inst_result(*self) {
18 result.pretty_print(db, store, w)?;
19 write!(w, ": ")?;
20
21 let result_ty = result.ty(db, store);
22 result_ty.pretty_print(db, store, w)?;
23 write!(w, " = ")?;
24 }
25
26 match &store.inst_data(*self).kind {
27 InstKind::Declare { local } => {
28 write!(w, "let ")?;
29 local.pretty_print(db, store, w)?;
30 write!(w, ": ")?;
31 store.value_ty(*local).pretty_print(db, store, w)
32 }
33
34 InstKind::Unary { op, value } => {
35 write!(w, "{op}")?;
36 value.pretty_print(db, store, w)
37 }
38
39 InstKind::Binary { op, lhs, rhs } => {
40 lhs.pretty_print(db, store, w)?;
41 write!(w, " {op} ")?;
42 rhs.pretty_print(db, store, w)
43 }
44
45 InstKind::Cast { value, to, .. } => {
46 value.pretty_print(db, store, w)?;
47 write!(w, " as ")?;
48 to.pretty_print(db, store, w)
49 }
50
51 InstKind::AggregateConstruct { ty, args } => {
52 ty.pretty_print(db, store, w)?;
53 write!(w, "{{")?;
54 if args.is_empty() {
55 return write!(w, "}}");
56 }
57
58 let arg_len = args.len();
59 for (arg_idx, arg) in args.iter().enumerate().take(arg_len - 1) {
60 write!(w, "<{arg_idx}>: ")?;
61 arg.pretty_print(db, store, w)?;
62 write!(w, ", ")?;
63 }
64 let arg = args[arg_len - 1];
65 write!(w, "<{}>: ", arg_len - 1)?;
66 arg.pretty_print(db, store, w)?;
67 write!(w, "}}")
68 }
69
70 InstKind::Bind { src } => {
71 write!(w, "bind ")?;
72 src.pretty_print(db, store, w)
73 }
74
75 InstKind::MemCopy { src } => {
76 write!(w, "memcopy ")?;
77 src.pretty_print(db, store, w)
78 }
79
80 InstKind::Load { src } => {
81 write!(w, "load ")?;
82 src.pretty_print(db, store, w)
83 }
84
85 InstKind::AggregateAccess { value, indices } => {
86 value.pretty_print(db, store, w)?;
87 for index in indices {
88 write!(w, ".<")?;
89 index.pretty_print(db, store, w)?;
90 write!(w, ">")?
91 }
92 Ok(())
93 }
94
95 InstKind::MapAccess { value, key } => {
96 value.pretty_print(db, store, w)?;
97 write!(w, "{{")?;
98 key.pretty_print(db, store, w)?;
99 write!(w, "}}")
100 }
101
102 InstKind::Call {
103 func,
104 args,
105 call_type,
106 } => {
107 let name = func.debug_name(db);
108 write!(w, "{name}@{call_type}(")?;
109 args.as_slice().pretty_print(db, store, w)?;
110 write!(w, ")")
111 }
112
113 InstKind::Jump { dest } => {
114 write!(w, "jump BB{}", dest.index())
115 }
116
117 InstKind::Branch { cond, then, else_ } => {
118 write!(w, "branch ")?;
119 cond.pretty_print(db, store, w)?;
120 write!(w, " then: BB{} else: BB{}", then.index(), else_.index())
121 }
122
123 InstKind::Switch {
124 disc,
125 table,
126 default,
127 } => {
128 write!(w, "switch ")?;
129 disc.pretty_print(db, store, w)?;
130 for (value, block) in table.iter() {
131 write!(w, " ")?;
132 value.pretty_print(db, store, w)?;
133 write!(w, ": BB{}", block.index())?;
134 }
135
136 if let Some(default) = default {
137 write!(w, " default: BB{}", default.index())
138 } else {
139 Ok(())
140 }
141 }
142
143 InstKind::Revert { arg } => {
144 write!(w, "revert ")?;
145 if let Some(arg) = arg {
146 arg.pretty_print(db, store, w)?;
147 }
148 Ok(())
149 }
150
151 InstKind::Emit { arg } => {
152 write!(w, "emit ")?;
153 arg.pretty_print(db, store, w)
154 }
155
156 InstKind::Return { arg } => {
157 if let Some(arg) = arg {
158 write!(w, "return ")?;
159 arg.pretty_print(db, store, w)
160 } else {
161 write!(w, "return")
162 }
163 }
164
165 InstKind::Keccak256 { arg } => {
166 write!(w, "keccak256 ")?;
167 arg.pretty_print(db, store, w)
168 }
169
170 InstKind::AbiEncode { arg } => {
171 write!(w, "abi_encode ")?;
172 arg.pretty_print(db, store, w)
173 }
174
175 InstKind::Nop => {
176 write!(w, "nop")
177 }
178
179 InstKind::Create { value, contract } => {
180 write!(w, "create ")?;
181 let contract_name = contract.name(db.upcast());
182 write!(w, "{contract_name} ")?;
183 value.pretty_print(db, store, w)
184 }
185
186 InstKind::Create2 {
187 value,
188 salt,
189 contract,
190 } => {
191 write!(w, "create2 ")?;
192 let contract_name = contract.name(db.upcast());
193 write!(w, "{contract_name} ")?;
194 value.pretty_print(db, store, w)?;
195 write!(w, " ")?;
196 salt.pretty_print(db, store, w)
197 }
198
199 InstKind::YulIntrinsic { op, args } => {
200 write!(w, "{op}(")?;
201 args.as_slice().pretty_print(db, store, w)?;
202 write!(w, ")")
203 }
204 }
205 }
206}