| 15334 | } |
| 15335 | |
| 15336 | int asCCompiler::MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectType *objectType, asCArray<asCExprContext*> &args, asCScriptNode *node, bool useVariable, int stackOffset, int funcPtrVar) |
| 15337 | { |
| 15338 | if( objectType ) |
| 15339 | Dereference(ctx, true); |
| 15340 | |
| 15341 | asCScriptFunction* descr = builder->GetFunctionDescription(funcId); |
| 15342 | |
| 15343 | // Store the expression node for error reporting |
| 15344 | if( ctx->exprNode == 0 ) |
| 15345 | ctx->exprNode = node; |
| 15346 | |
| 15347 | asCByteCode objBC(engine); |
| 15348 | objBC.AddCode(&ctx->bc); |
| 15349 | |
| 15350 | int r = PrepareFunctionCall(funcId, &ctx->bc, args); |
| 15351 | if (r < 0) |
| 15352 | return r; |
| 15353 | |
| 15354 | if (descr->IsVariadic()) |
| 15355 | { |
| 15356 | // Argument count |
| 15357 | ctx->bc.InstrDWORD(asBC_PshC4, (asDWORD)args.GetLength()); |
| 15358 | } |
| 15359 | |
| 15360 | // Verify if any of the args variable offsets are used in the other code. |
| 15361 | // If they are exchange the offset for a new one |
| 15362 | asUINT n; |
| 15363 | for( n = 0; n < args.GetLength(); n++ ) |
| 15364 | { |
| 15365 | if( args[n]->type.isTemporary && objBC.IsVarUsed(args[n]->type.stackOffset) ) |
| 15366 | { |
| 15367 | // Release the current temporary variable |
| 15368 | ReleaseTemporaryVariable(args[n]->type, 0); |
| 15369 | |
| 15370 | asCDataType dt = args[n]->type.dataType; |
| 15371 | dt.MakeReference(false); |
| 15372 | |
| 15373 | int l = int(reservedVariables.GetLength()); |
| 15374 | objBC.GetVarsUsed(reservedVariables); |
| 15375 | ctx->bc.GetVarsUsed(reservedVariables); |
| 15376 | int newOffset = AllocateVariable(dt, true, IsVariableOnHeap(args[n]->type.stackOffset)); |
| 15377 | reservedVariables.SetLength(l); |
| 15378 | |
| 15379 | asASSERT( IsVariableOnHeap(args[n]->type.stackOffset) == IsVariableOnHeap(newOffset) ); |
| 15380 | |
| 15381 | ctx->bc.ExchangeVar(args[n]->type.stackOffset, newOffset); |
| 15382 | args[n]->type.stackOffset = (short)newOffset; |
| 15383 | args[n]->type.isTemporary = true; |
| 15384 | args[n]->type.isVariable = true; |
| 15385 | } |
| 15386 | } |
| 15387 | |
| 15388 | // If the function will return a value type on the stack, then we must allocate space |
| 15389 | // for that here and push the address on the stack as a hidden argument to the function |
| 15390 | asCScriptFunction *func = builder->GetFunctionDescription(funcId); |
| 15391 | if( func->DoesReturnOnStack() ) |
| 15392 | { |
| 15393 | asASSERT(!useVariable); |
nothing calls this directly
no test coverage detected