@@ -5,7 +5,7 @@ use std::fs::File;
55use std:: mem;
66
77use cranelift_codegen:: binemit:: Reloc ;
8- use cranelift_codegen:: ir:: { BlockCall , ExternalName , InstructionData , Opcode } ;
8+ use cranelift_codegen:: ir:: { BlockCall , ExternalName , InstructionData , LibCall , Opcode } ;
99use cranelift_codegen:: isa:: { self , CallConv , TargetFrontendConfig } ;
1010use cranelift_module:: { DataId , ModuleDeclarations , ModuleReloc , ModuleRelocTarget } ;
1111use rustc_codegen_ssa:: { CodegenResults , CompiledModule , CrateInfo , ModuleKind } ;
@@ -186,6 +186,66 @@ impl WasmModule {
186186 mut self ,
187187 mut writer : W ,
188188 ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
189+ {
190+ let signature = & Signature {
191+ params : vec ! [ AbiParam :: new( types:: I32 ) ] ,
192+ returns : vec ! [ AbiParam :: new( types:: I32 ) ] ,
193+ call_conv : CallConv :: SystemV ,
194+ } ;
195+ let ( malloc_id, _linkage) =
196+ self . declarations . declare_function ( "malloc" , Linkage :: Local , signature) ?;
197+
198+ self . func_ids
199+ . entry ( malloc_id)
200+ . or_insert_with ( || self . waffle_module . funcs . push ( waffle:: FuncDecl :: None ) ) ;
201+
202+ let waffle_sig =
203+ FunctionBuilder :: translate_signature ( & mut self . waffle_module , & signature) ;
204+
205+ let mut waffle_func = waffle:: FunctionBody :: new ( & mut self . waffle_module , waffle_sig) ;
206+
207+ let alloc_size = waffle_func. blocks [ waffle_func. entry ] . params [ 0 ] . 1 ;
208+
209+ let page_size = waffle:: ValueDef :: Operator (
210+ waffle:: Operator :: I32Const { value : 65536 } ,
211+ waffle_func. arg_pool . from_iter ( [ ] . into_iter ( ) ) ,
212+ waffle_func. single_type_list ( waffle:: Type :: I32 ) ,
213+ ) ;
214+ let page_size = waffle_func. add_value ( page_size) ;
215+ waffle_func. append_to_block ( waffle_func. entry , page_size) ;
216+
217+ let alloc_size = waffle:: ValueDef :: Operator (
218+ waffle:: Operator :: I32Add ,
219+ waffle_func. arg_pool . from_iter ( [ alloc_size, page_size] . into_iter ( ) ) ,
220+ waffle_func. single_type_list ( waffle:: Type :: I32 ) ,
221+ ) ;
222+ let alloc_size = waffle_func. add_value ( alloc_size) ;
223+ waffle_func. append_to_block ( waffle_func. entry , alloc_size) ;
224+
225+ let page_count = waffle:: ValueDef :: Operator (
226+ waffle:: Operator :: I32DivU ,
227+ waffle_func. arg_pool . from_iter ( [ alloc_size, page_size] . into_iter ( ) ) ,
228+ waffle_func. single_type_list ( waffle:: Type :: I32 ) ,
229+ ) ;
230+ let page_count = waffle_func. add_value ( page_count) ;
231+ waffle_func. append_to_block ( waffle_func. entry , page_count) ;
232+
233+ let allocated = waffle:: ValueDef :: Operator (
234+ waffle:: Operator :: MemoryGrow { mem : self . main_memory } ,
235+ waffle_func. arg_pool . from_iter ( [ page_count] . into_iter ( ) ) ,
236+ waffle_func. single_type_list ( waffle:: Type :: I32 ) ,
237+ ) ;
238+ let allocated = waffle_func. add_value ( allocated) ;
239+ waffle_func. append_to_block ( waffle_func. entry , allocated) ;
240+
241+ waffle_func. set_terminator ( waffle_func. entry , waffle:: Terminator :: Return {
242+ values : vec ! [ allocated] ,
243+ } ) ;
244+
245+ self . waffle_module . funcs [ self . func_ids [ & malloc_id] ] =
246+ waffle:: FuncDecl :: Body ( waffle_sig, "malloc" . to_owned ( ) , waffle_func) ;
247+ }
248+
189249 for ( func_id, func_decl) in self . declarations . get_functions ( ) {
190250 if func_decl. linkage == Linkage :: Import {
191251 let func = self . func_ids [ & func_id] ;
@@ -470,6 +530,14 @@ impl Module for WasmModule {
470530 _ => unreachable ! ( ) ,
471531 } ) ;
472532 }
533+ Opcode :: Urem => {
534+ b. emit ( inst, match b. clif_func . dfg . ctrl_typevar ( inst) {
535+ types:: I8 | types:: I16 => todo ! ( ) ,
536+ types:: I32 => waffle:: Operator :: I32RemU ,
537+ types:: I64 => waffle:: Operator :: I64RemU ,
538+ _ => unreachable ! ( ) ,
539+ } ) ;
540+ }
473541 Opcode :: Uextend => {
474542 let arg = b. get_value ( b. clif_func . dfg . inst_args ( inst) [ 0 ] ) ;
475543 let ret = b. get_value ( b. clif_func . dfg . inst_results ( inst) [ 0 ] ) ;
@@ -768,27 +836,77 @@ impl Module for WasmModule {
768836 _ => unreachable ! ( ) ,
769837 }
770838 }
771- Opcode :: Call => {
772- let func_id = match ctx. func . dfg . insts [ inst] {
773- InstructionData :: Call { opcode : _, args : _, func_ref } => {
774- match ctx. func . dfg . ext_funcs [ func_ref] . name {
775- ExternalName :: User ( user) => {
776- let name = & ctx. func . params . user_named_funcs ( ) [ user] ;
777- assert_eq ! ( name. namespace, 0 ) ;
778- FuncId :: from_u32 ( name. index )
779- }
780- ExternalName :: TestCase ( _) => todo ! ( ) ,
781- ExternalName :: LibCall ( _libcall) => todo ! ( ) ,
782- ExternalName :: KnownSymbol ( _ks) => todo ! ( ) ,
839+ Opcode :: Call => match ctx. func . dfg . insts [ inst] {
840+ InstructionData :: Call { opcode : _, args : _, func_ref } => {
841+ match ctx. func . dfg . ext_funcs [ func_ref] . name {
842+ ExternalName :: User ( user) => {
843+ let name = & ctx. func . params . user_named_funcs ( ) [ user] ;
844+ assert_eq ! ( name. namespace, 0 ) ;
845+ let func_id = FuncId :: from_u32 ( name. index ) ;
846+ b. emit ( inst, waffle:: Operator :: Call {
847+ function_index : self . func_ids [ & func_id] ,
848+ } ) ;
849+ }
850+ ExternalName :: TestCase ( _) => todo ! ( ) ,
851+ ExternalName :: LibCall ( LibCall :: Memcpy | LibCall :: Memmove ) => {
852+ let block = b. clif_func . layout . inst_block ( inst) . unwrap ( ) ;
853+
854+ let args = b
855+ . clif_func
856+ . dfg
857+ . inst_args ( inst)
858+ . into_iter ( )
859+ . map ( |& arg| b. get_value ( arg) )
860+ . collect :: < Vec < _ > > ( ) ;
861+
862+ let ret_val =
863+ b. get_value ( b. clif_func . dfg . inst_results ( inst) [ 0 ] ) ;
864+
865+ let copy = waffle:: ValueDef :: Operator (
866+ waffle:: Operator :: MemoryCopy {
867+ dst_mem : self . main_memory ,
868+ src_mem : self . main_memory ,
869+ } ,
870+ b. waffle_func . arg_pool . from_iter ( args. iter ( ) . copied ( ) ) ,
871+ b. waffle_func . type_pool . from_iter ( [ ] . into_iter ( ) ) ,
872+ ) ;
873+ let copy = b. waffle_func . add_value ( copy) ;
874+ b. waffle_func . append_to_block ( b. block_map [ & block] , copy) ;
875+
876+ b. waffle_func . values [ ret_val] =
877+ waffle:: ValueDef :: Alias ( args[ 0 ] ) ;
783878 }
879+ ExternalName :: LibCall ( LibCall :: Memset ) => {
880+ let block = b. clif_func . layout . inst_block ( inst) . unwrap ( ) ;
881+
882+ let args = b
883+ . clif_func
884+ . dfg
885+ . inst_args ( inst)
886+ . into_iter ( )
887+ . map ( |& arg| b. get_value ( arg) )
888+ . collect :: < Vec < _ > > ( ) ;
889+
890+ let ret_val =
891+ b. get_value ( b. clif_func . dfg . inst_results ( inst) [ 0 ] ) ;
892+
893+ let copy = waffle:: ValueDef :: Operator (
894+ waffle:: Operator :: MemoryFill { mem : self . main_memory } ,
895+ b. waffle_func . arg_pool . from_iter ( args. iter ( ) . copied ( ) ) ,
896+ b. waffle_func . type_pool . from_iter ( [ ] . into_iter ( ) ) ,
897+ ) ;
898+ let copy = b. waffle_func . add_value ( copy) ;
899+ b. waffle_func . append_to_block ( b. block_map [ & block] , copy) ;
900+
901+ b. waffle_func . values [ ret_val] =
902+ waffle:: ValueDef :: Alias ( args[ 0 ] ) ;
903+ }
904+ ExternalName :: LibCall ( _libcall) => todo ! ( ) ,
905+ ExternalName :: KnownSymbol ( _ks) => todo ! ( ) ,
784906 }
785- _ => unreachable ! ( ) ,
786- } ;
787-
788- b. emit ( inst, waffle:: Operator :: Call {
789- function_index : self . func_ids [ & func_id] ,
790- } ) ;
791- }
907+ }
908+ _ => unreachable ! ( ) ,
909+ } ,
792910 Opcode :: Jump => {
793911 let target_block = ctx. func . dfg . insts [ inst]
794912 . branch_destination ( & ctx. func . dfg . jump_tables ) [ 0 ] ;
@@ -862,6 +980,9 @@ impl Module for WasmModule {
862980 ) -> cranelift_module:: ModuleResult < ( ) > {
863981 let global = self . data_ids [ & data_id] ;
864982
983+ let align = data. align . unwrap_or ( 1 ) ;
984+ self . next_data_offset = ( self . next_data_offset + align - 1 ) & !( align - 1 ) ;
985+
865986 match & data. init {
866987 cranelift_module:: Init :: Uninitialized => unreachable ! ( ) ,
867988 cranelift_module:: Init :: Zeros { size : _ } => { }
0 commit comments