@@ -7079,36 +7079,48 @@ export class Compiler extends DiagnosticEmitter {
70797079 }
70807080 }
70817081
7082+ let allTrivial = ( getSideEffects ( functionArg , module . ref ) & SideEffects . WritesGlobal ) == 0 ;
7083+ if ( operands && allTrivial ) {
7084+ for ( let i = 0 ; i < numOperands ; ++ i ) {
7085+ if ( ! module . isTrivialExpression ( operands [ i ] ) ) {
7086+ allTrivial = false ;
7087+ break ;
7088+ }
7089+ }
7090+ }
7091+
7092+ let stmts = new Array < ExpressionRef > ( ) ;
7093+ let sizeTypeRef = this . options . sizeTypeRef ;
7094+
7095+ if ( ! allTrivial ) {
7096+ let functionArgLocal = this . currentFlow . getTempLocal ( this . options . usizeType ) ;
7097+ let functionArgSetExpr = module . local_set ( functionArgLocal . index , functionArg , true ) ;
7098+ stmts . push ( functionArgSetExpr ) ;
7099+ functionArg = module . local_get ( functionArgLocal . index , sizeTypeRef ) ;
7100+ }
7101+
70827102 // We might be calling a varargs stub here, even if all operands have been
70837103 // provided, so we must set `argumentsLength` in any case. Inject setting it
70847104 // into the index argument, which becomes executed last after any operands.
70857105 let argumentsLength = this . ensureArgumentsLength ( ) ;
7086- let sizeTypeRef = this . options . sizeTypeRef ;
7087- if ( getSideEffects ( functionArg , module . ref ) & SideEffects . WritesGlobal ) {
7088- let flow = this . currentFlow ;
7089- let temp = flow . getTempLocal ( this . options . usizeType ) ;
7090- let tempIndex = temp . index ;
7091- functionArg = module . block ( null , [
7092- module . local_set ( tempIndex , functionArg , true ) , // Function
7093- module . global_set ( argumentsLength , module . i32 ( numArguments ) ) ,
7094- module . local_get ( tempIndex , sizeTypeRef )
7095- ] , sizeTypeRef ) ;
7096- } else { // simplify
7097- functionArg = module . block ( null , [
7098- module . global_set ( argumentsLength , module . i32 ( numArguments ) ) ,
7099- functionArg
7100- ] , sizeTypeRef ) ;
7101- }
7106+
7107+
7108+ let functionArgWithVararg = module . block ( null , [
7109+ module . global_set ( argumentsLength , module . i32 ( numArguments ) ) ,
7110+ functionArg
7111+ ] , sizeTypeRef ) ;
7112+
71027113 if ( operands ) this . operandsTostack ( signature , operands ) ;
71037114 let expr = module . call_indirect (
71047115 null , // TODO: handle multiple tables
7105- module . load ( 4 , false , functionArg , TypeRef . I32 ) , // ._index
7116+ module . load ( 4 , false , functionArgWithVararg , TypeRef . I32 ) , // ._index
71067117 operands ,
71077118 signature . paramRefs ,
71087119 signature . resultRefs
71097120 ) ;
71107121 this . currentType = returnType ;
7111- return expr ;
7122+ stmts . push ( expr ) ;
7123+ return module . flatten ( stmts , returnType . toRef ( ) ) ;
71127124 }
71137125
71147126 private compileCommaExpression (
0 commit comments