/* * wasm-ir - Intermediate Representation of WebAssembly * Copyright © 2019-2022 Blue Forest * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ use wasm_ir::{ Body, FunctionType, I32, Import, Instruction, Limit, Local, Module, }; use wasm_ir::code::control::{Call, CallIndirect}; use wasm_ir::code::numeric::I32Const; use wasm_ir::code::memory::I32Store; use wasm_ir::code::parametric::DropStack; use wasm_ir::code::variable::{LocalGet, LocalSet}; use super::imported; pub fn module(is_passive: bool) -> Module { let mut result = Module::with_name("caller".to_string()); result.import_memory( Import::new("env".to_string(), "memory".to_string()), Limit::new(1, Some(1)), ); let table_idx = result.import_table( Import::new("env".to_string(), "table".to_string()), Limit::new(1, Some(1)), ); let (_, fd_write_idx) = result.import_function( Import::new("wasi_unstable".to_string(), "fd_write".to_string()), FunctionType::new( vec![I32, I32, I32, I32], vec![I32], ), ); let imported_type_idx = result.add_type(imported::type_()); let instructions = start_instructions( &mut result, fd_write_idx, imported_type_idx, table_idx, is_passive, ); result.export_function( "_start".to_string(), FunctionType::new(Vec::new(), Vec::new()), Body::new( vec![ Local::new(1, I32), ], instructions, ), ); result } #[inline(always)] fn start_instructions( module: &mut Module, fd_write_idx: u32, imported_type_idx: u32, table_idx: u32, is_passive: bool, ) -> Vec> { let mut result: Vec> = Vec::new(); if is_passive { let (_, init_idx) = module.import_function( Import::new("env".to_string(), "init".to_string()), FunctionType::new(Vec::new(),Vec::new()), ); result.push(Call::with_stack(init_idx)); } result.extend(vec![ I32Const::create(0), // iovs base address CallIndirect::with_operands( imported_type_idx, table_idx, Vec::new(), I32Const::create(0), ), // get_test() -> iovs.base, iovs.length LocalSet::create(0), // set iovs.length I32Store::with_stack(2, 0), // store iovs.base I32Const::create(4), // iovs length address LocalGet::create(0), // get iovs.length I32Store::with_stack(2, 0), // store iovs.length Call::with_operands(fd_write_idx, vec![ I32Const::create(1), // file_descriptor - 1 for stdout I32Const::create(0), // iovs address I32Const::create(1), // iovs len I32Const::create(8), // nwritten ]), DropStack::create(), ]); result }