@@ -403,7 +403,41 @@ struct Compiler
403403
404404        setDebugLine (expr); //  normally compileExpr sets up line info, but compileExprVarargs can be called directly
405405
406-         bytecode.emitABC (LOP_GETVARARGS, target, multRet ? 0  : uint8_t (targetCount + 1 ), 0 );
406+         /* 
407+         bool doVararg = true; 
408+         if (inlineFrames.size() > 0) 
409+         { 
410+             bool foundArg = false; 
411+ 
412+             for (AstNode* arg : inlineFrames.back().call->args) 
413+                 if (arg == expr) 
414+                 { 
415+                     foundArg = true; 
416+                     break; 
417+                 } 
418+ 
419+             if (!foundArg) 
420+                 doVararg = false; 
421+         } 
422+         */  
423+ 
424+         if  (inlineFrames.size () == 0 )
425+             bytecode.emitABC (LOP_GETVARARGS, target, multRet ? 0  : uint8_t (targetCount + 1 ), 0 );
426+         else 
427+         {
428+             const  InlineFrame& frame = inlineFrames.back ();
429+             LUAU_ASSERT (frame.call );
430+ 
431+             //  we need to compile the arguments themselves instead of a vararg
432+ 
433+             for  (size_t  index = 0 ; index < frame.call ->args .size ; index++)
434+             {
435+                 AstExpr* arg = frame.call ->args .data [index]->asExpr ();
436+                 LUAU_ASSERT (arg);
437+ 
438+                 compileExpr (arg, target + index);
439+             }
440+         }
407441    }
408442
409443    void  compileExprSelectVararg (AstExprCall* expr, uint8_t  target, uint8_t  targetCount, bool  targetTop, bool  multRet, uint8_t  regs)
@@ -590,12 +624,18 @@ struct Compiler
590624        //  - additionally, we can't easily compile multret expressions into designated target as computed call arguments will get clobbered
591625        if  (multRet)
592626        {
593-             bytecode.addDebugRemark (" inlining failed: can't convert fixed returns  to multret "  );
627+             bytecode.addDebugRemark (" inlining failed: can't convert multret  to fixed returns "  );
594628            return  false ;
595629        }
596630
597631        if  (func->vararg )
598632        {
633+             if  (func->args .size  > expr->args .size )
634+             {
635+                 bytecode.addDebugRemark (" inlining failed: not enough arguments"  );
636+                 return  false ;
637+             }
638+ 
599639            for  (AstExpr* arg : expr->args )
600640            {
601641                if  (isExprMultRet (arg))
@@ -743,7 +783,7 @@ struct Compiler
743783        }
744784
745785        //  the inline frame will be used to compile return statements as well as to reject recursive inlining attempts
746-         inlineFrames.push_back ({func, oldLocals, target, targetCount});
786+         inlineFrames.push_back ({func, expr,  oldLocals, target, targetCount});
747787
748788        //  fold constant values updated above into expressions in the function body
749789        foldConstants (constants, variables, locstants, builtinsFold, builtinsFoldLibraryK, options.libraryMemberConstantCb , func->body , names);
@@ -989,7 +1029,7 @@ struct Compiler
9891029                CompileError::raise (expr->func ->location , " Exceeded jump distance limit; simplify the code to compile"  );
9901030        }
9911031
992-         bytecode.emitABC (LOP_CALL, regs, multCall ? 0  : uint8_t (expr->self  + expr->args .size  + 1 ), multRet ? 0  : uint8_t (targetCount + 1 ));
1032+         bytecode.emitABC (LOP_CALL, regs, ( multCall && inlineFrames. size () ==  0 )  ? 0  : uint8_t (expr->self  + expr->args .size  + 1 ), multRet ? 0  : uint8_t (targetCount + 1 ));
9931033
9941034        //  if we didn't output results directly to target, we need to move them
9951035        if  (!targetTop)
@@ -4136,6 +4176,7 @@ struct Compiler
41364176    struct  InlineFrame 
41374177    {
41384178        AstExprFunction* func;
4179+         AstExprCall* call;
41394180
41404181        size_t  localOffset;
41414182
0 commit comments