as_generic.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2012 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. asIScriptEngine *asCGeneric::GetEngine() const
  51. {
  52. return (asIScriptEngine*)engine;
  53. }
  54. #ifdef AS_DEPRECATED
  55. // Deprecated since 2.24.0 - 2012-05-25
  56. // interface
  57. int asCGeneric::GetFunctionId() const
  58. {
  59. return sysFunction->id;
  60. }
  61. #endif
  62. // interface
  63. asIScriptFunction *asCGeneric::GetFunction() const
  64. {
  65. return sysFunction;
  66. }
  67. #ifdef AS_DEPRECATED
  68. // Deprecated since 2.24.0 - 2012-05-25
  69. // interface
  70. void *asCGeneric::GetFunctionUserData() const
  71. {
  72. return sysFunction->userData;
  73. }
  74. #endif
  75. // interface
  76. void *asCGeneric::GetObject()
  77. {
  78. return currentObject;
  79. }
  80. // interface
  81. int asCGeneric::GetObjectTypeId() const
  82. {
  83. asCDataType dt = asCDataType::CreateObject(sysFunction->objectType, false);
  84. return engine->GetTypeIdFromDataType(dt);
  85. }
  86. // interface
  87. int asCGeneric::GetArgCount() const
  88. {
  89. return (int)sysFunction->parameterTypes.GetLength();
  90. }
  91. // interface
  92. asBYTE asCGeneric::GetArgByte(asUINT arg)
  93. {
  94. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  95. return 0;
  96. // Verify that the type is correct
  97. asCDataType *dt = &sysFunction->parameterTypes[arg];
  98. if( dt->IsObject() || dt->IsReference() )
  99. return 0;
  100. if( dt->GetSizeInMemoryBytes() != 1 )
  101. return 0;
  102. // Determine the position of the argument
  103. int offset = 0;
  104. for( asUINT n = 0; n < arg; n++ )
  105. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  106. // Get the value
  107. return *(asBYTE*)&stackPointer[offset];
  108. }
  109. // interface
  110. asWORD asCGeneric::GetArgWord(asUINT arg)
  111. {
  112. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  113. return 0;
  114. // Verify that the type is correct
  115. asCDataType *dt = &sysFunction->parameterTypes[arg];
  116. if( dt->IsObject() || dt->IsReference() )
  117. return 0;
  118. if( dt->GetSizeInMemoryBytes() != 2 )
  119. return 0;
  120. // Determine the position of the argument
  121. int offset = 0;
  122. for( asUINT n = 0; n < arg; n++ )
  123. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  124. // Get the value
  125. return *(asWORD*)&stackPointer[offset];
  126. }
  127. // interface
  128. asDWORD asCGeneric::GetArgDWord(asUINT arg)
  129. {
  130. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  131. return 0;
  132. // Verify that the type is correct
  133. asCDataType *dt = &sysFunction->parameterTypes[arg];
  134. if( dt->IsObject() || dt->IsReference() )
  135. return 0;
  136. if( dt->GetSizeInMemoryBytes() != 4 )
  137. return 0;
  138. // Determine the position of the argument
  139. int offset = 0;
  140. for( asUINT n = 0; n < arg; n++ )
  141. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  142. // Get the value
  143. return *(asDWORD*)&stackPointer[offset];
  144. }
  145. // interface
  146. asQWORD asCGeneric::GetArgQWord(asUINT arg)
  147. {
  148. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  149. return 0;
  150. // Verify that the type is correct
  151. asCDataType *dt = &sysFunction->parameterTypes[arg];
  152. if( dt->IsObject() || dt->IsReference() )
  153. return 0;
  154. if( dt->GetSizeInMemoryBytes() != 8 )
  155. return 0;
  156. // Determine the position of the argument
  157. int offset = 0;
  158. for( asUINT n = 0; n < arg; n++ )
  159. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  160. // Get the value
  161. return *(asQWORD*)(&stackPointer[offset]);
  162. }
  163. // interface
  164. float asCGeneric::GetArgFloat(asUINT arg)
  165. {
  166. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  167. return 0;
  168. // Verify that the type is correct
  169. asCDataType *dt = &sysFunction->parameterTypes[arg];
  170. if( dt->IsObject() || dt->IsReference() )
  171. return 0;
  172. if( dt->GetSizeInMemoryBytes() != 4 )
  173. return 0;
  174. // Determine the position of the argument
  175. int offset = 0;
  176. for( asUINT n = 0; n < arg; n++ )
  177. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  178. // Get the value
  179. return *(float*)(&stackPointer[offset]);
  180. }
  181. // interface
  182. double asCGeneric::GetArgDouble(asUINT arg)
  183. {
  184. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  185. return 0;
  186. // Verify that the type is correct
  187. asCDataType *dt = &sysFunction->parameterTypes[arg];
  188. if( dt->IsObject() || dt->IsReference() )
  189. return 0;
  190. if( dt->GetSizeInMemoryBytes() != 8 )
  191. return 0;
  192. // Determine the position of the argument
  193. int offset = 0;
  194. for( asUINT n = 0; n < arg; n++ )
  195. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  196. // Get the value
  197. return *(double*)(&stackPointer[offset]);
  198. }
  199. // interface
  200. void *asCGeneric::GetArgAddress(asUINT arg)
  201. {
  202. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  203. return 0;
  204. // Verify that the type is correct
  205. asCDataType *dt = &sysFunction->parameterTypes[arg];
  206. if( !dt->IsReference() && !dt->IsObjectHandle() )
  207. return 0;
  208. // Determine the position of the argument
  209. int offset = 0;
  210. for( asUINT n = 0; n < arg; n++ )
  211. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  212. // Get the value
  213. return (void*)*(asPWORD*)(&stackPointer[offset]);
  214. }
  215. // interface
  216. void *asCGeneric::GetArgObject(asUINT arg)
  217. {
  218. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  219. return 0;
  220. // Verify that the type is correct
  221. asCDataType *dt = &sysFunction->parameterTypes[arg];
  222. if( !dt->IsObject() )
  223. return 0;
  224. // Determine the position of the argument
  225. int offset = 0;
  226. for( asUINT n = 0; n < arg; n++ )
  227. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  228. // Get the value
  229. return *(void**)(&stackPointer[offset]);
  230. }
  231. // interface
  232. void *asCGeneric::GetAddressOfArg(asUINT arg)
  233. {
  234. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  235. return 0;
  236. // Determine the position of the argument
  237. int offset = 0;
  238. for( asUINT n = 0; n < arg; n++ )
  239. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  240. // For object variables it's necessary to dereference the pointer to get the address of the value
  241. if( !sysFunction->parameterTypes[arg].IsReference() &&
  242. sysFunction->parameterTypes[arg].IsObject() &&
  243. !sysFunction->parameterTypes[arg].IsObjectHandle() )
  244. return *(void**)&stackPointer[offset];
  245. // Get the address of the value
  246. return &stackPointer[offset];
  247. }
  248. // interface
  249. int asCGeneric::GetArgTypeId(asUINT arg) const
  250. {
  251. if( arg >= (unsigned)sysFunction->parameterTypes.GetLength() )
  252. return 0;
  253. asCDataType *dt = &sysFunction->parameterTypes[arg];
  254. if( dt->GetTokenType() != ttQuestion )
  255. return engine->GetTypeIdFromDataType(*dt);
  256. else
  257. {
  258. int offset = 0;
  259. for( asUINT n = 0; n < arg; n++ )
  260. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  261. // Skip the actual value to get to the type id
  262. offset += AS_PTR_SIZE;
  263. // Get the value
  264. return stackPointer[offset];
  265. }
  266. }
  267. // interface
  268. int asCGeneric::SetReturnByte(asBYTE val)
  269. {
  270. // Verify the type of the return value
  271. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  272. return asINVALID_TYPE;
  273. if( sysFunction->returnType.GetSizeInMemoryBytes() != 1 )
  274. return asINVALID_TYPE;
  275. // Store the value
  276. *(asBYTE*)&returnVal = val;
  277. return 0;
  278. }
  279. // interface
  280. int asCGeneric::SetReturnWord(asWORD val)
  281. {
  282. // Verify the type of the return value
  283. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  284. return asINVALID_TYPE;
  285. if( sysFunction->returnType.GetSizeInMemoryBytes() != 2 )
  286. return asINVALID_TYPE;
  287. // Store the value
  288. *(asWORD*)&returnVal = val;
  289. return 0;
  290. }
  291. // interface
  292. int asCGeneric::SetReturnDWord(asDWORD val)
  293. {
  294. // Verify the type of the return value
  295. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  296. return asINVALID_TYPE;
  297. if( sysFunction->returnType.GetSizeInMemoryBytes() != 4 )
  298. return asINVALID_TYPE;
  299. // Store the value
  300. *(asDWORD*)&returnVal = val;
  301. return 0;
  302. }
  303. // interface
  304. int asCGeneric::SetReturnQWord(asQWORD val)
  305. {
  306. // Verify the type of the return value
  307. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  308. return asINVALID_TYPE;
  309. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  310. return asINVALID_TYPE;
  311. // Store the value
  312. returnVal = val;
  313. return 0;
  314. }
  315. // interface
  316. int asCGeneric::SetReturnFloat(float val)
  317. {
  318. // Verify the type of the return value
  319. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  320. return asINVALID_TYPE;
  321. if( sysFunction->returnType.GetSizeOnStackDWords() != 1 )
  322. return asINVALID_TYPE;
  323. // Store the value
  324. *(float*)&returnVal = val;
  325. return 0;
  326. }
  327. // interface
  328. int asCGeneric::SetReturnDouble(double val)
  329. {
  330. // Verify the type of the return value
  331. if( sysFunction->returnType.IsObject() || sysFunction->returnType.IsReference() )
  332. return asINVALID_TYPE;
  333. if( sysFunction->returnType.GetSizeOnStackDWords() != 2 )
  334. return asINVALID_TYPE;
  335. // Store the value
  336. *(double*)&returnVal = val;
  337. return 0;
  338. }
  339. // interface
  340. int asCGeneric::SetReturnAddress(void *val)
  341. {
  342. // Verify the type of the return value
  343. if( sysFunction->returnType.IsReference() )
  344. {
  345. // Store the value
  346. *(void**)&returnVal = val;
  347. return 0;
  348. }
  349. else if( sysFunction->returnType.IsObjectHandle() )
  350. {
  351. // Store the handle without increasing reference
  352. objectRegister = val;
  353. return 0;
  354. }
  355. return asINVALID_TYPE;
  356. }
  357. // interface
  358. int asCGeneric::SetReturnObject(void *obj)
  359. {
  360. asCDataType *dt = &sysFunction->returnType;
  361. if( !dt->IsObject() )
  362. return asINVALID_TYPE;
  363. if( dt->IsReference() )
  364. {
  365. *(void**)&returnVal = obj;
  366. return 0;
  367. }
  368. if( dt->IsObjectHandle() )
  369. {
  370. // Increase the reference counter
  371. asSTypeBehaviour *beh = &dt->GetObjectType()->beh;
  372. if( obj && beh->addref )
  373. engine->CallObjectMethod(obj, beh->addref);
  374. }
  375. else
  376. {
  377. // If function returns object by value the memory is already allocated.
  378. // Here we should just initialize that memory by calling the copy constructor
  379. // or the default constructor followed by the assignment operator
  380. void *mem = (void*)*(asPWORD*)&stackPointer[-AS_PTR_SIZE];
  381. engine->ConstructScriptObjectCopy(mem, obj, dt->GetObjectType());
  382. return 0;
  383. }
  384. objectRegister = obj;
  385. return 0;
  386. }
  387. // internal
  388. void *asCGeneric::GetReturnPointer()
  389. {
  390. asCDataType &dt = sysFunction->returnType;
  391. if( dt.IsObject() && !dt.IsReference() )
  392. {
  393. // This function doesn't support returning on the stack but the use of
  394. // the function doesn't require it so we don't need to implement it here.
  395. asASSERT( !sysFunction->DoesReturnOnStack() );
  396. return &objectRegister;
  397. }
  398. return &returnVal;
  399. }
  400. // interface
  401. void *asCGeneric::GetAddressOfReturnLocation()
  402. {
  403. asCDataType &dt = sysFunction->returnType;
  404. if( dt.IsObject() && !dt.IsReference() )
  405. {
  406. if( sysFunction->DoesReturnOnStack() )
  407. {
  408. // The memory is already preallocated on the stack,
  409. // and the pointer to the location is found before the first arg
  410. return (void*)*(asPWORD*)&stackPointer[-AS_PTR_SIZE];
  411. }
  412. // Reference types store the handle in the objectReference
  413. return &objectRegister;
  414. }
  415. // Primitive types and references are stored in the returnVal property
  416. return &returnVal;
  417. }
  418. // interface
  419. int asCGeneric::GetReturnTypeId() const
  420. {
  421. return sysFunction->GetReturnTypeId();
  422. }
  423. END_AS_NAMESPACE