PageRenderTime 33ms CodeModel.GetById 12ms app.highlight 18ms 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
  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
 27#include "linden_common.h"
 28
 29#include "lscript_bytecode.h"
 30#include "lscript_error.h"
 31
 32#if defined(_MSC_VER)
 33# pragma warning(disable: 4102) // 'yy_more' : unreferenced label
 34# pragma warning(disable: 4702) // unreachable code
 35#endif
 36
 37LLScriptJumpTable::LLScriptJumpTable()
 38{
 39}
 40
 41LLScriptJumpTable::~LLScriptJumpTable()
 42{
 43	mLabelMap.deleteAllData();
 44	mJumpMap.deleteAllData();
 45}
 46
 47void LLScriptJumpTable::addLabel(char *name, S32 offset)
 48{
 49	char *temp = gScopeStringTable->addString(name);
 50	mLabelMap[temp] = new S32(offset);
 51}
 52
 53void LLScriptJumpTable::addJump(char *name, S32 offset)
 54{
 55	char *temp = gScopeStringTable->addString(name);
 56	mJumpMap[temp] = new S32(offset);
 57}
 58
 59
 60LLScriptByteCodeChunk::LLScriptByteCodeChunk(BOOL b_need_jumps)
 61: mCodeChunk(NULL), mCurrentOffset(0), mJumpTable(NULL)
 62{
 63	if (b_need_jumps)
 64	{
 65		mJumpTable = new LLScriptJumpTable();
 66	}
 67}
 68
 69LLScriptByteCodeChunk::~LLScriptByteCodeChunk()
 70{
 71	delete [] mCodeChunk;
 72	delete mJumpTable;
 73}
 74
 75void LLScriptByteCodeChunk::addByte(U8 byte)
 76{
 77	if (mCodeChunk)
 78	{
 79		U8 *temp = new U8[mCurrentOffset + 1];
 80		memcpy(temp, mCodeChunk, mCurrentOffset);	/* Flawfinder: ignore */
 81		delete [] mCodeChunk;
 82		mCodeChunk = temp;
 83	}
 84	else
 85	{
 86		mCodeChunk = new U8[1];
 87	}
 88	*(mCodeChunk + mCurrentOffset++) = byte;
 89}
 90
 91void LLScriptByteCodeChunk::addU16(U16 data)
 92{
 93	U8 temp[2];
 94	S32 offset = 0;
 95	u162bytestream(temp, offset, data);
 96	addBytes(temp, 2);
 97}
 98
 99void LLScriptByteCodeChunk::addBytes(const U8 *bytes, S32 size)
