00001
00032 #include "linden_common.h"
00033
00034 #include "lscript_bytecode.h"
00035 #include "lscript_error.h"
00036
00037 #if defined(_MSC_VER)
00038 # pragma warning(disable: 4102) // 'yy_more' : unreferenced label
00039 # pragma warning(disable: 4702) // unreachable code
00040 #endif
00041
00042 LLScriptJumpTable::LLScriptJumpTable()
00043 {
00044 }
00045
00046 LLScriptJumpTable::~LLScriptJumpTable()
00047 {
00048 mLabelMap.deleteAllData();
00049 mJumpMap.deleteAllData();
00050 }
00051
00052 void LLScriptJumpTable::addLabel(char *name, S32 offset)
00053 {
00054 char *temp = gScopeStringTable->addString(name);
00055 mLabelMap[temp] = new S32(offset);
00056 }
00057
00058 void LLScriptJumpTable::addJump(char *name, S32 offset)
00059 {
00060 char *temp = gScopeStringTable->addString(name);
00061 mJumpMap[temp] = new S32(offset);
00062 }
00063
00064
00065 LLScriptByteCodeChunk::LLScriptByteCodeChunk(BOOL b_need_jumps)
00066 : mCodeChunk(NULL), mCurrentOffset(0), mJumpTable(NULL)
00067 {
00068 if (b_need_jumps)
00069 {
00070 mJumpTable = new LLScriptJumpTable();
00071 }
00072 }
00073
00074 LLScriptByteCodeChunk::~LLScriptByteCodeChunk()
00075 {
00076 delete [] mCodeChunk;
00077 delete mJumpTable;
00078 }
00079
00080 void LLScriptByteCodeChunk::addByte(U8 byte)
00081 {
00082 if (mCodeChunk)
00083 {
00084 U8 *temp = new U8[mCurrentOffset + 1];
00085 memcpy(temp, mCodeChunk, mCurrentOffset);
00086 delete [] mCodeChunk;
00087 mCodeChunk = temp;
00088 }
00089 else
00090 {
00091 mCodeChunk = new U8[1];
00092 }
00093 *(mCodeChunk + mCurrentOffset++) = byte;
00094 }
00095
00096 void LLScriptByteCodeChunk::addU16(U16 data)
00097 {
00098 U8 temp[2];
00099 S32 offset = 0;
00100 u162bytestream(temp, offset, data);
00101 addBytes(temp, 2);
00102 }
00103
00104 void LLScriptByteCodeChunk::addBytes(U8 *bytes, S32 size)
00105 {
00106 if (mCodeChunk)
00107 {
00108 U8 *temp = new U8[mCurrentOffset + size];
00109 memcpy(temp, mCodeChunk, mCurrentOffset);
00110 delete [] mCodeChunk;
00111 mCodeChunk = temp;
00112 }
00113 else
00114 {
00115 mCodeChunk = new U8[size];
00116 }
00117 memcpy(mCodeChunk + mCurrentOffset, bytes, size);
00118 mCurrentOffset += size;
00119 }
00120
00121 void LLScriptByteCodeChunk::addBytes(char *bytes, S32 size)
00122 {
00123 if (mCodeChunk)
00124 {
00125 U8 *temp = new U8[mCurrentOffset + size];
00126 memcpy(temp, mCodeChunk, mCurrentOffset);
00127 delete [] mCodeChunk;
00128 mCodeChunk = temp;
00129 }
00130 else
00131 {
00132 mCodeChunk = new U8[size];
00133 }
00134 memcpy(mCodeChunk + mCurrentOffset, bytes, size);
00135 mCurrentOffset += size;
00136 }
00137
00138 void LLScriptByteCodeChunk::addBytes(S32 size)
00139 {
00140 if (mCodeChunk)
00141 {
00142 U8 *temp = new U8[mCurrentOffset + size];
00143 memcpy(temp, mCodeChunk, mCurrentOffset);
00144 delete [] mCodeChunk;
00145 mCodeChunk = temp;
00146 }
00147 else
00148 {
00149 mCodeChunk = new U8[size];
00150 }
00151 memset(mCodeChunk + mCurrentOffset, 0, size);
00152 mCurrentOffset += size;
00153 }
00154
00155 void LLScriptByteCodeChunk::addBytesDontInc(S32 size)
00156 {
00157 if (mCodeChunk)
00158 {
00159 U8 *temp = new U8[mCurrentOffset + size];
00160 memcpy(temp, mCodeChunk, mCurrentOffset);
00161 delete [] mCodeChunk;
00162 mCodeChunk = temp;
00163 }
00164 else
00165 {
00166 mCodeChunk = new U8[size];
00167 }
00168 memset(mCodeChunk + mCurrentOffset, 0, size);
00169 }
00170
00171 void LLScriptByteCodeChunk::addInteger(S32 value)
00172 {
00173 U8 temp[4];
00174 S32 offset = 0;
00175 integer2bytestream(temp, offset, value);
00176 addBytes(temp, 4);
00177 }
00178
00179 void LLScriptByteCodeChunk::addFloat(F32 value)
00180 {
00181 U8 temp[4];
00182 S32 offset = 0;
00183 float2bytestream(temp, offset, value);
00184 addBytes(temp, 4);
00185 }
00186
00187 void LLScriptByteCodeChunk::addLabel(char *name)
00188 {
00189 if (mJumpTable)
00190 {
00191 mJumpTable->addLabel(name, mCurrentOffset);
00192 }
00193 }
00194
00195 void LLScriptByteCodeChunk::addJump(char *name)
00196 {
00197 if (mJumpTable)
00198 {
00199 mJumpTable->addJump(name, mCurrentOffset);
00200 }
00201 }
00202
00203
00204
00205
00206
00207
00208
00209 void LLScriptByteCodeChunk::connectJumps()
00210 {
00211 char *jump;
00212 S32 offset, jumppos;
00213
00214 if (mJumpTable)
00215 {
00216 for (jump = mJumpTable->mJumpMap.getFirstKey();
00217 jump;
00218 jump = mJumpTable->mJumpMap.getNextKey())
00219 {
00220 jumppos = *mJumpTable->mJumpMap[jump];
00221 offset = *mJumpTable->mLabelMap[jump] - jumppos;
00222 jumppos = jumppos - 4;
00223 integer2bytestream(mCodeChunk, jumppos, offset);
00224 }
00225 }
00226 }
00227
00228 LLScriptScriptCodeChunk::LLScriptScriptCodeChunk(S32 total_size)
00229 : mTotalSize(total_size), mCompleteCode(NULL)
00230 {
00231 mRegisters = new LLScriptByteCodeChunk(FALSE);
00232 mGlobalVariables = new LLScriptByteCodeChunk(FALSE);
00233 mGlobalFunctions = new LLScriptByteCodeChunk(FALSE);
00234 mStates = new LLScriptByteCodeChunk(FALSE);
00235 mHeap = new LLScriptByteCodeChunk(FALSE);
00236 }
00237
00238 LLScriptScriptCodeChunk::~LLScriptScriptCodeChunk()
00239 {
00240 delete mRegisters;
00241 delete mGlobalVariables;
00242 delete mGlobalFunctions;
00243 delete mStates;
00244 delete mHeap;
00245 delete [] mCompleteCode;
00246 }
00247
00248 void LLScriptScriptCodeChunk::build(FILE *efp, FILE *bcfp)
00249 {
00250 S32 code_data_size = mRegisters->mCurrentOffset +
00251 mGlobalVariables->mCurrentOffset +
00252 mGlobalFunctions->mCurrentOffset +
00253 mStates->mCurrentOffset +
00254 mHeap->mCurrentOffset;
00255
00256 S32 offset = 0;
00257
00258 if (code_data_size < mTotalSize)
00259 {
00260 mCompleteCode = new U8[mTotalSize];
00261 memset(mCompleteCode, 0, mTotalSize);
00262
00263 memcpy(mCompleteCode, mRegisters->mCodeChunk, mRegisters->mCurrentOffset);
00264 offset += mRegisters->mCurrentOffset;
00265
00266 set_register(mCompleteCode, LREG_IP, 0);
00267 set_register(mCompleteCode, LREG_VN, LSL2_VERSION_NUMBER);
00268 set_event_register(mCompleteCode, LREG_IE, 0, LSL2_CURRENT_MAJOR_VERSION);
00269 set_register(mCompleteCode, LREG_BP, mTotalSize - 1);
00270 set_register(mCompleteCode, LREG_SP, mTotalSize - 1);
00271
00272 set_register(mCompleteCode, LREG_GVR, offset);
00273
00274 memcpy(mCompleteCode + offset, mGlobalVariables->mCodeChunk, mGlobalVariables->mCurrentOffset);
00275 offset += mGlobalVariables->mCurrentOffset;
00276
00277 set_register(mCompleteCode, LREG_GFR, offset);
00278
00279 memcpy(mCompleteCode + offset, mGlobalFunctions->mCodeChunk, mGlobalFunctions->mCurrentOffset);
00280 offset += mGlobalFunctions->mCurrentOffset;
00281
00282 set_register(mCompleteCode, LREG_SR, offset);
00283
00284 set_register(mCompleteCode, LREG_CS, 0);
00285 set_register(mCompleteCode, LREG_NS, 0);
00286 set_event_register(mCompleteCode, LREG_CE, LSCRIPTStateBitField[LSTT_STATE_ENTRY], LSL2_CURRENT_MAJOR_VERSION);
00287 S32 default_state_offset = 0;
00288 if (LSL2_CURRENT_MAJOR_VERSION == LSL2_MAJOR_VERSION_TWO)
00289 {
00290 default_state_offset = 8;
00291 }
00292 else
00293 {
00294 default_state_offset = 4;
00295 }
00296 set_event_register(mCompleteCode, LREG_ER, bytestream2u64(mStates->mCodeChunk, default_state_offset), LSL2_CURRENT_MAJOR_VERSION);
00297
00298 memcpy(mCompleteCode + offset, mStates->mCodeChunk, mStates->mCurrentOffset);
00299 offset += mStates->mCurrentOffset;
00300
00301 set_register(mCompleteCode, LREG_HR, offset);
00302
00303 memcpy(mCompleteCode + offset, mHeap->mCodeChunk, mHeap->mCurrentOffset);
00304 offset += mHeap->mCurrentOffset;
00305
00306 set_register(mCompleteCode, LREG_HP, offset);
00307 set_register(mCompleteCode, LREG_FR, 0);
00308 set_register(mCompleteCode, LREG_SLR, 0);
00309 set_register(mCompleteCode, LREG_ESR, 0);
00310 set_register(mCompleteCode, LREG_PR, 0);
00311 set_register(mCompleteCode, LREG_TM, mTotalSize);
00312
00313
00314 if (fwrite(mCompleteCode, 1, mTotalSize, bcfp) != mTotalSize)
00315 {
00316 llwarns << "Short write" << llendl;
00317 }
00318 }
00319 else
00320 {
00321 gErrorToText.writeError(efp, 0, 0, LSERROR_ASSEMBLE_OUT_OF_MEMORY);
00322 }
00323 }
00324
00325 LLScriptScriptCodeChunk *gScriptCodeChunk;