as_generic.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2016 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_generic.cpp
  25. //
  26. // This class handles the call to a function registered with asCALL_GENERIC
  27. //
  28. #include "as_generic.h"
  29. #include "as_scriptfunction.h"
  30. #include "as_objecttype.h"
  31. #include "as_scriptengine.h"
  32. BEGIN_AS_NAMESPACE
  33. // TODO: runtime optimize: The access to the arguments should be optimized so that code
  34. // doesn't have to count the position of the argument with every call
  35. // internal
  36. asCGeneric::asCGeneric(asCScriptEngine *engine, asCScriptFunction *sysFunction, void *currentObject, asDWORD *stackPointer)
  37. {
  38. this->engine = engine;
  39. this->sysFunction = sysFunction;
  40. this->currentObject = currentObject;
  41. this->stackPointer = stackPointer;
  42. objectRegister = 0;
  43. returnVal = 0;
  44. }
  45. // internal
  46. asCGeneric::~asCGeneric()
  47. {
  48. }
  49. // interface
  50. void *asCGeneric::GetAuxiliary() const
  51. {
  52. return sysFunction->GetAuxiliary();
  53. }
  54. // interface
  55. asIScriptEngine *asCGeneric::GetEngine() const
  56. {
  57. return (asIScriptEngine*)engine;
  58. }
  59. // interface
  60. asIScriptFunction *asCGeneric::GetFunction() const
  61. {
  62. return sysFunction;
  63. }
  64. // interface
  65. void *asCGeneric::GetObject()
  66. {
  67. return currentObject;
  68. }
  69. // interface
  70. int asCGeneric::GetObjectTypeId() const
  71. {
  72. asCDataType dt = asCDataType::CreateType(sysFunction->objectType, false);
  73. return engine->GetTypeIdFromDataType(dt);
  74. }
  75. // interface
  76. int asCGeneric::GetArgCount() const
  77. {
  78. return (int)sysFunction->parameterTypes.GetLength();
  79. }
  80. // interface
  81. asBYTE asCGeneric::GetArgByte(asUINT arg)
  82. {
  83. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  84. return 0;
  85. // Verify that the type is correct
  86. asCDataType *dt = &sysFunction->parameterTypes[arg];
  87. if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() )
  88. return 0;
  89. if( dt->GetSizeInMemoryBytes() != 1 )
  90. return 0;
  91. // Determine the position of the argument
  92. int offset = 0;
  93. for( asUINT n = 0; n < arg; n++ )
  94. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  95. // Get the value
  96. return *(asBYTE*)&stackPointer[offset];
  97. }
  98. // interface
  99. asWORD asCGeneric::GetArgWord(asUINT arg)
  100. {
  101. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  102. return 0;
  103. // Verify that the type is correct
  104. asCDataType *dt = &sysFunction->parameterTypes[arg];
  105. if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() )
  106. return 0;
  107. if( dt->GetSizeInMemoryBytes() != 2 )
  108. return 0;
  109. // Determine the position of the argument
  110. int offset = 0;
  111. for( asUINT n = 0; n < arg; n++ )
  112. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  113. // Get the value
  114. return *(asWORD*)&stackPointer[offset];
  115. }
  116. // interface
  117. asDWORD asCGeneric::GetArgDWord(asUINT arg)
  118. {
  119. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  120. return 0;
  121. // Verify that the type is correct
  122. asCDataType *dt = &sysFunction->parameterTypes[arg];
  123. if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() )
  124. return 0;
  125. if( dt->GetSizeInMemoryBytes() != 4 )
  126. return 0;
  127. // Determine the position of the argument
  128. int offset = 0;
  129. for( asUINT n = 0; n < arg; n++ )
  130. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  131. // Get the value
  132. return *(asDWORD*)&stackPointer[offset];
  133. }
  134. // interface
  135. asQWORD asCGeneric::GetArgQWord(asUINT arg)
  136. {
  137. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  138. return 0;
  139. // Verify that the type is correct
  140. asCDataType *dt = &sysFunction->parameterTypes[arg];
  141. if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() )
  142. return 0;
  143. if( dt->GetSizeInMemoryBytes() != 8 )
  144. return 0;
  145. // Determine the position of the argument
  146. int offset = 0;
  147. for( asUINT n = 0; n < arg; n++ )
  148. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  149. // Get the value
  150. return *(asQWORD*)(&stackPointer[offset]);
  151. }
  152. // interface
  153. float asCGeneric::GetArgFloat(asUINT arg)
  154. {
  155. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  156. return 0;
  157. // Verify that the type is correct
  158. asCDataType *dt = &sysFunction->parameterTypes[arg];
  159. if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() )
  160. return 0;
  161. if( dt->GetSizeInMemoryBytes() != 4 )
  162. return 0;
  163. // Determine the position of the argument
  164. int offset = 0;
  165. for( asUINT n = 0; n < arg; n++ )
  166. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  167. // Get the value
  168. return *(float*)(&stackPointer[offset]);
  169. }
  170. // interface
  171. double asCGeneric::GetArgDouble(asUINT arg)
  172. {
  173. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  174. return 0;
  175. // Verify that the type is correct
  176. asCDataType *dt = &sysFunction->parameterTypes[arg];
  177. if( (dt->IsObject() || dt->IsFuncdef()) || dt->IsReference() )
  178. return 0;
  179. if( dt->GetSizeInMemoryBytes() != 8 )
  180. return 0;
  181. // Determine the position of the argument
  182. int offset = 0;
  183. for( asUINT n = 0; n < arg; n++ )
  184. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  185. // Get the value
  186. return *(double*)(&stackPointer[offset]);
  187. }
  188. // interface
  189. void *asCGeneric::GetArgAddress(asUINT arg)
  190. {
  191. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  192. return 0;
  193. // Verify that the type is correct
  194. asCDataType *dt = &sysFunction->parameterTypes[arg];
  195. if( !dt->IsReference() && !dt->IsObjectHandle() )
  196. return 0;
  197. // Determine the position of the argument
  198. int offset = 0;
  199. for( asUINT n = 0; n < arg; n++ )
  200. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  201. // Get the value
  202. return (void*)*(asPWORD*)(&stackPointer[offset]);
  203. }
  204. // interface
  205. void *asCGeneric::GetArgObject(asUINT arg)
  206. {
  207. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  208. return 0;
  209. // Verify that the type is correct
  210. asCDataType *dt = &sysFunction->parameterTypes[arg];
  211. if( !dt->IsObject() && !dt->IsFuncdef() )
  212. return 0;
  213. // Determine the position of the argument
  214. int offset = 0;
  215. for( asUINT n = 0; n < arg; n++ )
  216. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  217. // Get the value
  218. return *(void**)(&stackPointer[offset]);
  219. }
  220. // interface
  221. void *asCGeneric::GetAddressOfArg(asUINT arg)
  222. {
  223. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  224. return 0;
  225. // Determine the position of the argument
  226. int offset = 0;
  227. for( asUINT n = 0; n < arg; n++ )
  228. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  229. // For object variables it's necessary to dereference the pointer to get the address of the value
  230. if( !sysFunction->parameterTypes[arg].IsReference() &&
  231. sysFunction->parameterTypes[arg].IsObject() &&
  232. !sysFunction->parameterTypes[arg].IsObjectHandle() )
  233. return *(void**)&stackPointer[offset];
  234. // Get the address of the value
  235. return &stackPointer[offset];
  236. }
  237. // interface
  238. int asCGeneric::GetArgTypeId(asUINT arg, asDWORD *flags) const
  239. {
  240. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  241. return 0;
  242. if( flags )
  243. {
  244. *flags = sysFunction->inOutFlags[arg];
  245. *flags |= sysFunction->parameterTypes[arg].IsReadOnly() ? asTM_CONST : 0;
  246. }
  247. asCDataType *dt = &sysFunction->parameterTypes[arg];
  248. if( dt->GetTokenType() != ttQuestion )
  249. return engine->GetTypeIdFromDataType(*dt);
  250. else
  251. {
  252. int offset = 0;
  253. for( asUINT n = 0; n < arg; n++ )
  254. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  255. // Skip the actual value to get to the type id
  256. offset += AS_PTR_SIZE;
  257. // Get the value
  258. return stackPointer[offset];
  259. }
  260. }
  261. // interface
  262. int asCGeneric::SetReturnByte(asBYTE val)
  263. {
  264. // Verify the type of the return value
  265. if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() )
  266. return asINVALID_TYPE;
  267. if( sysFunction->returnType.GetSizeInMemoryBytes() != 1 )
  268. return asINVALID_TYPE;
  269. // Store the value
  270. *(asBYTE*)&returnVal = val;
  271. return 0;
  272. }
  273. // interface
  274. int asCGeneric::SetReturnWord(asWORD val)
  275. {
  276. // Verify the type of the return value
  277. if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() )
  278. return asINVALID_TYPE;
  279. if( sysFunction->returnType.GetSizeInMemoryBytes() != 2 )
  280. return asINVALID_TYPE;
  281. // Store the value
  282. *(asWORD*)&returnVal = val;
  283. return 0;
  284. }
  285. // interface
  286. int asCGeneric::SetReturnDWord(asDWORD val)
  287. {
  288. // Verify the type of the return value
  289. if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() )
  290. return asINVALID_TYPE;
  291. if( sysFunction->returnType.GetSizeInMemoryBytes() != 4 )
  292. return asINVALID_TYPE;
  293. // Store the value
  294. *(asDWORD*)&returnVal = val;
  295. return 0;
  296. }
  297. // interface
  298. int asCGeneric::SetReturnQWord(asQWORD val)
  299. {
  300. // Verify the type of the return value
  301. if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() )
  302. return asINVALID_TYPE;
  303. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  304. return asINVALID_TYPE;
  305. // Store the value
  306. returnVal = val;
  307. return 0;
  308. }
  309. // interface
  310. int asCGeneric::SetReturnFloat(float val)
  311. {
  312. // Verify the type of the return value
  313. if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() )
  314. return asINVALID_TYPE;
  315. if( sysFunction->returnType.GetSizeOnStackDWords() != 1 )
  316. return asINVALID_TYPE;
  317. // Store the value
  318. *(float*)&returnVal = val;
  319. return 0;
  320. }
  321. // interface
  322. int asCGeneric::SetReturnDouble(double val)
  323. {
  324. // Verify the type of the return value
  325. if( (sysFunction->returnType.IsObject() || sysFunction->returnType.IsFuncdef()) || sysFunction->returnType.IsReference() )
  326. return asINVALID_TYPE;
  327. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  328. return asINVALID_TYPE;
  329. // Store the value
  330. *(double*)&returnVal = val;
  331. return 0;
  332. }
  333. // interface
  334. int asCGeneric::SetReturnAddress(void *val)
  335. {
  336. // Verify the type of the return value
  337. if( sysFunction->returnType.IsReference() )
  338. {
  339. // Store the value
  340. *(void**)&returnVal = val;
  341. return 0;
  342. }
  343. else if( sysFunction->returnType.IsObjectHandle() )
  344. {
  345. // Store the handle without increasing reference
  346. objectRegister = val;
  347. return 0;
  348. }
  349. return asINVALID_TYPE;
  350. }
  351. // interface
  352. int asCGeneric::SetReturnObject(void *obj)
  353. {
  354. asCDataType *dt = &sysFunction->returnType;
  355. if( !dt->IsObject() && !dt->IsFuncdef() )
  356. return asINVALID_TYPE;
  357. if( dt->IsReference() )
  358. {
  359. *(void**)&returnVal = obj;
  360. return 0;
  361. }
  362. if( dt->IsObjectHandle() )
  363. {
  364. // Increase the reference counter
  365. if (dt->IsFuncdef())
  366. {
  367. if (obj)
  368. reinterpret_cast<asIScriptFunction*>(obj)->AddRef();
  369. }
  370. else
  371. {
  372. asSTypeBehaviour *beh = &CastToObjectType(dt->GetTypeInfo())->beh;
  373. if (obj && beh && beh->addref)
  374. engine->CallObjectMethod(obj, beh->addref);
  375. }
  376. }
  377. else
  378. {
  379. // If function returns object by value the memory is already allocated.
  380. // Here we should just initialize that memory by calling the copy constructor
  381. // or the default constructor followed by the assignment operator
  382. void *mem = (void*)*(asPWORD*)&stackPointer[-AS_PTR_SIZE];
  383. engine->ConstructScriptObjectCopy(mem, obj, CastToObjectType(dt->GetTypeInfo()));
  384. return 0;
  385. }
  386. objectRegister = obj;
  387. return 0;
  388. }
  389. // internal
  390. void *asCGeneric::GetReturnPointer()
  391. {
  392. asCDataType &dt = sysFunction->returnType;
  393. if( (dt.IsObject() ||dt.IsFuncdef()) && !dt.IsReference() )
  394. {
  395. // This function doesn't support returning on the stack but the use of
  396. // the function doesn't require it so we don't need to implement it here.
  397. asASSERT( !sysFunction->DoesReturnOnStack() );
  398. return &objectRegister;
  399. }
  400. return &returnVal;
  401. }
  402. // interface
  403. void *asCGeneric::GetAddressOfReturnLocation()
  404. {
  405. asCDataType &dt = sysFunction->returnType;
  406. if( (dt.IsObject() || dt.IsFuncdef()) && !dt.IsReference() )
  407. {
  408. if( sysFunction->DoesReturnOnStack() )
  409. {
  410. // The memory is already preallocated on the stack,
  411. // and the pointer to the location is found before the first arg
  412. return (void*)*(asPWORD*)&stackPointer[-AS_PTR_SIZE];
  413. }
  414. // Reference types store the handle in the objectReference
  415. return &objectRegister;
  416. }
  417. // Primitive types and references are stored in the returnVal property
  418. return &returnVal;
  419. }
  420. // interface
  421. int asCGeneric::GetReturnTypeId(asDWORD *flags) const
  422. {
  423. return sysFunction->GetReturnTypeId(flags);
  424. }
  425. END_AS_NAMESPACE