100{
101	if (mCodeChunk)
102	{
103		U8 *temp = new U8[mCurrentOffset + size];
104		memcpy(temp, mCodeChunk, mCurrentOffset);	/* Flawfinder: ignore */
105		delete [] mCodeChunk;
106		mCodeChunk = temp;
107	}
108	else
109	{
110		mCodeChunk = new U8[size];
111	}
112	memcpy(mCodeChunk + mCurrentOffset, bytes, size);/* Flawfinder: ignore */
113	mCurrentOffset += size;
114}
115
116void LLScriptByteCodeChunk::addBytes(const char *bytes, S32 size)
117{
118	if (mCodeChunk)
119	{
120		U8 *temp = new U8[mCurrentOffset + size];
121		memcpy(temp, mCodeChunk, mCurrentOffset);	 	/*Flawfinder: ignore*/
122		delete [] mCodeChunk;
123		mCodeChunk = temp;
124	}
125	else
126	{
127		mCodeChunk = new U8[size];
128	}
129	memcpy(mCodeChunk + mCurrentOffset, bytes, size);	/*Flawfinder: ignore*/
130	mCurrentOffset += size;
131}
132
133void LLScriptByteCodeChunk::addBytes(S32 size)
134{
135	if (mCodeChunk)
136	{
137		U8 *temp = new U8[mCurrentOffset + size];
138		memcpy(temp, mCodeChunk, mCurrentOffset);	/*Flawfinder: ignore*/
139		delete [] mCodeChunk;
140		mCodeChunk = temp;
141	}
142	else
143	{
144		mCodeChunk = new U8[size];
145	}
146	memset(mCodeChunk + mCurrentOffset, 0, size);
147	mCurrentOffset += size;
148}
149
150void LLScriptByteCodeChunk::addBytesDontInc(S32 size)
151{
152	if (mCodeChunk)
153	{
154		U8 *temp = new U8[mCurrentOffset + size];
155		memcpy(temp, mCodeChunk, mCurrentOffset);	 	/*Flawfinder: ignore*/
156		delete [] mCodeChunk;
157		mCodeChunk = temp;
158	}
159	else
160	{
161		mCodeChunk = new U8[size];
162	}
163	memset(mCodeChunk + mCurrentOffset, 0, size);
164}
165
166void LLScriptByteCodeChunk::addInteger(S32 value)
167{
168	U8 temp[4];
169	S32 offset = 0;
170	integer2bytestream(temp, offset, value);
171	addBytes(temp, 4);
172}
173
174void LLScriptByteCodeChunk::addFloat(F32 value)
175{
176	U8 temp[4];
177	S32 offset = 0;
178	float2bytestream(temp, offset, value);
179	addBytes(temp, 4);
180}
181
182void LLScriptByteCodeChunk::addLabel(char *name)
183{
184	if (mJumpTable)
185	{
186		mJumpTable->addLabel(name, mCurrentOffset);
187	}
188}
189
190void LLScriptByteCodeChunk::addJump(char *name)
191{
192	if (mJumpTable)
193	{
194		mJumpTable->addJump(name, mCurrentOffset);
195	}
196}
197
198// format is Byte 0: jump op code Byte 1 - 4: offset
199// the jump position points to Byte 5, so we need to add the data at
200//  offset - 4, offset - 3, offset - 2, and offset - 1
201
202// offset is label - jump
203
204void LLScriptByteCodeChunk::connectJumps()
205{
206	char *jump;
207	S32 offset, jumppos;
208
209	if (mJumpTable)
210	{
211		for (jump = mJumpTable->mJumpMap.getFirstKey();
212			 jump;
213			 jump = mJumpTable->mJumpMap.getNextKey())
214		{
215			jumppos = *mJumpTable->mJumpMap[jump];
216			offset = *mJumpTable->mLabelMap[jump] - jumppos;
217			jumppos = jumppos - 4;
218			integer2bytestream(mCodeChunk, jumppos, offset);
219		}
220	}
221}
222
223LLScriptScriptCodeChunk::LLScriptScriptCodeChunk(S32 total_size)
224: mTotalSize(total_size), mCompleteCode(NULL)
225{
226	mRegisters = new LLScriptByteCodeChunk(FALSE);
227	mGlobalVariables = new LLScriptByteCodeChunk(FALSE);
228	mGlobalFunctions = new LLScriptByteCodeChunk(FALSE);
229	mStates = new LLScriptByteCodeChunk(FALSE);
230	mHeap = new LLScriptByteCodeChunk(FALSE);
231}
232
233LLScriptScriptCodeChunk::~LLScriptScriptCodeChunk()
234{
235	delete mRegisters;
236	delete mGlobalVariables;
237	delete mGlobalFunctions;
238	delete mStates;
239	delete mHeap;
240	delete [] mCompleteCode;
241}
242
243void LLScriptScriptCodeChunk::build(LLFILE *efp, LLFILE *bcfp)
244{
245	S32 code_data_size = mRegisters->mCurrentOffset + 
246					 mGlobalVariables->mCurrentOffset +
247					 mGlobalFunctions->mCurrentOffset +
248					 mStates->mCurrentOffset +
249					 mHeap->mCurrentOffset;
250
251	S32 offset = 0;
252
253	if (code_data_size < mTotalSize)
254	{
255		mCompleteCode = new U8[mTotalSize];
256		memset(mCompleteCode, 0, mTotalSize);
257		
258		memcpy(mCompleteCode, mRegisters->mCodeChunk, mRegisters->mCurrentOffset);	
259		offset += mRegisters->mCurrentOffset;
260
261		set_register(mCompleteCode, LREG_IP, 0);
262		set_register(mCompleteCode, LREG_VN, LSL2_VERSION_NUMBER);
263		set_event_register(mCompleteCode, LREG_IE, 0, LSL2_CURRENT_MAJOR_VERSION);
264		set_register(mCompleteCode, LREG_BP, mTotalSize - 1);
265		set_register(mCompleteCode, LREG_SP, mTotalSize - 1);
266
267		set_register(mCompleteCode, LREG_GVR, offset);
268		
269		memcpy(mCompleteCode + offset, mGlobalVariables->mCodeChunk, mGlobalVariables->mCurrentOffset);	 	/*Flawfinder: ignore*/
270		offset += mGlobalVariables->mCurrentOffset;
271
272		set_register(mCompleteCode, LREG_GFR, offset);
273		
274		memcpy(mCompleteCode + offset, mGlobalFunctions->mCodeChunk, mGlobalFunctions->mCurrentOffset);	/*Flawfinder: ignore*/
275		offset += mGlobalFunctions->mCurrentOffset;
276
277		set_register(mCompleteCode, LREG_SR, offset);
278		// zero is, by definition the default state
279		set_register(mCompleteCode, LREG_CS, 0);
280		set_register(mCompleteCode, LREG_NS, 0);
281		set_event_register(mCompleteCode, LREG_CE, LSCRIPTStateBitField[LSTT_STATE_ENTRY], LSL2_CURRENT_MAJOR_VERSION);
282		S32 default_state_offset = 0;
283		if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
284		{
285			default_state_offset = 8;
286		}
287		else
288		{
289			default_state_offset = 4;
290		}
291		set_event_register(mCompleteCode, LREG_ER, bytestream2u64(mStates->mCodeChunk, default_state_offset), LSL2_CURRENT_MAJOR_VERSION);
292		
293		memcpy(mCompleteCode + offset, mStates->mCodeChunk, mStates->mCurrentOffset);	 	/*Flawfinder: ignore*/
294		offset += mStates->mCurrentOffset;
295
296		set_register(mCompleteCode, LREG_HR, offset);
297		
298		memcpy(mCompleteCode + offset, mHeap->mCodeChunk, mHeap->mCurrentOffset);	 	/*Flawfinder: ignore*/
299		offset += mHeap->mCurrentOffset;
300		
301		set_register(mCompleteCode, LREG_HP, offset);
302		set_register(mCompleteCode, LREG_FR, 0);
303		set_register(mCompleteCode, LREG_SLR, 0);
304		set_register(mCompleteCode, LREG_ESR, 0);
305		set_register(mCompleteCode, LREG_PR, 0);
306		set_register(mCompleteCode, LREG_TM, mTotalSize);
307
308
309		if (fwrite(mCompleteCode, 1, mTotalSize, bcfp) != (size_t)mTotalSize)
310		{
311			llwarns << "Short write" << llendl;
312		}
313	}
314	else
315	{
316		gErrorToText.writeError(efp, 0, 0, LSERROR_ASSEMBLE_OUT_OF_MEMORY);
317	}
318}
319
320LLScriptScriptCodeChunk	*gScriptCodeChunk;