| 90 | asQWORD GetReturnedDouble(); |
| 91 | |
| 92 | asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/, void *secondObject) |
| 93 | { |
| 94 | asCScriptEngine *engine = context->m_engine; |
| 95 | asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf; |
| 96 | |
| 97 | asQWORD retQW = 0; |
| 98 | |
| 99 | // Prepare the parameters |
| 100 | asDWORD paramBuffer[64]; |
| 101 | int callConv = sysFunc->callConv; |
| 102 | |
| 103 | // Changed because need check for ICC_THISCALL_OBJFIRST or |
| 104 | // ICC_THISCALL_OBJLAST if sysFunc->takesObjByVal (avoid copy code) |
| 105 | // Check if is THISCALL_OBJ* calling convention (in this case needs to add secondObject pointer into stack). |
| 106 | bool isThisCallMethod = callConv >= ICC_THISCALL_OBJLAST; |
| 107 | int paramSize = isThisCallMethod || sysFunc->takesObjByVal ? 0 : sysFunc->paramSize; |
| 108 | |
| 109 | int dpos = 1; |
| 110 | |
| 111 | if( isThisCallMethod && |
| 112 | (callConv >= ICC_THISCALL_OBJFIRST && |
| 113 | callConv <= ICC_VIRTUAL_THISCALL_OBJFIRST_RETURNINMEM) ) |
| 114 | { |
| 115 | // Add the object pointer as the first parameter |
| 116 | paramBuffer[dpos++] = (asDWORD)secondObject; |
| 117 | paramSize++; |
| 118 | } |
| 119 | |
| 120 | if( sysFunc->takesObjByVal || isThisCallMethod ) |
| 121 | { |
| 122 | int spos = 0; |
| 123 | |
| 124 | for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ ) |
| 125 | { |
| 126 | if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() ) |
| 127 | { |
| 128 | #ifdef COMPLEX_OBJS_PASSED_BY_REF |
| 129 | if( descr->parameterTypes[n].GetTypeInfo()->flags & COMPLEX_MASK ) |
| 130 | { |
| 131 | paramBuffer[dpos++] = args[spos++]; |
| 132 | paramSize++; |
| 133 | } |
| 134 | else |
| 135 | #endif |
| 136 | { |
| 137 | // Copy the object's memory to the buffer |
| 138 | // TODO: bug: Must call the object's copy constructor instead of doing a memcpy, |
| 139 | // as the object may hold a pointer to itself. It's not enough to |
| 140 | // change only this memcpy as the assembler routine also makes a copy |
| 141 | // of paramBuffer to the final stack location. To avoid the second |
| 142 | // copy the C++ routine should point paramBuffer to the final stack |
| 143 | // position and copy the values directly to that location. The assembler |
| 144 | // routines then don't need to copy anything, and will just be |
| 145 | // responsible for setting up the registers and the stack frame appropriately. |
| 146 | memcpy(¶mBuffer[dpos], *(void**)(args+spos), descr->parameterTypes[n].GetSizeInMemoryBytes()); |
| 147 | |
| 148 | // Delete the original memory |
| 149 | engine->CallFree(*(char**)(args+spos)); |
no test coverage detected