lscript_bytecode.cpp

Go to the documentation of this file.
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);       /* Flawfinder: ignore */
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);       /* Flawfinder: ignore */
00110                 delete [] mCodeChunk;
00111                 mCodeChunk = temp;
00112         }
00113         else
00114         {
00115                 mCodeChunk = new U8[size];
00116         }
00117         memcpy(mCodeChunk + mCurrentOffset, bytes, size);/* Flawfinder: ignore */
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);               /*Flawfinder: ignore*/
00127                 delete [] mCodeChunk;
00128                 mCodeChunk = temp;
00129         }
00130         else
00131         {
00132                 mCodeChunk = new U8[size];
00133         }
00134         memcpy(mCodeChunk + mCurrentOffset, bytes, size);       /*Flawfinder: ignore*/
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);       /*Flawfinder: ignore*/
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);               /*Flawfinder: ignore*/
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 // format is Byte 0: jump op code Byte 1 - 4: offset
00204 // the jump position points to Byte 5, so we need to add the data at
00205 //  offset - 4, offset - 3, offset - 2, and offset - 1
00206 
00207 // offset is label - jump
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);         /*Flawfinder: ignore*/
00275                 offset += mGlobalVariables->mCurrentOffset;
00276 
00277                 set_register(mCompleteCode, LREG_GFR, offset);
00278                 
00279                 memcpy(mCompleteCode + offset, mGlobalFunctions->mCodeChunk, mGlobalFunctions->mCurrentOffset); /*Flawfinder: ignore*/
00280                 offset += mGlobalFunctions->mCurrentOffset;
00281 
00282                 set_register(mCompleteCode, LREG_SR, offset);
00283                 // zero is, by definition the default state
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);           /*Flawfinder: ignore*/
00299                 offset += mStates->mCurrentOffset;
00300 
00301                 set_register(mCompleteCode, LREG_HR, offset);
00302                 
00303                 memcpy(mCompleteCode + offset, mHeap->mCodeChunk, mHeap->mCurrentOffset);               /*Flawfinder: ignore*/
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;

Generated on Thu Jul 1 06:09:49 2010 for Second Life Viewer by  doxygen 1.4.7