as_generic.cpp 12 KB

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