interface
| 6402 | |
| 6403 | // interface |
| 6404 | int asCContext::GetArgOnStack(asUINT stackLevel, asUINT arg, int* outTypeId, asUINT* outFlags, void** outAddress) |
| 6405 | { |
| 6406 | // Don't return anything if there is no bytecode, e.g. before calling Execute() |
| 6407 | if (m_regs.programPointer == 0) return asERROR; |
| 6408 | |
| 6409 | if (stackLevel >= GetCallstackSize()) return asINVALID_ARG; |
| 6410 | |
| 6411 | asCScriptFunction* func; |
| 6412 | asDWORD* sp; |
| 6413 | asDWORD* progPointer; |
| 6414 | if (stackLevel == 0) |
| 6415 | { |
| 6416 | func = m_currentFunction; |
| 6417 | sp = m_regs.stackPointer; |
| 6418 | progPointer = m_regs.programPointer; |
| 6419 | } |
| 6420 | else |
| 6421 | { |
| 6422 | asPWORD* s = m_callStack.AddressOf() + (GetCallstackSize() - stackLevel - 1) * CALLSTACK_FRAME_SIZE; |
| 6423 | func = (asCScriptFunction*)s[1]; |
| 6424 | sp = (asDWORD*)s[3]; |
| 6425 | progPointer = (asDWORD*)s[2]; |
| 6426 | } |
| 6427 | |
| 6428 | // If a function is already being called at a higher call stack position, subtract the args for that function |
| 6429 | asCScriptFunction* calledFunc = 0; |
| 6430 | if (stackLevel == 1) |
| 6431 | calledFunc = m_currentFunction; |
| 6432 | else if (stackLevel > 1) |
| 6433 | { |
| 6434 | asPWORD* s = m_callStack.AddressOf() + (GetCallstackSize() - stackLevel - 2) * CALLSTACK_FRAME_SIZE; |
| 6435 | calledFunc = (asCScriptFunction*)s[1]; |
| 6436 | } |
| 6437 | if (calledFunc) |
| 6438 | sp += calledFunc->GetSpaceNeededForArguments() + (calledFunc->DoesReturnOnStack() ? AS_PTR_SIZE : 0) + (calledFunc->GetObjectType() ? AS_PTR_SIZE : 0); |
| 6439 | |
| 6440 | // Check that the cache for GetArgsOnStack is up-to-date |
| 6441 | if (m_argsOnStackCacheFunc != func || m_argsOnStackCacheProgPos != asUINT(progPointer - &func->scriptData->byteCode[0])) |
| 6442 | GetArgsOnStackCount(stackLevel); |
| 6443 | |
| 6444 | // The arg types in the array are stored from top to bottom, so we'll go through them in the inverse order |
| 6445 | // TODO: Check that arg is not too high |
| 6446 | arg = m_argsOnStackCache.GetLength() / 2 - arg - 1; |
| 6447 | asUINT stackDelta = 0; |
| 6448 | for (asUINT n = 0; n < arg; n++) |
| 6449 | { |
| 6450 | int typeId = m_argsOnStackCache[n * 2]; |
| 6451 | asUINT flags = m_argsOnStackCache[n * 2 + 1]; |
| 6452 | |
| 6453 | if ((flags & asTM_INOUTREF) || (typeId & asTYPEID_MASK_OBJECT)) |
| 6454 | stackDelta += AS_PTR_SIZE; |
| 6455 | else if (typeId == asTYPEID_UINT64 || typeId == asTYPEID_INT64 || typeId == asTYPEID_DOUBLE) |
| 6456 | stackDelta += 2; |
| 6457 | else |
| 6458 | stackDelta += 1; |
| 6459 | } |
| 6460 | |
| 6461 | if (outAddress) *outAddress = sp + stackDelta; |