int CFParser :: buildDerivationTree(_ScriptReader& reader, size_t startRuleId, MemoryWriter& writer) { DerivationQueue predictions; predictions.push(DerivationItem(startRuleId, 0, -1)); ScriptBookmark bm; while (predictions.Count() > 0) { predictions.push(DerivationItem(0)); bm = reader.read(); int terminalOffset = writer.Position(); writer.write(&bm, sizeof(ScriptBookmark)); DerivationItem current = predictions.pop(); while (current.ruleId != 0) { if (current.ruleId == -1) { return current.trace; } predict(predictions, current, reader, bm, terminalOffset, writer); current = predictions.pop(); } } throw EParseError(bm.column, bm.row); }
void JITLinker::ReferenceHelper :: writeReference(MemoryWriter& writer, ref_t reference, size_t disp, _Module* module) { ref_t mask = reference & mskAnyRef; ref_t refID = reference & ~mskAnyRef; //// check if it is a constant, resolve it immediately //if (mask == mskLinkerConstant) { // writer.writeDWord(getLinkerConstant(refID)); // return; //} if (!module) module = _module; ref_t position = writer.Position(); writer.writeDWord(disp); // vmt entry offset should be resolved later if (mask == mskVMTEntryOffset) { _references->add(position, RefInfo(reference, module)); return; } // try to resolve immediately void* vaddress = _owner->_loader->resolveReference( _owner->_loader->retrieveReference(module, refID, mask), mask); if (vaddress != LOADER_NOTLOADED) { resolveReference(writer.Memory(), position, (ref_t)vaddress, mask, _owner->_virtualMode); } // or resolve later else _references->add(position, RefInfo(reference, module)); }
void JITCompiler32 :: allocateVMT(MemoryWriter& vmtWriter, size_t flags, size_t vmtLength) { alignCode(&vmtWriter, VA_ALIGNMENT, false); // create VMT header: // dummy package reference vmtWriter.writeDWord(0); // vmt length vmtWriter.writeDWord(vmtLength); // vmt flags vmtWriter.writeDWord(flags); // dummy class reference vmtWriter.writeDWord(0); int position = vmtWriter.Position(); size_t vmtSize = 0; if (test(flags, elStandartVMT)) { // + VMT length vmtSize = vmtLength * sizeof(VMTEntry); } vmtWriter.writeBytes(0, vmtSize); vmtWriter.seek(position); }
void Instance::ImageReferenceHelper :: writeReference(MemoryWriter& writer, ref_t reference, size_t disp, _Module* module) { size_t pos = reference & ~mskAnyRef; if (test(reference, mskRelCodeRef)) { writer.writeDWord(pos - writer.Position() - 4); } else writer.writeDWord((test(reference, mskRDataRef) ? _statBase : _codeBase) + pos + disp); }
void ECodesAssembler :: compileJump(ByteCode code, TokenInfo& token, MemoryWriter& writer, LabelInfo& info) { writer.writeByte(code); int label = 0; token.read(); if (info.labels.exist(token.value)) { label = info.labels.get(token.value) - writer.Position() - 4; } else { info.fwdJumps.add(token.value, writer.Position()); } writer.writeDWord(label); }
inline int writeTrailItem(MemoryWriter& writer, int nonterminal, int next) { int offset = writer.Position(); writer.writeDWord(nonterminal); writer.writeDWord(next); return offset; }
int JITCompiler32 :: allocateConstant(MemoryWriter& writer, size_t objectOffset) { writer.writeBytes(0, objectOffset); alignCode(&writer, VA_ALIGNMENT, false); return writer.Position() - 4; }
size_t JITLinker :: loadMethod(ReferenceHelper& refHelper, MemoryReader& reader, MemoryWriter& writer) { size_t position = writer.Position(); // method just in time compilation _compiler->compileProcedure(refHelper, reader, writer); return _virtualMode ? position : (size_t)writer.Memory()->get(position); }
inline int writeDerivationItem(MemoryWriter& writer, int key, int terminal, int trace) { int offset = writer.Position(); writer.writeDWord(key); writer.writeDWord(terminal); writer.writeDWord(trace); return offset; }
void ECodesAssembler :: compileRJump(ByteCode code, TokenInfo& token, MemoryWriter& writer, LabelInfo& info, _Module* binary) { writer.writeByte(code); int label = 0; token.read(); if (info.labels.exist(token.value)) { label = info.labels.get(token.value) - writer.Position() - 8; } else { info.fwdJumps.add(token.value, writer.Position() + 4); } size_t reference = compileRArg(token, binary); writer.writeDWord(reference); writer.writeDWord(label); }
void ECodesAssembler :: compileMccJump(ByteCode code, TokenInfo& token, MemoryWriter& writer, LabelInfo& info) { writer.writeByte(code); int label = 0; token.read(); if (info.labels.exist(token.value)) { label = info.labels.get(token.value) - writer.Position() - 8; } else { info.fwdJumps.add(token.value, 4 + writer.Position()); } int message = token.readInteger(constants); writer.writeDWord(message); writer.writeDWord(label); }
void ECodesAssembler :: fixJump(ident_t label, MemoryWriter& writer, LabelInfo& info) { _Memory* code = writer.Memory(); Map<ident_t, int>::Iterator it = info.fwdJumps.start(); while (!it.Eof()) { if (label.compare(it.key())) { (*code)[*it] = writer.Position() - *it - 4; } it++; } }
void ECodesAssembler :: fixJump(const wchar16_t* label, MemoryWriter& writer, LabelInfo& info) { _Memory* code = writer.Memory(); Map<const wchar16_t*, int>::Iterator it = info.fwdJumps.start(); while (!it.Eof()) { if (StringHelper::compare(it.key(), label)) { (*code)[*it] = writer.Position(); } it++; } }
void JITCompiler32 :: fixVMT(MemoryWriter& vmtWriter, void* classClassVAddress, void* packageVAddress, int count, bool virtualMode) { _Memory* image = vmtWriter.Memory(); // update class package reference if available if (packageVAddress != NULL) { int position = vmtWriter.Position(); vmtWriter.seek(position - 0x10); if (virtualMode) { vmtWriter.writeRef((ref_t)packageVAddress, 0); } else vmtWriter.writeDWord((int)packageVAddress); vmtWriter.seek(position); } // update class vmt reference if available if (classClassVAddress != NULL) { vmtWriter.seek(vmtWriter.Position() - 4); if (virtualMode) { vmtWriter.writeRef((ref_t)classClassVAddress, 0); } else vmtWriter.writeDWord((int)classClassVAddress); } // if in virtual mode mark method addresses as reference if (virtualMode) { ref_t entryPosition = vmtWriter.Position(); for (int i = 0 ; i < count ; i++) { image->addReference(mskCodeRef, entryPosition + 4); entryPosition += 8; } } }
void ECodesAssembler :: compileCommand(TokenInfo& token, MemoryWriter& writer, LabelInfo& info, _Module* binary) { bool recognized = true; ByteCode opcode = ByteCodeCompiler::code(token.value); if (opcode != bcNone) { switch (opcode) { case bcCallR: case bcACopyR: case bcPushR: compileRCommand(opcode, token, writer, binary); break; case bcCallExtR: compileExtCommand(opcode, token, writer, binary); break; case bcACallVI: case bcAJumpVI: case bcALoadSI: case bcBLoadSI: case bcBLoadFI: case bcACopyS: case bcACopyF: case bcBCopyS: case bcBCopyF: case bcALoadAI: case bcALoadFI: case bcPushAI: case bcOpen: case bcAddN: case bcMulN: case bcDLoadFI: case bcDLoadSI: case bcDSaveFI: case bcDSaveSI: case bcRestore: case bcReserve: case bcALoadBI: case bcASaveSI: case bcASaveFI: case bcNSaveI: case bcNLoadI: case bcESwapSI: case bcBSwapSI: case bcAXSaveBI: case bcELoadFI: case bcELoadSI: case bcESaveSI: case bcESaveFI: case bcShiftN: case bcEAddN: case bcDSwapSI: case bcAJumpI: case bcACallI: case bcNReadI: case bcNWriteI: compileICommand(opcode, token, writer); break; case bcQuitN: case bcPopI: case bcDCopy: case bcECopy: case bcSetVerb: case bcSetSubj: case bcAndN: case bcOrN: case bcPushN: compileNCommand(opcode, token, writer); break; case bcCopyM: compileMCommand(opcode, token, writer, binary); break; case bcIfB: case bcElseB: case bcIf: case bcElse: case bcLess: case bcNotLess: case bcNext: case bcJump: case bcHook: case bcAddress: compileJump(opcode, token, writer, info); break; case bcIfM: case bcElseM: compileMccJump(opcode, token, writer, info); break; case bcIfN: case bcElseN: case bcLessN: compileNJump(opcode, token, writer, info); break; case bcIfR: case bcElseR: compileRJump(opcode, token, writer, info, binary); break; case bcNewN: compileCreateCommand(opcode, token, writer, binary); break; case bcSelectR: compileRRCommand(opcode, token, writer, binary); break; case bcXIndexRM: compileRMCommand(opcode, token, writer, binary); break; default: writeCommand(ByteCommand(opcode), writer); break; } } else recognized = false; if (!recognized) { info.labels.add(token.value, writer.Position()); fixJump(token.value, writer, info); writeCommand(ByteCommand(bcNop), writer); token.read(":", "':' expected (%d)\n"); } token.read(); }
void ECodesAssembler :: compileCommand(TokenInfo& token, MemoryWriter& writer, LabelInfo& info, _Module* binary) { bool recognized = true; ByteCode opcode = ByteCodeCompiler::code(token.value); switch (opcode) { case bcNop: case bcBreakpoint: case bcPushB: case bcPop: case bcPushM: case bcMCopyVerb: case bcThrow: case bcMCopySubj: case bcPushA: case bcPopA: case bcACopyB: case bcBCopyA: case bcPopM: case bcBSRedirect: case bcBSGRedirect: case bcClose: case bcPopB: case bcMQuit: case bcGet: case bcSet: case bcALoadD: case bcDDec: case bcGetLen: case bcDInc: writeCommand(ByteCommand(opcode), writer); break; case bcCallR: case bcACopyR: compileRCommand(opcode, token, writer, binary); break; case bcACopyF: case bcACallVI: case bcALoadSI: case bcASaveSI: case bcPushFI: case bcALoadAI: case bcMLoadAI: case bcMLoadSI: case bcMLoadFI: case bcMAddAI: case bcPushAI: case bcMSaveParams: case bcPushSI: case bcACopyS: case bcDAddAI: case bcDSubAI: case bcDAddSI: case bcDSubSI: case bcDLoadAI: case bcDSaveAI: case bcDLoadSI: case bcDSaveSI: case bcDLoadFI: case bcDSaveFI: case bcPopSI: compileICommand(opcode, token, writer); break; case bcOpen: case bcMAdd: case bcAJumpVI: case bcMCopy: case bcMReset: case bcQuitN: case bcPushN: case bcPopI: case bcDCopy: compileNCommand(opcode, token, writer); break; case bcJump: case bcDElse: case bcDThen: case bcWSTest: case bcBSTest: case bcTest: compileJump(opcode, token, writer, info); break; case bcMElse: case bcMThen: case bcMElseVerb: case bcMThenVerb: compileMccJump(opcode, token, writer, info); break; case bcTestFlag: case bcAElseSI: case bcAThenSI: case bcElseFlag: case bcMElseAI: case bcMThenAI: case bcDElseN: case bcDThenN: compileNJump(opcode, token, writer, info); break; case bcSCallVI: compileNNCommand(opcode, token, writer); break; default: recognized = false; break; } // check if it is function if (!recognized) { ByteCode code = bcNone; const wchar16_t* func = token.value; if (token.value[0]=='n') { code = bcNFunc; func++; } else if (token.value[0]=='l') { code = bcLFunc; func++; } else if (token.value[0]=='r') { code = bcRFunc; func++; } else if (token.value[0]=='w' && token.value[1]=='s') { code = bcWSFunc; func+=2; } else if (token.value[0]=='b' && token.value[1]=='s') { code = bcBSFunc; func+=2; } if (code != bcNone) { FunctionCode function = ByteCodeCompiler::codeFunction(func); if (function != fnUnknown) { writeCommand(ByteCommand(code, function), writer); recognized = true; } } } if (!recognized) { info.labels.add(token.value, writer.Position()); fixJump(token.value, writer, info); writeCommand(ByteCommand(bcNop), writer); token.read(_T(":"), _T("':' expected (%d)\n")); } token.read(); }