/indra/lscript/lscript_compile/lscript_bytecode.cpp
C++ | 320 lines | 247 code | 43 blank | 30 comment | 15 complexity | 57f98875d3febc4c437e1ef16c8c514e MD5 | raw file
Possible License(s): LGPL-2.1
- /**
- * @file lscript_bytecode.cpp
- * @brief classes to build actual bytecode
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "lscript_bytecode.h"
- #include "lscript_error.h"
- #if defined(_MSC_VER)
- # pragma warning(disable: 4102) // 'yy_more' : unreferenced label
- # pragma warning(disable: 4702) // unreachable code
- #endif
- LLScriptJumpTable::LLScriptJumpTable()
- {
- }
- LLScriptJumpTable::~LLScriptJumpTable()
- {
- mLabelMap.deleteAllData();
- mJumpMap.deleteAllData();
- }
- void LLScriptJumpTable::addLabel(char *name, S32 offset)
- {
- char *temp = gScopeStringTable->addString(name);
- mLabelMap[temp] = new S32(offset);
- }
- void LLScriptJumpTable::addJump(char *name, S32 offset)
- {
- char *temp = gScopeStringTable->addString(name);
- mJumpMap[temp] = new S32(offset);
- }
- LLScriptByteCodeChunk::LLScriptByteCodeChunk(BOOL b_need_jumps)
- : mCodeChunk(NULL), mCurrentOffset(0), mJumpTable(NULL)
- {
- if (b_need_jumps)
- {
- mJumpTable = new LLScriptJumpTable();
- }
- }
- LLScriptByteCodeChunk::~LLScriptByteCodeChunk()
- {
- delete [] mCodeChunk;
- delete mJumpTable;
- }
- void LLScriptByteCodeChunk::addByte(U8 byte)
- {
- if (mCodeChunk)
- {
- U8 *temp = new U8[mCurrentOffset + 1];
- memcpy(temp, mCodeChunk, mCurrentOffset); /* Flawfinder: ignore */
- delete [] mCodeChunk;
- mCodeChunk = temp;
- }
- else
- {
- mCodeChunk = new U8[1];
- }
- *(mCodeChunk + mCurrentOffset++) = byte;
- }
- void LLScriptByteCodeChunk::addU16(U16 data)
- {
- U8 temp[2];
- S32 offset = 0;
- u162bytestream(temp, offset, data);
- addBytes(temp, 2);
- }
- void LLScriptByteCodeChunk::addBytes(const U8 *bytes, S32 size)
- {
- if (mCodeChunk)
- {
- U8 *temp = new U8[mCurrentOffset + size];
- memcpy(temp, mCodeChunk, mCurrentOffset); /* Flawfinder: ignore */
- delete [] mCodeChunk;
- mCodeChunk = temp;
- }
- else
- {
- mCodeChunk = new U8[size];
- }
- memcpy(mCodeChunk + mCurrentOffset, bytes, size);/* Flawfinder: ignore */
- mCurrentOffset += size;
- }
- void LLScriptByteCodeChunk::addBytes(const char *bytes, S32 size)
- {
- if (mCodeChunk)
- {
- U8 *temp = new U8[mCurrentOffset + size];
- memcpy(temp, mCodeChunk, mCurrentOffset); /*Flawfinder: ignore*/
- delete [] mCodeChunk;
- mCodeChunk = temp;
- }
- else
- {
- mCodeChunk = new U8[size];
- }
- memcpy(mCodeChunk + mCurrentOffset, bytes, size); /*Flawfinder: ignore*/
- mCurrentOffset += size;
- }
- void LLScriptByteCodeChunk::addBytes(S32 size)
- {
- if (mCodeChunk)
- {
- U8 *temp = new U8[mCurrentOffset + size];
- memcpy(temp, mCodeChunk, mCurrentOffset); /*Flawfinder: ignore*/
- delete [] mCodeChunk;
- mCodeChunk = temp;
- }
- else
- {
- mCodeChunk = new U8[size];
- }
- memset(mCodeChunk + mCurrentOffset, 0, size);
- mCurrentOffset += size;
- }
- void LLScriptByteCodeChunk::addBytesDontInc(S32 size)
- {
- if (mCodeChunk)
- {
- U8 *temp = new U8[mCurrentOffset + size];
- memcpy(temp, mCodeChunk, mCurrentOffset); /*Flawfinder: ignore*/
- delete [] mCodeChunk;
- mCodeChunk = temp;
- }
- else
- {
- mCodeChunk = new U8[size];
- }
- memset(mCodeChunk + mCurrentOffset, 0, size);
- }
- void LLScriptByteCodeChunk::addInteger(S32 value)
- {
- U8 temp[4];
- S32 offset = 0;
- integer2bytestream(temp, offset, value);
- addBytes(temp, 4);
- }
- void LLScriptByteCodeChunk::addFloat(F32 value)
- {
- U8 temp[4];
- S32 offset = 0;
- float2bytestream(temp, offset, value);
- addBytes(temp, 4);
- }
- void LLScriptByteCodeChunk::addLabel(char *name)
- {
- if (mJumpTable)
- {
- mJumpTable->addLabel(name, mCurrentOffset);
- }
- }
- void LLScriptByteCodeChunk::addJump(char *name)
- {
- if (mJumpTable)
- {
- mJumpTable->addJump(name, mCurrentOffset);
- }
- }
- // format is Byte 0: jump op code Byte 1 - 4: offset
- // the jump position points to Byte 5, so we need to add the data at
- // offset - 4, offset - 3, offset - 2, and offset - 1
- // offset is label - jump
- void LLScriptByteCodeChunk::connectJumps()
- {
- char *jump;
- S32 offset, jumppos;
- if (mJumpTable)
- {
- for (jump = mJumpTable->mJumpMap.getFirstKey();
- jump;
- jump = mJumpTable->mJumpMap.getNextKey())
- {
- jumppos = *mJumpTable->mJumpMap[jump];
- offset = *mJumpTable->mLabelMap[jump] - jumppos;
- jumppos = jumppos - 4;
- integer2bytestream(mCodeChunk, jumppos, offset);
- }
- }
- }
- LLScriptScriptCodeChunk::LLScriptScriptCodeChunk(S32 total_size)
- : mTotalSize(total_size), mCompleteCode(NULL)
- {
- mRegisters = new LLScriptByteCodeChunk(FALSE);
- mGlobalVariables = new LLScriptByteCodeChunk(FALSE);
- mGlobalFunctions = new LLScriptByteCodeChunk(FALSE);
- mStates = new LLScriptByteCodeChunk(FALSE);
- mHeap = new LLScriptByteCodeChunk(FALSE);
- }
- LLScriptScriptCodeChunk::~LLScriptScriptCodeChunk()
- {
- delete mRegisters;
- delete mGlobalVariables;
- delete mGlobalFunctions;
- delete mStates;
- delete mHeap;
- delete [] mCompleteCode;
- }
- void LLScriptScriptCodeChunk::build(LLFILE *efp, LLFILE *bcfp)
- {
- S32 code_data_size = mRegisters->mCurrentOffset +
- mGlobalVariables->mCurrentOffset +
- mGlobalFunctions->mCurrentOffset +
- mStates->mCurrentOffset +
- mHeap->mCurrentOffset;
- S32 offset = 0;
- if (code_data_size < mTotalSize)
- {
- mCompleteCode = new U8[mTotalSize];
- memset(mCompleteCode, 0, mTotalSize);
-
- memcpy(mCompleteCode, mRegisters->mCodeChunk, mRegisters->mCurrentOffset);
- offset += mRegisters->mCurrentOffset;
- set_register(mCompleteCode, LREG_IP, 0);
- set_register(mCompleteCode, LREG_VN, LSL2_VERSION_NUMBER);
- set_event_register(mCompleteCode, LREG_IE, 0, LSL2_CURRENT_MAJOR_VERSION);
- set_register(mCompleteCode, LREG_BP, mTotalSize - 1);
- set_register(mCompleteCode, LREG_SP, mTotalSize - 1);
- set_register(mCompleteCode, LREG_GVR, offset);
-
- memcpy(mCompleteCode + offset, mGlobalVariables->mCodeChunk, mGlobalVariables->mCurrentOffset); /*Flawfinder: ignore*/
- offset += mGlobalVariables->mCurrentOffset;
- set_register(mCompleteCode, LREG_GFR, offset);
-
- memcpy(mCompleteCode + offset, mGlobalFunctions->mCodeChunk, mGlobalFunctions->mCurrentOffset); /*Flawfinder: ignore*/
- offset += mGlobalFunctions->mCurrentOffset;
- set_register(mCompleteCode, LREG_SR, offset);
- // zero is, by definition the default state
- set_register(mCompleteCode, LREG_CS, 0);
- set_register(mCompleteCode, LREG_NS, 0);
- set_event_register(mCompleteCode, LREG_CE, LSCRIPTStateBitField[LSTT_STATE_ENTRY], LSL2_CURRENT_MAJOR_VERSION);
- S32 default_state_offset = 0;
- if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
- {
- default_state_offset = 8;
- }
- else
- {
- default_state_offset = 4;
- }
- set_event_register(mCompleteCode, LREG_ER, bytestream2u64(mStates->mCodeChunk, default_state_offset), LSL2_CURRENT_MAJOR_VERSION);
-
- memcpy(mCompleteCode + offset, mStates->mCodeChunk, mStates->mCurrentOffset); /*Flawfinder: ignore*/
- offset += mStates->mCurrentOffset;
- set_register(mCompleteCode, LREG_HR, offset);
-
- memcpy(mCompleteCode + offset, mHeap->mCodeChunk, mHeap->mCurrentOffset); /*Flawfinder: ignore*/
- offset += mHeap->mCurrentOffset;
-
- set_register(mCompleteCode, LREG_HP, offset);
- set_register(mCompleteCode, LREG_FR, 0);
- set_register(mCompleteCode, LREG_SLR, 0);
- set_register(mCompleteCode, LREG_ESR, 0);
- set_register(mCompleteCode, LREG_PR, 0);
- set_register(mCompleteCode, LREG_TM, mTotalSize);
- if (fwrite(mCompleteCode, 1, mTotalSize, bcfp) != (size_t)mTotalSize)
- {
- llwarns << "Short write" << llendl;
- }
- }
- else
- {
- gErrorToText.writeError(efp, 0, 0, LSERROR_ASSEMBLE_OUT_OF_MEMORY);
- }
- }
- LLScriptScriptCodeChunk *gScriptCodeChunk;