1use super::{FuncDecl, FunctionBody, Module, SourceLoc, ValueDef};
4use crate::entity::EntityRef;
5use std::collections::HashMap;
6use std::fmt::{Display, Formatter, Result as FmtResult};
7
8pub struct FunctionBodyDisplay<'a> {
11 pub(crate) body: &'a FunctionBody,
12 pub(crate) indent: &'a str,
13 pub(crate) verbose: bool,
14 pub(crate) module: Option<&'a Module<'a>>,
15}
16
17impl<'a> Display for FunctionBodyDisplay<'a> {
18 fn fmt(&self, f: &mut Formatter) -> FmtResult {
19 let arg_tys = self
20 .body
21 .locals
22 .values()
23 .take(self.body.n_params)
24 .map(|&ty| format!("{}", ty))
25 .collect::<Vec<_>>();
26 let ret_tys = self
27 .body
28 .rets
29 .iter()
30 .map(|&ty| format!("{}", ty))
31 .collect::<Vec<_>>();
32 writeln!(
33 f,
34 "{}function({}) -> {} {{",
35 self.indent,
36 arg_tys.join(", "),
37 ret_tys.join(", ")
38 )?;
39
40 for (value, value_def) in self.body.values.entries() {
41 match value_def {
42 ValueDef::Operator(op, args, tys) if self.verbose => writeln!(
43 f,
44 "{} {} = {} {} # {}",
45 self.indent,
46 value,
47 op,
48 self.body.arg_pool[*args]
49 .iter()
50 .map(|arg| format!("{}", arg))
51 .collect::<Vec<_>>()
52 .join(", "),
53 self.body.type_pool[*tys]
54 .iter()
55 .map(|arg| format!("{}", arg))
56 .collect::<Vec<_>>()
57 .join(", ")
58 )?,
59 ValueDef::BlockParam(block, idx, ty) if self.verbose => writeln!(
60 f,
61 "{} {} = blockparam {}, {} # {}",
62 self.indent, value, block, idx, ty
63 )?,
64 ValueDef::Alias(alias_target) => {
65 if self.verbose {
66 writeln!(f, "{} {} = {}", self.indent, value, alias_target)?
67 }
68 }
69 ValueDef::PickOutput(val, idx, ty) => {
70 writeln!(f, "{} {} = {}.{} # {}", self.indent, value, val, idx, ty)?
71 }
72 ValueDef::Placeholder(ty) => {
73 writeln!(f, "{} {} = placeholder # {}", self.indent, value, ty)?
74 }
75 ValueDef::None => writeln!(f, "{} {} = none", self.indent, value)?,
76 _ => {}
77 }
78 }
79
80 for (block_id, block) in self.body.blocks.entries() {
81 let block_params = block
82 .params
83 .iter()
84 .map(|(ty, val)| format!("{}: {}", val, ty))
85 .collect::<Vec<_>>();
86 writeln!(
87 f,
88 "{} {}({}): # {}",
89 self.indent,
90 block_id,
91 block_params.join(", "),
92 block.desc
93 )?;
94 writeln!(
95 f,
96 "{} # preds: {}",
97 self.indent,
98 block
99 .preds
100 .iter()
101 .map(|pred| format!("{} ({})", pred, self.body.blocks[*pred].desc))
102 .collect::<Vec<_>>()
103 .join(", ")
104 )?;
105 writeln!(
106 f,
107 "{} # succs: {}",
108 self.indent,
109 block
110 .succs
111 .iter()
112 .map(|succ| format!("{} ({})", succ, self.body.blocks[*succ].desc))
113 .collect::<Vec<_>>()
114 .join(", ")
115 )?;
116 for (_, param) in &block.params {
117 if let Some(local) = self.body.value_locals[*param] {
118 writeln!(f, "{} # {}: {}", self.indent, param, local)?;
119 }
120 }
121 for &inst in &block.insts {
122 if let Some(local) = self.body.value_locals[inst] {
123 writeln!(f, "{} # {}: {}", self.indent, inst, local)?;
124 }
125 match &self.body.values[inst] {
126 ValueDef::Operator(op, args, tys) => {
127 let args = self.body.arg_pool[*args]
128 .iter()
129 .map(|&v| format!("{}", v))
130 .collect::<Vec<_>>();
131 let tys = self.body.type_pool[*tys]
132 .iter()
133 .map(|&ty| format!("{}", ty))
134 .collect::<Vec<_>>();
135 let loc = if self.body.source_locs[inst] != SourceLoc::invalid()
136 && self.module.is_some()
137 {
138 let module = self.module.as_ref().unwrap();
139 let loc = self.body.source_locs[inst];
140 let data = &module.debug.source_locs[loc];
141 let filename = &module.debug.source_files[data.file];
142 format!("@{} {}:{}:{}", loc, filename, data.line, data.col)
143 } else {
144 "".to_owned()
145 };
146 writeln!(
147 f,
148 "{} {} = {} {} # {} {}",
149 self.indent,
150 inst,
151 op,
152 args.join(", "),
153 tys.join(", "),
154 loc,
155 )?;
156 }
157 ValueDef::PickOutput(val, idx, ty) => {
158 writeln!(f, "{} {} = {}.{} # {}", self.indent, inst, val, idx, ty)?;
159 }
160 ValueDef::Alias(val) => {
161 writeln!(f, "{} {} = {}", self.indent, inst, val)?;
162 }
163 _ => unreachable!(),
164 }
165 }
166 writeln!(f, "{} {}", self.indent, block.terminator)?;
167 }
168
169 writeln!(f, "{}}}", self.indent)?;
170
171 Ok(())
172 }
173}
174
175pub struct ModuleDisplay<'a> {
176 pub(crate) module: &'a Module<'a>,
177}
178
179impl<'a> Display for ModuleDisplay<'a> {
180 fn fmt(&self, f: &mut Formatter) -> FmtResult {
181 writeln!(f, "module {{")?;
182 if let Some(func) = self.module.start_func {
183 writeln!(f, " start = {}", func)?;
184 }
185 let mut sig_strs = HashMap::new();
186 for (sig, sig_data) in self.module.signatures.entries() {
187 let arg_tys = sig_data
188 .params
189 .iter()
190 .map(|&ty| format!("{}", ty))
191 .collect::<Vec<_>>();
192 let ret_tys = sig_data
193 .returns
194 .iter()
195 .map(|&ty| format!("{}", ty))
196 .collect::<Vec<_>>();
197 let sig_str = format!("{} -> {}", arg_tys.join(", "), ret_tys.join(", "));
198 sig_strs.insert(sig, sig_str.clone());
199 writeln!(f, " {}: {}", sig, sig_str)?;
200 }
201 for (global, global_data) in self.module.globals.entries() {
202 writeln!(
203 f,
204 " {}: {:?} # {}",
205 global, global_data.value, global_data.ty
206 )?;
207 }
208 for (table, table_data) in self.module.tables.entries() {
209 writeln!(f, " {}: {}", table, table_data.ty)?;
210 if let Some(funcs) = &table_data.func_elements {
211 for (i, &func) in funcs.iter().enumerate() {
212 writeln!(f, " {}[{}]: {}", table, i, func)?;
213 }
214 }
215 }
216 for (memory, memory_data) in self.module.memories.entries() {
217 writeln!(
218 f,
219 " {}: initial {} max {:?}",
220 memory, memory_data.initial_pages, memory_data.maximum_pages
221 )?;
222 for seg in &memory_data.segments {
223 writeln!(
224 f,
225 " {} offset {}: # {} bytes",
226 memory,
227 seg.offset,
228 seg.data.len()
229 )?;
230 }
231 }
232 for import in &self.module.imports {
233 writeln!(
234 f,
235 " import \"{}\".\"{}\": {}",
236 import.module, import.name, import.kind
237 )?;
238 }
239 for export in &self.module.exports {
240 writeln!(f, " export \"{}\": {}", export.name, export.kind)?;
241 }
242 for (func, func_decl) in self.module.funcs.entries() {
243 match func_decl {
244 FuncDecl::Body(sig, name, body) => {
245 writeln!(
246 f,
247 " {} \"{}\": {} = # {}",
248 func,
249 name,
250 sig,
251 sig_strs.get(&sig).unwrap()
252 )?;
253 writeln!(f, "{}", body.display(" ", Some(self.module)))?;
254 }
255 FuncDecl::Lazy(sig, name, reader) => {
256 writeln!(
257 f,
258 " {} \"{}\": {} = # {}",
259 func,
260 name,
261 sig,
262 sig_strs.get(&sig).unwrap()
263 )?;
264 writeln!(f, " # raw bytes (length {})", reader.range().len())?;
265 }
266 FuncDecl::Compiled(sig, name, _) => {
267 writeln!(
268 f,
269 " {} \"{}\": {} = # {}",
270 func,
271 name,
272 sig,
273 sig_strs.get(&sig).unwrap()
274 )?;
275 writeln!(f, " # already compiled")?;
276 }
277 FuncDecl::Import(sig, name) => {
278 writeln!(
279 f,
280 " {} \"{}\": {} # {}",
281 func,
282 name,
283 sig,
284 sig_strs.get(&sig).unwrap()
285 )?;
286 }
287 FuncDecl::None => {
288 writeln!(f, " {}: none", func)?;
289 }
290 }
291 }
292 for (loc, loc_data) in self.module.debug.source_locs.entries() {
293 writeln!(
294 f,
295 " {} = {} line {} column {}",
296 loc, loc_data.file, loc_data.line, loc_data.col
297 )?;
298 }
299 for (file, file_name) in self.module.debug.source_files.entries() {
300 writeln!(f, " {} = \"{}\"", file, file_name)?;
301 }
302 writeln!(f, "}}")?;
303 Ok(())
304 }
305}