Files
SingularityViewer/indra/lscript/lscript_compile/lscript_bytecode.cpp
2011-06-16 23:56:56 -05:00

327 lines
8.4 KiB
C++

/**
* @file lscript_bytecode.cpp
* @brief classes to build actual bytecode
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/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;