PageRenderTime 38ms CodeModel.GetById 9ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/visualizations/Vortex/angelscript/angelscript/source/as_callfunc_arm.cpp

http://github.com/xbmc/xbmc
C++ | 344 lines | 233 code | 36 blank | 75 comment | 49 complexity | 9a1568b6b283860a160adf76109446d5 MD5 | raw file
  1/*
  2   AngelCode Scripting Library
  3   Copyright (c) 2003-2009 Andreas Jonsson
  4
  5   This software is provided 'as-is', without any express or implied
  6   warranty. In no event will the authors be held liable for any
  7   damages arising from the use of this software.
  8
  9   Permission is granted to anyone to use this software for any
 10   purpose, including commercial applications, and to alter it and
 11   redistribute it freely, subject to the following restrictions:
 12
 13   1. The origin of this software must not be misrepresented; you
 14      must not claim that you wrote the original software. If you use
 15      this software in a product, an acknowledgment in the product
 16      documentation would be appreciated but is not required.
 17
 18   2. Altered source versions must be plainly marked as such, and
 19      must not be misrepresented as being the original software.
 20
 21   3. This notice may not be removed or altered from any source
 22      distribution.
 23
 24   The original version of this library can be located at:
 25   http://www.angelcode.com/angelscript/
 26
 27   Andreas Jonsson
 28   andreas@angelcode.com
 29*/
 30
 31
 32//
 33// as_callfunc_arm.cpp
 34//
 35// These functions handle the actual calling of system functions on the arm platform
 36//
 37// Written by Fredrik Ehnbom in June 2009, based on as_callfunc_x86.cpp
 38
 39
 40#include "as_config.h"
 41
 42#ifndef AS_MAX_PORTABILITY
 43#ifdef AS_ARM
 44
 45#include "as_callfunc.h"
 46#include "as_scriptengine.h"
 47#include "as_texts.h"
 48#include "as_tokendef.h"
 49
 50BEGIN_AS_NAMESPACE
 51
 52extern "C" asQWORD armFunc(const asDWORD *, int, size_t);
 53extern "C" asQWORD armFuncR0(const asDWORD *, int, size_t, asDWORD r0);
 54extern "C" asQWORD armFuncR0R1(const asDWORD *, int, size_t, asDWORD r0, asDWORD r1);
 55extern "C" asQWORD armFuncObjLast(const asDWORD *, int, size_t, asDWORD obj);
 56extern "C" asQWORD armFuncR0ObjLast(const asDWORD *, int, size_t, asDWORD r0, asDWORD obj);
 57
 58// TODO: CallSystemFunction should be split in two layers. The top layer
 59//       implements the parts that are common to all system functions,
 60//       e.g. the check for generic calling convention, the extraction of the
 61//       object pointer, the processing of auto handles, and the pop size.
 62//       Remember that the proper handling of auto handles is implemented in
 63//       as_callfunc_x64_gcc.cpp as that code can handle both 32bit and 64bit pointers.
 64//
 65//       The lower layer implemented in CallNativeSystemFunction will then
 66//       be responsible for just transforming the parameters to the native
 67//       calling convention.
 68//
 69//       This should be done for all supported platforms.
 70int CallSystemFunction(int id, asCContext *context, void *objectPointer)
 71{
 72	asCScriptEngine *engine = context->engine;
 73	asCScriptFunction *descr = engine->scriptFunctions[id];
 74	asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
 75	int callConv = sysFunc->callConv;
 76	if( callConv == ICC_GENERIC_FUNC || callConv == ICC_GENERIC_METHOD )
 77		return context->CallGeneric(id, objectPointer);
 78
 79	asQWORD  retQW             = 0;
 80	void    *func              = (void*)sysFunc->func;
 81	int      paramSize         = sysFunc->paramSize;
 82	asDWORD *args              = context->regs.stackPointer;
 83	void    *retPointer        = 0;
 84	void    *obj               = 0;
 85	asDWORD *vftable;
 86	int      popSize           = paramSize;
 87
 88	context->regs.objectType = descr->returnType.GetObjectType();
 89	if( descr->returnType.IsObject() && !descr->returnType.IsReference() && !descr->returnType.IsObjectHandle() )
 90	{
 91		// Allocate the memory for the object
 92		retPointer = engine->CallAlloc(descr->returnType.GetObjectType());
 93
 94		if( sysFunc->hostReturnInMemory )
 95		{
 96			// The return is made in memory
 97			callConv++;
 98		}
 99	}
100
101	if( callConv >= ICC_THISCALL )
102	{
103		if( objectPointer )
104		{
105			obj = objectPointer;
106		}
107		else
108		{
109			// The object pointer should be popped from the context stack
110			popSize++;
111
112			// Check for null pointer
113			obj = (void*)*(size_t*)(args);
114			if( obj == 0 )
115			{
116				context->SetInternalException(TXT_NULL_POINTER_ACCESS);
117				if( retPointer )
118					engine->CallFree(retPointer);
119				return 0;
120			}
121
122			// Add the base offset for multiple inheritance
123#ifdef __GNUC__
124			// On GNUC + ARM the lsb of the offset is used to indicate a virtual function
125			// and the whole offset is thus shifted one bit left to keep the original
126			// offset resolution
127			obj = (void*)(size_t(obj) + (sysFunc->baseOffset>>1));
128#else
129			obj = (void*)(size_t(obj) + sysFunc->baseOffset);
130#endif
131
132			// Skip the object pointer
133			args++;
134		}
135	}
136
137	asDWORD paramBuffer[64];
138	if( sysFunc->takesObjByVal )
139	{
140		paramSize = 0;
141		int spos = 0;
142		int dpos = 1;
143		for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
144		{
145            if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
146			{
147#ifdef COMPLEX_OBJS_PASSED_BY_REF
148				if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK )
149				{
150					paramBuffer[dpos++] = args[spos++];
151					paramSize++;
152				}
153				else
154#endif
155				{
156					// Copy the object's memory to the buffer
157					memcpy(&paramBuffer[dpos], *(void**)(args+spos), descr->parameterTypes[n].GetSizeInMemoryBytes());
158
159					// Delete the original memory
160					engine->CallFree(*(char**)(args+spos));
161					spos++;
162					dpos += descr->parameterTypes[n].GetSizeInMemoryDWords();
163					paramSize += descr->parameterTypes[n].GetSizeInMemoryDWords();
164				}
165			}
166			else
167			{
168				// Copy the value directly
169				paramBuffer[dpos++] = args[spos++];
170				if( descr->parameterTypes[n].GetSizeOnStackDWords() > 1 )
171					paramBuffer[dpos++] = args[spos++];
172				paramSize += descr->parameterTypes[n].GetSizeOnStackDWords();
173			}
174		}
175		// Keep a free location at the beginning
176		args = &paramBuffer[1];
177	}
178
179	context->isCallingSystemFunction = true;
180
181	switch( callConv )
182	{
183	case ICC_CDECL_RETURNINMEM:     // fall through
184	case ICC_STDCALL_RETURNINMEM:
185        retQW = armFuncR0(args, paramSize<<2, (asDWORD)func, (asDWORD) retPointer);
186        break;
187    case ICC_CDECL:     // fall through
188    case ICC_STDCALL:
189		retQW = armFunc(args, paramSize<<2, (asDWORD)func);
190		break;
191    case ICC_THISCALL:  // fall through
192	case ICC_CDECL_OBJFIRST:
193        retQW = armFuncR0(args, paramSize<<2, (asDWORD)func, (asDWORD) obj);
194        break;
195    case ICC_THISCALL_RETURNINMEM:
196#ifndef __GNUC__
197        retQW = armFuncR0R1(args, paramSize<<2, (asDWORD)func, (asDWORD) obj, (asDWORD) retPointer);
198		break;
199#endif
200    case ICC_CDECL_OBJFIRST_RETURNINMEM:
201        retQW = armFuncR0R1(args, paramSize<<2, (asDWORD)func, (asDWORD) retPointer, (asDWORD) obj);
202		break;
203	case ICC_VIRTUAL_THISCALL:
204		// Get virtual function table from the object pointer
205		vftable = *(asDWORD**)obj;
206        retQW = armFuncR0(args, paramSize<<2, vftable[asDWORD(func)>>2], (asDWORD) obj);
207        break;
208    case ICC_VIRTUAL_THISCALL_RETURNINMEM:
209		// Get virtual function table from the object pointer
210		vftable = *(asDWORD**)obj;
211#ifndef __GNUC__
212        retQW = armFuncR0R1(args, (paramSize+1)<<2, vftable[asDWORD(func)>>2], (asDWORD) retPointer, (asDWORD) obj);
213#else
214        retQW = armFuncR0R1(args, (paramSize+1)<<2, vftable[asDWORD(func)>>2], (asDWORD) obj, (asDWORD) retPointer);
215#endif
216		break;
217	case ICC_CDECL_OBJLAST:
218		retQW = armFuncObjLast(args, paramSize<<2, (asDWORD)func, (asDWORD) obj);
219        break;
220    case ICC_CDECL_OBJLAST_RETURNINMEM:
221		retQW = armFuncR0ObjLast(args, paramSize<<2, (asDWORD)func, (asDWORD) retPointer, (asDWORD) obj);
222		break;
223	default:
224		context->SetInternalException(TXT_INVALID_CALLING_CONVENTION);
225	}
226	context->isCallingSystemFunction = false;
227#ifdef COMPLEX_OBJS_PASSED_BY_REF
228	if( sysFunc->takesObjByVal )
229	{
230		// Need to free the complex objects passed by value
231		args = context->regs.stackPointer;
232		if( callConv >= ICC_THISCALL && !objectPointer )
233		    args++;
234
235		int spos = 0;
236		for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
237		{
238			if( descr->parameterTypes[n].IsObject() &&
239				!descr->parameterTypes[n].IsReference() &&
240                !descr->parameterTypes[n].IsObjectHandle()
241                )
242            {
243                if (descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK)
244                {
245			        void *obj = (void*)args[spos++];
246
247                    // Running the destructor here results in the destructor being 
248                    // run twice as it has already been called in the native function.
249                    // TODO: Should this be an ifdef or removed completely?
250//			        asSTypeBehaviour *beh = &descr->parameterTypes[n].GetObjectType()->beh;
251//			        if( beh->destruct )
252//				        engine->CallObjectMethod(obj, beh->destruct);
253
254			        engine->CallFree(obj);
255                }
256                else
257                {
258                    // The original data was already freed earlier
259                    spos += descr->parameterTypes[n].GetSizeInMemoryDWords();
260                }
261            }
262		    else
263            {
264			    spos += descr->parameterTypes[n].GetSizeOnStackDWords();
265            }
266        }
267	}
268#endif
269
270	// Store the returned value in our stack
271	if( descr->returnType.IsObject() && !descr->returnType.IsReference() )
272	{
273		if( descr->returnType.IsObjectHandle() )
274		{
275			context->regs.objectRegister = (void*)(size_t)retQW;
276
277			if( sysFunc->returnAutoHandle && context->regs.objectRegister )
278				engine->CallObjectMethod(context->regs.objectRegister, descr->returnType.GetObjectType()->beh.addref);
279		}
280		else
281		{
282			if( !sysFunc->hostReturnInMemory )
283			{
284				// Copy the returned value to the pointer sent by the script engine
285				if( sysFunc->hostReturnSize == 1 )
286					*(asDWORD*)retPointer = (asDWORD)retQW;
287				else
288					*(asQWORD*)retPointer = retQW;
289			}
290
291			// Store the object in the register
292			context->regs.objectRegister = retPointer;
293		}
294	}
295	else
296	{
297		// Store value in valueRegister
298		if( sysFunc->hostReturnFloat )
299		{
300			if( sysFunc->hostReturnSize == 1 )
301				*(asDWORD*)&context->regs.valueRegister = (asDWORD) retQW;
302			else
303				context->regs.valueRegister = retQW;
304		}
305		else if( sysFunc->hostReturnSize == 1 )
306			*(asDWORD*)&context->regs.valueRegister = (asDWORD)retQW;
307		else
308			context->regs.valueRegister = retQW;
309	}
310
311	if( sysFunc->hasAutoHandles )
312	{
313		args = context->regs.stackPointer;
314		if( callConv >= ICC_THISCALL && !objectPointer )
315			args++;
316
317		int spos = 0;
318		for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
319		{
320			if( sysFunc->paramAutoHandles[n] && args[spos] )
321			{
322				// Call the release method on the type
323				engine->CallObjectMethod((void*)*(size_t*)&args[spos], descr->parameterTypes[n].GetObjectType()->beh.release);
324				args[spos] = 0;
325			}
326
327			if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() && !descr->parameterTypes[n].IsReference() )
328				spos++;
329			else
330				spos += descr->parameterTypes[n].GetSizeOnStackDWords();
331		}
332	}
333
334	return popSize;
335}
336
337END_AS_NAMESPACE
338
339#endif // AS_ARM
340#endif // AS_MAX_PORTABILITY
341
342
343
344