diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/lscript/lscript_compile/lscript_bytecode.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/lscript/lscript_compile/lscript_bytecode.cpp')
-rw-r--r-- | linden/indra/lscript/lscript_compile/lscript_bytecode.cpp | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/linden/indra/lscript/lscript_compile/lscript_bytecode.cpp b/linden/indra/lscript/lscript_compile/lscript_bytecode.cpp new file mode 100644 index 0000000..6d18a1a --- /dev/null +++ b/linden/indra/lscript/lscript_compile/lscript_bytecode.cpp | |||
@@ -0,0 +1,318 @@ | |||
1 | /** | ||
2 | * @file lscript_bytecode.cpp | ||
3 | * @brief classes to build actual bytecode | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "linden_common.h" | ||
29 | |||
30 | #include "lscript_bytecode.h" | ||
31 | #include "lscript_error.h" | ||
32 | |||
33 | #if defined(_MSC_VER) | ||
34 | # pragma warning(disable: 4102) // 'yy_more' : unreferenced label | ||
35 | # pragma warning(disable: 4702) // unreachable code | ||
36 | #endif | ||
37 | |||
38 | LLScriptJumpTable::LLScriptJumpTable() | ||
39 | { | ||
40 | } | ||
41 | |||
42 | LLScriptJumpTable::~LLScriptJumpTable() | ||
43 | { | ||
44 | mLabelMap.deleteAllData(); | ||
45 | mJumpMap.deleteAllData(); | ||
46 | } | ||
47 | |||
48 | void LLScriptJumpTable::addLabel(char *name, S32 offset) | ||
49 | { | ||
50 | char *temp = gScopeStringTable->addString(name); | ||
51 | mLabelMap[temp] = new S32(offset); | ||
52 | } | ||
53 | |||
54 | void LLScriptJumpTable::addJump(char *name, S32 offset) | ||
55 | { | ||
56 | char *temp = gScopeStringTable->addString(name); | ||
57 | mJumpMap[temp] = new S32(offset); | ||
58 | } | ||
59 | |||
60 | |||
61 | LLScriptByteCodeChunk::LLScriptByteCodeChunk(BOOL b_need_jumps) | ||
62 | : mCodeChunk(NULL), mCurrentOffset(0), mJumpTable(NULL) | ||
63 | { | ||
64 | if (b_need_jumps) | ||
65 | { | ||
66 | mJumpTable = new LLScriptJumpTable(); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | LLScriptByteCodeChunk::~LLScriptByteCodeChunk() | ||
71 | { | ||
72 | delete [] mCodeChunk; | ||
73 | delete mJumpTable; | ||
74 | } | ||
75 | |||
76 | void LLScriptByteCodeChunk::addByte(U8 byte) | ||
77 | { | ||
78 | if (mCodeChunk) | ||
79 | { | ||
80 | U8 *temp = new U8[mCurrentOffset + 1]; | ||
81 | memcpy(temp, mCodeChunk, mCurrentOffset); | ||
82 | delete [] mCodeChunk; | ||
83 | mCodeChunk = temp; | ||
84 | } | ||
85 | else | ||
86 | { | ||
87 | mCodeChunk = new U8[1]; | ||
88 | } | ||
89 | *(mCodeChunk + mCurrentOffset++) = byte; | ||
90 | } | ||
91 | |||
92 | void LLScriptByteCodeChunk::addU16(U16 data) | ||
93 | { | ||
94 | U8 temp[2]; | ||
95 | S32 offset = 0; | ||
96 | u162bytestream(temp, offset, data); | ||
97 | addBytes(temp, 2); | ||
98 | } | ||
99 | |||
100 | void LLScriptByteCodeChunk::addBytes(U8 *bytes, S32 size) | ||
101 | { | ||
102 | if (mCodeChunk) | ||
103 | { | ||
104 | U8 *temp = new U8[mCurrentOffset + size]; | ||
105 | memcpy(temp, mCodeChunk, mCurrentOffset); | ||
106 | delete [] mCodeChunk; | ||
107 | mCodeChunk = temp; | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | mCodeChunk = new U8[size]; | ||
112 | } | ||
113 | memcpy(mCodeChunk + mCurrentOffset, bytes, size); | ||
114 | mCurrentOffset += size; | ||
115 | } | ||
116 | |||
117 | void LLScriptByteCodeChunk::addBytes(char *bytes, S32 size) | ||
118 | { | ||
119 | if (mCodeChunk) | ||
120 | { | ||
121 | U8 *temp = new U8[mCurrentOffset + size]; | ||
122 | memcpy(temp, mCodeChunk, mCurrentOffset); | ||
123 | delete [] mCodeChunk; | ||
124 | mCodeChunk = temp; | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | mCodeChunk = new U8[size]; | ||
129 | } | ||
130 | memcpy(mCodeChunk + mCurrentOffset, bytes, size); | ||
131 | mCurrentOffset += size; | ||
132 | } | ||
133 | |||
134 | void LLScriptByteCodeChunk::addBytes(S32 size) | ||
135 | { | ||
136 | if (mCodeChunk) | ||
137 | { | ||
138 | U8 *temp = new U8[mCurrentOffset + size]; | ||
139 | memcpy(temp, mCodeChunk, mCurrentOffset); | ||
140 | delete [] mCodeChunk; | ||
141 | mCodeChunk = temp; | ||
142 | } | ||
143 | else | ||
144 | { | ||
145 | mCodeChunk = new U8[size]; | ||
146 | } | ||
147 | memset(mCodeChunk + mCurrentOffset, 0, size); | ||
148 | mCurrentOffset += size; | ||
149 | } | ||
150 | |||
151 | void LLScriptByteCodeChunk::addBytesDontInc(S32 size) | ||
152 | { | ||
153 | if (mCodeChunk) | ||
154 | { | ||
155 | U8 *temp = new U8[mCurrentOffset + size]; | ||
156 | memcpy(temp, mCodeChunk, mCurrentOffset); | ||
157 | delete [] mCodeChunk; | ||
158 | mCodeChunk = temp; | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | mCodeChunk = new U8[size]; | ||
163 | } | ||
164 | memset(mCodeChunk + mCurrentOffset, 0, size); | ||
165 | } | ||
166 | |||
167 | void LLScriptByteCodeChunk::addInteger(S32 value) | ||
168 | { | ||
169 | U8 temp[4]; | ||
170 | S32 offset = 0; | ||
171 | integer2bytestream(temp, offset, value); | ||
172 | addBytes(temp, 4); | ||
173 | } | ||
174 | |||
175 | void LLScriptByteCodeChunk::addFloat(F32 value) | ||
176 | { | ||
177 | U8 temp[4]; | ||
178 | S32 offset = 0; | ||
179 | float2bytestream(temp, offset, value); | ||
180 | addBytes(temp, 4); | ||
181 | } | ||
182 | |||
183 | void LLScriptByteCodeChunk::addLabel(char *name) | ||
184 | { | ||
185 | if (mJumpTable) | ||
186 | { | ||
187 | mJumpTable->addLabel(name, mCurrentOffset); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | void LLScriptByteCodeChunk::addJump(char *name) | ||
192 | { | ||
193 | if (mJumpTable) | ||
194 | { | ||
195 | mJumpTable->addJump(name, mCurrentOffset); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | // format is Byte 0: jump op code Byte 1 - 4: offset | ||
200 | // the jump position points to Byte 5, so we need to add the data at | ||
201 | // offset - 4, offset - 3, offset - 2, and offset - 1 | ||
202 | |||
203 | // offset is label - jump | ||
204 | |||
205 | void LLScriptByteCodeChunk::connectJumps() | ||
206 | { | ||
207 | char *jump; | ||
208 | S32 offset, jumppos; | ||
209 | |||
210 | if (mJumpTable) | ||
211 | { | ||
212 | for (jump = mJumpTable->mJumpMap.getFirstKey(); | ||
213 | jump; | ||
214 | jump = mJumpTable->mJumpMap.getNextKey()) | ||
215 | { | ||
216 | jumppos = *mJumpTable->mJumpMap[jump]; | ||
217 | offset = *mJumpTable->mLabelMap[jump] - jumppos; | ||
218 | jumppos = jumppos - 4; | ||
219 | integer2bytestream(mCodeChunk, jumppos, offset); | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
224 | LLScriptScriptCodeChunk::LLScriptScriptCodeChunk(S32 total_size) | ||
225 | : mTotalSize(total_size), mCompleteCode(NULL) | ||
226 | { | ||
227 | mRegisters = new LLScriptByteCodeChunk(FALSE); | ||
228 | mGlobalVariables = new LLScriptByteCodeChunk(FALSE); | ||
229 | mGlobalFunctions = new LLScriptByteCodeChunk(FALSE); | ||
230 | mStates = new LLScriptByteCodeChunk(FALSE); | ||
231 | mHeap = new LLScriptByteCodeChunk(FALSE); | ||
232 | } | ||
233 | |||
234 | LLScriptScriptCodeChunk::~LLScriptScriptCodeChunk() | ||
235 | { | ||
236 | delete mRegisters; | ||
237 | delete mGlobalVariables; | ||
238 | delete mGlobalFunctions; | ||
239 | delete mStates; | ||
240 | delete mHeap; | ||
241 | delete [] mCompleteCode; | ||
242 | } | ||
243 | |||
244 | void LLScriptScriptCodeChunk::build(FILE *efp, FILE *bcfp) | ||
245 | { | ||
246 | S32 code_data_size = mRegisters->mCurrentOffset + | ||
247 | mGlobalVariables->mCurrentOffset + | ||
248 | mGlobalFunctions->mCurrentOffset + | ||
249 | mStates->mCurrentOffset + | ||
250 | mHeap->mCurrentOffset; | ||
251 | |||
252 | S32 offset = 0; | ||
253 | |||
254 | if (code_data_size < mTotalSize) | ||
255 | { | ||
256 | mCompleteCode = new U8[mTotalSize]; | ||
257 | memset(mCompleteCode, 0, mTotalSize); | ||
258 | |||
259 | memcpy(mCompleteCode, mRegisters->mCodeChunk, mRegisters->mCurrentOffset); | ||
260 | offset += mRegisters->mCurrentOffset; | ||
261 | |||
262 | set_register(mCompleteCode, LREG_IP, 0); | ||
263 | set_register(mCompleteCode, LREG_VN, LSL2_VERSION_NUMBER); | ||
264 | set_event_register(mCompleteCode, LREG_IE, 0, LSL2_CURRENT_MAJOR_VERSION); | ||
265 | set_register(mCompleteCode, LREG_BP, mTotalSize - 1); | ||
266 | set_register(mCompleteCode, LREG_SP, mTotalSize - 1); | ||
267 | |||
268 | set_register(mCompleteCode, LREG_GVR, offset); | ||
269 | |||
270 | memcpy(mCompleteCode + offset, mGlobalVariables->mCodeChunk, mGlobalVariables->mCurrentOffset); | ||
271 | offset += mGlobalVariables->mCurrentOffset; | ||
272 | |||
273 | set_register(mCompleteCode, LREG_GFR, offset); | ||
274 | |||
275 | memcpy(mCompleteCode + offset, mGlobalFunctions->mCodeChunk, mGlobalFunctions->mCurrentOffset); | ||
276 | offset += mGlobalFunctions->mCurrentOffset; | ||
277 | |||
278 | set_register(mCompleteCode, LREG_SR, offset); | ||
279 | // zero is, by definition the default state | ||
280 | set_register(mCompleteCode, LREG_CS, 0); | ||
281 | set_register(mCompleteCode, LREG_NS, 0); | ||
282 | set_event_register(mCompleteCode, LREG_CE, LSCRIPTStateBitField[LSTT_STATE_ENTRY], LSL2_CURRENT_MAJOR_VERSION); | ||
283 | S32 default_state_offset = 0; | ||
284 | if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO) | ||
285 | { | ||
286 | default_state_offset = 8; | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | default_state_offset = 4; | ||
291 | } | ||
292 | set_event_register(mCompleteCode, LREG_ER, bytestream2u64(mStates->mCodeChunk, default_state_offset), LSL2_CURRENT_MAJOR_VERSION); | ||
293 | |||
294 | memcpy(mCompleteCode + offset, mStates->mCodeChunk, mStates->mCurrentOffset); | ||
295 | offset += mStates->mCurrentOffset; | ||
296 | |||
297 | set_register(mCompleteCode, LREG_HR, offset); | ||
298 | |||
299 | memcpy(mCompleteCode + offset, mHeap->mCodeChunk, mHeap->mCurrentOffset); | ||
300 | offset += mHeap->mCurrentOffset; | ||
301 | |||
302 | set_register(mCompleteCode, LREG_HP, offset); | ||
303 | set_register(mCompleteCode, LREG_FR, 0); | ||
304 | set_register(mCompleteCode, LREG_SLR, 0); | ||
305 | set_register(mCompleteCode, LREG_ESR, 0); | ||
306 | set_register(mCompleteCode, LREG_PR, 0); | ||
307 | set_register(mCompleteCode, LREG_TM, mTotalSize); | ||
308 | |||
309 | |||
310 | fwrite(mCompleteCode, 1, mTotalSize, bcfp); | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | gErrorToText.writeError(efp, 0, 0, LSERROR_ASSEMBLE_OUT_OF_MEMORY); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | LLScriptScriptCodeChunk *gScriptCodeChunk; | ||