@@ -9,6 +9,53 @@ use crate::{OperandStack, lower::NativePtr};
99
1010/// Allocation
1111impl OpEmitter < ' _ > {
12+ /// Emit the loop header for a counted `while.true` loop.
13+ ///
14+ /// The caller provides the `dup` instruction needed to bring `count` to the top of the stack
15+ /// after the loop index has been seeded with zero.
16+ ///
17+ /// Stack transition:
18+ ///
19+ /// - Before: `[loop_state..]`
20+ /// - After: `[count > 0, i = 0, loop_state..]`
21+ ///
22+ /// For example:
23+ ///
24+ /// - `memset`: `[dst, count, value..] -> [count > 0, i = 0, dst, count, value..]`
25+ /// - `memcpy`: `[src, dst, count] -> [count > 0, i = 0, src, dst, count]`
26+ fn emit_counted_loop_header ( & mut self , count_dup : masm:: Instruction , span : SourceSpan ) {
27+ self . emit_push ( 0u32 , span) ;
28+ self . emit ( count_dup, span) ;
29+ self . emit_push ( 0u32 , span) ;
30+ self . emit ( masm:: Instruction :: U32Gt , span) ;
31+ }
32+
33+ /// Emit the loop back-edge condition for a counted `while.true` loop.
34+ ///
35+ /// The caller provides the `dup` instruction needed to bring `count` to the top of the stack
36+ /// after incrementing the loop index.
37+ ///
38+ /// Stack transition:
39+ ///
40+ /// - Before: `[i, loop_state..]`
41+ /// - After: `[i + 1 < count, i + 1, loop_state..]`
42+ ///
43+ /// For example:
44+ ///
45+ /// - `memset`: `[i, dst, count, value..] -> [i + 1 < count, i + 1, dst, count, value..]`
46+ /// - `memcpy`: `[i, src, dst, count] -> [i + 1 < count, i + 1, src, dst, count]`
47+ fn emit_counted_loop_next_condition ( & mut self , count_dup : masm:: Instruction , span : SourceSpan ) {
48+ self . emit_all (
49+ [
50+ masm:: Instruction :: U32WrappingAddImm ( 1 . into ( ) ) ,
51+ masm:: Instruction :: Dup0 ,
52+ count_dup,
53+ masm:: Instruction :: U32Lt ,
54+ ] ,
55+ span,
56+ ) ;
57+ }
58+
1259 /// Grow the heap (from the perspective of Wasm programs) by N pages, returning the previous
1360 /// size of the heap (in pages) if successful, or -1 if the heap could not be grown.
1461 pub fn mem_grow ( & mut self , span : SourceSpan ) {
@@ -651,27 +698,15 @@ impl OpEmitter<'_> {
651698 body_emitter. store ( span) ; // [i, dst, count, value]
652699
653700 // Loop body - increment iteration count, determine whether to continue loop
654- body_emitter. emit_all (
655- [
656- masm:: Instruction :: U32WrappingAddImm ( 1 . into ( ) ) ,
657- masm:: Instruction :: Dup0 , // [i++, i++, dst, count, value]
658- masm:: Instruction :: Dup3 , // [count, i++, i++, dst, count, value]
659- masm:: Instruction :: U32Lt , // [i++ < count, i++, dst, count, value]
660- ] ,
661- span,
662- ) ;
701+ body_emitter. emit_counted_loop_next_condition ( masm:: Instruction :: Dup3 , span) ;
702+ // [i++ < count, i++, dst, count, value]
663703
664704 // Switch back to original block and emit loop header and 'while.true' instruction
665705 //
666706 // Loop header - prepare to loop until `count` iterations have been performed
667707 // [dst, count, value..]
668- self . emit_push ( 0u32 , span) ; // [i, dst, count, value..]
669- self . emit ( masm:: Instruction :: Dup2 , span) ; // [count, i, dst, count, value..]
670- self . emit_push ( 0u32 , span) ;
671- self . emit (
672- masm:: Instruction :: U32Gt , // [count > 0, i, dst, count, value..]
673- span,
674- ) ;
708+ self . emit_counted_loop_header ( masm:: Instruction :: Dup2 , span) ;
709+ // [count > 0, i, dst, count, value..]
675710 self . current_block . push ( masm:: Op :: While {
676711 span,
677712 body : masm:: Block :: new ( span, body) ,
@@ -897,28 +932,16 @@ impl OpEmitter<'_> {
897932 body_emitter. store ( span) ; // [i, src, dst, count]
898933
899934 // Increment iteration count, determine whether to continue loop
900- body_emitter. emit_all (
901- [
902- masm:: Instruction :: U32WrappingAddImm ( 1 . into ( ) ) ,
903- masm:: Instruction :: Dup0 , // [i++, i++, src, dst, count]
904- masm:: Instruction :: Dup4 , // [count, i++, i++, src, dst, count]
905- masm:: Instruction :: U32Lt , // [i++ < count, i++, src, dst, count]
906- ] ,
907- span,
908- ) ;
935+ body_emitter. emit_counted_loop_next_condition ( masm:: Instruction :: Dup4 , span) ;
936+ // [i++ < count, i++, src, dst, count]
909937
910938 // Switch back to original block and emit loop header and 'while.true' instruction
911939 //
912940 // Loop header - prepare to loop until `count` iterations have been performed
913941
914942 // [src, dst, count]
915- self . emit_push ( 0u32 , span) ; // [i, src, dst, count]
916- self . emit ( masm:: Instruction :: Dup3 , span) ; // [count, i, src, dst, count]
917- self . emit_push ( 0u32 , span) ;
918- self . emit (
919- masm:: Instruction :: U32Gt , // [count > 0, i, src, dst, count]
920- span,
921- ) ;
943+ self . emit_counted_loop_header ( masm:: Instruction :: Dup3 , span) ;
944+ // [count > 0, i, src, dst, count]
922945 self . current_block . push ( masm:: Op :: While {
923946 span,
924947 body : masm:: Block :: new ( span, body) ,
0 commit comments