PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/lscript/lscript_compile/lscript_bytecode.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 320 lines | 247 code | 43 blank | 30 comment | 15 complexity | 57f98875d3febc4c437e1ef16c8c514e MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lscript_bytecode.cpp
  3. * @brief classes to build actual bytecode
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "lscript_bytecode.h"
  28. #include "lscript_error.h"
  29. #if defined(_MSC_VER)
  30. # pragma warning(disable: 4102) // 'yy_more' : unreferenced label
  31. # pragma warning(disable: 4702) // unreachable code
  32. #endif
  33. LLScriptJumpTable::LLScriptJumpTable()
  34. {
  35. }
  36. LLScriptJumpTable::~LLScriptJumpTable()
  37. {
  38. mLabelMap.deleteAllData();
  39. mJumpMap.deleteAllData();
  40. }
  41. void LLScriptJumpTable::addLabel(char *name, S32 offset)
  42. {
  43. char *temp = gScopeStringTable->addString(name);
  44. mLabelMap[temp] = new S32(offset);
  45. }
  46. void LLScriptJumpTable::addJump(char *name, S32 offset)
  47. {
  48. char *temp = gScopeStringTable->addString(name);
  49. mJumpMap[temp] = new S32(offset);
  50. }
  51. LLScriptByteCodeChunk::LLScriptByteCodeChunk(BOOL b_need_jumps)
  52. : mCodeChunk(NULL), mCurrentOffset(0), mJumpTable(NULL)
  53. {
  54. if (b_need_jumps)
  55. {
  56. mJumpTable = new LLScriptJumpTable();
  57. }
  58. }
  59. LLScriptByteCodeChunk::~LLScriptByteCodeChunk()
  60. {
  61. delete [] mCodeChunk;
  62. delete mJumpTable;
  63. }
  64. void LLScriptByteCodeChunk::addByte(U8 byte)
  65. {
  66. if (mCodeChunk)
  67. {
  68. U8 *temp = new U8[mCurrentOffset + 1];
  69. memcpy(temp, mCodeChunk, mCurrentOffset); /* Flawfinder: ignore */
  70. delete [] mCodeChunk;
  71. mCodeChunk = temp;
  72. }
  73. else
  74. {
  75. mCodeChunk = new U8[1];
  76. }
  77. *(mCodeChunk + mCurrentOffset++) = byte;
  78. }
  79. void LLScriptByteCodeChunk::addU16(U16 data)
  80. {
  81. U8 temp[2];
  82. S32 offset = 0;
  83. u162bytestream(temp, offset, data);
  84. addBytes(temp, 2);
  85. }
  86. void LLScriptByteCodeChunk::addBytes(const U8 *bytes, S32 size)
  87. {
  88. if (mCodeChunk)
  89. {
  90. U8 *temp = new U8[mCurrentOffset + size];
  91. memcpy(temp, mCodeChunk, mCurrentOffset); /* Flawfinder: ignore */
  92. delete [] mCodeChunk;
  93. mCodeChunk = temp;
  94. }
  95. else
  96. {
  97. mCodeChunk = new U8[size];
  98. }
  99. memcpy(mCodeChunk + mCurrentOffset, bytes, size);/* Flawfinder: ignore */
  100. mCurrentOffset += size;
  101. }
  102. void LLScriptByteCodeChunk::addBytes(const char *bytes, S32 size)
  103. {
  104. if (mCodeChunk)
  105. {
  106. U8 *temp = new U8[mCurrentOffset + size];
  107. memcpy(temp, mCodeChunk, mCurrentOffset); /*Flawfinder: ignore*/
  108. delete [] mCodeChunk;
  109. mCodeChunk = temp;
  110. }
  111. else
  112. {
  113. mCodeChunk = new U8[size];
  114. }
  115. memcpy(mCodeChunk + mCurrentOffset, bytes, size); /*Flawfinder: ignore*/
  116. mCurrentOffset += size;
  117. }
  118. void LLScriptByteCodeChunk::addBytes(S32 size)
  119. {
  120. if (mCodeChunk)
  121. {
  122. U8 *temp = new U8[mCurrentOffset + size];
  123. memcpy(temp, mCodeChunk, mCurrentOffset); /*Flawfinder: ignore*/
  124. delete [] mCodeChunk;
  125. mCodeChunk = temp;
  126. }
  127. else
  128. {
  129. mCodeChunk = new U8[size];
  130. }
  131. memset(mCodeChunk + mCurrentOffset, 0, size);
  132. mCurrentOffset += size;
  133. }
  134. void LLScriptByteCodeChunk::addBytesDontInc(S32 size)
  135. {
  136. if (mCodeChunk)
  137. {
  138. U8 *temp = new U8[mCurrentOffset + size];
  139. memcpy(temp, mCodeChunk, mCurrentOffset); /*Flawfinder: ignore*/
  140. delete [] mCodeChunk;
  141. mCodeChunk = temp;
  142. }
  143. else
  144. {
  145. mCodeChunk = new U8[size];
  146. }
  147. memset(mCodeChunk + mCurrentOffset, 0, size);
  148. }
  149. void LLScriptByteCodeChunk::addInteger(S32 value)
  150. {
  151. U8 temp[4];
  152. S32 offset = 0;
  153. integer2bytestream(temp, offset, value);
  154. addBytes(temp, 4);
  155. }
  156. void LLScriptByteCodeChunk::addFloat(F32 value)
  157. {
  158. U8 temp[4];
  159. S32 offset = 0;
  160. float2bytestream(temp, offset, value);
  161. addBytes(temp, 4);
  162. }
  163. void LLScriptByteCodeChunk::addLabel(char *name)
  164. {
  165. if (mJumpTable)
  166. {
  167. mJumpTable->addLabel(name, mCurrentOffset);
  168. }
  169. }
  170. void LLScriptByteCodeChunk::addJump(char *name)
  171. {
  172. if (mJumpTable)
  173. {
  174. mJumpTable->addJump(name, mCurrentOffset);
  175. }
  176. }
  177. // format is Byte 0: jump op code Byte 1 - 4: offset
  178. // the jump position points to Byte 5, so we need to add the data at
  179. // offset - 4, offset - 3, offset - 2, and offset - 1
  180. // offset is label - jump
  181. void LLScriptByteCodeChunk::connectJumps()
  182. {
  183. char *jump;
  184. S32 offset, jumppos;
  185. if (mJumpTable)
  186. {
  187. for (jump = mJumpTable->mJumpMap.getFirstKey();
  188. jump;
  189. jump = mJumpTable->mJumpMap.getNextKey())
  190. {
  191. jumppos = *mJumpTable->mJumpMap[jump];
  192. offset = *mJumpTable->mLabelMap[jump] - jumppos;
  193. jumppos = jumppos - 4;
  194. integer2bytestream(mCodeChunk, jumppos, offset);
  195. }
  196. }
  197. }
  198. LLScriptScriptCodeChunk::LLScriptScriptCodeChunk(S32 total_size)
  199. : mTotalSize(total_size), mCompleteCode(NULL)
  200. {
  201. mRegisters = new LLScriptByteCodeChunk(FALSE);
  202. mGlobalVariables = new LLScriptByteCodeChunk(FALSE);
  203. mGlobalFunctions = new LLScriptByteCodeChunk(FALSE);
  204. mStates = new LLScriptByteCodeChunk(FALSE);
  205. mHeap = new LLScriptByteCodeChunk(FALSE);
  206. }
  207. LLScriptScriptCodeChunk::~LLScriptScriptCodeChunk()
  208. {
  209. delete mRegisters;
  210. delete mGlobalVariables;
  211. delete mGlobalFunctions;
  212. delete mStates;
  213. delete mHeap;
  214. delete [] mCompleteCode;
  215. }
  216. void LLScriptScriptCodeChunk::build(LLFILE *efp, LLFILE *bcfp)
  217. {
  218. S32 code_data_size = mRegisters->mCurrentOffset +
  219. mGlobalVariables->mCurrentOffset +
  220. mGlobalFunctions->mCurrentOffset +
  221. mStates->mCurrentOffset +
  222. mHeap->mCurrentOffset;
  223. S32 offset = 0;
  224. if (code_data_size < mTotalSize)
  225. {
  226. mCompleteCode = new U8[mTotalSize];
  227. memset(mCompleteCode, 0, mTotalSize);
  228. memcpy(mCompleteCode, mRegisters->mCodeChunk, mRegisters->mCurrentOffset);
  229. offset += mRegisters->mCurrentOffset;
  230. set_register(mCompleteCode, LREG_IP, 0);
  231. set_register(mCompleteCode, LREG_VN, LSL2_VERSION_NUMBER);
  232. set_event_register(mCompleteCode, LREG_IE, 0, LSL2_CURRENT_MAJOR_VERSION);
  233. set_register(mCompleteCode, LREG_BP, mTotalSize - 1);
  234. set_register(mCompleteCode, LREG_SP, mTotalSize - 1);
  235. set_register(mCompleteCode, LREG_GVR, offset);
  236. memcpy(mCompleteCode + offset, mGlobalVariables->mCodeChunk, mGlobalVariables->mCurrentOffset); /*Flawfinder: ignore*/
  237. offset += mGlobalVariables->mCurrentOffset;
  238. set_register(mCompleteCode, LREG_GFR, offset);
  239. memcpy(mCompleteCode + offset, mGlobalFunctions->mCodeChunk, mGlobalFunctions->mCurrentOffset); /*Flawfinder: ignore*/
  240. offset += mGlobalFunctions->mCurrentOffset;
  241. set_register(mCompleteCode, LREG_SR, offset);
  242. // zero is, by definition the default state
  243. set_register(mCompleteCode, LREG_CS, 0);
  244. set_register(mCompleteCode, LREG_NS, 0);
  245. set_event_register(mCompleteCode, LREG_CE, LSCRIPTStateBitField[LSTT_STATE_ENTRY], LSL2_CURRENT_MAJOR_VERSION);
  246. S32 default_state_offset = 0;
  247. if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
  248. {
  249. default_state_offset = 8;
  250. }
  251. else
  252. {
  253. default_state_offset = 4;
  254. }
  255. set_event_register(mCompleteCode, LREG_ER, bytestream2u64(mStates->mCodeChunk, default_state_offset), LSL2_CURRENT_MAJOR_VERSION);
  256. memcpy(mCompleteCode + offset, mStates->mCodeChunk, mStates->mCurrentOffset); /*Flawfinder: ignore*/
  257. offset += mStates->mCurrentOffset;
  258. set_register(mCompleteCode, LREG_HR, offset);
  259. memcpy(mCompleteCode + offset, mHeap->mCodeChunk, mHeap->mCurrentOffset); /*Flawfinder: ignore*/
  260. offset += mHeap->mCurrentOffset;
  261. set_register(mCompleteCode, LREG_HP, offset);
  262. set_register(mCompleteCode, LREG_FR, 0);
  263. set_register(mCompleteCode, LREG_SLR, 0);
  264. set_register(mCompleteCode, LREG_ESR, 0);
  265. set_register(mCompleteCode, LREG_PR, 0);
  266. set_register(mCompleteCode, LREG_TM, mTotalSize);
  267. if (fwrite(mCompleteCode, 1, mTotalSize, bcfp) != (size_t)mTotalSize)
  268. {
  269. llwarns << "Short write" << llendl;
  270. }
  271. }
  272. else
  273. {
  274. gErrorToText.writeError(efp, 0, 0, LSERROR_ASSEMBLE_OUT_OF_MEMORY);
  275. }
  276. }
  277. LLScriptScriptCodeChunk *gScriptCodeChunk;