1use crate::{parser::Parser, Artifact, Config, Error, Result};
4use zabi::Abi;
5use zingen::{
6 wasm::{self, Env},
7 Buffer, Dispatcher, Function, JumpTable, BUFFER_LIMIT,
8};
9
10#[derive(Default)]
12pub struct Compiler {
13 pub(crate) abi: Vec<Abi>,
15 pub(crate) buffer: Buffer,
17 pub config: Config,
19 table: JumpTable,
21}
22
23impl Compiler {
24 pub fn new(config: Config) -> Self {
26 Self {
27 config,
28 ..Default::default()
29 }
30 }
31
32 pub fn compile(mut self, wasm: &[u8]) -> Result<Artifact> {
36 let mut parser = Parser::try_from(wasm)?;
37 let env = parser.env.clone();
38
39 self.compile_dispatcher(&mut parser)?;
40 for func in parser.funcs.into_funcs() {
41 self.compile_func(env.with_index(func.index()), func)?;
42 }
43
44 self.table.code_offset(self.buffer.len() as u16);
45 self.table.relocate(&mut self.buffer)?;
46 self.artifact()
47 }
48
49 fn artifact(self) -> Result<Artifact> {
53 let Compiler {
54 abi,
55 buffer,
56 config,
57 ..
58 } = self;
59
60 tracing::debug!("code length: {}", buffer.len());
61 Ok(Artifact {
62 abi,
63 config,
64 runtime_bytecode: buffer.to_vec(),
65 })
66 }
67
68 fn compile_dispatcher(&mut self, parser: &mut Parser) -> Result<()> {
72 let selectors = parser.drain_selectors();
73 let env = parser.env.clone();
74
75 if !self.config.dispatcher {
76 self.abi.append(&mut env.load_abis(&selectors)?);
77 return Ok(());
78 }
79
80 let mut dispatcher = Dispatcher::new(env, &parser.funcs)?;
81 let buffer = dispatcher.finish(selectors, &mut self.table)?;
82 self.buffer.extend_from_slice(&buffer);
83 if self.buffer.len() > BUFFER_LIMIT {
84 return Err(Error::BufferOverflow(self.buffer.len()));
85 }
86
87 self.abi.append(&mut dispatcher.abi);
88 Ok(())
89 }
90
91 fn compile_func(&mut self, env: Env, mut func: wasm::Function<'_>) -> Result<()> {
93 let func_index = func.index();
94 let sig = func.sig()?;
95 let abi = self.abi(&env, func_index);
96
97 tracing::debug!("compile function {func_index} {:?}, abi: {abi:#?}", sig);
98 let is_main = !self.config.dispatcher && env.is_main(func_index);
99
100 let mut codegen = Function::new(env, sig, abi, is_main)?;
101 let mut locals_reader = func.body.get_locals_reader()?;
102 let mut ops_reader = func.body.get_operators_reader()?;
103
104 codegen.emit_locals(&mut locals_reader, &mut func.validator)?;
105 codegen.emit_operators(&mut ops_reader, &mut func.validator)?;
106
107 self.emit_buffer(func_index, codegen)?;
108 Ok(())
109 }
110
111 fn emit_buffer(&mut self, func_index: u32, codegen: Function) -> Result<()> {
113 let buffer = codegen.finish(&mut self.table, self.buffer.len() as u16)?;
114 self.table
115 .call_offset(func_index, self.buffer.len() as u16)?;
116 self.buffer.extend_from_slice(&buffer);
117
118 if self.buffer.len() > BUFFER_LIMIT {
119 return Err(Error::BufferOverflow(buffer.len()));
120 }
121
122 Ok(())
123 }
124
125 fn abi(&self, env: &Env, index: u32) -> Option<Abi> {
127 let name = env.exports.get(&index)?;
128 self.abi.iter().find(|a| name == &a.name).cloned()
129 }
130}