From 7713a8f45ae690c759a17ee5bd77ee0409ed0a98 Mon Sep 17 00:00:00 2001 From: Blair McGlashan Date: Mon, 2 Dec 2019 18:39:07 +0000 Subject: [PATCH] Use fixed width integer types in Compiler - Contributes to #535 - Contributes to #531 - Also address many code analysis issues from VS19 in-IDE parser - e.g. Use of enum class in preference to unscoped enums - Define specific integer types (using enum class) for IPs and text positions to help identify errors --- Core/DolphinVM/Compiler/Compiler.idl | 5 +- Core/DolphinVM/Compiler/CompilerSupport.cpp | 4 +- Core/DolphinVM/Compiler/LexicalScope.cpp | 273 +-- Core/DolphinVM/Compiler/LexicalScope.h | 380 ++-- .../Compiler/ParseInlinedMessages.cpp | 266 ++- Core/DolphinVM/Compiler/bytecode.h | 301 ++-- Core/DolphinVM/Compiler/compiler.cpp | 1594 ++++++++--------- Core/DolphinVM/Compiler/compiler.h | 377 ++-- Core/DolphinVM/Compiler/disasm.cpp | 32 +- Core/DolphinVM/Compiler/lexer.cpp | 132 +- Core/DolphinVM/Compiler/lexer.h | 194 +- Core/DolphinVM/Compiler/optimizer.cpp | 926 +++++----- Core/DolphinVM/Compiler/str.h | 23 +- Core/DolphinVM/DolphinSmalltalk.idl | 64 +- Core/DolphinVM/DolphinX.h | 86 +- Core/DolphinVM/EnumHelpers.h | 133 ++ Core/DolphinVM/InProcStub/StdAfx.h | 4 +- Core/DolphinVM/InProcToGo/StdAfx.h | 4 +- Core/DolphinVM/STMethodHeader.h | 12 +- Core/DolphinVM/decode.cpp | 68 +- Core/DolphinVM/disassembler.h | 87 +- Core/DolphinVM/extcall.cpp | 72 +- Core/DolphinVM/ist.h | 14 +- Core/DolphinVM/textrange.h | 19 + 24 files changed, 2705 insertions(+), 2365 deletions(-) create mode 100644 Core/DolphinVM/EnumHelpers.h create mode 100644 Core/DolphinVM/textrange.h diff --git a/Core/DolphinVM/Compiler/Compiler.idl b/Core/DolphinVM/Compiler/Compiler.idl index 7bd2dd6e09..ce2f23ed48 100644 --- a/Core/DolphinVM/Compiler/Compiler.idl +++ b/Core/DolphinVM/Compiler/Compiler.idl @@ -144,7 +144,10 @@ library CompilerLib CInfoLast = CInfoHardBreakpoint } FirstAndLastCodes; - typedef enum FLAGS {Default=0x00, SyntaxCheckOnly=0x02, NoOptimize=0x08, TextMap=0x10, TempsMap=0x20, DebugMethod=0x40, Boot=0x80, ScanOnly=0x100, Interactive=0x200, SendYourself=0x400} FLAGS; + cpp_quote("#define class_CompilerFlags class CompilerFlags") + typedef enum class_CompilerFlags + {Default=0x00, SyntaxCheckOnly=0x02, NoOptimize=0x08, TextMap=0x10, TempsMap=0x20, DebugMethod=0x40, Boot=0x80, ScanOnly=0x100, Interactive=0x200, SendYourself=0x400} FLAGS; + cpp_quote("#undef CompilerFlags") [ object, diff --git a/Core/DolphinVM/Compiler/CompilerSupport.cpp b/Core/DolphinVM/Compiler/CompilerSupport.cpp index e6b6ce5c90..639b893b85 100644 --- a/Core/DolphinVM/Compiler/CompilerSupport.cpp +++ b/Core/DolphinVM/Compiler/CompilerSupport.cpp @@ -14,7 +14,7 @@ be thrown away eventually, or perhaps compiled into a separate DLL. #include "..\VMPointers.h" -POTE Compiler::NewCompiledMethod(POTE classPointer, unsigned numBytes, const STMethodHeader& hdr) +POTE Compiler::NewCompiledMethod(POTE classPointer, size_t numBytes, const STMethodHeader& hdr) { //_ASSERTE(ObjectMemory::inheritsFrom(classPointer, GetVMPointers().ClassCompiledMethod)); // Note we subtract @@ -22,7 +22,7 @@ POTE Compiler::NewCompiledMethod(POTE classPointer, unsigned numBytes, const STM ((sizeof(STCompiledMethod) - sizeof(Oop) // Deduct dummy literal frame entry (arrays cannot be zero sized in IDL) // -sizeof(ObjectHeader) // Deduct size of head which NewObjectWithPointers includes implicitly -) / sizeof(Oop)) + GetLiteralCount()); +) / sizeof(Oop)) + LiteralCount); STCompiledMethod* method = reinterpret_cast(GetObj(methodPointer)); POTE bytes = m_piVM->NewByteArray(numBytes); m_piVM->StorePointerWithValue((Oop*)&method->byteCodes, Oop(bytes)); diff --git a/Core/DolphinVM/Compiler/LexicalScope.cpp b/Core/DolphinVM/Compiler/LexicalScope.cpp index 65cdeb13d4..9de38aa722 100644 --- a/Core/DolphinVM/Compiler/LexicalScope.cpp +++ b/Core/DolphinVM/Compiler/LexicalScope.cpp @@ -24,17 +24,17 @@ void TempVarDecl::MergeRef(const TempVarRef* pRef, Compiler* pCompiler) // the temps declared in optimized scopes will have been moved into their // nearest enclosing real scope. We still need to use the actual scope of // the ref., however, in case it is a ref. from an optimized scope. - _ASSERTE(GetOuter() == NULL); - _ASSERTE(pRef->GetDecl()->GetActualDecl() == this); + _ASSERTE(Outer == nullptr); + _ASSERTE(pRef->Decl->ActualDecl == this); // Decl's should have been promoted out of optimized scopes by now to nearest enclosing real scope - _ASSERTE(!m_pScope->IsOptimizedBlock()); + _ASSERTE(!m_pScope->IsOptimizedBlock); - if (pCompiler->IsInteractive() && m_refType == vrtUnknown && pRef->GetRefType() == vrtRead && !IsReadOnly()) - pCompiler->Warning(pRef->GetTextRange(), CWarnReadBeforeWritten); + if (pCompiler->IsInteractive && m_refType == VarRefType::Unknown && pRef->RefType == VarRefType::Read && !IsReadOnly) + pCompiler->Warning(pRef->TextRange, CWarnReadBeforeWritten); - m_refType = static_cast(m_refType | pRef->GetRefType()); + m_refType = static_cast((int)m_refType | (int)pRef->RefType); - LexicalScope* pRefScope = pRef->GetRealScope(); + LexicalScope* pRefScope = pRef->RealScope; if (m_pScope == pRefScope) { @@ -42,12 +42,12 @@ void TempVarDecl::MergeRef(const TempVarRef* pRef, Compiler* pCompiler) switch(m_varType) { - case tvtUnaccessed: + case TempVarType::Unaccessed: // Currently unaccessed, so promote to accessed in local scope - m_varType = tvtStack; + m_varType = TempVarType::Stack; break; - case tvtCopied: + case TempVarType::Copied: // Already referenced from a nested scope. If this reference // is to write to the variable, then we must promote the temp // into a shared variable so the nested scope can see the new @@ -55,13 +55,13 @@ void TempVarDecl::MergeRef(const TempVarRef* pRef, Compiler* pCompiler) // may be made to "arguments" if they are the args to optimized // (inlined) blocks, such as a #to:do:. These are not treated // as promoting the variable to shared. - if (pRef->GetRefType() > vrtRead && !m_bIsReadOnly) - m_varType = tvtShared; + if (pRef->RefType > VarRefType::Read && !m_bIsReadOnly) + m_varType = TempVarType::Shared; break; - case tvtShared: + case TempVarType::Shared: // Already the most generate type of temp, so nothing to do - case tvtStack: + case TempVarType::Stack: // Already accessed in local scope break; @@ -77,20 +77,20 @@ void TempVarDecl::MergeRef(const TempVarRef* pRef, Compiler* pCompiler) switch(m_varType) { - case tvtCopied: + case TempVarType::Copied: // Already referenced from a nested scope. If this reference // is to write to the variable, then we must promote the temp // into a shared variable - case tvtUnaccessed: - case tvtStack: + case TempVarType::Unaccessed: + case TempVarType::Stack: // Currently unaccessed, or local only. - if (pRef->GetRefType() > vrtRead) - m_varType = tvtShared; + if (pRef->RefType > VarRefType::Read) + m_varType = TempVarType::Shared; else - m_varType = tvtCopied; + m_varType = TempVarType::Copied; break; - case tvtShared: + case TempVarType::Shared: // Already a full shared temp break; @@ -108,20 +108,20 @@ void TempVarDecl::MergeRef(const TempVarRef* pRef, Compiler* pCompiler) /////////////////////////////////////////////////////////////////////////////// // TempVarRef class members -LexicalScope* TempVarRef::GetRealScope() const +LexicalScope* TempVarRef::get_RealScope() const { - return m_pScope->GetRealScope(); + return m_pScope->RealScope; } void TempVarRef::MergeRefIntoDecl(Compiler* pCompiler) { - GetDecl()->MergeRef(this, pCompiler); + Decl->MergeRef(this, pCompiler); } -int TempVarRef::GetActualDistance() const +unsigned TempVarRef::GetActualDistance() const { - LexicalScope* pScope = GetRealScope(); - return pScope->GetActualDistance(GetDecl()->GetScope()); + LexicalScope* pScope = RealScope; + return pScope->GetActualDistance(Decl->Scope); } // End of TempVarRef class members @@ -134,8 +134,8 @@ LexicalScope::~LexicalScope() { // Delete decls { - const int count = m_tempVarDecls.size(); - for (int i = 0; i < count; i++) + const size_t count = m_tempVarDecls.size(); + for (size_t i = 0; i < count; i++) { TempVarDecl* pDecl = m_tempVarDecls[i]; delete pDecl; @@ -148,8 +148,8 @@ LexicalScope::~LexicalScope() for (REFLISTMAP::iterator it=m_tempVarRefs.begin();it != loopEnd;it++) { REFLIST& refs = (*it).second; - const int listEnd = refs.size(); - for (int i = 0; i < listEnd; i++) + const size_t listEnd = refs.size(); + for (size_t i = 0; i < listEnd; i++) delete refs[i]; } } @@ -168,41 +168,41 @@ TempVarDecl* LexicalScope::FindTempDecl(const Str& strName) for (DECLLIST::reverse_iterator it=pScope->m_tempVarDecls.rbegin();it != loopEnd;it++) { TempVarDecl* pDecl = (*it); - if (pDecl->GetName() == strName) + if (pDecl->Name == strName) return pDecl; } - pScope = pScope->GetOuter(); + pScope = pScope->Outer; } - while (pScope != NULL); + while (pScope != nullptr); - return NULL; + return nullptr; } void LexicalScope::PropagateFarReturn() { - if (HasFarReturn()) + if (HasFarReturn) { - LexicalScope* pOuter = GetOuter(); + LexicalScope* pOuter = Outer; // Outer scope cannot be null in the case of a block - _ASSERTE(pOuter != NULL); + _ASSERTE(pOuter != nullptr); do { pOuter->m_bHasFarReturn = true; - pOuter = pOuter->GetOuter(); - } while (pOuter != NULL); + pOuter = pOuter->Outer; + } while (pOuter != nullptr); } } void LexicalScope::PropagateNeedsSelf() { - if (NeedsSelf()) + if (NeedsSelf) { - LexicalScope* pOuter = GetOuter(); + LexicalScope* pOuter = Outer; // Outer scope cannot be null in the case of a block - while (pOuter != NULL) + while (pOuter != nullptr) { pOuter->m_bRefersToSelf = true; - pOuter = pOuter->GetOuter(); + pOuter = pOuter->Outer; } } } @@ -216,21 +216,21 @@ void LexicalScope::PropagateOuterRequirements() TempVarDecl* LexicalScope::CopyTemp(TempVarDecl* pTemp, Compiler* pCompiler) { - _ASSERTE(pTemp->GetVarType() == tvtCopied); - _ASSERTE(pTemp->GetActualDecl() == pTemp); + _ASSERTE(pTemp->VarType == TempVarType::Copied); + _ASSERTE(pTemp->ActualDecl == pTemp); - LexicalScope* pScope = pTemp->GetScope(); + LexicalScope* pScope = pTemp->Scope; if (pScope == this) // This is the declaring scope already return pTemp; - LexicalScope* outer = GetRealOuter(); - _ASSERTE(outer != NULL); + LexicalScope* outer = RealOuter; + _ASSERTE(outer != nullptr); // Temps should never be copied into optimized blocks, as they have no // runtime representation, but we do need to update the reference TempVarDecl* pNewVar; - if (IsOptimizedBlock()) + if (IsOptimizedBlock) { pNewVar = outer->CopyTemp(pTemp, pCompiler); } @@ -238,40 +238,40 @@ TempVarDecl* LexicalScope::CopyTemp(TempVarDecl* pTemp, Compiler* pCompiler) { // First we must see if it has already been copied into this scope, // perhaps when processing a preceeding nested scope - const int declCount = m_tempVarDecls.size(); - for (int i = 0; i < declCount; i++) + const size_t declCount = m_tempVarDecls.size(); + for (size_t i = 0; i < declCount; i++) { TempVarDecl* pDecl = m_tempVarDecls[i]; - if (pDecl->GetActualDecl() == pTemp) + if (pDecl->ActualDecl == pTemp) return pDecl; } pNewVar = new TempVarDecl(*pTemp); - _ASSERTE(pNewVar->GetVarType() == tvtCopied); + _ASSERTE(pNewVar->VarType == TempVarType::Copied); // Hmmm, do we want to do this. Means can only find true decl by searching // up, though that may not matter. - pNewVar->SetScope(this); + pNewVar->Scope = this; // We must recursively copy into any enclosing scopes - pNewVar->SetOuter(outer->CopyTemp(pTemp, pCompiler)); + pNewVar->Outer = outer->CopyTemp(pTemp, pCompiler); - pNewVar->SetVarType(tvtCopy); - pNewVar->SetIndex(m_copiedTemps.size()); + pNewVar->VarType = TempVarType::Copy; + pNewVar->Index = m_copiedTemps.size(); m_copiedTemps.push_back(pNewVar); m_tempVarDecls.push_back(pNewVar); if (m_tempVarDecls.size() > TEMPORARYLIMIT) - pCompiler->CompileError(pTemp->GetTextRange(), CErrTooManyTemps); + pCompiler->CompileError(pTemp->TextRange, CErrTooManyTemps); } // We must update any ref in this scope to use the new local declaration - REFLIST& refs = m_tempVarRefs[pTemp->GetName()]; + REFLIST& refs = m_tempVarRefs[pTemp->Name]; const int refcount = refs.size(); for (int i = 0; i < refcount; i++) { TempVarRef* pRef = refs[i]; - if (pRef->GetDecl() == pTemp) - pRef->SetDecl(pNewVar); + if (pRef->Decl == pTemp) + pRef->Decl = pNewVar; // else already copied } @@ -294,15 +294,15 @@ void LexicalScope::CopyTemps(Compiler* pCompiler) if (refs.size() < 1) continue; - TempVarDecl* pDecl = refs[0]->GetDecl(); - _ASSERTE(!pDecl->GetScope()->IsOptimizedBlock()); - if (pDecl->GetVarType() == tvtCopied) + TempVarDecl* pDecl = refs[0]->Decl; + _ASSERTE(!pDecl->Scope->IsOptimizedBlock); + if (pDecl->VarType == TempVarType::Copied) { - LexicalScope* pDeclScope = pDecl->GetScope(); + LexicalScope* pDeclScope = pDecl->Scope; if (pDeclScope == this) { // Reached its declaring scope - _ASSERTE(pDecl->GetOuter() == NULL); + _ASSERTE(pDecl->Outer == nullptr); } else CopyTemp(pDecl, pCompiler); @@ -312,7 +312,7 @@ void LexicalScope::CopyTemps(Compiler* pCompiler) void LexicalScope::CopyDownOptimizedDecls(Compiler* pCompiler) { - LexicalScope* pActualScope = GetRealScope(); + LexicalScope* pActualScope = RealScope; _ASSERTE(pActualScope != this); _ASSERTE(m_bIsOptimizedBlock); @@ -320,14 +320,14 @@ void LexicalScope::CopyDownOptimizedDecls(Compiler* pCompiler) for (int i = 0; i < count; i++) { TempVarDecl* pDecl = m_tempVarDecls[i]; - _ASSERTE(pDecl->GetScope() == this); - _ASSERTE(pDecl->GetOuter() == NULL); + _ASSERTE(pDecl->Scope == this); + _ASSERTE(pDecl->Outer == nullptr); TempVarDecl* pNewVar = new TempVarDecl(*pDecl); m_tempVarDecls[i] = pNewVar; - _ASSERTE(pDecl->GetOuter() == NULL); - _ASSERTE(pNewVar->GetOuter() == pDecl); + _ASSERTE(pDecl->Outer == nullptr); + _ASSERTE(pNewVar->Outer == pDecl); pDecl->MarkInvisible(); pActualScope->AddTempDecl(pDecl, pCompiler); } @@ -346,7 +346,7 @@ void LexicalScope::PatchOptimized(Compiler* pCompiler) // any optimized blocks will have been inlined. PropagateOuterRequirements(); - if (IsOptimizedBlock()) + if (IsOptimizedBlock) { CopyDownOptimizedDecls(pCompiler); } @@ -365,48 +365,48 @@ void LexicalScope::AllocTempIndices(Compiler* pCompiler) _ASSERTE(m_nStackSize == 0); _ASSERTE(m_nSharedTemps == 0); // All temps in optimized blocks must be allocated in the nearest enclosing unoptimized scope - _ASSERTE(!IsOptimizedBlock()); + _ASSERTE(!IsOptimizedBlock); - const int nCopiedValues = GetCopiedValuesCount(); + const tempcount_t nCopiedValues = CopiedValuesCount; // We must allow sufficient space for the copied values before the other temps m_nStackSize = m_nArgs + nCopiedValues; const int count = m_tempVarDecls.size(); for (int i = 0; i < count; i++) { TempVarDecl* pDecl = m_tempVarDecls[i]; - if (pDecl->IsArgument()) + if (pDecl->IsArgument) { - _ASSERTE(pDecl->GetIndex() >= 0 && pDecl->GetIndex() < m_nArgs); + _ASSERTE(pDecl->Index != -1 && pDecl->Index < m_nArgs); } else { - switch(pDecl->GetVarType()) + switch(pDecl->VarType) { - case tvtUnaccessed: - if (pDecl->IsReadOnly()) - pDecl->SetIndex(m_nStackSize++); + case TempVarType::Unaccessed: + if (pDecl->IsReadOnly) + pDecl->Index = m_nStackSize++; else { // Unaccessed temp, issue a warning, but don't allocate any space - if (pCompiler->IsInteractive()) - pCompiler->Warning(pDecl->GetTextRange(), CWarnUnreferencedTemp); + if (pCompiler->IsInteractive) + pCompiler->Warning(pDecl->TextRange, CWarnUnreferencedTemp); continue; } break; - case tvtStack: - case tvtCopied: - pDecl->SetIndex(m_nStackSize++); + case TempVarType::Stack: + case TempVarType::Copied: + pDecl->Index = m_nStackSize++; break; - case tvtCopy: - _ASSERTE(pDecl->GetIndex() >= 0 && pDecl->GetIndex() < nCopiedValues); - _ASSERTE(pDecl->GetOuter() != NULL); - pDecl->SetIndex(pDecl->GetIndex() + m_nArgs); + case TempVarType::Copy: + _ASSERTE(pDecl->Index != static_cast(-1) && pDecl->Index < nCopiedValues); + _ASSERTE(pDecl->Outer != nullptr); + pDecl->Index = pDecl->Index + m_nArgs; break; - case tvtShared: - pDecl->SetIndex(m_nSharedTemps++); + case TempVarType::Shared: + pDecl->Index = m_nSharedTemps++; break; default: @@ -415,28 +415,28 @@ void LexicalScope::AllocTempIndices(Compiler* pCompiler) break; } - VarRefType refType = pDecl->GetRefType(); + VarRefType refType = pDecl->RefType; switch(refType) { - case vrtRead: // Read, not written - if (pCompiler->IsInteractive() && !pDecl->IsReadOnly()) + case VarRefType::Read: // Read, not written + if (pCompiler->IsInteractive && !pDecl->IsReadOnly) { // Would be better to report this on the first such read, but we'd need to search for it. // The in-image parser does this anyway, so not worth the effort - pCompiler->Warning(pDecl->GetTextRange(), CWarnReadNotWritten); + pCompiler->Warning(pDecl->TextRange, CWarnReadNotWritten); } break; - case vrtWrite: // Written, not read - if (pCompiler->IsInteractive()) + case VarRefType::Write: // Written, not read + if (pCompiler->IsInteractive) { // As above, better reported on the first write, but not worth it for the same reasons. - pCompiler->Warning(pDecl->GetTextRange(), CWarnWrittenNotRead); + pCompiler->Warning(pDecl->TextRange, CWarnWrittenNotRead); } break; - case vrtUnknown: // Unreferenced - case vrtReadWrite: // Normal + case VarRefType::Unknown: // Unreferenced + case VarRefType::ReadWrite: // Normal default: break; } @@ -447,14 +447,14 @@ void LexicalScope::AllocTempIndices(Compiler* pCompiler) TempVarRef* LexicalScope::AddTempRef(TempVarDecl* pDecl, VarRefType refType, const TEXTRANGE& range) { TempVarRef* pNewVarRef = new TempVarRef(this, pDecl, refType, range); - m_tempVarRefs[pDecl->GetName()].push_back(pNewVarRef); + m_tempVarRefs[pDecl->Name].push_back(pNewVarRef); return pNewVarRef; } void LexicalScope::AddSharedDeclsTo(DECLMAP& allSharedDecls) const { - LexicalScope* outer = GetOuter(); - if (outer != NULL) + LexicalScope* outer = Outer; + if (outer != nullptr) { outer->AddSharedDeclsTo(allSharedDecls); } @@ -463,9 +463,9 @@ void LexicalScope::AddSharedDeclsTo(DECLMAP& allSharedDecls) const for (DECLLIST::const_iterator it = this->m_tempVarDecls.begin(); it != end; it++) { TempVarDecl* pDecl = *it; - if (pDecl->GetVarType() == tvtShared) + if (pDecl->VarType == TempVarType::Shared) { - allSharedDecls[pDecl->GetName()] = pDecl; + allSharedDecls[pDecl->Name] = pDecl; } } } @@ -477,14 +477,14 @@ void LexicalScope::AddSharedDeclsTo(DECLMAP& allSharedDecls) const // temps. void LexicalScope::AddVisibleDeclsTo(DECLMAP& allVisibleDecls) const { - LexicalScope* outer = GetOuter(); + LexicalScope* outer = Outer; - bool isOptimized = IsOptimizedBlock(); + bool isOptimized = IsOptimizedBlock; // Optimized blocks are effectively inlined within their enclosing scope so all temps visible in that scope are implicitly visible in the optimized // block. It is convenient in the debugger to see all the declared values in the outer scopes in this case. if (isOptimized) { - _ASSERTE(outer != NULL); + _ASSERTE(outer != nullptr); outer->AddVisibleDeclsTo(allVisibleDecls); } @@ -494,7 +494,7 @@ void LexicalScope::AddVisibleDeclsTo(DECLMAP& allVisibleDecls) const if (m_bRefsOuterTemps) { - _ASSERTE(outer != NULL); + _ASSERTE(outer != nullptr); outer->AddSharedDeclsTo(allVisibleDecls); } @@ -503,10 +503,10 @@ void LexicalScope::AddVisibleDeclsTo(DECLMAP& allVisibleDecls) const for (int i = 0; i < count; i++) { TempVarDecl* pDecl = m_tempVarDecls[i]; - TempVarDecl* pRealDecl = isOptimized ? pDecl->GetOuter() : pDecl; - if (pDecl->IsVisible() && pRealDecl->IsReferenced()) + TempVarDecl* pRealDecl = isOptimized ? pDecl->Outer : pDecl; + if (pDecl->IsVisible && pRealDecl->IsReferenced) { - allVisibleDecls[pDecl->GetName()] = pRealDecl; + allVisibleDecls[pDecl->Name] = pRealDecl; } } } @@ -522,10 +522,13 @@ void LexicalScope::AddVisibleDeclsTo(DECLMAP& allVisibleDecls) const // POTE LexicalScope::BuildTempMapEntry(IDolphin* piVM) const { + _ASSERTE(m_initialIP != ip_t::npos || CodeLength == 0); + POTE scopeTuplePointer = piVM->NewArray(3); STVarObject& scopeTuple = *(STVarObject*)GetObj(scopeTuplePointer); - scopeTuple.fields[0] = IntegerObjectOf(m_initialIP+1); - scopeTuple.fields[1] = IntegerObjectOf(m_finalIP+1); + intptr_t ip = static_cast(m_initialIP) + 1; + scopeTuple.fields[0] = IntegerObjectOf(ip); + scopeTuple.fields[1] = IntegerObjectOf(ip + CodeLength - 1); DECLMAP allVisibleDecls; AddVisibleDeclsTo(allVisibleDecls); @@ -542,20 +545,20 @@ POTE LexicalScope::BuildTempMapEntry(IDolphin* piVM) const _ASSERTE(it != allVisibleDecls.end()); TempVarDecl* pDecl = (*it).second; - _ASSERTE(pDecl->IsReadOnly() || pDecl->GetVarType() != tvtUnaccessed); + _ASSERTE(pDecl->IsReadOnly || pDecl->VarType != TempVarType::Unaccessed); POTE tempPointer = piVM->NewArray(3); piVM->StorePointerWithValue(temps.fields+i, Oop(tempPointer)); STVarObject& temp = *(STVarObject*)GetObj(tempPointer); - piVM->StorePointerWithValue(temp.fields+0, Oop(piVM->NewUtf8String(reinterpret_cast(pDecl->GetName().c_str())))); + piVM->StorePointerWithValue(temp.fields+0, Oop(piVM->NewUtf8String(reinterpret_cast(pDecl->Name.c_str())))); - int nDepth = pDecl->IsStack() + int nDepth = pDecl->IsStack ? 0 - : GetActualDistance(pDecl->GetScope()) + 1; + : GetActualDistance(pDecl->Scope) + 1; piVM->StorePointerWithValue(temp.fields+1, IntegerObjectOf(nDepth)); - piVM->StorePointerWithValue(temp.fields+2, IntegerObjectOf(pDecl->GetIndex()+1)); + piVM->StorePointerWithValue(temp.fields+2, IntegerObjectOf(pDecl->Index+1)); } return scopeTuplePointer; @@ -565,11 +568,11 @@ extern void __cdecl DolphinTrace(LPCTSTR format, ...); void LexicalScope::AddTempDecl(TempVarDecl* pDecl, Compiler* pCompiler) { - pDecl->SetScope(this); + pDecl->Scope = this; m_tempVarDecls.push_back(pDecl); if (m_tempVarDecls.size() > TEMPORARYLIMIT) - pCompiler->CompileError(pDecl->GetTextRange(), CErrTooManyTemps); + pCompiler->CompileError(pDecl->TextRange, CErrTooManyTemps); } void LexicalScope::RenameTemporary(int temporary, const Str& newName, const TEXTRANGE& range) @@ -579,38 +582,38 @@ void LexicalScope::RenameTemporary(int temporary, const Str& newName, const TEXT // TRACE("Renaming temp '%s' (%d..%d) to '%s'\n", m_tempVarDecls[temporary]->GetName().c_str(), range.m_start, range.m_stop, newName.c_str()); #endif TempVarDecl* pDecl = m_tempVarDecls[temporary]; - _ASSERTE(pDecl != NULL); - pDecl->SetName(newName); - pDecl->SetTextRange(range); + _ASSERTE(pDecl != nullptr); + pDecl->Name = newName; + pDecl->TextRange = range; } void LexicalScope::PatchBlockLiteral(IDolphin* piVM, POTE oteMethod) { - _ASSERTE(IsCleanBlock()); + _ASSERTE(IsCleanBlock); - if (m_oteBlockLiteral == NULL) + if (m_oteBlockLiteral == nullptr) { // Empty block - _ASSERTE(IsEmptyBlock()); + _ASSERTE(IsEmptyBlock); return; } - _ASSERTE((m_finalIP - m_initialIP) > 0); // A minimal block must push a value and return requiring at least two bytes + _ASSERTE(CodeLength > 1); // A minimal block must push a value and return requiring at least two bytes STBlockClosure& block = *(STBlockClosure*)GetObj(m_oteBlockLiteral); //block.m_outer = nil; piVM->StorePointerWithValue(reinterpret_cast(&block.m_method), reinterpret_cast(oteMethod)); - block.m_initialIP = IntegerObjectOf(GetInitialIP()+1); + block.m_initialIP = IntegerObjectOf(static_cast(InitialIP)+1); *reinterpret_cast(&block.m_infoFlags) = 1; _ASSERTE(block.m_infoFlags.isInteger); - block.m_infoFlags.argumentCount = GetArgumentCount(); - block.m_infoFlags.stackTempsCount = GetStackTempCount(); - _ASSERTE(GetCopiedValuesCount() == 0); - _ASSERTE(GetSharedTempsCount() == 0); + block.m_infoFlags.argumentCount = static_cast(ArgumentCount); + block.m_infoFlags.stackTempsCount = static_cast(StackTempCount); + _ASSERTE(CopiedValuesCount == 0); + _ASSERTE(SharedTempsCount == 0); _ASSERTE(block.m_infoFlags.envTempsCount == 0); piVM->MakeImmutable(reinterpret_cast(m_oteBlockLiteral), TRUE); @@ -626,7 +629,7 @@ void LexicalScope::BeOptimizedBlock() for (int i = 0; i < count; i++) { TempVarDecl* pDecl = m_tempVarDecls[i]; - pDecl->SetIsArgument(false); + pDecl->IsArgument = false; } m_nArgs = 0; } diff --git a/Core/DolphinVM/Compiler/LexicalScope.h b/Core/DolphinVM/Compiler/LexicalScope.h index 6f0f2d3ce6..d237a38d2c 100644 --- a/Core/DolphinVM/Compiler/LexicalScope.h +++ b/Core/DolphinVM/Compiler/LexicalScope.h @@ -8,20 +8,30 @@ LexicalScope.h #include "Str.h" #include #include +#include "bytecode.h" +#include "textrange.h" #define TEMPORARYLIMIT 255 // maximum number of temporaries permitted (ditto) #define MAXBLOCKNESTING 255 // maximum depth to which blocks (actually contexts) can be nested -enum TempVarType { - tvtUnaccessed=0, // Temp variable which is not accessed at all - tvtStack, // Temp variable accessed only from local scope (or optimized blocks) - tvtCopied, // Temp variable which is closed over, but only read after closure - tvtShared, // Temp variable which is written after being closed over - tvtCopy, // Temp variable decl created to represent a copied temp in the closure +enum class TempVarType { + Unaccessed=0, // Temp variable which is not accessed at all + Stack, // Temp variable accessed only from local scope (or optimized blocks) + Copied, // Temp variable which is closed over, but only read after closure + Shared, // Temp variable which is written after being closed over + Copy, // Temp variable decl created to represent a copied temp in the closure }; -enum VarRefType { vrtUnknown = 0, vrtRead=1, vrtWrite=2, vrtReadWrite=3}; +enum class VarRefType +{ + Unknown = 0, + Read=1, + Write=2, + ReadWrite=3 +}; +ENABLE_BITMASK_OPERATORS(VarRefType) + class LexicalScope; class TempVarRef; class Compiler; @@ -34,15 +44,15 @@ class TempVarDecl TempVarType m_varType; VarRefType m_refType; TempVarDecl* m_pOuter; - int m_nIndex; + size_t m_nIndex; bool m_bInvisible; // Not visible in this scope (used for real declarations of temps in optimized blocks) bool m_bIsArgument; bool m_bIsReadOnly; public: TempVarDecl(const Str& strName, const TEXTRANGE& range) : - m_strName(strName), m_pScope(NULL), m_range(range), - m_varType(tvtUnaccessed), m_refType(vrtUnknown), m_pOuter(NULL), + m_strName(strName), m_pScope(nullptr), m_range(range), + m_varType(TempVarType::Unaccessed), m_refType(VarRefType::Unknown), m_pOuter(nullptr), m_nIndex(-1), m_bInvisible(false), m_bIsArgument(false), m_bIsReadOnly(false) { @@ -61,95 +71,91 @@ class TempVarDecl ///////////////////////// // Accessing - TempVarType GetVarType() const + __declspec(property(get = get_VarType, put = put_VarType)) TempVarType VarType; + TempVarType get_VarType() const { return m_varType; } - - void SetVarType(TempVarType varType) + void put_VarType(TempVarType varType) { m_varType = varType; } - VarRefType GetRefType() const + __declspec(property(get = get_RefType)) VarRefType RefType; + VarRefType get_RefType() const { return m_refType; } - int GetIndex() const + __declspec(property(get = get_Index, put=put_Index)) size_t Index; + size_t get_Index() const { - return m_varType == tvtCopy || GetOuter() == NULL + return m_varType == TempVarType::Copy || Outer == nullptr ? m_nIndex - : GetOuter()->GetIndex(); + : Outer->Index; } - - void SetIndex(int index) + void put_Index(size_t index) { - _ASSERTE(m_varType == tvtCopy || GetOuter() == NULL); + _ASSERTE(m_varType == TempVarType::Copy || Outer == nullptr); m_nIndex = index; } - const Str& GetName() const + __declspec(property(get = get_Name, put = put_Name)) const Str& Name; + const Str& get_Name() const { return m_strName; } - - void SetName(const Str& strName) + void put_Name(const Str& strName) { m_strName = strName; } - LexicalScope* GetScope() const + __declspec(property(get = get_Scope, put = put_Scope)) LexicalScope* Scope; + LexicalScope* get_Scope() const { return m_pScope; } - - void SetScope(LexicalScope* pScope) + void put_Scope(LexicalScope* pScope) { m_pScope = pScope; } - LexicalScope* GetActualScope() const + __declspec(property(get = get_ActualScope)) LexicalScope* ActualScope; + LexicalScope* get_ActualScope() const { - return GetActualDecl()->GetScope(); + return ActualDecl->Scope; } - TempVarDecl* GetOuter() const + __declspec(property(get = get_Outer, put = put_Outer)) TempVarDecl* Outer; + TempVarDecl* get_Outer() const { return m_pOuter; } - - void SetOuter(TempVarDecl* pOuter) + void put_Outer(TempVarDecl* pOuter) { m_pOuter = pOuter; } - const TEXTRANGE& GetTextRange() const + __declspec(property(get = get_TextRange, put = put_TextRange)) const TEXTRANGE& TextRange; + const TEXTRANGE& get_TextRange() const { return m_range; } - - void SetTextRange(const TEXTRANGE& range) + void put_TextRange(const TEXTRANGE& range) { m_range = range; } - TempVarDecl* GetActualDecl() const + __declspec(property(get = get_ActualDecl)) TempVarDecl* ActualDecl; + TempVarDecl* get_ActualDecl() const { TempVarDecl* pDecl = const_cast(this); - while (pDecl->m_pOuter != NULL) + while (pDecl->m_pOuter != nullptr) pDecl = pDecl->m_pOuter; return pDecl; } - void SetIsArgument(bool bIsArgument) - { - m_bIsArgument = bIsArgument; - if (bIsArgument) - BeReadOnly(); - } - void BeReadOnly() { m_bIsReadOnly = true; @@ -164,40 +170,51 @@ class TempVarDecl void MergeRef(const TempVarRef*, Compiler* pCompiler); // Testing - bool IsArgument() const + __declspec(property(get = get_IsArgument, put = put_IsArgument)) bool IsArgument; + bool get_IsArgument() const { return m_bIsArgument; } + void put_IsArgument(bool bIsArgument) + { + m_bIsArgument = bIsArgument; + if (bIsArgument) + BeReadOnly(); + } - bool IsStack() const + __declspec(property(get = get_IsStack)) bool IsStack; + bool get_IsStack() const { switch (m_varType) { - case tvtCopy: + case TempVarType::Copy: // break; - case tvtStack: - case tvtCopied: + case TempVarType::Stack: + case TempVarType::Copied: return true; - case tvtUnaccessed: + case TempVarType::Unaccessed: return m_bIsReadOnly; - case tvtShared: + case TempVarType::Shared: default: break; } return false; } - bool IsReferenced() const + __declspec(property(get = get_IsReferenced)) bool IsReferenced; + bool get_IsReferenced() const { - return m_varType != tvtUnaccessed || m_bIsReadOnly; + return m_varType != TempVarType::Unaccessed || m_bIsReadOnly; } - bool IsVisible() const + __declspec(property(get = get_IsVisible)) bool IsVisible; + bool get_IsVisible() const { return !m_bInvisible; } - bool IsReadOnly() const + __declspec(property(get = get_IsReadOnly)) bool IsReadOnly; + bool get_IsReadOnly() const { return m_bIsReadOnly; } @@ -219,48 +236,53 @@ class TempVarRef ////////////////////////////////////////////// // Accessing - int GetEstimatedDistance() const; - int GetActualDistance() const; + unsigned GetEstimatedDistance() const; + unsigned GetActualDistance() const; - VarRefType GetRefType() const + __declspec(property(get = get_RefType, put = put_RefType)) VarRefType RefType; + VarRefType get_RefType() const { return m_refType; } - - void SetRefType(VarRefType refType) + void put_RefType(VarRefType refType) { _ASSERTE(refType >= m_refType); m_refType = refType; } - TempVarDecl* GetDecl() const + __declspec(property(get = get_Decl, put = put_Decl)) TempVarDecl* Decl; + TempVarDecl* get_Decl() const { return m_pDecl; } - - void SetDecl(TempVarDecl* pDecl) + void put_Decl(TempVarDecl* pDecl) { m_pDecl = pDecl; } - TempVarType GetVarType() const + __declspec(property(get = get_VarType)) TempVarType VarType; + TempVarType get_VarType() const { - return m_pDecl->GetVarType(); + return m_pDecl->VarType; } - LexicalScope* GetScope() const + __declspec(property(get = get_Scope)) LexicalScope* Scope; + LexicalScope* get_Scope() const { return m_pScope; } - LexicalScope* GetRealScope() const; + __declspec(property(get = get_RealScope)) LexicalScope* RealScope; + LexicalScope* get_RealScope() const; - const Str& GetName() const + __declspec(property(get = get_Name)) const Str& Name; + const Str& get_Name() const { - return GetDecl()->GetName(); + return Decl->Name; } - const TEXTRANGE& GetTextRange() const + __declspec(property(get = get_TextRange)) const TEXTRANGE& TextRange; + const TEXTRANGE& get_TextRange() const { return m_range; } @@ -268,14 +290,16 @@ class TempVarRef ////////////////////////////////////////////// // Testing - bool IsShared() const + __declspec(property(get = get_IsShared)) bool IsShared; + bool get_IsShared() const { - return GetVarType() == tvtShared; + return VarType == TempVarType::Shared; } - bool IsStack() const + __declspec(property(get = get_IsStack)) bool IsStack; + bool get_IsStack() const { - return GetDecl()->IsStack(); + return Decl->IsStack; } ///////////////////////////////////////////// @@ -290,6 +314,9 @@ typedef std::vector REFLIST; typedef std::map REFLISTMAP; typedef std::vector OOPVECTOR; +typedef size_t tempcount_t; +typedef size_t argcount_t; + class LexicalScope { LexicalScope* m_pOuter; @@ -300,11 +327,11 @@ class LexicalScope TEXTRANGE m_textRange; // Range of text this scope represents - int m_nArgs; - int m_nStackSize; - int m_nSharedTemps; - int m_initialIP; - int m_finalIP; + argcount_t m_nArgs; + tempcount_t m_nStackSize; + tempcount_t m_nSharedTemps; + ip_t m_initialIP; + ip_t m_finalIP; POTE m_oteBlockLiteral; @@ -320,70 +347,78 @@ class LexicalScope LexicalScope(const LexicalScope&); public: - LexicalScope(LexicalScope* pOuter, int nStart, bool bOptimized) : m_pOuter(pOuter), + LexicalScope(LexicalScope* pOuter, textpos_t nStart, bool bOptimized) : m_pOuter(pOuter), m_nArgs(0), m_nStackSize(0), m_nSharedTemps(0), - m_initialIP(-1), m_finalIP(-2), + m_initialIP(ip_t::npos), m_finalIP(ip_t::npos), m_bIsEmptyBlock(false), m_bIsOptimizedBlock(bOptimized), m_bHasFarReturn(false), m_bRefersToSelf(false), m_bRefsOuterTemps(false), - m_textRange(nStart, -1), m_oteBlockLiteral(NULL) + m_textRange(nStart, textpos_t::npos), m_oteBlockLiteral(nullptr) { } ~LexicalScope(); - int GetCopiedValuesCount() const + __declspec(property(get = get_CopiedValuesCount)) tempcount_t CopiedValuesCount; + tempcount_t get_CopiedValuesCount() const { - return m_copiedTemps.size(); + return static_cast(m_copiedTemps.size()); } - int GetStackTempCount() const + __declspec(property(get = get_StackTempCount)) tempcount_t StackTempCount; + tempcount_t get_StackTempCount() const { - return m_nStackSize - GetArgumentCount() - GetCopiedValuesCount(); + return m_nStackSize - ArgumentCount - CopiedValuesCount; } - int GetTempCount() const + __declspec(property(get = get_TempCount)) tempcount_t TempCount; + tempcount_t get_TempCount() const { - return m_tempVarDecls.size(); + return static_cast(m_tempVarDecls.size()); } - int GetArgumentCount() const + __declspec(property(get = get_ArgumentCount)) argcount_t ArgumentCount; + argcount_t get_ArgumentCount() const { return m_nArgs; } - int GetSharedTempsCount() const + __declspec(property(get = get_SharedTempsCount)) tempcount_t SharedTempsCount; + tempcount_t get_SharedTempsCount() const { - _ASSERTE(!IsOptimizedBlock() || m_nSharedTemps == 0); + _ASSERTE(!IsOptimizedBlock || m_nSharedTemps == 0); return m_nSharedTemps; } - LexicalScope* GetOuter() const + __declspec(property(get = get_Outer, put = put_Outer)) LexicalScope* Outer; + LexicalScope* get_Outer() const { return m_pOuter; } - LexicalScope* GetRealOuter() const + __declspec(property(get = get_RealOuter)) LexicalScope* RealOuter; + LexicalScope* get_RealOuter() const { - return GetOuter()->GetRealScope(); + return Outer->RealScope; } // Answer the nearest real (non-optimized) scope. If the scope // is itself unoptimized, then this will be the receiver. The // actual scope is the scope in which any variables declared in the // receiver will actually be allocated. - LexicalScope* GetRealScope() const + __declspec(property(get = get_RealScope)) LexicalScope* RealScope; + LexicalScope* get_RealScope() const { LexicalScope* pScope = const_cast(this); - while (pScope != NULL && pScope->IsOptimizedBlock()) + while (pScope != nullptr && pScope->IsOptimizedBlock) { - pScope = pScope->GetOuter(); + pScope = pScope->Outer; } return pScope; } private: - void SetOuter(LexicalScope* pOuter) + void put_Outer(LexicalScope* pOuter) { m_pOuter = pOuter; } @@ -394,7 +429,8 @@ class LexicalScope return m_copiedTemps; } - int GetStackSize() const + __declspec(property(get = get_StackSize)) tempcount_t StackSize; + tempcount_t get_StackSize() const { return m_nStackSize; } @@ -404,30 +440,30 @@ class LexicalScope void ArgumentAdded(TempVarDecl* pArg) { - pArg->SetIsArgument(true); - pArg->SetIndex(m_nArgs++); + pArg->IsArgument = true; + pArg->Index = m_nArgs++; } - int GetDepth() const + unsigned GetDepth() const { - int depth = 0; + unsigned depth = 0; const LexicalScope* current = this; const LexicalScope* outer; - while ((outer = current->GetOuter()) != NULL) + while ((outer = current->Outer) != nullptr) { - if (!current->IsOptimizedBlock()) + if (!current->IsOptimizedBlock) depth++; current = outer; } return depth; } - int GetLogicalDepth() const + unsigned GetLogicalDepth() const { - int depth = 0; + unsigned depth = 0; const LexicalScope* current = this; const LexicalScope* outer; - while ((outer = current->GetOuter()) != NULL) + while ((outer = current->Outer) != nullptr) { depth++; current = outer; @@ -435,17 +471,17 @@ class LexicalScope return depth; } - int GetActualDistance(LexicalScope* pDeclScope) const + unsigned GetActualDistance(LexicalScope* pDeclScope) const { - const LexicalScope* pScope = GetRealScope(); - int distance = 0; + const LexicalScope* pScope = RealScope; + unsigned distance = 0; while (pScope != pDeclScope) { - _ASSERTE(pScope != NULL); - pScope = pScope->GetOuter(); - if (pScope->GetSharedTempsCount() != 0) + _ASSERTE(pScope != nullptr); + pScope = pScope->Outer; + if (pScope->SharedTempsCount != 0) { - _ASSERTE(!pScope->IsOptimizedBlock()); + _ASSERTE(!pScope->IsOptimizedBlock); distance++; _ASSERTE(distance <= MAXBLOCKNESTING); } @@ -454,12 +490,13 @@ class LexicalScope return distance; } - const TEXTRANGE& GetTextRange() const + __declspec(property(get = get_TextRange)) const TEXTRANGE& TextRange; + const TEXTRANGE& get_TextRange() const { return m_textRange; } - void SetTextStop(int stop) + void SetTextStop(textpos_t stop) { m_textRange.m_stop = stop; } @@ -471,11 +508,11 @@ class LexicalScope void MarkFarReturner() { - if (m_bHasFarReturn) return; + if (HasFarReturn) return; m_bHasFarReturn = true; - LexicalScope* outer = GetOuter(); - if (outer != NULL) + LexicalScope* outer = Outer; + if (outer != nullptr) { outer->MarkFarReturner(); } @@ -489,66 +526,74 @@ class LexicalScope while (pScope != pDeclScope) { pScope->m_bRefsOuterTemps = true; - pScope = pScope->GetOuter(); - _ASSERTE(pScope != NULL); + pScope = pScope->Outer; + _ASSERTE(pScope != nullptr); } } - void SetInitialIP(int ip) + void MaybeSetInitialIP(ip_t ip) { - m_initialIP = ip; - } - - void MaybeSetInitialIP(int ip) - { - if (GetInitialIP() < 0) + if (InitialIP == ip_t::npos) { - SetInitialIP(ip); + InitialIP = ip; // If an optimized block, such as a repeat loop, may need to chain out // to the outer scope so that cases such as the following are handled // correctly: [[.,..] repeat] value - if (IsOptimizedBlock()) + if (IsOptimizedBlock) { - GetOuter()->MaybeSetInitialIP(ip); + Outer->MaybeSetInitialIP(ip); } } } - int GetInitialIP() const + __declspec(property(get = get_InitialIP, put=put_InitialIP)) ip_t InitialIP; + ip_t get_InitialIP() const { return m_initialIP; } + void put_InitialIP(ip_t ip) + { + _ASSERTE(ip >= ip_t::zero); + m_initialIP = ip; + } - int GetFinalIP() const + __declspec(property(get = get_FinalIP, put=put_FinalIP)) ip_t FinalIP; + ip_t get_FinalIP() const { return m_finalIP; } - void SetFinalIP(int ip) + void put_FinalIP(ip_t ip) { if (m_finalIP < ip) { m_finalIP = ip; - if (GetOuter()) + if (Outer != nullptr) { - GetOuter()->SetFinalIP(ip); + Outer->FinalIP = ip; } } } + __declspec(property(get = get_CodeLength)) intptr_t CodeLength; + intptr_t get_CodeLength() const + { + return m_initialIP == ip_t::npos ? 0 : static_cast(m_finalIP - m_initialIP + 1); + } + void IncrementIPs() { - if (m_initialIP >= 0) + if (m_initialIP != ip_t::npos) { - _ASSERTE(m_finalIP >= 0); - m_initialIP++; - m_finalIP++; + _ASSERTE(m_finalIP != ip_t::npos); + ++m_initialIP; + ++m_finalIP; // If associated with a clean block, we need to update it's initialIP too // Note that the initialIP of the block is 1-based, whereas the m_initialIP // of this object is zero-based. //STBlockClosure* pBlock = GetBlock(); - //if (pBlock != NULL) + //if (pBlock != nullptr) //{ // _ASSERTE(IntegerValueOf(pBlock->m_initialIP) == m_initialIP); // pBlock->m_initialIP = IntegerObjectOf(m_initialIP + 1); @@ -561,59 +606,68 @@ class LexicalScope m_oteBlockLiteral = block; } - STBlockClosure* GetBlock() + __declspec(property(get = get_Block)) STBlockClosure* Block; + STBlockClosure* get_Block() { - return m_oteBlockLiteral ? reinterpret_cast(GetObj(m_oteBlockLiteral)) : NULL; + return m_oteBlockLiteral ? reinterpret_cast(GetObj(m_oteBlockLiteral)) : nullptr; } + /////////////////////////////////////////////////////////////////////////// // Testing - bool HasFarReturn() const + __declspec(property(get = get_HasFarReturn)) bool HasFarReturn; + bool get_HasFarReturn() const { return m_bHasFarReturn; } - bool NeedsSelf() const + __declspec(property(get = get_NeedsSelf)) bool NeedsSelf; + bool get_NeedsSelf() const { return m_bRefersToSelf; } - bool NeedsOuter() const + __declspec(property(get = get_NeedsOuter)) bool NeedsOuter; + bool get_NeedsOuter() const { - return HasFarReturn() || m_bRefsOuterTemps; + return HasFarReturn || m_bRefsOuterTemps; } - bool IsOptimizedBlock() const + __declspec(property(get = get_IsOptimizedBlock)) bool IsOptimizedBlock; + bool get_IsOptimizedBlock() const { return m_bIsOptimizedBlock; } - bool IsEmptyBlock() const + __declspec(property(get = get_IsEmptyBlock)) bool IsEmptyBlock; + bool get_IsEmptyBlock() const { - return m_bIsEmptyBlock && GetArgumentCount() == 0; + return m_bIsEmptyBlock && ArgumentCount == 0; } - bool IsInBlock() const + __declspec(property(get = get_IsInBlock)) bool IsInBlock; + bool get_IsInBlock() const { - return GetOuter() != NULL - && (!IsOptimizedBlock() || GetOuter()->IsInBlock()); + return Outer != nullptr && (!IsOptimizedBlock || Outer->IsInBlock); } - bool IsBlock() const + __declspec(property(get = get_IsBlock)) bool IsBlock; + bool get_IsBlock() const { - return GetOuter() != NULL && !IsOptimizedBlock(); + return Outer != nullptr && !IsOptimizedBlock; } // Clean blocks can be allocated statically as they don't close over any // of their creation time environment and don't contain a ^-return - bool IsCleanBlock() const + __declspec(property(get = get_IsCleanBlock)) bool IsCleanBlock; + bool get_IsCleanBlock() const { - return IsBlock() - && !NeedsSelf() - && !NeedsOuter() - && GetSharedTempsCount() == 0 - && GetCopiedValuesCount() == 0; + return IsBlock + && !NeedsSelf + && !NeedsOuter + && SharedTempsCount == 0 + && CopiedValuesCount == 0; } ///////////////////////////////////////////////////////////////// @@ -644,10 +698,10 @@ class LexicalScope void CopyDownOptimizedDecls(Compiler*); }; -inline int TempVarRef::GetEstimatedDistance() const +inline unsigned TempVarRef::GetEstimatedDistance() const { // Note that this will be an overestimate until the optimized scopes have been // unlinked. - return GetRealScope()->GetDepth() - GetDecl()->GetScope()->GetDepth(); + return RealScope->GetDepth() - Decl->Scope->GetDepth(); } diff --git a/Core/DolphinVM/Compiler/ParseInlinedMessages.cpp b/Core/DolphinVM/Compiler/ParseInlinedMessages.cpp index 3aceec7afb..3b5f9462d0 100644 --- a/Core/DolphinVM/Compiler/ParseInlinedMessages.cpp +++ b/Core/DolphinVM/Compiler/ParseInlinedMessages.cpp @@ -17,10 +17,10 @@ #define _ASSERTE assert #endif -template bool Compiler::ParseWhileLoop(const int, const TEXTRANGE&); -template bool Compiler::ParseWhileLoop(const int, const TEXTRANGE&); -template bool Compiler::ParseWhileLoopBlock(const int, const TEXTRANGE&, const TEXTRANGE&); -template bool Compiler::ParseWhileLoopBlock(const int, const TEXTRANGE&, const TEXTRANGE&); +template bool Compiler::ParseWhileLoop(const ip_t, const TEXTRANGE&); +template bool Compiler::ParseWhileLoop(const ip_t, const TEXTRANGE&); +template bool Compiler::ParseWhileLoopBlock(const ip_t, const TEXTRANGE&, const TEXTRANGE&); +template bool Compiler::ParseWhileLoopBlock(const ip_t, const TEXTRANGE&, const TEXTRANGE&); /////////////////////////////////////////////////////////////////////////////// // When inlining code the compiler sometimes has to generate temporaries. It prefixes @@ -30,7 +30,7 @@ static const uint8_t valueTempName[] = GENERATEDTEMPSTART "value"; /////////////////////////////////////////////////////////////////////////////// -void Compiler::PopOptimizedScope(int textStop) +void Compiler::PopOptimizedScope(textpos_t textStop) { PopScope(textStop); } @@ -39,8 +39,8 @@ bool Compiler::ParseZeroArgOptimizedBlock() { PushOptimizedScope(); ParseOptimizeBlock(0); - bool isEmpty = m_pCurrentScope->IsEmptyBlock(); - PopOptimizedScope(ThisTokenRange().m_stop); + bool isEmpty = m_pCurrentScope->IsEmptyBlock; + PopOptimizedScope(ThisTokenRange.m_stop); NextToken(); return isEmpty; } @@ -53,16 +53,16 @@ bool Compiler::ParseIfTrue(const TEXTRANGE& messageRange) return false; } - int condJumpMark = GenJumpInstruction(LongJumpIfFalse); + ip_t condJumpMark = GenJumpInstruction(LongJumpIfFalse); AddTextMap(condJumpMark, messageRange); ParseZeroArgOptimizedBlock(); // Need to jump over the false block at end of true block - int jumpOutMark = GenJumpInstruction(LongJump); - int elseMark = m_codePointer; + ip_t jumpOutMark = GenJumpInstruction(LongJump); + ip_t elseMark = m_codePointer; - if (strcmp((LPCSTR)ThisTokenText(), "ifFalse:") == 0) + if (strcmp((LPCSTR)ThisTokenText, "ifFalse:") == 0) { // An else block exists POTE oteSelector = AddSymbolToFrame("ifTrue:ifFalse:", messageRange); @@ -96,16 +96,16 @@ bool Compiler::ParseIfFalse(const TEXTRANGE& messageRange) return false; } - int condJumpMark = GenJumpInstruction(LongJumpIfTrue); + ip_t condJumpMark = GenJumpInstruction(LongJumpIfTrue); AddTextMap(condJumpMark, messageRange); ParseZeroArgOptimizedBlock(); // Need to jump over the false block at end of true block - int jumpOutMark = GenJumpInstruction(LongJump); - int elseMark = m_codePointer; + ip_t jumpOutMark = GenJumpInstruction(LongJump); + ip_t elseMark = m_codePointer; - if (strcmp((LPCSTR)ThisTokenText(), "ifTrue:") == 0) + if (strcmp((LPCSTR)ThisTokenText, "ifTrue:") == 0) { // An else block exists @@ -163,17 +163,17 @@ bool Compiler::ParseAndCondition(const TEXTRANGE& messageRange) // If the receiver is false, then the whole expression is false, so // jump over (shortcut) the block argument - int branchMark = GenJumpInstruction(LongJumpIfFalse); + ip_t branchMark = GenJumpInstruction(LongJumpIfFalse); AddTextMap(branchMark, messageRange); - int blockStart = ThisTokenRange().m_start; + textpos_t blockStart = ThisTokenRange.m_start; if (ParseZeroArgOptimizedBlock()) { - CompileError(TEXTRANGE(blockStart, LastTokenRange().m_stop), CErrEmptyConditionBlock, (Oop)oteSelector); + CompileError(TEXTRANGE(blockStart, LastTokenRange.m_stop), CErrEmptyConditionBlock, (Oop)oteSelector); return false; } - int jumpOutMark = GenJumpInstruction(LongJump); + ip_t jumpOutMark = GenJumpInstruction(LongJump); SetJumpTarget(branchMark, GenInstruction(ShortPushFalse)); SetJumpTarget(jumpOutMark, GenNop()); @@ -197,17 +197,17 @@ bool Compiler::ParseOrCondition(const TEXTRANGE& messageRange) // result in a small overall size reduction. Which has a speed // advantage is difficult to say. // - int branchMark = GenJumpInstruction(LongJumpIfFalse); + ip_t branchMark = GenJumpInstruction(LongJumpIfFalse); AddTextMap(branchMark, messageRange); GenInstruction(ShortPushTrue); - int jumpOutMark = GenJumpInstruction(LongJump); + ip_t jumpOutMark = GenJumpInstruction(LongJump); - int ifFalse = m_codePointer; - int blockStart = ThisTokenRange().m_start; + ip_t ifFalse = m_codePointer; + textpos_t blockStart = ThisTokenRange.m_start; if (ParseZeroArgOptimizedBlock()) { - CompileError(TEXTRANGE(blockStart, LastTokenRange().m_stop), CErrEmptyConditionBlock, (Oop)oteSelector); + CompileError(TEXTRANGE(blockStart, LastTokenRange.m_stop), CErrEmptyConditionBlock, (Oop)oteSelector); return false; } @@ -220,12 +220,12 @@ bool Compiler::ParseOrCondition(const TEXTRANGE& messageRange) return true; } -int Compiler::ParseIfNotNilBlock() +bool Compiler::ParseIfNotNilBlock() { if (!ThisTokenIsBinary('[')) { CompileError(CErrExpectLiteralBlock); - return 0; + return false; } PushOptimizedScope(); @@ -233,22 +233,22 @@ int Compiler::ParseIfNotNilBlock() // We now allow either zero or one arguments to the ifNotNil: block //ParseOptimizeBlock(1); - int nTextStart = ThisTokenRange().m_start; + textpos_t nTextStart = ThisTokenRange.m_start; - _ASSERTE(IsInOptimizedBlock()); + _ASSERTE(IsInOptimizedBlock); // Generate the body code for an optimized block NextToken(); - int argc = 0; + argcount_t argc = 0; while (m_ok && ThisTokenIsSpecial(':')) { - if (NextToken() == NameConst) + if (NextToken() == TokenType::NameConst) { argc++; - CheckTemporaryName(ThisTokenText(), ThisTokenRange(), true); + CheckTemporaryName(ThisTokenText, ThisTokenRange, true); if (m_ok) { - TempVarRef* pValueTempRef = AddOptimizedTemp(ThisTokenText(), ThisTokenRange()); + TempVarRef* pValueTempRef = AddOptimizedTemp(ThisTokenText, ThisTokenRange); GenPopAndStoreTemp(pValueTempRef); } NextToken(); @@ -270,25 +270,24 @@ int Compiler::ParseIfNotNilBlock() break; default: - CompileError(TEXTRANGE(nTextStart, ThisTokenRange().m_stop), CErrTooManyIfNotNilBlockArgs); + CompileError(TEXTRANGE(nTextStart, ThisTokenRange.m_stop), CErrTooManyIfNotNilBlockArgs); break; } - int nBlockTemps = 0; if (m_ok) { // Temporarily commented out for interim release ParseTemporaries(); ParseBlockStatements(); - if (m_ok && ThisToken() != CloseSquare) - CompileError(TEXTRANGE(nTextStart, LastTokenRange().m_stop), CErrBlockNotClosed); + if (m_ok && ThisToken != TokenType::CloseSquare) + CompileError(TEXTRANGE(nTextStart, LastTokenRange.m_stop), CErrBlockNotClosed); } - PopOptimizedScope(ThisTokenRange().m_stop); + PopOptimizedScope(ThisTokenRange.m_stop); NextToken(); - return argc; + return argc != 0; } bool Compiler::ParseIfNilBlock(bool noPop) @@ -298,7 +297,7 @@ bool Compiler::ParseIfNilBlock(bool noPop) // Pop off the implicit argument, which is not needed GenPopStack(); ParseOptimizeBlock(0); - PopOptimizedScope(ThisTokenRange().m_stop); + PopOptimizedScope(ThisTokenRange.m_stop); NextToken(); return m_ok; } @@ -344,7 +343,7 @@ Inlined forms of #ifNil:[ifNotNil:] and #ifNotNil:[ifNil:] @exit */ -bool Compiler::ParseIfNil(const TEXTRANGE& messageRange, int exprStartPos) +bool Compiler::ParseIfNil(const TEXTRANGE& messageRange, textpos_t exprStartPos) { if (!ThisTokenIsBinary('[')) { @@ -352,25 +351,25 @@ bool Compiler::ParseIfNil(const TEXTRANGE& messageRange, int exprStartPos) return false; } - int dupMark = GenDup(); + ip_t dupMark = GenDup(); BreakPoint(); // We're going to add a pop and jump on condition instruction here // Its a forward jump, so we need to patch up the target later - const int popAndJumpMark = GenJumpInstruction(LongJumpIfNotNil); - const int mapEntry = AddTextMap(popAndJumpMark, exprStartPos, LastTokenRange().m_stop); + const ip_t popAndJumpMark = GenJumpInstruction(LongJumpIfNotNil); + const size_t mapEntry = AddTextMap(popAndJumpMark, exprStartPos, LastTokenRange.m_stop); ParseIfNilBlock(false); - int ifNotNilMark; + ip_t ifNotNilMark; - if (strcmp((LPCSTR)ThisTokenText(), "ifNotNil:") == 0) + if (strcmp((LPCSTR)ThisTokenText, "ifNotNil:") == 0) { POTE oteSelector = AddSymbolToFrame("ifNil:ifNotNil:", messageRange); // Generate the jump out instruction (forward jump, so target not yet known) - int jumpOutMark = GenJumpInstruction(LongJump); + ip_t jumpOutMark = GenJumpInstruction(LongJump); // Mark first instruction of the "else" branch ifNotNilMark = m_codePointer; @@ -378,14 +377,14 @@ bool Compiler::ParseIfNil(const TEXTRANGE& messageRange, int exprStartPos) // #ifNil:ifNotNil: form NextToken(); - int argc = ParseIfNotNilBlock(); + bool hasArg = ParseIfNotNilBlock(); // Be careful, may not actually be a literal block there if (m_ok) { // If the ifNotNil: block does not need an argument, we can patch out the Dup // and corresponding pop - if (!argc) + if (!hasArg) { UngenInstruction(dupMark); _ASSERTE(m_bytecodes[popAndJumpMark + lengthOfByteCode(LongJumpIfFalse)].byte == PopStackTop); @@ -411,14 +410,14 @@ bool Compiler::ParseIfNil(const TEXTRANGE& messageRange, int exprStartPos) // Conditional jump to the "else" branch (or the Nop if no else branch) SetJumpTarget(popAndJumpMark, ifNotNilMark); - if (mapEntry >= 0) - m_textMaps[mapEntry].stop = LastTokenRange().m_stop; + if (mapEntry != -1) + m_textMaps[mapEntry].stop = LastTokenRange.m_stop; } return true; } -bool Compiler::ParseIfNotNil(const TEXTRANGE& messageRange, int exprStartPos) +bool Compiler::ParseIfNotNil(const TEXTRANGE& messageRange, textpos_t exprStartPos) { if (!ThisTokenIsBinary('[')) { @@ -426,33 +425,33 @@ bool Compiler::ParseIfNotNil(const TEXTRANGE& messageRange, int exprStartPos) return false; } - int dupMark = GenDup(); + ip_t dupMark = GenDup(); BreakPoint(); // We're going to add a pop and jump on condition instruction here // Its a forward jump, so we need to patch up the target later - const int popAndJumpMark = GenJumpInstruction(LongJumpIfNil); - AddTextMap(popAndJumpMark, exprStartPos, LastTokenRange().m_stop); + const ip_t popAndJumpMark = GenJumpInstruction(LongJumpIfNil); + AddTextMap(popAndJumpMark, exprStartPos, LastTokenRange.m_stop); - int argc = ParseIfNotNilBlock(); + bool hasArg = ParseIfNotNilBlock(); // If the ifNotNil: block did not have any arguments, then we do not need the Dup, and we also // need to patch out the corresponding pop. - if (!argc) + if (!hasArg) { UngenInstruction(dupMark); UngenInstruction(popAndJumpMark + lengthOfByteCode(LongJumpIfTrue)); } - int ifNilMark; + ip_t ifNilMark; // Has an #ifNil: branch? - if (strcmp((LPCSTR)ThisTokenText(), "ifNil:") == 0) + if (strcmp((LPCSTR)ThisTokenText, "ifNil:") == 0) { POTE oteSelector = AddSymbolToFrame("ifNotNil:ifNil:", messageRange); // Generate the jump out instruction (forward jump, so target not yet known) - int jumpOutMark = GenJumpInstruction(LongJump); + ip_t jumpOutMark = GenJumpInstruction(LongJump); // Mark first instruction of the "else" branch ifNilMark = m_codePointer; @@ -460,7 +459,7 @@ bool Compiler::ParseIfNotNil(const TEXTRANGE& messageRange, int exprStartPos) // ifNotNil:ifNil: form NextToken(); - ParseIfNilBlock(!argc); + ParseIfNilBlock(!hasArg); SetJumpTarget(jumpOutMark, GenNop()); } @@ -470,13 +469,13 @@ bool Compiler::ParseIfNotNil(const TEXTRANGE& messageRange, int exprStartPos) POTE oteSelector = AddSymbolToFrame("ifNotNil:", messageRange); - if (!argc) + if (!hasArg) { // Since we've removed the Dup if the ifNotNil: block had no args, we need to ensure there is nil atop the stack // This should normally get optimized away later if the expression value is not used. // Generate the jump out instruction - int jumpOutMark = GenJumpInstruction(LongJump); + ip_t jumpOutMark = GenJumpInstruction(LongJump); ifNilMark = GenInstruction(ShortPushNil); @@ -496,14 +495,14 @@ bool Compiler::ParseIfNotNil(const TEXTRANGE& messageRange, int exprStartPos) // Inline an optimized block that was only detected after it had been generated // (e.g. a #repeat block). This is very easy in D6 - all we need to do is // translate any far returns to method returns -void Compiler::InlineOptimizedBlock(int nStart, int nStop) +void Compiler::InlineOptimizedBlock(ip_t nStart, ip_t nStop) { - int i=nStart; + ip_t i=nStart; while (i < nStop) { BYTECODE& bytecode=m_bytecodes[i]; - _ASSERTE(bytecode.isOpCode()); - int len = bytecode.instructionLength(); + _ASSERTE(bytecode.IsOpCode); + size_t len = bytecode.InstructionLength; switch(bytecode.byte) { @@ -511,11 +510,11 @@ void Compiler::InlineOptimizedBlock(int nStart, int nStop) // We must skip any nested blocks _ASSERTE(bytecode.target > i+len); i = bytecode.target; - _ASSERTE(m_bytecodes[i-1].isReturn()); + _ASSERTE(m_bytecodes[i-1].IsReturn); break; case FarReturn: - if (!IsInBlock()) + if (!IsInBlock) bytecode.byte = ReturnMessageStackTop; // Drop through @@ -526,11 +525,11 @@ void Compiler::InlineOptimizedBlock(int nStart, int nStop) } } -Compiler::LoopReceiverType Compiler::InlineLoopBlock(const int loopmark, const TEXTRANGE& tokenRange) +Compiler::LoopReceiverType Compiler::InlineLoopBlock(const ip_t loopmark, const TEXTRANGE& tokenRange) { - const int nPrior = m_codePointer-2; - BYTECODE& prior=m_bytecodes[nPrior]; // Nop following this instruction - if (!prior.isOpCode() || prior.byte != ReturnBlockStackTop || m_bytecodes[loopmark+1].byte != BlockCopy) + const ip_t nPrior = m_codePointer-2; + const BYTECODE& prior=m_bytecodes[nPrior]; // Nop following this instruction + if (!prior.IsOpCode || prior.byte != ReturnBlockStackTop || m_bytecodes[loopmark+1].byte != BlockCopy) { // Receiver is not a literal block so do not use optimized loop block form return LoopReceiverType::Other; @@ -539,19 +538,19 @@ Compiler::LoopReceiverType Compiler::InlineLoopBlock(const int loopmark, const T // We have a block on the stack, remove its wrapper to leave // only the contained code, but first check that it is a niladic block BYTECODE& loopHead = m_bytecodes[loopmark]; - if (loopHead.pScope->GetArgumentCount() != 0) + if (loopHead.pScope->ArgumentCount != 0) { // Receiver is not a niladic block so do not use optimized loop block form return LoopReceiverType::NonNiladicBlock; } - if (loopHead.pScope->IsEmptyBlock()) + if (loopHead.pScope->IsEmptyBlock) { return LoopReceiverType::EmptyBlock; } _ASSERTE(loopHead.byte == Nop); - int firstInBlock = loopmark + 1 + BlockCopyInstructionSize; + ip_t firstInBlock = loopmark + 1 + BlockCopyInstructionSize; InlineOptimizedBlock(firstInBlock, nPrior); // Mark the scope as being optimized @@ -564,7 +563,7 @@ Compiler::LoopReceiverType Compiler::InlineLoopBlock(const int loopmark, const T VERIFY(RemoveTextMapEntry(nPrior)); UngenInstruction(nPrior); // Return block stack top // If a debug method, also Nop out the breakpoint before the return instruction - if (WantDebugMethod()) + if (WantDebugMethod) { _ASSERTE(m_bytecodes[nPrior-1].byte == Break); UngenInstruction(nPrior-1); @@ -573,14 +572,14 @@ Compiler::LoopReceiverType Compiler::InlineLoopBlock(const int loopmark, const T return LoopReceiverType::NiladicBlock; } -bool Compiler::ParseRepeatLoop(const int loopmark, const TEXTRANGE& receiverRange) +bool Compiler::ParseRepeatLoop(const ip_t loopmark, const TEXTRANGE& receiverRange) { // We add a literal symbol to the frame for the message send regardless of // whether we are able to generate the inlined version so that searching // for references, etc, works as expected. - POTE oteSelector = AddSymbolToFrame(ThisTokenText(), ThisTokenRange()); + POTE oteSelector = AddSymbolToFrame(ThisTokenText, ThisTokenRange); - switch (InlineLoopBlock(loopmark, ThisTokenRange())) + switch (InlineLoopBlock(loopmark, ThisTokenRange)) { case LoopReceiverType::NonNiladicBlock: case LoopReceiverType::Other: @@ -607,7 +606,7 @@ POTE Compiler::AddSymbolToFrame(LPUTF8 s, const TEXTRANGE& tokenRange) // Return whether we it was suitable to optimize this loop block -template bool Compiler::ParseWhileLoopBlock(const int loopmark, +template bool Compiler::ParseWhileLoopBlock(const ip_t loopmark, const TEXTRANGE& tokenRange, const TEXTRANGE& receiverRange) { POTE oteSelector = AddSymbolToFrame(WhileTrue ? "whileTrue:" : "whileFalse:", tokenRange); @@ -637,10 +636,10 @@ template bool Compiler::ParseWhileLoopBlock(const int loopmark, // To have a breakpoint on the loop condition check uncomment the breakpoint and the text map lines marked with *1* //BreakPoint(); // *1* - const int popAndJumpInstruction = WhileTrue ? LongJumpIfFalse : LongJumpIfTrue; - int condJumpMark = GenJumpInstruction(popAndJumpInstruction); + const uint8_t popAndJumpInstruction = WhileTrue ? LongJumpIfFalse : LongJumpIfTrue; + ip_t condJumpMark = GenJumpInstruction(popAndJumpInstruction); // We need a text map entry for the loop jump in case a mustBeBoolean error gets raised here - int nLoopTextMap = AddTextMap(condJumpMark, tokenRange);// *1* textStart, LastTokenRange().m_stop); + size_t nLoopTextMap = AddTextMap(condJumpMark, tokenRange);// *1* textStart, LastTokenRange.m_stop); // Parse the loop body @@ -650,7 +649,7 @@ template bool Compiler::ParseWhileLoopBlock(const int loopmark, // Parse the loop body ... ParseOptimizeBlock(0); - PopOptimizedScope(ThisTokenRange().m_stop); + PopOptimizedScope(ThisTokenRange.m_stop); //... and ignore its result GenPopStack(); @@ -658,12 +657,12 @@ template bool Compiler::ParseWhileLoopBlock(const int loopmark, } // Unconditionally jump back to the loop condition - int jumpPos = GenJump(LongJump, loopmark); + ip_t jumpPos = GenJump(LongJump, loopmark); - //if (WantTextMap()) m_textMaps[nLoopTextMap].stop = LastTokenRange().m_stop; // *1* + //if (WantTextMap()) m_textMaps[nLoopTextMap].stop = LastTokenRange.m_stop; // *1* // Return Nil - int exitMark = GenInstruction(ShortPushNil); + ip_t exitMark = GenInstruction(ShortPushNil); // We can now set the target of the forward conditional jump SetJumpTarget(condJumpMark, exitMark); @@ -672,11 +671,11 @@ template bool Compiler::ParseWhileLoopBlock(const int loopmark, } // Returns whether we were able to optimize this loop -template bool Compiler::ParseWhileLoop(const int loopmark, const TEXTRANGE& receiverRange) +template bool Compiler::ParseWhileLoop(const ip_t loopmark, const TEXTRANGE& receiverRange) { - POTE oteSelector = AddSymbolToFrame(ThisTokenText(), ThisTokenRange()); + POTE oteSelector = AddSymbolToFrame(ThisTokenText, ThisTokenRange); - switch (InlineLoopBlock(loopmark, ThisTokenRange())) + switch (InlineLoopBlock(loopmark, ThisTokenRange)) { case LoopReceiverType::NonNiladicBlock: case LoopReceiverType::Other: @@ -691,8 +690,8 @@ template bool Compiler::ParseWhileLoop(const int loopmark, cons // #whileTrue/#whileFalse is very simple to inline - we only need one conditional jump at the end // after the condition block - int jumpPos = GenJump(WhileTrue ? LongJumpIfTrue : LongJumpIfFalse, loopmark); - AddTextMap(jumpPos, ThisTokenRange()); + ip_t jumpPos = GenJump(WhileTrue ? LongJumpIfTrue : LongJumpIfFalse, loopmark); + AddTextMap(jumpPos, ThisTokenRange); // Result of a #whileTrue/#whileFalse should be nil GenInstruction(ShortPushNil); @@ -702,13 +701,13 @@ template bool Compiler::ParseWhileLoop(const int loopmark, cons TempVarRef* Compiler::AddOptimizedTemp(const Str& tempName, const TEXTRANGE& range) { - _ASSERTE(m_pCurrentScope->IsOptimizedBlock()); + _ASSERTE(m_pCurrentScope->IsOptimizedBlock); TempVarDecl* pDecl = AddTemporary(tempName, range, false); pDecl->BeReadOnly(); - return m_pCurrentScope->AddTempRef(pDecl, vrtWrite, range); + return m_pCurrentScope->AddTempRef(pDecl, VarRefType::Write, range); } -void Compiler::ParseToByNumberDo(int toPointer, Oop oopNumber, bool bNegativeStep) +void Compiler::ParseToByNumberDo(ip_t toPointer, Oop oopNumber, bool bNegativeStep) { PushOptimizedScope(); @@ -720,11 +719,11 @@ void Compiler::ParseToByNumberDo(int toPointer, Oop oopNumber, bool bNegativeSte // First we must store that from value into our 'each' counter variable/argument. This involves // stepping back a bit ... _ASSERTE(toPointer < m_codePointer); - int currentPos = m_codePointer; + ip_t currentPos = m_codePointer; m_codePointer = toPointer; // Note we store so leaving the value on the stack as the result of the whole expression GenStoreTemp(pEachTempRef); - m_codePointer = currentPos + m_bytecodes[toPointer].instructionLength(); + m_codePointer = currentPos + m_bytecodes[toPointer].InstructionLength; // Dup the to: value GenDup(); @@ -732,9 +731,9 @@ void Compiler::ParseToByNumberDo(int toPointer, Oop oopNumber, bool bNegativeSte GenPushTemp(pEachTempRef); // We must jump over the block to the test first time through - int jumpOver = GenJumpInstruction(LongJump); + ip_t jumpOver = GenJumpInstruction(LongJump); - int loopHead = m_codePointer; + ip_t loopHead = m_codePointer; // Parse the one argument block. // Leave nothing on the stack, expect 1 argument @@ -746,11 +745,11 @@ void Compiler::ParseToByNumberDo(int toPointer, Oop oopNumber, bool bNegativeSte GenDup(); GenPushTemp(pEachTempRef); // If the step is 1/-1, this will be optimised down to Increment/Decrement - GenNumber(oopNumber, LastTokenRange()); - int add = GenInstruction(SendArithmeticAdd); - int store = GenStoreTemp(pEachTempRef); + GenNumber(oopNumber, LastTokenRange); + ip_t add = GenInstruction(SendArithmeticAdd); + ip_t store = GenStoreTemp(pEachTempRef); - int comparePointer = m_codePointer; + ip_t comparePointer = m_codePointer; if (bNegativeStep) GenInstruction(SendArithmeticGT); @@ -766,14 +765,14 @@ void Compiler::ParseToByNumberDo(int toPointer, Oop oopNumber, bool bNegativeSte SetJumpTarget(jumpOver, comparePointer); TODO("Is this in the right place? What is the last real IP of the loop"); - PopOptimizedScope(ThisTokenRange().m_stop); + PopOptimizedScope(ThisTokenRange.m_stop); NextToken(); } // produce optimized form of to:do: message -bool Compiler::ParseToDoBlock(int exprStart, int toPointer) +bool Compiler::ParseToDoBlock(textpos_t exprStart, ip_t toPointer) { - POTE oteSelector = AddSymbolToFrame("to:do:", TEXTRANGE(toPointer, toPointer + 2)); + POTE oteSelector = AddSymbolToFrame("to:do:", TEXTRANGE(exprStart, exprStart + 2)); // Only optimize if a block is next if (!ThisTokenIsBinary('[')) @@ -787,11 +786,11 @@ bool Compiler::ParseToDoBlock(int exprStart, int toPointer) } // Produce optimized form of to:by:do: message -bool Compiler::ParseToByDoBlock(int exprStart, int toPointer, int byPointer) +bool Compiler::ParseToByDoBlock(textpos_t exprStart, ip_t toPointer, ip_t byPointer) { - _ASSERTE(toPointer>0 && byPointer>0); + _ASSERTE(toPointer>ip_t::zero && byPointer>ip_t::zero); - POTE oteSelector = AddSymbolToFrame("to:by:do:", TEXTRANGE(toPointer, toPointer+2)); + POTE oteSelector = AddSymbolToFrame("to:by:do:", TEXTRANGE(exprStart, exprStart +2)); // Only optimize if a block is next if (!ThisTokenIsBinary('[')) @@ -834,7 +833,7 @@ bool Compiler::ParseToByDoBlock(int exprStart, int toPointer, int byPointer) // Produce optimized form of timesRepeat: [...]. // Returns true if optimization performed. // Note that we perform the conditional jump as a backwards jump at the end for optimal performance -bool Compiler::ParseTimesRepeatLoop(const TEXTRANGE& messageRange, const int textPosition) +bool Compiler::ParseTimesRepeatLoop(const TEXTRANGE& messageRange, const textpos_t textPosition) { POTE oteSelector = AddSymbolToFrame("timesRepeat:", messageRange); @@ -845,27 +844,27 @@ bool Compiler::ParseTimesRepeatLoop(const TEXTRANGE& messageRange, const int tex } // Can apply extra optimizations if receiver is known SmallInteger - int loopTimes=0; + intptr_t loopTimes=0; bool isIntReceiver = LastIsPushSmallInteger(loopTimes); - int startMark = GenDup(); + ip_t startMark = GenDup(); - int jumpOver = GenJumpInstruction(LongJump); - int loopHead = m_codePointer; + ip_t jumpOver = GenJumpInstruction(LongJump); + ip_t loopHead = m_codePointer; PushOptimizedScope(); // Parse the loop block and ignore its result ParseOptimizeBlock(0); GenPopStack(); - PopOptimizedScope(ThisTokenRange().m_stop); + PopOptimizedScope(ThisTokenRange.m_stop); NextToken(); if (isIntReceiver && loopTimes <= 0) { // Blank out all our bytecodes if we have 0 or less loops - const int loopEnd = m_codePointer; - for (int p = startMark; p < loopEnd; p++) + const ip_t loopEnd = m_codePointer; + for (ip_t p = startMark; p < loopEnd; p++) UngenInstruction(p); return true; @@ -875,7 +874,7 @@ bool Compiler::ParseTimesRepeatLoop(const TEXTRANGE& messageRange, const int tex GenInstruction(DecrementStackTop); // Dup counter for compare - int testMark = GenDup(); + ip_t testMark = GenDup(); // Fill in forward unconditional jump before the head of the loop // which jumps to the conditional test @@ -907,30 +906,30 @@ bool Compiler::ParseTimesRepeatLoop(const TEXTRANGE& messageRange, const int tex } // Parse the loop block and ignore its result -int Compiler::ParseOptimizeBlock(int arguments) +void Compiler::ParseOptimizeBlock(argcount_t arguments) { if (!ThisTokenIsBinary('[')) { CompileError(CErrExpectLiteralBlock); - return 0; + return; } - int nTextStart = ThisTokenRange().m_start; + textpos_t nTextStart = ThisTokenRange.m_start; - _ASSERTE(IsInOptimizedBlock()); + _ASSERTE(IsInOptimizedBlock); // Parse the arguments - note we parse them anyway, regardless of whether they are wanted, // and subsequently complain if there are too many NextToken(); - int argument = 0; + argcount_t argument = 0; while (m_ok && ThisTokenIsSpecial(':') ) { - if (NextToken()==NameConst) + if (NextToken()==TokenType::NameConst) { if (argument < arguments) - RenameTemporary(argument, ThisTokenText(), ThisTokenRange()); + RenameTemporary(argument, ThisTokenText, ThisTokenRange); else - AddTemporary(ThisTokenText(), ThisTokenRange(), true); + AddTemporary(ThisTokenText, ThisTokenRange, true); argument++; NextToken(); } @@ -938,34 +937,31 @@ int Compiler::ParseOptimizeBlock(int arguments) CompileError(CErrExpectVariable); } - int argBar = -1; + textpos_t argBar = textpos_t::npos; if (m_ok && argument > 0) { if (ThisTokenIsBinary(TEMPSDELIMITER)) { - argBar = ThisTokenRange().m_stop; + argBar = ThisTokenRange.m_stop; NextToken(); } else { - CompileError(TEXTRANGE(nTextStart, LastTokenRange().m_stop), CErrBlockArgListNotClosed); + CompileError(TEXTRANGE(nTextStart, LastTokenRange.m_stop), CErrBlockArgListNotClosed); } } - int nBlockTemps = 0; if (m_ok) { // Temporarily commented out for interim release ParseTemporaries(); ParseBlockStatements(); - if (m_ok && ThisToken() != CloseSquare) - CompileError(TEXTRANGE(nTextStart, LastTokenRange().m_stop), CErrBlockNotClosed); + if (m_ok && ThisToken != TokenType::CloseSquare) + CompileError(TEXTRANGE(nTextStart, LastTokenRange.m_stop), CErrBlockNotClosed); } if (m_ok && argument != arguments) - CompileError(TEXTRANGE(nTextStart, argBar < 0 ? ThisTokenRange().m_stop : argBar), CErrIncorrectBlockArgCount); - - return nBlockTemps; + CompileError(TEXTRANGE(nTextStart, argBar < textpos_t::start ? ThisTokenRange.m_stop : argBar), CErrIncorrectBlockArgCount); } diff --git a/Core/DolphinVM/Compiler/bytecode.h b/Core/DolphinVM/Compiler/bytecode.h index d80b3f0477..d7235a4f9b 100644 --- a/Core/DolphinVM/Compiler/bytecode.h +++ b/Core/DolphinVM/Compiler/bytecode.h @@ -9,40 +9,59 @@ Smalltalk compiler #define _IST_BYTECODE_H_ #include "..\bytecdes.h" +#include "EnumHelpers.h" + class LexicalScope; +class TempVarRef; + +enum class ip_t : intptr_t +{ + npos = -1, + zero, + one, + two, + three +}; + +ENABLE_INT_OPERATORS(ip_t) struct BYTECODE { - enum BYTEFLAGS { IsOpCode=0x00, IsData=0x01, IsJump=0x02 }; + enum class FLAGS : uint8_t { IsOpCode=0x00, IsData=0x01, IsJump=0x02 }; - BYTE byte; - BYTE flags; // BYTEFLAGS - WORD jumpsTo; // count of the number of other byte codes using this as a jump target + uint8_t byte; + FLAGS flags; + uint16_t jumpsTo; // count of the number of other byte codes using this as a jump target union { - int target; // Jump target location. Max jump is +/-32K, but this is checked only when the jump instruction is fixed up + ip_t target; // Jump target location. Max jump is +/-32K, but this is checked only when the jump instruction is fixed up TempVarRef* pVarRef; }; LexicalScope* pScope; bool isInstruction(BYTE b) const - { return byte == b && isOpCode(); }; - bool isData() const { return flags & IsData; } + { return byte == b && IsOpCode; }; + + __declspec(property(get = get_IsData)) bool IsData; + bool get_IsData() const { return ((uint8_t)flags & (uint8_t)FLAGS::IsData) != 0; } + void makeData() { - flags |= IsData; - pScope = NULL; + flags = (FLAGS)((uint8_t)flags | (uint8_t)FLAGS::IsData); + pScope = nullptr; } // A byte code is either instruction or data, not both - bool isOpCode() const { return !isData(); } + __declspec(property(get = get_IsOpCode)) bool IsOpCode; + bool get_IsOpCode() const { return !get_IsData(); } + void makeOpCode(BYTE b, LexicalScope* pScope) { - _ASSERTE(pScope != NULL); + _ASSERTE(pScope != nullptr); byte = b; - flags &= ~IsData; + makeNonData(); this->pScope = pScope; } @@ -51,177 +70,199 @@ struct BYTECODE makeOpCode(Nop, pScope); } - bool isJumpSource() const + __declspec(property(get = get_IsJumpSource)) bool IsJumpSource; + bool get_IsJumpSource() const { - return (flags & IsJump) != 0; + return ((uint8_t)flags & (uint8_t)FLAGS::IsJump) != 0; } - void makeNonJump() { flags &= ~IsJump; } - void makeJump() { flags |= IsJump; } - void makeJumpTo(int pos) + + void makeNonData() { flags = (FLAGS)((uint8_t)flags & ~(uint8_t)FLAGS::IsData); } + void makeNonJump() { flags = (FLAGS)((uint8_t)flags & ~(uint8_t)FLAGS::IsJump); } + void makeJump() { flags = (FLAGS)((uint8_t)flags | (uint8_t)FLAGS::IsJump); } + void makeJumpTo(ip_t pos) { - _ASSERTE(pos >= 0); - target = static_cast(pos); + target = pos; makeJump(); } - __forceinline bool isJumpTarget() const + __declspec(property(get = get_IsJumpTarget)) bool IsJumpTarget; + __forceinline bool get_IsJumpTarget() const { return jumpsTo > 0; } void addJumpTo() { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); jumpsTo++; _ASSERTE(jumpsTo < 256); } void removeJumpTo() { - _ASSERTE(isOpCode() && jumpsTo > 0); + _ASSERTE(IsOpCode && jumpsTo > 0); jumpsTo--; } - __forceinline int instructionLength() const + __declspec(property(get = get_InstructionLength)) size_t InstructionLength; + __forceinline size_t get_InstructionLength() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return lengthOfByteCode(byte); } - BYTECODE(BYTE b=0, BYTE f=0, LexicalScope* s=NULL) : pVarRef(NULL), jumpsTo(0), byte(b), flags(f), pScope(s) {} + BYTECODE(uint8_t b=0, FLAGS f=FLAGS::IsOpCode, LexicalScope* s=nullptr) : pVarRef(nullptr), jumpsTo(0), byte(b), flags(f), pScope(s) {} - INLINE bool isBreak() const + __declspec(property(get = get_IsBreak)) bool IsBreak; + INLINE bool get_IsBreak() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == Break; } - INLINE bool isShortPushConst() const + __declspec(property(get = get_IsShortPushConst)) bool IsShortPushConst; + INLINE bool get_IsShortPushConst() const { return byte >= ShortPushConst && byte < ShortPushConst + NumShortPushConsts; } - INLINE bool isShortPushStatic() const + __declspec(property(get = get_IsShortPushStatic)) bool IsShortPushStatic; + INLINE bool get_IsShortPushStatic() const { return byte >= ShortPushStatic && byte < ShortPushStatic + NumShortPushStatics; } - INLINE bool isShortPushTemp() const + __declspec(property(get = get_IsShortPushTemp)) bool IsShortPushTemp; + INLINE bool get_IsShortPushTemp() const { return byte >= ShortPushTemp && byte < ShortPushTemp + NumShortPushTemps; } - INLINE bool isPushTemp() const + __declspec(property(get = get_IsPushTemp)) bool IsPushTemp; + INLINE bool get_IsPushTemp() const { - return byte == PushTemp || isShortPushTemp(); + return byte == PushTemp || IsShortPushTemp; } - INLINE bool isShortPopStoreInstVar() const + __declspec(property(get = get_IsShortPopStoreInstVar)) bool IsShortPopStoreInstVar; + INLINE bool get_IsShortPopStoreInstVar() const { return byte >= ShortPopStoreInstVar && byte < ShortPopStoreInstVar + NumShortPopStoreInstVars; } - INLINE bool isShortPopStoreContextTemp() const + __declspec(property(get = get_IsShortPopStoreContextTemp)) bool IsShortPopStoreContextTemp; + INLINE bool get_IsShortPopStoreContextTemp() const { return byte >= PopStoreContextTemp && byte < PopStoreContextTemp + NumPopStoreContextTemps; } - INLINE bool isShortPopStoreOuterTemp() const + __declspec(property(get = get_IsShortPopStoreOuterTemp)) bool IsShortPopStoreOuterTemp; + INLINE bool get_IsShortPopStoreOuterTemp() const { return byte >= ShortPopStoreOuterTemp && byte < ShortPopStoreOuterTemp + NumPopStoreOuterTemps; } - INLINE bool isShortPopStore() const + __declspec(property(get = get_IsShortPopStore)) bool IsShortPopStore; + INLINE bool get_IsShortPopStore() const { - return isShortPopStoreContextTemp() || isShortPopStoreOuterTemp() || isShortPopStoreInstVar() || isShortPopStoreTemp(); + return IsShortPopStoreContextTemp || IsShortPopStoreOuterTemp || IsShortPopStoreInstVar || IsShortPopStoreTemp; } - INLINE BYTE indexOfShortPushConst() const + INLINE uint8_t indexOfShortPushConst() const { - _ASSERTE(isShortPushConst()); + _ASSERTE(IsShortPushConst); return byte - ShortPushConst; } - INLINE BYTE indexOfShortPushStatic() const + INLINE uint8_t indexOfShortPushStatic() const { - _ASSERTE(isShortPushStatic()); + _ASSERTE(IsShortPushStatic); return byte - ShortPushStatic; } INLINE BYTE indexOfShortPushTemp() const { - _ASSERTE(isShortPushTemp()); + _ASSERTE(IsShortPushTemp); return byte - ShortPushTemp; } - INLINE bool isPseudoReturn() const + __declspec(property(get = get_IsPseudoReturn)) bool IsPseudoReturn; + INLINE bool get_IsPseudoReturn() const { return byte >= FirstPseudoReturn && byte <= LastPseudoReturn; } - INLINE bool isPseudoPush() const + __declspec(property(get = get_IsPseudoPush)) bool IsPseudoPush; + INLINE bool get_IsPseudoPush() const { return byte >= FirstPseudoPush && byte <= LastPseudoPush; } - INLINE bool isShortPushInstVar() const + __declspec(property(get = get_IsShortPushInstVar)) bool IsShortPushInstVar; + INLINE bool get_IsShortPushInstVar() const { return byte >= ShortPushInstVar && byte < ShortPushInstVar + NumShortPushInstVars; } - INLINE bool isShortPopStoreTemp() const + __declspec(property(get = get_IsShortPopStoreTemp)) bool IsShortPopStoreTemp; + INLINE bool get_IsShortPopStoreTemp() const { return byte >= ShortPopStoreTemp && byte < ShortPopStoreTemp + NumShortPopStoreTemps; } INLINE BYTE indexOfShortPopStoreTemp() const { - _ASSERTE(isShortPopStoreTemp()); + _ASSERTE(IsShortPopStoreTemp); return byte - ShortPopStoreTemp; } - INLINE bool isShortStoreTemp() const + __declspec(property(get = get_IsShortStoreTemp)) bool IsShortStoreTemp; + INLINE bool get_IsShortStoreTemp() const { return byte >= ShortStoreTemp && byte < ShortStoreTemp + NumShortStoreTemps; } INLINE BYTE indexOfShortStoreTemp() const { - _ASSERTE(isShortStoreTemp()); + _ASSERTE(IsShortStoreTemp); return byte - ShortStoreTemp; } - INLINE bool isShortSendWithNoArgs() const + __declspec(property(get = get_IsShortSendWithNoArgs)) bool IsShortSendWithNoArgs; + INLINE bool get_IsShortSendWithNoArgs() const { return byte >= ShortSendWithNoArgs && byte < ShortSendWithNoArgs + NumShortSendsWithNoArgs; } INLINE int indexOfShortSendNoArgs() const { - _ASSERTE(isShortSendWithNoArgs()); + _ASSERTE(IsShortSendWithNoArgs); return byte - ShortSendWithNoArgs; } - INLINE bool isShortPushImmediate() const + __declspec(property(get = get_IsShortPushImmediate)) bool IsShortPushImmediate; + INLINE bool get_IsShortPushImmediate() const { return byte >= ShortPushMinusOne && byte <= ShortPushTwo; } INLINE BYTE indexOfPushInstVar() const { - _ASSERTE(isShortPushInstVar()); + _ASSERTE(IsShortPushInstVar); return byte - ShortPushInstVar; } - INLINE bool isShortPush() const + __declspec(property(get = get_IsShortPush)) bool IsShortPush; + INLINE bool get_IsShortPush() const { return byte >= FirstShortPush && byte <= LastPush; // Note that this includes pseudo pushes and push 0, 1, etc } - inline bool isExtendedPush() const + __declspec(property(get = get_IsExtendedPush)) bool IsExtendedPush; + INLINE bool get_IsExtendedPush() const { return (byte >= PushInstVar && byte < FirstExtendedStore) || byte == PushOuterTemp || @@ -229,7 +270,8 @@ struct BYTECODE byte == PushChar; } - inline bool isDoubleExtendedPush() const + __declspec(property(get = get_IsDoubleExtendedPush)) bool IsDoubleExtendedPush; + INLINE bool get_IsDoubleExtendedPush() const { return byte == LongPushOuterTemp || byte == LongPushConst || @@ -237,157 +279,196 @@ struct BYTECODE byte == LongPushImmediate; } - inline bool isPush() const + __declspec(property(get = get_IsPush)) bool IsPush; + INLINE bool get_IsPush() const { - return isShortPush() || isExtendedPush() || isDoubleExtendedPush() || byte == ExLongPushImmediate; + return IsShortPush || IsExtendedPush || IsDoubleExtendedPush || byte == ExLongPushImmediate; } - INLINE bool isExtendedStore() const + __declspec(property(get = get_IsExtendedStore)) bool IsExtendedStore; + INLINE bool get_IsExtendedStore() const { return (byte >= FirstExtendedStore && byte <= LastExtendedStore) || (byte == StoreOuterTemp); } - INLINE bool isExtendedPopStore() const + __declspec(property(get = get_IsExtendedPopStore)) bool IsExtendedPopStore; + INLINE bool get_IsExtendedPopStore() const { return (byte >= FirstPopStore && byte <= LastPopStore) || (byte == PopStoreOuterTemp); } - INLINE bool isStoreTemp() const + __declspec(property(get = get_IsStoreTemp)) bool IsStoreTemp; + INLINE bool get_IsStoreTemp() const { - return byte == StoreTemp || byte == StoreOuterTemp || isShortStoreTemp(); + return byte == StoreTemp || byte == StoreOuterTemp || IsShortStoreTemp; } - INLINE bool isStoreStackTemp() const + __declspec(property(get = get_IsStoreStackTemp)) bool IsStoreStackTemp; + INLINE bool get_IsStoreStackTemp() const { - return byte == StoreTemp || isShortStoreTemp(); + return byte == StoreTemp || IsShortStoreTemp; } - inline bool isShortJump() const + __declspec(property(get = get_IsShortJump)) bool IsShortJump; + INLINE bool get_IsShortJump() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte >= ShortJump && byte <= LastShortJump; } - inline bool isLongJump() const + __declspec(property(get = get_IsLongJump)) bool IsLongJump; + INLINE bool get_IsLongJump() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == LongJump; } - inline bool isNearJump() const + __declspec(property(get = get_IsNearJump)) bool IsNearJump; + INLINE bool get_IsNearJump() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == NearJump; } - inline bool isUnconditionalJump() const + __declspec(property(get = get_IsUnconditionalJump)) bool IsUnconditionalJump; + INLINE bool get_IsUnconditionalJump() const { // Faster to test for long jump first, as this is mainly used by the optimizer // which always works on long jumps - return isLongJump() || isNearJump() || isShortJump(); + return IsLongJump || IsNearJump || IsShortJump; } - inline bool isShortJumpIfFalse() const + __declspec(property(get = get_IsShortJumpIfFalse)) bool IsShortJumpIfFalse; + INLINE bool get_IsShortJumpIfFalse() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte >= ShortJumpIfFalse && byte < ShortJumpIfFalse+NumShortJumpsIfFalse; } - inline bool isJumpIfFalse() const + __declspec(property(get = get_IsJumpIfFalse)) bool IsJumpIfFalse; + INLINE bool get_IsJumpIfFalse() const { - return isShortJumpIfFalse() || + return IsShortJumpIfFalse || byte == NearJumpIfFalse || byte == LongJumpIfFalse; } - inline bool isJumpIfTrue() const + __declspec(property(get = get_IsJumpIfTrue)) bool IsJumpIfTrue; + INLINE bool get_IsJumpIfTrue() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == NearJumpIfTrue || byte == LongJumpIfTrue; } - inline bool isJumpIfNil() const + __declspec(property(get = get_IsJumpIfNil)) bool IsJumpIfNil; + INLINE bool get_IsJumpIfNil() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == NearJumpIfNil || byte == LongJumpIfNil; } - inline bool isJumpIfNotNil() const + __declspec(property(get = get_IsJumpIfNotNil)) bool IsJumpIfNotNil; + INLINE bool get_IsJumpIfNotNil() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == NearJumpIfNotNil || byte == LongJumpIfNotNil; } - inline bool isConditionalJump() const + __declspec(property(get = get_IsConditionalJump)) bool IsConditionalJump; + INLINE bool get_IsConditionalJump() const { return - isJumpIfFalse() || - isJumpIfTrue() || - isJumpIfNil() || - isJumpIfNotNil(); + IsJumpIfFalse || + IsJumpIfTrue || + IsJumpIfNil || + IsJumpIfNotNil; } - inline bool isJumpInstruction() const + __declspec(property(get = get_IsJumpInstruction)) bool IsJumpInstruction; + INLINE bool get_IsJumpInstruction() const { - _ASSERTE(isOpCode()); - return isUnconditionalJump() || - isJumpIfFalse() || - isJumpIfTrue() || - isJumpIfNil() || - isJumpIfNotNil() || + _ASSERTE(IsOpCode); + return IsUnconditionalJump || + IsJumpIfFalse || + IsJumpIfTrue || + IsJumpIfNil || + IsJumpIfNotNil || byte == BlockCopy; } - inline bool isLongConditionalJump() const + __declspec(property(get = get_IsLongConditionalJump)) bool IsLongConditionalJump; + INLINE bool get_IsLongConditionalJump() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == LongJumpIfTrue || byte == LongJumpIfFalse || byte == LongJumpIfNil || byte == LongJumpIfNotNil; } - inline bool isReturn() const + __declspec(property(get = get_IsReturn)) bool IsReturn; + INLINE bool get_IsReturn() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte >= FirstReturn && byte <= LastReturn; } - inline bool isReturnStackTop() const + __declspec(property(get = get_IsReturnStackTop)) bool IsReturnStackTop; + INLINE bool get_IsReturnStackTop() const { - _ASSERTE(isOpCode()); + _ASSERTE(IsOpCode); return byte == ReturnMessageStackTop || byte == ReturnBlockStackTop; } - inline bool isMethodReturn() const + __declspec(property(get = get_IsMethodReturn)) bool IsMethodReturn; + INLINE bool get_IsMethodReturn() const { - _ASSERTE(isOpCode()); - return byte != ReturnBlockStackTop && isReturn(); + _ASSERTE(IsOpCode); + return byte != ReturnBlockStackTop && IsReturn; } - inline bool isShortSend() const + __declspec(property(get = get_IsShortSend)) bool IsShortSend; + INLINE bool get_IsShortSend() const { return (byte >= FirstShortSend && byte <= LastShortSend) || (byte >= FirstExSpecialSend && byte <= LastExSpecialSend); } - inline bool isSend() const + __declspec(property(get = get_IsSend)) bool IsSend; + INLINE bool get_IsSend() const { - _ASSERTE(isOpCode()); - return isShortSend() + _ASSERTE(IsOpCode); + return IsShortSend || byte == Send || byte == Supersend || byte == SpecialSend || byte == SendTempWithNoArgs || byte == SendSelfWithNoArgs || byte == PopSendSelfNoArgs || byte == LongSend || byte == LongSupersend || byte == ExLongSend || byte == ExLongSupersend; } - inline bool isStore() const + __declspec(property(get = get_IsStore)) bool IsStore; + INLINE bool get_IsStore() const { - return isShortStoreTemp() || isShortPopStore() || isExtendedStore() || isExtendedPopStore() + return IsShortStoreTemp || IsShortPopStore || IsExtendedStore || IsExtendedPopStore || byte == LongStoreStatic || byte == LongStoreOuterTemp; } }; -typedef std::vector BYTECODES; +class BYTECODES : public std::vector +{ +public: + BYTECODE& operator[](const ip_t ip) + { + size_t pos = static_cast(ip); + _ASSERTE(pos < size()); + return at(pos); + } + + const BYTECODE& operator[](const ip_t ip) const + { + size_t pos = static_cast(ip); + _ASSERTE(pos < size()); + return at(pos); + } +}; INLINE static int indexOfPushX(BYTE /*b1*/, BYTE b2) { diff --git a/Core/DolphinVM/Compiler/compiler.cpp b/Core/DolphinVM/Compiler/compiler.cpp index 6d140ddc4f..dada886465 100755 --- a/Core/DolphinVM/Compiler/compiler.cpp +++ b/Core/DolphinVM/Compiler/compiler.cpp @@ -71,47 +71,41 @@ LPUTF8 s_restrictedSelectors[] = /////////////////////// -Compiler::LibCallType Compiler::callTypes[DolphinX::NumCallConventions] = +Compiler::LibCallType Compiler::callTypes[4] = { - (LPUTF8)"stdcall:", DolphinX::ExtCallStdCall, - (LPUTF8)"cdecl:", DolphinX::ExtCallCDecl, - (LPUTF8)"thiscall:", DolphinX::ExtCallThisCall, - (LPUTF8)"fastcall:", DolphinX::ExtCallFastCall + (LPUTF8)"stdcall:", DolphinX::ExtCallDeclSpec::StdCall, + (LPUTF8)"cdecl:", DolphinX::ExtCallDeclSpec::CDecl, + (LPUTF8)"thiscall:", DolphinX::ExtCallDeclSpec::ThisCall, + (LPUTF8)"fastcall:", DolphinX::ExtCallDeclSpec::FastCall }; /////////////////////// Compiler::Compiler() : - m_allScopes(NULL), - m_bytecodes(NULL), m_class(0), - m_codePointer(0), - m_compiledMethodClass(NULL), + m_codePointer((ip_t)0), + m_compiledMethodClass(nullptr), m_compilerObject(0), m_context(0), - m_flags(Default), - m_instVars(NULL), + m_flags(CompilerFlags::Default), m_instVarsInitialized(false), - m_literalFrame(NULL), m_literalLimit(LITERALLIMIT), m_notifier(0), m_ok(true), - m_oopWorkspacePools(NULL), - m_pCurrentScope(NULL), + m_oopWorkspacePools(nullptr), + m_pCurrentScope(nullptr), m_primitiveIndex(0), m_selector(), - m_sendType(SendOther), - m_textMaps(NULL) + m_sendType(SendType::SendOther) { - m_bytecodes.reserve(128); } Compiler::~Compiler() { // Free scopes { - const int count = m_allScopes.size(); - for (int i = 0; i < count ; i++) + const size_t count = m_allScopes.size(); + for (size_t i = 0; i < count ; i++) { LexicalScope* pScope = m_allScopes[i]; delete pScope; @@ -120,22 +114,22 @@ Compiler::~Compiler() // Free literal frame { - const int count = m_literalFrame.size(); - for (int i = 0; i < count; i++) + const size_t count = m_literalFrame.size(); + for (size_t i = 0; i < count; i++) { m_piVM->RemoveReference(m_literalFrame[i]); } } } -inline void Compiler::SetFlagsAndText(FLAGS flags, LPUTF8 text, int offset) +inline void Compiler::SetFlagsAndText(CompilerFlags flags, LPUTF8 text, textpos_t offset) { m_flags=flags; SetText(text, offset); NextToken(); } -void Compiler::PrepareToCompile(FLAGS flags, LPUTF8 compiletext, int offset, POTE aClass, Oop compiler, Oop notifier, POTE workspacePools, POTE compiledMethodClass, Oop context) +void Compiler::PrepareToCompile(CompilerFlags flags, LPUTF8 compiletext, textpos_t offset, POTE aClass, Oop compiler, Oop notifier, POTE workspacePools, POTE compiledMethodClass, Oop context) { // Prepare to compile methods for the given class. // This gets the list of instance variable names for this class @@ -187,41 +181,41 @@ Str Compiler::GetNameOfClass(Oop oopClass, bool recurse) } } -POTE Compiler::CompileExpression(LPUTF8 compiletext, Oop compiler, Oop notifier, Oop contextOop, FLAGS flags, unsigned& len, int exprStart) +POTE Compiler::CompileExpression(LPUTF8 compiletext, Oop compiler, Oop notifier, Oop contextOop, CompilerFlags flags, size_t& len, textpos_t exprStart) { POTE classPointer = m_piVM->FetchClassOf(contextOop); PrepareToCompile(flags, compiletext, exprStart, classPointer, compiler, notifier, Nil(), GetVMPointers().ClassCompiledExpression, contextOop); POTE oteMethod; if (m_ok) { - oteMethod = ParseEvalExpression(CloseParen); + oteMethod = ParseEvalExpression(TokenType::CloseParen); } else oteMethod = Nil(); - len = GetParsedLength(); + len = ParsedLength; return oteMethod; } -POTE Compiler::CompileForClassHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aClass, FLAGS flags) +POTE Compiler::CompileForClassHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aClass, CompilerFlags flags) { BOOL wasDisabled = m_piVM->DisableAsyncGC(true); POTE method = Nil(); __try { - if (flags & ScanOnly) + if (!(flags & CompilerFlags::ScanOnly)) { - while (!AtEnd()) - NextToken(); - } - else - { - PrepareToCompile(flags, compiletext, 0, aClass, compiler, notifier, Nil(), GetVMPointers().ClassCompiledMethod); + PrepareToCompile(flags, compiletext, textpos_t::start, aClass, compiler, notifier, Nil(), GetVMPointers().ClassCompiledMethod); if (m_ok) // Do the compile method=ParseMethod(); } + else + { + while (!AtEnd) + NextToken(); + } } __finally { @@ -230,17 +224,17 @@ POTE Compiler::CompileForClassHelper(LPUTF8 compiletext, Oop compiler, Oop notif return method; } -POTE Compiler::CompileForEvaluationHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aBehavior, POTE aWorkspacePool, FLAGS flags) +POTE Compiler::CompileForEvaluationHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aBehavior, POTE aWorkspacePool, CompilerFlags flags) { BOOL wasDisabled = m_piVM->DisableAsyncGC(true); POTE method = Nil(); __try { - PrepareToCompile(flags, compiletext, 0, aBehavior, compiler, notifier, aWorkspacePool, GetVMPointers().ClassCompiledExpression); + PrepareToCompile(flags, compiletext, textpos_t::start, aBehavior, compiler, notifier, aWorkspacePool, GetVMPointers().ClassCompiledExpression); if (m_ok) { - method = ParseEvalExpression(Eof); - if (m_ok && ThisToken() != Eof) + method = ParseEvalExpression(TokenType::Eof); + if (m_ok && ThisToken != TokenType::Eof) CompileError(CErrNonsenseAtMethodEnd); } } @@ -260,25 +254,25 @@ Str Compiler::GetClassName() /////////////////////////////////// -inline int Compiler::FindNameAsSpecialMessage(const Str& name) const +inline uint8_t Compiler::FindNameAsSpecialMessage(const Str& name) const { // Returns true and an appropriate (index) if (name) is a // special message // const VMPointers& pointers = GetVMPointers(); - for (int i = 0; i < NumSpecialSelectors; i++) + for (uint8_t i = 0; i < NumSpecialSelectors; i++) { const POTE stringPointer = pointers.specialSelectors[i]; _ASSERTE(m_piVM->IsKindOf(Oop(stringPointer), pointers.ClassSymbol)); LPUTF8 psz = (LPUTF8)FetchBytesOf(stringPointer); if (name == psz) { - return i + ShortSpecialSend; + return ShortSpecialSend + i; } } - for (int i = 0; i < NumExSpecialSends; i++) + for (uint8_t i = 0; i < NumExSpecialSends; i++) { const POTE stringPointer = pointers.exSpecialSelectors[i]; if (stringPointer != pointers.Nil) @@ -292,10 +286,10 @@ inline int Compiler::FindNameAsSpecialMessage(const Str& name) const } } - return -1; + return 0; } -inline int Compiler::FindNameAsInstanceVariable(const Str& name) const +inline size_t Compiler::FindNameAsInstanceVariable(const Str& name) const { // Search for an instance variable if (name) and return true and its // (index) if one is found. We go through the list backwards for speed @@ -303,16 +297,15 @@ inline int Compiler::FindNameAsInstanceVariable(const Str& name) const // if (!m_instVarsInitialized) const_cast(this)->GetInstVars(); - int i; - for (i=m_instVars.size()-1; i>=0; i--) + for (size_t i=m_instVars.size(); i>0; i--) { - if (name == m_instVars[i]) - break; + if (name == m_instVars[i-1]) + return i - 1; } - return i; + return -1; } -TempVarRef* Compiler::AddTempRef(const Str& strName, VarRefType refType, const TEXTRANGE& range, int expressionEnd) +TempVarRef* Compiler::AddTempRef(const Str& strName, VarRefType refType, const TEXTRANGE& range, textpos_t expressionEnd) { // Search for a temporary variable of (name) and return true and its // (index) if one is found. We MUST look through the list backwards to @@ -321,15 +314,15 @@ TempVarRef* Compiler::AddTempRef(const Str& strName, VarRefType refType, const T LexicalScope* pScope = m_pCurrentScope; TempVarDecl* pDecl = pScope->FindTempDecl(strName); - if (pDecl == NULL) + if (pDecl == nullptr) // Undeclared - return NULL; + return nullptr; - if (pDecl->IsReadOnly() && refType > vrtRead) + if (pDecl->IsReadOnly && refType > VarRefType::Read) { CompileError(TEXTRANGE(range.m_start, expressionEnd), CErrAssignmentToArgument, (Oop)NewUtf8String(strName)); - return NULL; + return nullptr; } // Create a new usage ref and return it @@ -346,13 +339,13 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic Oop scope = reinterpret_cast(m_class == nil ? GetVMPointers().ClassUndefinedObject : m_class); POTE oteBinding = reinterpret_cast(m_piVM->PerformWith(scope, GetVMPointers().fullBindingForSymbol, reinterpret_cast(NewUtf8String(name)))); - STVarObject* pools = NULL; + STVarObject* pools = nullptr; // Look in Workspace pools (if any) next if (oteBinding == nil && m_oopWorkspacePools != nil) { pools = (STVarObject*)GetObj(m_oopWorkspacePools); - const MWORD poolsSize = FetchWordLengthOf(m_oopWorkspacePools); - for (MWORD i=0; i(pools->fields[i]); if (pool != nil) @@ -368,7 +361,7 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic { if (IsCharUpper(name[0])) { - if (IsInteractive()) + if (IsInteractive) { char szPrompt[256]; ::LoadString(GetResLibHandle(), IDP_AUTO_DEFINE_GLOBAL, szPrompt, sizeof(szPrompt)-1); @@ -376,7 +369,7 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic ::wsprintf(msg, szPrompt, name.c_str()); char szCaption[256]; ::LoadString(GetResLibHandle(), IDR_COMPILER, szCaption, sizeof(szCaption)-1); - int answer = ::MessageBox(NULL, msg, szCaption, MB_YESNOCANCEL|MB_ICONQUESTION|MB_TASKMODAL); + int answer = ::MessageBox(nullptr, msg, szCaption, MB_YESNOCANCEL|MB_ICONQUESTION|MB_TASKMODAL); delete[] msg; switch(answer) @@ -388,7 +381,7 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic } break; case IDCANCEL: - return STATICCANCEL; + return StaticType::STATICCANCEL; case IDNO: default: @@ -398,7 +391,7 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic } else { - if (!WantSyntaxCheckOnly() && pools != NULL) + if (!WantSyntaxCheckOnly && pools != nullptr) { POTE pool = reinterpret_cast(pools->fields[0]); if (pool != nil) @@ -412,12 +405,12 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic if (oteBinding != nil) { - StaticType sharedType = m_piVM->IsImmutable(reinterpret_cast(oteBinding)) ? STATICCONSTANT : STATICVARIABLE; + StaticType sharedType = m_piVM->IsImmutable(reinterpret_cast(oteBinding)) ? StaticType::STATICCONSTANT : StaticType::STATICVARIABLE; oteStatic = oteBinding; return sharedType; } else - return STATICNOTFOUND; + return StaticType::STATICNOTFOUND; } ////////////////////////////////////////////////////////////// @@ -425,7 +418,7 @@ Compiler::StaticType Compiler::FindNameAsStatic(const Str& name, POTE& oteStatic // Add a new temporary at the top of the temporaries stack TempVarDecl* Compiler::AddTemporary(const Str& name, const TEXTRANGE& range, bool isArg) { - TempVarDecl* pVar = NULL; + TempVarDecl* pVar = nullptr; CheckTemporaryName(name, range, isArg); if (m_ok) @@ -437,15 +430,15 @@ TempVarDecl* Compiler::AddTemporary(const Str& name, const TEXTRANGE& range, boo TempVarDecl* Compiler::AddArgument(const Str& name, const TEXTRANGE& range) { TempVarDecl* pNewVar = AddTemporary(name, range, true); - if (pNewVar == NULL) - return NULL; + if (pNewVar == nullptr) + return nullptr; m_pCurrentScope->ArgumentAdded(pNewVar); return pNewVar; } // Rename the temporary at location "temporary" to the name "newName" -void Compiler::RenameTemporary(int temporary, LPUTF8 newName, const TEXTRANGE& range) +void Compiler::RenameTemporary(size_t temporary, LPUTF8 newName, const TEXTRANGE& range) { CheckTemporaryName(newName, range, false); m_pCurrentScope->RenameTemporary(temporary, newName, range); @@ -463,27 +456,27 @@ void Compiler::CheckTemporaryName(const Str& name, const TEXTRANGE& range, bool } TempVarDecl* pDecl = m_pCurrentScope->FindTempDecl(name); - if (pDecl && pDecl->GetScope() == m_pCurrentScope) + if (pDecl && pDecl->Scope == m_pCurrentScope) { if (isArg) { - _ASSERTE(pDecl->IsArgument()); + _ASSERTE(pDecl->IsArgument); CompileError(range, CErrDuplicateArgName); } else - CompileError(range, pDecl->IsArgument() ? CErrRedefiningArg : CErrDuplicateTempName); + CompileError(range, pDecl->IsArgument ? CErrRedefiningArg : CErrDuplicateTempName); } - if (IsInteractive()) + if (IsInteractive) { if (pDecl) - Warning(range, pDecl->IsArgument() ? CWarnRedefiningArg : CWarnRedefiningTemp); - else if (FindNameAsInstanceVariable(name) >= 0) + Warning(range, pDecl->IsArgument ? CWarnRedefiningArg : CWarnRedefiningTemp); + else if (FindNameAsInstanceVariable(name) != -1) Warning(range, CWarnRedefiningInstVar); else { POTE oteStatic; - if (FindNameAsStatic(name, oteStatic) > STATICNOTFOUND) + if (FindNameAsStatic(name, oteStatic) > StaticType::STATICNOTFOUND) { m_piVM->RemoveReference(reinterpret_cast(oteStatic)); Warning(range, CWarnRedefiningStatic); @@ -494,66 +487,63 @@ void Compiler::CheckTemporaryName(const Str& name, const TEXTRANGE& range, bool ////////////////////////////////////////////////// -int Compiler::GenByte(BYTE value, BYTE flags, LexicalScope* pScope) +ip_t Compiler::GenByte(uint8_t value, BYTECODE::FLAGS flags, LexicalScope* pScope) { - _ASSERTE(m_pCurrentScope != NULL); + _ASSERTE(m_pCurrentScope != nullptr); InsertByte(m_codePointer, value, flags, pScope); - int ip = m_codePointer; - m_codePointer++; + ip_t ip = m_codePointer; + m_codePointer = (ip_t)((intptr_t)m_codePointer + 1); return ip; } // Insert an extended instruction at the code pointer, returning the position at which // the instruction was inserted. -inline int Compiler::GenInstructionExtended(BYTE basic, BYTE extension) +inline ip_t Compiler::GenInstructionExtended(uint8_t basic, uint8_t extension) { - int pos=GenInstruction(basic); + ip_t pos=GenInstruction(basic); GenData(extension); return pos; } // Insert an extended instruction at the code pointer, returning the position at which // the instruction was inserted. -int Compiler::GenLongInstruction(BYTE basic, WORD extension) +ip_t Compiler::GenLongInstruction(uint8_t basic, uint16_t extension) { // Generate a double extended instruction. // - int pos=GenInstruction(basic); - GenData(extension & 0xFF); + ip_t pos=GenInstruction(basic); + GenData(extension & UINT8_MAX); GenData(extension >> 8); return pos; } -void Compiler::UngenInstruction(int pos) +void Compiler::UngenInstruction(ip_t pos) { - _ASSERTE(pos < GetCodeSize()); BYTECODE& bc = m_bytecodes[pos]; - _ASSERTE(bc.isOpCode()); + _ASSERTE(bc.IsOpCode); _ASSERTE(FindTextMapEntry(pos) == m_textMaps.end()); // Marks the byte at pos as being unwanted by changing it to a Nop - if (bc.isJumpSource()) + if (bc.IsJumpSource) { - _ASSERTE(bc.target < GetCodeSize()); - _ASSERTE(static_cast(bc.target) >= 0); m_bytecodes[bc.target].removeJumpTo(); bc.makeNonJump(); } - const int len = bc.instructionLength(); + const size_t len = bc.InstructionLength; // Nop-out the instruction (N.B. doesn't remove it!) bc.byte = Nop; // Also nop-out any data bytes associated with the instruction - for (int i=1;i(CodeSize); if (pos == codeSize) { @@ -561,18 +551,18 @@ void Compiler::InsertByte(int pos, BYTE value, BYTE flags, LexicalScope* pScope) } else { - _ASSERTE(pos >= 0 && pos < codeSize); - m_bytecodes.insert(m_bytecodes.begin()+pos, BYTECODE(value, flags, pScope)); + _ASSERTE(pos < codeSize); + m_bytecodes.insert(m_bytecodes.begin()+(size_t)pos, BYTECODE(value, flags, pScope)); // New byte may become jump target // Adjust the jumps providing we are not appending to the end of the code. // Note use of <= because we have inserted an additional bytecode - for (int i=0; i <= codeSize; i++) + for (ip_t i=ip_t::zero; i <= codeSize; i++) { BYTECODE& bc = m_bytecodes[i]; - if (bc.isJumpSource()) + if (bc.IsJumpSource) { - _ASSERTE(bc.target < GetCodeSize() - 1); + _ASSERTE((size_t)bc.target < CodeSize - 1); // This is a jump. Does it cross the boundary? if (bc.target >= pos) @@ -583,8 +573,8 @@ void Compiler::InsertByte(int pos, BYTE value, BYTE flags, LexicalScope* pScope) } // Adjust ip of any TextMaps - const int textMapCount = m_textMaps.size(); - for (int i = 0; i < textMapCount; i++) + const size_t textMapCount = m_textMaps.size(); + for (size_t i = 0; i < textMapCount; i++) { TEXTMAP& textMap = m_textMaps[i]; if (textMap.ip >= pos) @@ -594,12 +584,12 @@ void Compiler::InsertByte(int pos, BYTE value, BYTE flags, LexicalScope* pScope) } -int Compiler::GenPushTemp(TempVarRef* pTemp) +ip_t Compiler::GenPushTemp(TempVarRef* pTemp) { return GenTempRefInstruction(LongPushOuterTemp, pTemp); } -inline int Compiler::GenPushInstVar(BYTE index) +inline ip_t Compiler::GenPushInstVar(uint8_t index) { m_pCurrentScope->MarkNeedsSelf(); @@ -614,19 +604,19 @@ inline void Compiler::GenPushStaticVariable(const Str& strName, const TEXTRANGE& POTE oteStatic; switch (FindNameAsStatic(strName, oteStatic)) { - case STATICCONSTANT: + case StaticType::STATICCONSTANT: GenPushStaticConstant(oteStatic, range); break; - case STATICVARIABLE: + case StaticType::STATICVARIABLE: GenStatic(oteStatic, range); break; - case STATICCANCEL: + case StaticType::STATICCANCEL: m_ok = false; return; - case STATICNOTFOUND: + case StaticType::STATICNOTFOUND: default: CompileError(range, CErrUndeclared, (Oop)NewUtf8String(strName)); return; @@ -668,7 +658,7 @@ void Compiler::GenPushVariable(const Str& strName, const TEXTRANGE& range) if (strName == VarSelf) { GenPushSelf(); - m_sendType = SendSelf; + m_sendType = SendType::SendSelf; } else if (strName == VarSuper && // Cannot supersend from class with no superclass ((STBehavior*)GetObj(m_class))->superclass != Nil()) @@ -677,24 +667,24 @@ void Compiler::GenPushVariable(const Str& strName, const TEXTRANGE& range) // that messages must be sent to superclass of self. // GenPushSelf(); - m_sendType = SendSuper; + m_sendType = SendType::SendSuper; } else if (strName == VarThisContext) GenInstruction(PushActiveFrame); else { - TempVarRef* pRef = AddTempRef(strName, vrtRead, range, range.m_stop); + TempVarRef* pRef = AddTempRef(strName, VarRefType::Read, range, range.m_stop); - if (pRef != NULL) + if (pRef != nullptr) GenPushTemp(pRef); else { - int index = FindNameAsInstanceVariable(strName); + ptrdiff_t index = FindNameAsInstanceVariable(strName); if (index >= 0) { // Only 255 inst vars recognised, so index should not be > 255 _ASSERTE(index < 256); - GenPushInstVar(static_cast(index)); + GenPushInstVar(static_cast(index & 0xff)); } else GenPushStaticVariable(strName, range); @@ -702,53 +692,55 @@ void Compiler::GenPushVariable(const Str& strName, const TEXTRANGE& range) } } -void Compiler::GenInteger(int val, const TEXTRANGE& range) +void Compiler::GenInteger(intptr_t val, const TEXTRANGE& range) { // Generates code to push a small integer constant. if (val >= -1 && val <= 2) - GenInstruction(ShortPushZero + val); - else if (val >= -128 && val <= 127) - GenInstructionExtended(PushImmediate, static_cast(val)); - else if (val >= -32768 && val <= 32767) - GenLongInstruction(LongPushImmediate, static_cast(val)); - else if (IsIntegerValue(val)) + GenInstruction((ShortPushZero + val) & 0xff); + else if (val >= _I8_MIN && val <= _I8_MAX) + GenInstructionExtended(PushImmediate, static_cast(val)); + else if (val >= _I16_MIN && val <= _I16_MAX) + GenLongInstruction(LongPushImmediate, static_cast(val)); + else if (val >= _I32_MIN && val <= _I32_MAX && IsIntegerValue(val)) { // Note that although there is sufficient space in the instruction to represent the full range of // 32-bit integers, we don't bother with those outside the SmallInteger range since those would // then need to be allocated each time, rather than read from a constant in the literal frame. GenInstruction(ExLongPushImmediate); - GenData(val & 0xFF); - GenData((val >> 8) & 0xFF); - GenData((val >> 16) & 0xFF); - GenData((val >> 24) & 0xFF); + GenData(val & UINT8_MAX); + GenData((val >> 8) & UINT8_MAX); + GenData((val >> 16) & UINT8_MAX); + GenData((val >> 24) & UINT8_MAX); } else + { GenLiteralConstant(m_piVM->NewSignedInteger(val), range); + } } -template int Compiler::PriorInstruction() const +template ip_t Compiler::PriorInstruction() const { - int priorIndex = m_codePointer-1; - while (priorIndex >= 0 && (m_bytecodes[priorIndex].isData() || (m_bytecodes[priorIndex].byte == Nop && ignoreNops))) - priorIndex--; + ip_t priorIndex = m_codePointer-1; + while (priorIndex >= ip_t::zero && (m_bytecodes[priorIndex].IsData || (m_bytecodes[priorIndex].byte == Nop && ignoreNops))) + --priorIndex; return priorIndex; } bool Compiler::LastIsPushNil() const { - int priorIndex = PriorInstruction(); - if (priorIndex < 0) + ip_t priorIndex = PriorInstruction(); + if (priorIndex == ip_t::npos) return false; - return m_bytecodes[priorIndex].byte == ShortPushNil; + return const_cast(this)->m_bytecodes[priorIndex].byte == ShortPushNil; } // Answer whether the previous instruction is a push SmallInteger // There are a number of possibilities -bool Compiler::LastIsPushSmallInteger(int& value) const +bool Compiler::LastIsPushSmallInteger(intptr_t& value) const { - int priorIndex = PriorInstruction(); - if (priorIndex < 0) + ip_t priorIndex = PriorInstruction(); + if (priorIndex == ip_t::npos) return false; Oop literal = IsPushLiteral(priorIndex); @@ -763,8 +755,8 @@ bool Compiler::LastIsPushSmallInteger(int& value) const Oop Compiler::LastIsPushNumber() const { - int priorIndex = PriorInstruction(); - if (priorIndex < 0) + ip_t priorIndex = PriorInstruction(); + if (priorIndex == ip_t::npos) return NULL; Oop literal = IsPushLiteral(priorIndex); @@ -780,9 +772,9 @@ Oop Compiler::LastIsPushNumber() const } } -Oop Compiler::IsPushLiteral(int pos) const +Oop Compiler::IsPushLiteral(ip_t pos) const { - BYTE opCode = m_bytecodes[pos].byte; + uint8_t opCode = m_bytecodes[pos].byte; switch(opCode) { @@ -793,14 +785,14 @@ Oop Compiler::IsPushLiteral(int pos) const return IntegerObjectOf(opCode - ShortPushZero); case PushImmediate: - return IntegerObjectOf(SBYTE(m_bytecodes[pos+1].byte)); + return IntegerObjectOf(static_cast(m_bytecodes[pos+1].byte)); case LongPushImmediate: // Remember x86 is little endian - return IntegerObjectOf(SWORD(m_bytecodes[pos+1].byte | (m_bytecodes[pos+2].byte << 8))); + return IntegerObjectOf(static_cast(m_bytecodes[pos+1].byte | (m_bytecodes[pos+2].byte << 8))); case ExLongPushImmediate: - return IntegerObjectOf(static_cast((m_bytecodes[pos+ExLongPushImmediateInstructionSize-1].byte) << 24 + return IntegerObjectOf(static_cast((m_bytecodes[pos+ExLongPushImmediateInstructionSize-1].byte) << 24 | (m_bytecodes[pos + ExLongPushImmediateInstructionSize - 2].byte << 16) | (m_bytecodes[pos + ExLongPushImmediateInstructionSize - 3].byte << 8) | m_bytecodes[pos + ExLongPushImmediateInstructionSize - 4].byte)); @@ -824,13 +816,13 @@ Oop Compiler::IsPushLiteral(int pos) const case ShortPushConst+13: case ShortPushConst+14: case ShortPushConst+15: - _ASSERTE(m_bytecodes[pos].isShortPushConst()); + _ASSERTE(m_bytecodes[pos].IsShortPushConst); return m_literalFrame[opCode - ShortPushConst]; default: // If this assertion fires, then the above case may need updating to reflect the // change in the bytecode set, i.e. more or less ShortPushConst instructions - _ASSERTE(!m_bytecodes[pos].isShortPushConst()); + _ASSERTE(!m_bytecodes[pos].IsShortPushConst); break; } @@ -864,49 +856,51 @@ void Compiler::GenNumber(Oop numPointer, const TEXTRANGE& range) GenLiteralConstant(numPointer, range); } -int Compiler::AddToFrameUnconditional(Oop object, const TEXTRANGE& errRange) +size_t Compiler::AddToFrameUnconditional(Oop object, const TEXTRANGE& errRange) { // Adds (object) to the literal frame even if it is already there. // Returns the index to the object in the literal frame. // _ASSERTE(object); - _ASSERTE(!IsIntegerObject(object) || IntegerValueOf(object) < -32768 || IntegerValueOf(object) > 32767 || errRange.span() <= 0); - int index=-1; - int count = GetLiteralCount(); - if (count < m_literalLimit) + _ASSERTE(!IsIntegerObject(object) || IntegerValueOf(object) < INT16_MIN || IntegerValueOf(object) > INT16_MAX || errRange.Span <= 0); + size_t index = LiteralCount; + if (index < m_literalLimit) { - index = count; m_literalFrame.push_back(object); m_piVM->AddReference(object); CHECKREFERENCES } else + { + index = -1; CompileError(errRange, CErrTooManyLiterals, object); + } return index; } -int Compiler::AddToFrame(Oop object, const TEXTRANGE& errRange) +size_t Compiler::AddToFrame(Oop object, const TEXTRANGE& errRange) { // Adds (object) to the literal frame if it is not already there. // Returns the index to the object in the literal frame. // - for (int i=GetLiteralCount()-1;i>=0;i--) + for (size_t i=LiteralCount;i>0;i--) { - Oop literalPointer = m_literalFrame[i]; + Oop literalPointer = m_literalFrame[i-1]; _ASSERTE(literalPointer); if (literalPointer == object) { CHECKREFERENCES - return i; + return i-1; } } return AddToFrameUnconditional(object, errRange); } -int Compiler::AddStringToFrame(POTE stringPointer, const TEXTRANGE& range) + +size_t Compiler::AddStringToFrame(POTE stringPointer, const TEXTRANGE& range) { // Adds (object) to the literal frame if it is not already there. // Returns the index to the object in the literal frame. @@ -915,22 +909,22 @@ int Compiler::AddStringToFrame(POTE stringPointer, const TEXTRANGE& range) POTE classPointer = m_piVM->FetchClassOf(Oop(stringPointer)); LPUTF8 szValue = (LPUTF8)FetchBytesOf(stringPointer); - for (int i=GetLiteralCount()-1;i>=0;i--) + for (size_t i=LiteralCount;i>0;i--) { - Oop literalPointer = m_literalFrame[i]; + Oop literalPointer = m_literalFrame[i - 1]; _ASSERTE(literalPointer); if ((m_piVM->FetchClassOf(literalPointer) == classPointer) && strcmp((LPCSTR)FetchBytesOf(POTE(literalPointer)), (LPCSTR)szValue) == 0) { m_piVM->RemoveReference((Oop)stringPointer); - return i; + return i - 1; } } Oop oopString = reinterpret_cast(stringPointer); m_piVM->MakeImmutable(oopString, TRUE); - int i = AddToFrameUnconditional(oopString, range); + size_t i = AddToFrameUnconditional(oopString, range); m_piVM->RemoveReference((Oop)stringPointer); return i; } @@ -963,12 +957,12 @@ bool Compiler::GenPushImmediate(Oop objectPointer, const TEXTRANGE& range) STVarObject* pChar = GetObj((POTE)objectPointer); Oop asciiValue = pChar->fields[0]; _ASSERT(IsIntegerObject(asciiValue)); - MWORD codePoint = IntegerValueOf(asciiValue); + char32_t codePoint = IntegerValueOf(asciiValue) & UINT32_MAX; if (codePoint > 127) { return false; } - GenInstructionExtended(PushChar, static_cast(codePoint)); + GenInstructionExtended(PushChar, static_cast(codePoint)); } else { @@ -990,25 +984,24 @@ void Compiler::GenPushConstant(Oop objectPointer, const TEXTRANGE& range) // Generates code to push a literal constant -void Compiler::GenConstant(int index) +void Compiler::GenConstant(size_t index) { if (m_ok) { - // Index should be >=0 if no error detected - _ASSERTE(index >= 0); - // Generate the push if (index < NumShortPushConsts) // In range of short instructions ? - GenInstruction(ShortPushConst, index); + GenInstruction(ShortPushConst, static_cast(index)); else if (index < 256) // In range of single extended instructions ? { - GenInstructionExtended(PushConst, static_cast(index)); + GenInstructionExtended(PushConst, static_cast(index)); } else { // Too many literals detected when adding to frame, so index should be in range - _ASSERTE(index < 65536); - GenLongInstruction(LongPushConst, static_cast(index)); + if (index >= 65536) + InternalError(__FILE__, __LINE__, ThisTokenRange, "Literal index out of range %Iu", index); + + GenLongInstruction(LongPushConst, static_cast(index)); } } } @@ -1016,44 +1009,46 @@ void Compiler::GenConstant(int index) // Generates code to push a literal variable. void Compiler::GenStatic(const POTE oteStatic, const TEXTRANGE& range) { - int index = AddToFrame(reinterpret_cast(oteStatic), range); + size_t index = AddToFrame(reinterpret_cast(oteStatic), range); if (m_ok) { // Index should be >=0 if no error detected - _ASSERT(index >= 0); + _ASSERT(index != -1); // Generate the push if (index < NumShortPushStatics) // In range of short instructions ? - GenInstruction(ShortPushStatic, index); - else if (index < 256) // In range of single extended instructions ? { - GenInstructionExtended(PushStatic, static_cast(index)); + GenInstruction(ShortPushStatic, static_cast(index)); + } + else if (index <= UINT8_MAX) // In range of single extended instructions ? + { + GenInstructionExtended(PushStatic, static_cast(index)); } else { // Too many literals detected when adding to frame, so index should be in range - _ASSERTE(index < 65536); - GenLongInstruction(LongPushStatic, static_cast(index)); + _ASSERTE(index <= UINT16_MAX); + GenLongInstruction(LongPushStatic, static_cast(index)); } } } -int Compiler::GenReturn(BYTE retOp) +ip_t Compiler::GenReturn(uint8_t retOp) { BreakPoint(); return GenInstruction(retOp); } -int Compiler::GenMessage(const Str& pattern, int argCount, int messageStart) +ip_t Compiler::GenMessage(const Str& pattern, argcount_t argCount, textpos_t messageStart) { BreakPoint(); // Generates code to send a message (pattern) with (argCount) arguments - if (m_sendType != SendSuper) + if (m_sendType != SendType::SendSuper) { // Look for special or arithmetic messages - int bytecode = FindNameAsSpecialMessage(pattern); - if (bytecode > 0) + uint8_t bytecode = FindNameAsSpecialMessage(pattern); + if (bytecode != 0) { return GenInstruction(bytecode); } @@ -1062,23 +1057,23 @@ int Compiler::GenMessage(const Str& pattern, int argCount, int messageStart) // It wasn't that simple so we'll need a literal // symbol in the frame. POTE oteSelector = InternSymbol(pattern); - TEXTRANGE errRange = TEXTRANGE(messageStart, argCount == 0 ? ThisTokenRange().m_stop : LastTokenRange().m_stop); - int symbolIndex=AddToFrame(reinterpret_cast(oteSelector), errRange); - if (symbolIndex < 0) - return 0; + TEXTRANGE errRange = TEXTRANGE(messageStart, argCount == 0 ? ThisTokenRange.m_stop : LastTokenRange.m_stop); + size_t symbolIndex=AddToFrame(reinterpret_cast(oteSelector), errRange); + if (symbolIndex == -1) + return ip_t::npos; - if (m_sendType == SendSuper) + if (m_sendType == SendType::SendSuper) { // Warn if supersends a message which is not implemented - be sure not to wrongly flag // recursive self send first time the method is compiled POTE superclass = ((STBehavior*)GetObj(m_class))->superclass; - if (IsInteractive() && !CanUnderstand(superclass, oteSelector)) + if (IsInteractive && !CanUnderstand(superclass, oteSelector)) WarningV(errRange, CWarnMsgUnimplemented, reinterpret_cast(oteSelector), m_piVM->NewString("super"), superclass, 0); } else { // Warn if self-sends a message which is not implemented - if (m_sendType == SendSelf && IsInteractive() + if (m_sendType == SendType::SendSelf && IsInteractive && pattern != m_selector && !CanUnderstand(m_class, oteSelector)) WarningV(errRange, CWarnMsgUnimplemented, reinterpret_cast(oteSelector), m_piVM->NewString("self"), m_class, 0); @@ -1090,19 +1085,19 @@ int Compiler::GenMessage(const Str& pattern, int argCount, int messageStart) case 0: if (symbolIndex < NumShortSendsWithNoArgs) { - return GenInstruction(ShortSendWithNoArgs, static_cast(symbolIndex)); + return GenInstruction(ShortSendWithNoArgs, static_cast(symbolIndex)); } break; case 1: if (symbolIndex < NumShortSendsWith1Arg) { - return GenInstruction(ShortSendWith1Arg, static_cast(symbolIndex)); + return GenInstruction(ShortSendWith1Arg, static_cast(symbolIndex)); } break; case 2: if (symbolIndex < NumShortSendsWith2Args) { - return GenInstruction(ShortSendWith2Args, static_cast(symbolIndex)); + return GenInstruction(ShortSendWith2Args, static_cast(symbolIndex)); } break; default: @@ -1111,20 +1106,20 @@ int Compiler::GenMessage(const Str& pattern, int argCount, int messageStart) } } - int sendIP; + ip_t sendIP; // Ok, so its got to be longwinded but how long if (symbolIndex <= SendXMaxLiteral && argCount <= SendXMaxArgs) { // Single extended send (2 bytes) will do - BYTE part2 = static_cast((argCount << SendXLiteralBits) | (symbolIndex & SendXMaxLiteral)); - BYTE code = m_sendType == SendSuper ? Supersend : Send; + uint8_t part2 = static_cast((argCount << SendXLiteralBits) | (symbolIndex & SendXMaxLiteral)); + uint8_t code = m_sendType == SendType::SendSuper ? Supersend : Send; sendIP = GenInstructionExtended(code, part2); } else if (symbolIndex <= Send2XMaxLiteral && argCount <= Send2XMaxArgs) { - BYTE code = m_sendType == SendSuper ? LongSupersend : LongSend; - sendIP = GenInstructionExtended(code, static_cast(argCount)); - GenData(static_cast(symbolIndex)); + uint8_t code = m_sendType == SendType::SendSuper ? LongSupersend : LongSend; + sendIP = GenInstructionExtended(code, static_cast(argCount)); + GenData(static_cast(symbolIndex)); } else { @@ -1143,46 +1138,46 @@ int Compiler::GenMessage(const Str& pattern, int argCount, int messageStart) symbolIndex = Send3XMaxLiteral; } - BYTE code = m_sendType == SendSuper ? ExLongSupersend : ExLongSend; - sendIP = GenInstructionExtended(code, static_cast(argCount)); - GenData(symbolIndex & 0xFF); - GenData(symbolIndex >> 8); + uint8_t code = m_sendType == SendType::SendSuper ? ExLongSupersend : ExLongSend; + sendIP = GenInstructionExtended(code, static_cast(argCount)); + GenData(symbolIndex & UINT8_MAX); + GenData((symbolIndex >> 8) & UINT8_MAX); } return sendIP; } // Basic generation of jump instruction for when target not yet known -int Compiler::GenJumpInstruction(BYTE basic) +ip_t Compiler::GenJumpInstruction(BYTE basic) { // IT MUST be one of the long jump instructions _ASSERTE(basic == LongJump || basic == LongJumpIfTrue || basic == LongJumpIfFalse || basic == LongJumpIfNil || basic == LongJumpIfNotNil); - int pos = GenInstruction(basic); + ip_t pos = GenInstruction(basic); GenData(0); // Long jumps have two byte extension GenData(0); - m_bytecodes[pos].target = static_cast(-1); + m_bytecodes[pos].target = ip_t::npos; // So that we know the target hasn't been set yet, we leave the jump flag turned off - _ASSERTE(!m_bytecodes[pos].isJumpSource()); + _ASSERTE(!m_bytecodes[pos].IsJumpSource); return pos; } // N.B. Assumes no previously established jump target -inline void Compiler::SetJumpTarget(int pos, int target) +inline void Compiler::SetJumpTarget(ip_t pos, ip_t target) { _ASSERT(pos != target); - _ASSERTE(target >= 0 && target < GetCodeSize()); - _ASSERTE(pos >= 0 && pos < GetCodeSize()-2); + _ASSERTE(static_cast(target) < CodeSize); + _ASSERTE(static_cast(pos) < CodeSize-2); BYTECODE& bytecode = m_bytecodes[pos]; - _ASSERTE(bytecode.isOpCode()); - _ASSERTE(bytecode.isJumpInstruction()); + _ASSERTE(bytecode.IsOpCode); + _ASSERTE(bytecode.IsJumpInstruction); bytecode.makeJumpTo(target); // Mark the target location as being jumped to m_bytecodes[target].addJumpTo(); } -int Compiler::GenJump(BYTE basic, int location) +ip_t Compiler::GenJump(BYTE basic, ip_t location) { // Generate a first pass (long) jump instruction. // Make no attempt to shorten the instruction or to compute the real @@ -1194,16 +1189,15 @@ int Compiler::GenJump(BYTE basic, int location) if (location > m_codePointer) location += 3; - int pos = GenJumpInstruction(basic); + ip_t pos = GenJumpInstruction(basic); - _ASSERTE(location < GetCodeSize()); // Jumping off the end of the code - _ASSERTE(m_bytecodes[location].isOpCode()); // Attempting to jump to a data item! + _ASSERTE(m_bytecodes[location].IsOpCode); // Attempting to jump to a data item! SetJumpTarget(pos, location); return pos; } -int Compiler::GenStoreInstVar(BYTE index) +ip_t Compiler::GenStoreInstVar(uint8_t index) { m_pCurrentScope->MarkNeedsSelf(); return GenInstructionExtended(StoreInstVar, index); @@ -1214,22 +1208,22 @@ bool Compiler::IsPseudoVariable(const Str& name) const return name == VarSelf || name == VarSuper || name == VarThisContext; } -int Compiler::GenStore(const Str& name, const TEXTRANGE& range, int assignmentEnd) +ip_t Compiler::GenStore(const Str& name, const TEXTRANGE& range, textpos_t assignmentEnd) { - TempVarRef* pRef = AddTempRef(name, vrtWrite, range, assignmentEnd); - int storeIP = -1; - if (pRef != NULL) + TempVarRef* pRef = AddTempRef(name, VarRefType::Write, range, assignmentEnd); + ip_t storeIP = ip_t::npos; + if (pRef != nullptr) { storeIP = GenStoreTemp(pRef); } else if (m_ok) { - int index = FindNameAsInstanceVariable(name); - if (index >= 0) + ptrdiff_t index = FindNameAsInstanceVariable(name); + if (index != -1) { // Maximum of 255 inst vars recognised - _ASSERTE(index < 256); - storeIP = GenStoreInstVar(static_cast(index)); + _ASSERTE(index <= UINT8_MAX); + storeIP = GenStoreInstVar(static_cast(index)); } else storeIP = GenStaticStore(name, range, assignmentEnd); @@ -1237,30 +1231,30 @@ int Compiler::GenStore(const Str& name, const TEXTRANGE& range, int assignmentEn return storeIP; } -int Compiler::GenStaticStore(const Str& name, const TEXTRANGE& range, int assignmentEnd) +ip_t Compiler::GenStaticStore(const Str& name, const TEXTRANGE& range, textpos_t assignmentEnd) { POTE oteStatic; - int storeIP = 0; + ip_t storeIP = ip_t::npos; switch(FindNameAsStatic(name, oteStatic, true)) { - case STATICCONSTANT: + case StaticType::STATICCONSTANT: m_piVM->RemoveReference(reinterpret_cast(oteStatic)); CompileError(TEXTRANGE(range.m_start, assignmentEnd), CErrAssignConstant, (Oop)NewUtf8String(name)); break; - case STATICVARIABLE: + case StaticType::STATICVARIABLE: { - int index = AddToFrame(reinterpret_cast(oteStatic), range); - _ASSERTE(index >= 0 && index < 65536); - storeIP = index < 255 - ? GenInstructionExtended(StoreStatic, static_cast(index)) - : GenLongInstruction(LongStoreStatic, static_cast(index)); + size_t index = AddToFrame(reinterpret_cast(oteStatic), range); + _ASSERTE(index <= UINT16_MAX); + storeIP = index <= UINT8_MAX + ? GenInstructionExtended(StoreStatic, static_cast(index)) + : GenLongInstruction(LongStoreStatic, static_cast(index)); m_piVM->RemoveReference(reinterpret_cast(oteStatic)); } break; - case STATICNOTFOUND: + case StaticType::STATICNOTFOUND: default: if (IsPseudoVariable(name)) CompileError(TEXTRANGE(range.m_start, assignmentEnd), @@ -1276,9 +1270,9 @@ int Compiler::GenStaticStore(const Str& name, const TEXTRANGE& range, int assign void Compiler::GenPopAndStoreTemp(TempVarRef* pRef) { - int depth = m_pCurrentScope->GetDepth(); + uint8_t depth = m_pCurrentScope->GetDepth(); _ASSERTE(depth >= 0 && depth < 256); - int pos = GenInstructionExtended(LongStoreOuterTemp, static_cast(depth)); + ip_t pos = GenInstructionExtended(LongStoreOuterTemp, static_cast(depth)); m_bytecodes[pos].pVarRef = pRef; // Placeholder for index, not yet known GenData(0); @@ -1288,10 +1282,10 @@ void Compiler::GenPopAndStoreTemp(TempVarRef* pRef) POTE Compiler::ParseMethod() { // Method is outermost scope - _ASSERTE(m_pCurrentScope == NULL); + _ASSERTE(m_pCurrentScope == nullptr); _ASSERTE(m_allScopes.empty()); - PushNewScope(0); + PushNewScope(textpos_t::start); ParseMessagePattern(); if (ThisTokenIsBinary('<')) @@ -1302,30 +1296,30 @@ POTE Compiler::ParseMethod() if (m_ok) { - ParseStatements(Eof); + ParseStatements(TokenType::Eof); } if (m_ok) { - int last = PriorInstruction(); + ip_t last = PriorInstruction(); // If the method doesn't already end in a return, return the receiver. - if (last < 0 || m_bytecodes[last].byte != ReturnMessageStackTop) + if (last == ip_t::npos || m_bytecodes[last].byte != ReturnMessageStackTop) { - if (last >= 0) + if (last != ip_t::npos) GenPopStack(); - const int returnIP = GenReturn(ReturnSelf); + const ip_t returnIP = GenReturn(ReturnSelf); // Generate text map entry with empty interval for the implicit return - int textPos = ThisTokenRange().m_start; + textpos_t textPos = ThisTokenRange.m_start; AddTextMap(returnIP, textPos, textPos-1); } - if (!AtEnd()) - CompileError(TEXTRANGE(LastTokenRange().m_stop, GetTextLength()), CErrNonsenseAtMethodEnd); + if (!AtEnd) + CompileError(TEXTRANGE(LastTokenRange.m_stop, EndOfText), CErrNonsenseAtMethodEnd); } - PopScope(GetTextLength()-1); - _ASSERTE(m_pCurrentScope == NULL); + PopScope(EndOfText); + _ASSERTE(m_pCurrentScope == nullptr); return NewMethod(); } @@ -1335,7 +1329,7 @@ POTE Compiler::ParseEvalExpression(TokenType closingToken) // We may be called from an evaluation in a workspace window or // perhaps from a previous compiler evaluating a constant expression. - PushNewScope(0); + PushNewScope(textpos_t::start); // In either case we are always compiling "doit" m_selector= (LPUTF8)"doIt"; @@ -1350,12 +1344,12 @@ POTE Compiler::ParseEvalExpression(TokenType closingToken) if (m_ok) { - if (GetCodeSize() == 0) + if (CodeSize == 0) GenPushSelf(); // Implicit return - const int returnIP = GenReturn(ReturnMessageStackTop); + const ip_t returnIP = GenReturn(ReturnMessageStackTop); // Generate empty text map entry for the implicit return - debugger may need to map from release to debug method - const int textPos = ThisTokenRange().m_start; + const textpos_t textPos = ThisTokenRange.m_start; AddTextMap(returnIP, textPos, textPos-1); // We don't complain about junk at the end of the method as we do @@ -1363,19 +1357,19 @@ POTE Compiler::ParseEvalExpression(TokenType closingToken) // expression the trailing text is valid. } - PopScope(GetTextLength()-1); + PopScope(EndOfText); return NewMethod(); } -void Compiler::WarnIfRestrictedSelector(int start) +void Compiler::WarnIfRestrictedSelector(textpos_t start) { - if (!IsInteractive()) return; + if (!IsInteractive) return; for (int i=0; i < NumRestrictedSelectors; i++) if (m_selector == s_restrictedSelectors[i]) { - Warning(TEXTRANGE(start, LastTokenRange().m_stop), CWarnRestrictedSelector); + Warning(TEXTRANGE(start, LastTokenRange.m_stop), CWarnRestrictedSelector); return; } } @@ -1383,34 +1377,34 @@ void Compiler::WarnIfRestrictedSelector(int start) void Compiler::ParseMessagePattern() { // Parse the message selector and arguments for this method. - int start = ThisTokenRange().m_start; + textpos_t start = ThisTokenRange.m_start; - switch(ThisToken()) + switch(ThisToken) { - case NilConst: - case TrueConst: - case FalseConst: - case NameConst: + case TokenType::NilConst: + case TokenType::TrueConst: + case TokenType::FalseConst: + case TokenType::NameConst: // Unary message pattern - m_selector=ThisTokenText(); + m_selector=ThisTokenText; NextToken(); break; - case NameColon: + case TokenType::NameColon: // Keyword message pattern - while (m_ok && (ThisToken()==NameColon)) + while (m_ok && (ThisToken== TokenType::NameColon)) { - m_selector+=ThisTokenText(); + m_selector+=ThisTokenText; NextToken(); ParseArgument(); } break; - case Binary: + case TokenType::Binary: // Binary message pattern while (isAnsiBinaryChar(PeekAtChar())) Step(); - m_selector = ThisTokenText(); + m_selector = ThisTokenText; NextToken(); ParseArgument(); break; @@ -1428,10 +1422,10 @@ void Compiler::ParseArgument() // Parse an argument name and add it to the // array of arguments. // - if (ThisToken()==NameConst) + if (ThisToken == TokenType::NameConst) { // Get argument name - AddArgument(ThisTokenText(), ThisTokenRange()); + AddArgument(ThisTokenText, ThisTokenRange); NextToken(); } else @@ -1439,30 +1433,34 @@ void Compiler::ParseArgument() } // Parse a block of temporaries between delimiters. Answer the number parsed. -int Compiler::ParseTemporaries() +tempcount_t Compiler::ParseTemporaries() { - int nTempsAdded = 0; + tempcount_t nTempsAdded = 0; if (m_ok && ThisTokenIsBinary(TEMPSDELIMITER)) { - int start = ThisTokenRange().m_start; + textpos_t start = ThisTokenRange.m_start; - while (m_ok && NextToken()==NameConst) + while (m_ok && NextToken() == TokenType::NameConst) { - AddTemporary(ThisTokenText(), ThisTokenRange(), false); + AddTemporary(ThisTokenText, ThisTokenRange, false); nTempsAdded++; } if (ThisTokenIsBinary(TEMPSDELIMITER)) + { NextToken(); + } else + { if (m_ok) - CompileError(TEXTRANGE(start, ThisTokenRange().m_start-1), CErrTempListNotClosed); + CompileError(TEXTRANGE(start, ThisTokenRange.m_start - 1), CErrTempListNotClosed); + } } return nTempsAdded; } -int Compiler::ParseStatements(TokenType closingToken, bool popResults) +unsigned Compiler::ParseStatements(TokenType closingToken, bool popResults) { - if (!m_ok || ThisToken() == closingToken || AtEnd()) + if (!m_ok || ThisToken == closingToken || AtEnd) return 0; // TEMPORARY: This nop may later be used as an insertion point for copying arguments from the @@ -1474,10 +1472,10 @@ int Compiler::ParseStatements(TokenType closingToken, bool popResults) int count = 0; while (m_ok) { - int statementStart = ThisTokenRange().m_start; + textpos_t statementStart = ThisTokenRange.m_start; ParseStatement(); bool foundPeriod = false; - if (ThisToken() == CloseStatement) + if (ThisToken == TokenType::CloseStatement) { // Statements are to be concatenated and previous // result ignored (except for brace arrays) @@ -1485,15 +1483,15 @@ int Compiler::ParseStatements(TokenType closingToken, bool popResults) NextToken(); } - count = count + 1; + count++; - if (ThisToken() == closingToken) + if (ThisToken == closingToken) break; - else if (AtEnd()) + else if (AtEnd) break; if (m_ok && !foundPeriod) - CompileError(TEXTRANGE(statementStart, LastTokenRange().m_stop), CErrUnterminatedStatement); + CompileError(TEXTRANGE(statementStart, LastTokenRange.m_stop), CErrUnterminatedStatement); if (popResults) { @@ -1508,9 +1506,9 @@ int Compiler::ParseStatements(TokenType closingToken, bool popResults) // test and different valid terminators void Compiler::ParseBlockStatements() { - _ASSERTE(IsInOptimizedBlock() || IsInBlock()); + _ASSERTE(IsInOptimizedBlock || IsInBlock); - if (ThisToken() == CloseSquare) + if (ThisToken == TokenType::CloseSquare) { // We're compiling a block but it's empty. // This returns a nil @@ -1519,16 +1517,16 @@ void Compiler::ParseBlockStatements() } else { - if (AtEnd() || ThisToken() == CloseParen) + if (AtEnd || ThisToken == TokenType::CloseParen) return; - int start = m_codePointer; + ip_t start = m_codePointer; while (m_ok) { - int statementStart = ThisTokenRange().m_start; + textpos_t statementStart = ThisTokenRange.m_start; ParseStatement(); bool foundClosing = false; - if (ThisToken() == CloseStatement) + if (ThisToken == TokenType::CloseStatement) { // Statements are to be concatenated and previous // result ignored. @@ -1536,7 +1534,7 @@ void Compiler::ParseBlockStatements() foundClosing = true; } - if (ThisTokenIsClosing()) + if (ThisTokenIsClosing) { // Some other closing character so we break but // leaving result on stack @@ -1544,20 +1542,20 @@ void Compiler::ParseBlockStatements() } if (m_ok && !foundClosing) - CompileError(TEXTRANGE(statementStart, LastTokenRange().m_stop), CErrUnterminatedStatement); + CompileError(TEXTRANGE(statementStart, LastTokenRange.m_stop), CErrUnterminatedStatement); GenPopStack(); } // If the block contains only one real instruction, and that is Push Nil, then the block is effectively empty - if (m_bytecodes[start].byte == ShortPushNil && PriorInstruction() == start) + if (m_ok && m_bytecodes[start].byte == ShortPushNil && PriorInstruction() == start) { m_pCurrentScope->BeEmptyBlock(); } } } -int Compiler::GenFarReturn() +ip_t Compiler::GenFarReturn() { - _ASSERTE(IsInBlock()); + _ASSERTE(IsInBlock); // It is easiest to set the far return mark later, when patching up the blocks. That // way it is based on whether a FarReturn instruction actually exists in the instruction // stream, rather than attemping to keep the flags in sync as the optimized blocks are @@ -1568,15 +1566,15 @@ int Compiler::GenFarReturn() void Compiler::ParseStatement() { - if (ThisTokenIsReturn()) + if (ThisTokenIsReturn) { - int textPosition = ThisTokenRange().m_start; + textpos_t textPosition = ThisTokenRange.m_start; NextToken(); ParseExpression(); if (m_ok) { - const int returnIP = IsInBlock() ? GenFarReturn() : GenReturn(ReturnMessageStackTop); - AddTextMap(returnIP, textPosition, LastTokenRange().m_stop); + const ip_t returnIP = IsInBlock ? GenFarReturn() : GenReturn(ReturnMessageStackTop); + AddTextMap(returnIP, textPosition, LastTokenRange.m_stop); } } else @@ -1589,8 +1587,8 @@ inline void Compiler::ParseAssignment(const Str& lvalueName, const TEXTRANGE& ra // a shared variable. ParseExpression(); BreakPoint(); - int expressionEnd = LastTokenRange().m_stop; - int storeIP = GenStore(lvalueName, range, expressionEnd); + textpos_t expressionEnd = LastTokenRange.m_stop; + ip_t storeIP = GenStore(lvalueName, range, expressionEnd); AddTextMap(storeIP, range.m_start, expressionEnd); } @@ -1598,18 +1596,18 @@ void Compiler::ParseExpression() { // Stack the last expression type SendType lastSend = m_sendType; - m_sendType = SendOther; + m_sendType = SendType::SendOther; // We may need to know the mark of the current expression - int exprMark = m_codePointer; - TEXTRANGE tokenRange = ThisTokenRange(); + ip_t exprMark = m_codePointer; + TEXTRANGE tokenRange = ThisTokenRange; - if (ThisToken() == NameConst) + if (ThisToken == TokenType::NameConst) { // Possibly assignment - Str name = ThisTokenText(); + Str name = ThisTokenText; NextToken(); - if (ThisTokenIsAssignment()) + if (ThisTokenIsAssignment) { // This is an assignment NextToken(); @@ -1633,9 +1631,9 @@ void Compiler::ParseExpression() m_sendType = lastSend; } -void Compiler::ParseBinaryTerm(int textPosition) +void Compiler::ParseBinaryTerm(textpos_t textPosition) { - LPUTF8 szTok = ThisTokenText(); + LPUTF8 szTok = ThisTokenText; if (strlen((LPCSTR)szTok) != 1) { CompileError(CErrInvalExprStart); @@ -1647,16 +1645,16 @@ void Compiler::ParseBinaryTerm(int textPosition) case '(': { // Nested expression - int nExprStart = ThisTokenRange().m_start; + textpos_t nExprStart = ThisTokenRange.m_start; NextToken(); ParseExpression(); if (m_ok) { - if (ThisToken() == CloseParen) + if (ThisToken == TokenType::CloseParen) NextToken(); else - CompileError(TEXTRANGE(nExprStart, LastTokenRange().m_stop), CErrParenNotClosed); + CompileError(TEXTRANGE(nExprStart, LastTokenRange.m_stop), CErrParenNotClosed); } } break; @@ -1675,149 +1673,149 @@ void Compiler::ParseBinaryTerm(int textPosition) }; } -void Compiler::ParseBraceArray(int textPosition) +void Compiler::ParseBraceArray(textpos_t textPosition) { NextToken(); - int count = ParseStatements(CloseBrace, false); + int count = ParseStatements(TokenType::CloseBrace, false); if (m_ok) { GenPushStaticVariable((LPUTF8)"Smalltalk.Array", TEXTRANGE(textPosition, textPosition)); - GenInteger(count, ThisTokenRange()); + GenInteger(count, ThisTokenRange); GenMessage((LPUTF8)"newFromStack:", 1, textPosition); } - if (ThisToken() == CloseBrace) + if (ThisToken == TokenType::CloseBrace) { NextToken(); } else { if (m_ok) - CompileError(TEXTRANGE(textPosition, ThisTokenRange().m_stop), CErrBraceNotClosed); + CompileError(TEXTRANGE(textPosition, ThisTokenRange.m_stop), CErrBraceNotClosed); } } -void Compiler::ParseTerm(int textPosition) +void Compiler::ParseTerm(textpos_t textPosition) { - TokenType tokenType = ThisToken(); + TokenType tokenType = ThisToken; switch(tokenType) { - case NameConst: - GenPushVariable(ThisTokenText(), ThisTokenRange()); + case TokenType::NameConst: + GenPushVariable(ThisTokenText, ThisTokenRange); NextToken(); break; - case SmallIntegerConst: - GenInteger(ThisTokenInteger(), ThisTokenRange()); + case TokenType::SmallIntegerConst: + GenInteger(ThisTokenInteger, ThisTokenRange); NextToken(); break; - case LargeIntegerConst: - case ScaledDecimalConst: + case TokenType::LargeIntegerConst: + case TokenType::ScaledDecimalConst: { - GenNumber(ThisTokenText(), ThisTokenRange()); + GenNumber(ThisTokenText, ThisTokenRange); NextToken(); } break; - case FloatingConst: - GenLiteralConstant(reinterpret_cast(m_piVM->NewFloat(ThisTokenFloat())), ThisTokenRange()); + case TokenType::FloatingConst: + GenLiteralConstant(reinterpret_cast(m_piVM->NewFloat(ThisTokenFloat)), ThisTokenRange); NextToken(); break; - case CharConst: + case TokenType::CharConst: { - long codePoint = ThisTokenInteger(); + intptr_t codePoint = ThisTokenInteger; if (__isascii(codePoint)) { // We only generate the PushChar instruction for ASCII code points - GenInstructionExtended(PushChar, static_cast(codePoint)); + GenInstructionExtended(PushChar, static_cast(codePoint)); } else { - GenLiteralConstant(reinterpret_cast(m_piVM->NewCharacter(static_cast(codePoint))), ThisTokenRange()); + GenLiteralConstant(reinterpret_cast(m_piVM->NewCharacter(static_cast(codePoint))), ThisTokenRange); } NextToken(); } break; - case SymbolConst: - GenConstant(AddToFrame(reinterpret_cast(InternSymbol(ThisTokenText())), ThisTokenRange())); + case TokenType::SymbolConst: + GenConstant(AddToFrame(reinterpret_cast(InternSymbol(ThisTokenText)), ThisTokenRange)); NextToken(); break; - case TrueConst: + case TokenType::TrueConst: GenInstruction(ShortPushTrue); NextToken(); break; - case FalseConst: + case TokenType::FalseConst: GenInstruction(ShortPushFalse); NextToken(); break; - case NilConst: + case TokenType::NilConst: GenInstruction(ShortPushNil); NextToken(); break; - case AnsiStringConst: + case TokenType::AnsiStringConst: { - LPUTF8 szLiteral = ThisTokenText(); + LPUTF8 szLiteral = ThisTokenText; POTE oteString = *szLiteral ? NewAnsiString(szLiteral) : GetVMPointers().EmptyString; - GenConstant(AddStringToFrame(oteString, ThisTokenRange())); + GenConstant(AddStringToFrame(oteString, ThisTokenRange)); NextToken(); } break; - case Utf8StringConst: + case TokenType::Utf8StringConst: { - LPUTF8 szLiteral = ThisTokenText(); + LPUTF8 szLiteral = ThisTokenText; POTE oteString = *szLiteral ? NewUtf8String(szLiteral) : GetVMPointers().EmptyString; - GenConstant(AddStringToFrame(oteString, ThisTokenRange())); + GenConstant(AddStringToFrame(oteString, ThisTokenRange)); NextToken(); } break; - case ExprConstBegin: + case TokenType::ExprConstBegin: { - int start = ThisTokenRange().m_start; + textpos_t start = ThisTokenRange.m_start; Oop literal=ParseConstExpression(); if (m_ok) { - GenPushConstant(literal, TEXTRANGE(start, LastTokenRange().m_stop)); + GenPushConstant(literal, TEXTRANGE(start, LastTokenRange.m_stop)); } m_piVM->RemoveReference(literal); NextToken(); } break; - case ArrayBegin: + case TokenType::ArrayBegin: { - int start = ThisTokenRange().m_start; + textpos_t start = ThisTokenRange.m_start; POTE array=ParseArray(); if (m_ok) - GenLiteralConstant(reinterpret_cast(array), TEXTRANGE(start, LastTokenRange().m_stop)); + GenLiteralConstant(reinterpret_cast(array), TEXTRANGE(start, LastTokenRange.m_stop)); } break; - case ByteArrayBegin: + case TokenType::ByteArrayBegin: { - int start = ThisTokenRange().m_start; + textpos_t start = ThisTokenRange.m_start; POTE array=ParseByteArray(); if (m_ok) - GenLiteralConstant(reinterpret_cast(array), TEXTRANGE(start, LastTokenRange().m_stop)); + GenLiteralConstant(reinterpret_cast(array), TEXTRANGE(start, LastTokenRange.m_stop)); } break; - case Binary: + case TokenType::Binary: ParseBinaryTerm(textPosition); break; @@ -1827,25 +1825,25 @@ void Compiler::ParseTerm(int textPosition) }; } -void Compiler::ParseContinuation(int exprMark, int textPosition) +void Compiler::ParseContinuation(ip_t exprMark, textpos_t textPosition) { - int continuationPointer = ParseKeyContinuation(exprMark, textPosition); - int currentPos = m_codePointer; + ip_t continuationPointer = ParseKeyContinuation(exprMark, textPosition); + ip_t currentPos = m_codePointer; m_codePointer = continuationPointer; GenDup(); _ASSERTE(lengthOfByteCode(DuplicateStackTop) == 1); m_codePointer = currentPos + 1; - while (m_ok && ThisToken() == Cascade) + while (m_ok && ThisToken == TokenType::Cascade) { TokenType tok = NextToken(); - int continueTextPosition = ThisTokenRange().m_start; + textpos_t continueTextPosition = ThisTokenRange.m_start; continuationPointer= GenInstruction(PopDup); switch(tok) { - case NameConst: - case Binary: - case NameColon: + case TokenType::NameConst: + case TokenType::Binary: + case TokenType::NameColon: ParseKeyContinuation(exprMark, continueTextPosition); break; default: @@ -1867,24 +1865,24 @@ void Compiler::ParseContinuation(int exprMark, int textPosition) } } -int Compiler::ParseKeyContinuation(int exprMark, int textPosition) +ip_t Compiler::ParseKeyContinuation(ip_t exprMark, textpos_t textPosition) { - int continuationPointer = ParseBinaryContinuation(exprMark, textPosition); - if (ThisToken()!=NameColon) + ip_t continuationPointer = ParseBinaryContinuation(exprMark, textPosition); + if (ThisToken!=TokenType::NameColon) { - if (m_sendType == SendSuper) + if (m_sendType == SendType::SendSuper) CompileError(CErrExpectMessage); return continuationPointer; } - int argumentCount=1; + size_t argumentCount=1; bool specialCase=false; continuationPointer = m_codePointer; - Str strPattern = ThisTokenText(); - TEXTRANGE range = ThisTokenRange(); - TEXTRANGE receiverRange = TEXTRANGE(textPosition, LastTokenRange().m_stop); + Str strPattern = ThisTokenText; + TEXTRANGE range = ThisTokenRange; + TEXTRANGE receiverRange = TEXTRANGE(textPosition, LastTokenRange.m_stop); NextToken(); // There are some special cases to deal with optimized @@ -1948,13 +1946,13 @@ int Compiler::ParseKeyContinuation(int exprMark, int textPosition) if (!specialCase) { // For to:[by:]do: optimization. Messy... - int toPointer = 0; - int byPointer = 0; + ip_t toPointer = ip_t::zero; + ip_t byPointer = ip_t::zero; while (m_ok) { // Otherwise just handle normally SendType lastSend=m_sendType; - m_sendType=SendOther; + m_sendType=SendType::SendOther; // to:[by:]do: interface if (strPattern == (LPUTF8)"to:") @@ -1980,14 +1978,14 @@ int Compiler::ParseKeyContinuation(int exprMark, int textPosition) } } - int newExprMark = m_codePointer; - int newTextPosition = ThisTokenRange().m_start; + ip_t newExprMark = m_codePointer; + textpos_t newTextPosition = ThisTokenRange.m_start; ParseTerm(newTextPosition); ParseBinaryContinuation(newExprMark, newTextPosition); m_sendType = lastSend; - if (ThisToken() == NameColon) + if (ThisToken == TokenType::NameColon) { - strPattern += ThisTokenText(); + strPattern += ThisTokenText; argumentCount++; NextToken(); } @@ -1997,8 +1995,8 @@ int Compiler::ParseKeyContinuation(int exprMark, int textPosition) if (!specialCase) { - int sendIP = GenMessage(strPattern, argumentCount, textPosition); - AddTextMap(sendIP, textPosition, LastTokenRange().m_stop); + ip_t sendIP = GenMessage(strPattern, argumentCount, textPosition); + AddTextMap(sendIP, textPosition, LastTokenRange.m_stop); } } @@ -2007,19 +2005,19 @@ int Compiler::ParseKeyContinuation(int exprMark, int textPosition) void Compiler::MaybePatchNegativeNumber() { - if (ThisTokenIsNumber() && ThisTokenText()[0] == '-') + if (ThisTokenIsNumber && ThisTokenText[0] == '-') { - StepBack(strlen((LPCSTR)ThisTokenText())-1); - SetTokenType(Binary); + StepBack(strlen((LPCSTR)ThisTokenText)-1); + ThisToken = TokenType::Binary; _ASSERTE(ThisTokenIsBinary('-')); } } -int Compiler::ParseBinaryContinuation(int exprMark, int textPosition) +ip_t Compiler::ParseBinaryContinuation(ip_t exprMark, textpos_t textPosition) { - int continuationPointer = ParseUnaryContinuation(exprMark, textPosition); + ip_t continuationPointer = ParseUnaryContinuation(exprMark, textPosition); MaybePatchNegativeNumber(); - while (m_ok && (ThisToken()==Binary)) + while (m_ok && (ThisToken== TokenType::Binary)) { continuationPointer = m_codePointer; uint8_t ch; @@ -2030,83 +2028,83 @@ int Compiler::ParseBinaryContinuation(int exprMark, int textPosition) else Step(); } - Str pattern = ThisTokenText(); + Str pattern = ThisTokenText; NextToken(); SendType lastSend = m_sendType; - m_sendType = SendOther; - int newExprMark = m_codePointer; - int newTextPosition = ThisTokenRange().m_start; + m_sendType = SendType::SendOther; + ip_t newExprMark = m_codePointer; + textpos_t newTextPosition = ThisTokenRange.m_start; ParseTerm(newTextPosition); ParseUnaryContinuation(newExprMark, newTextPosition); - if (m_sendType == SendSuper) + if (m_sendType == SendType::SendSuper) CompileError(CErrExpectMessage); m_sendType = lastSend; MaybePatchNegativeNumber(); TODO("See if m_sendsToSuper can be reset inside GenMessage"); - int sendIP = GenMessage(pattern, 1, textPosition); - AddTextMap(sendIP, textPosition, LastTokenRange().m_stop); - m_sendType = SendOther; + ip_t sendIP = GenMessage(pattern, 1, textPosition); + AddTextMap(sendIP, textPosition, LastTokenRange.m_stop); + m_sendType = SendType::SendOther; } return continuationPointer; } void Compiler::MaybePatchLiteralMessage() { - switch (ThisToken()) + switch (ThisToken) { - case NilConst: - case FalseConst: - case TrueConst: - SetTokenType(NameConst); + case TokenType::NilConst: + case TokenType::FalseConst: + case TokenType::TrueConst: + ThisToken = TokenType::NameConst; break; default: break; } } -int Compiler::ParseUnaryContinuation(int exprMark, int textPosition) +ip_t Compiler::ParseUnaryContinuation(ip_t exprMark, textpos_t textPosition) { - int continuationPointer = m_codePointer; + ip_t continuationPointer = m_codePointer; MaybePatchLiteralMessage(); - while (m_ok && (ThisToken()==NameConst)) + while (m_ok && (ThisToken==TokenType::NameConst)) { bool isSpecialCase=false; continuationPointer = m_codePointer; - Str strToken = ThisTokenText(); + Str strToken = ThisTokenText; // Check for some optimizations if (strToken == (LPUTF8)"whileTrue") { - if (ParseWhileLoop(exprMark, TEXTRANGE(textPosition, LastTokenRange().m_stop))) + if (ParseWhileLoop(exprMark, TEXTRANGE(textPosition, LastTokenRange.m_stop))) isSpecialCase=true; } else if (strToken == (LPUTF8)"whileFalse") { - if (ParseWhileLoop(exprMark, TEXTRANGE(textPosition, LastTokenRange().m_stop))) + if (ParseWhileLoop(exprMark, TEXTRANGE(textPosition, LastTokenRange.m_stop))) isSpecialCase=true; } else if (strToken == (LPUTF8)"repeat") { - if (ParseRepeatLoop(exprMark, TEXTRANGE(textPosition, LastTokenRange().m_stop))) + if (ParseRepeatLoop(exprMark, TEXTRANGE(textPosition, LastTokenRange.m_stop))) isSpecialCase=true; } - else if (strToken == (LPUTF8)"yourself" && !(m_flags & SendYourself)) + else if (strToken == (LPUTF8)"yourself" && !(m_flags & CompilerFlags::SendYourself)) { - AddSymbolToFrame(ThisTokenText(), ThisTokenRange()); + AddSymbolToFrame(ThisTokenText, ThisTokenRange); // We don't send yourself, since it is a Nop isSpecialCase=true; } if (!isSpecialCase) { - int sendIP = GenMessage(ThisTokenText(), 0, textPosition); - AddTextMap(sendIP, textPosition, ThisTokenRange().m_stop); + ip_t sendIP = GenMessage(ThisTokenText, 0, textPosition); + AddTextMap(sendIP, textPosition, ThisTokenRange.m_stop); } - m_sendType = SendOther; + m_sendType = SendType::SendOther; NextToken(); MaybePatchLiteralMessage(); } @@ -2116,40 +2114,40 @@ int Compiler::ParseUnaryContinuation(int exprMark, int textPosition) void Compiler::ParsePrimitive() { TokenType next = NextToken(); - Str strToken = ThisTokenText(); + Str strToken = ThisTokenText; // Declare the implicit _failureCode temporary - this will always be the first temp of the method after the arguments - TempVarDecl* pErrorCodeDecl = AddTemporary((LPUTF8)"_failureCode", ThisTokenRange(), false); - TempVarRef* pErrorTempRef = m_pCurrentScope->AddTempRef(pErrorCodeDecl, vrtWrite, ThisTokenRange()); + TempVarDecl* pErrorCodeDecl = AddTemporary((LPUTF8)"_failureCode", ThisTokenRange, false); + TempVarRef* pErrorTempRef = m_pCurrentScope->AddTempRef(pErrorCodeDecl, VarRefType::Write, ThisTokenRange); // Implicitly written to by the primitive itself, but is then read-only and cannot be assigned pErrorCodeDecl->BeReadOnly(); - if (next == NameColon) + if (next == TokenType::NameColon) { if (strToken == (LPUTF8)"primitive:") { - if (NextToken() != SmallIntegerConst) + if (NextToken() != TokenType::SmallIntegerConst) CompileError(CErrExpectPrimIdx); else { - m_primitiveIndex=ThisTokenInteger(); - if (m_primitiveIndex > PRIMITIVE_MAX && !(m_flags & Boot)) - CompileError(ThisTokenRange(), CErrBadPrimIdx); + m_primitiveIndex = static_cast(ThisTokenInteger); + if (m_primitiveIndex > PRIMITIVE_MAX && !(m_flags & CompilerFlags::Boot)) + CompileError(ThisTokenRange, CErrBadPrimIdx); next = NextToken(); - if (next == TokenType::NameColon && Str(ThisTokenText()) == (LPUTF8)"error:") + if (next == TokenType::NameColon && Str(ThisTokenText) == (LPUTF8)"error:") { if (NextToken() == TokenType::NameConst) { // Rename the _failureCode temporary - Str errorCodeName = ThisTokenText(); - CheckTemporaryName(errorCodeName, ThisTokenRange(), false); - pErrorCodeDecl->SetName(errorCodeName); - pErrorCodeDecl->SetTextRange(ThisTokenRange()); + Str errorCodeName = ThisTokenText; + CheckTemporaryName(errorCodeName, ThisTokenRange, false); + pErrorCodeDecl->Name = errorCodeName; + pErrorCodeDecl->TextRange = ThisTokenRange; NextToken(); } else - CompileError(ThisTokenRange(), CErrExpectVariable); + CompileError(ThisTokenRange, CErrExpectVariable); } if (ThisTokenIsBinary('>')) @@ -2166,20 +2164,20 @@ void Compiler::ParsePrimitive() LibCallType* callType = ParseCallingConvention(strToken); if (callType) { - ParseLibCall(callType->nCallType, DolphinX::LibCallPrim); + ParseLibCall(callType->nCallType, DolphinX::ExtCallPrimitive::LibCall); return; } } } else { - if (next == NameConst) + if (next == TokenType::NameConst) { if (strToken == (LPUTF8)"virtual") { - if (NextToken() == NameColon) + if (NextToken() == TokenType::NameColon) { - LibCallType* callType = ParseCallingConvention(ThisTokenText()); + LibCallType* callType = ParseCallingConvention(ThisTokenText); if (callType) { ParseVirtualCall(callType->nCallType); @@ -2189,12 +2187,12 @@ void Compiler::ParsePrimitive() } else if (strToken == (LPUTF8)"overlap") { - if (NextToken() == NameColon) + if (NextToken() == TokenType::NameColon) { - LibCallType* callType = ParseCallingConvention(ThisTokenText()); + LibCallType* callType = ParseCallingConvention(ThisTokenText); if (callType) { - ParseLibCall(callType->nCallType, DolphinX::AsyncLibCallPrim); + ParseLibCall(callType->nCallType, DolphinX::ExtCallPrimitive::AsyncLibCall); return; } } @@ -2208,7 +2206,7 @@ void Compiler::ParsePrimitive() Compiler::LibCallType* Compiler::ParseCallingConvention(const Str& strToken) { - for (int i=0; i') && !AtEnd()) + while (m_ok && !ThisTokenIsBinary('>') && !AtEnd) { - TEXTRANGE typeRange = ThisTokenRange(); + TEXTRANGE typeRange = ThisTokenRange; ParseExtCallArgument(args[argcount]); if (m_ok) { - if (args[argcount].type != DolphinX::ExtCallArgVOID) + if (args[argcount].type != DolphinX::ExtCallArgType::Void) argcount++; else CompileError(typeRange, CErrArgTypeCannotBeVoid); @@ -2241,11 +2239,11 @@ int Compiler::ParseExtCallArgs(TypeDescriptor args[]) if (m_ok) { - if (argcount < GetArgumentCount()) - CompileError(TEXTRANGE(nArgsStart, LastTokenRange().m_stop), CErrInsufficientArgTypes); + if (argcount < ArgumentCount) + CompileError(TEXTRANGE(nArgsStart, LastTokenRange.m_stop), CErrInsufficientArgTypes); else - if (argcount > GetArgumentCount()) - CompileError(TEXTRANGE(nArgsStart, LastTokenRange().m_stop), CErrTooManyArgTypes); + if (argcount > ArgumentCount) + CompileError(TEXTRANGE(nArgsStart, LastTokenRange.m_stop), CErrTooManyArgTypes); } if (m_ok) @@ -2259,24 +2257,24 @@ int Compiler::ParseExtCallArgs(TypeDescriptor args[]) return argcount; } -void Compiler::ParseVirtualCall(DolphinX::ExtCallDeclSpecs decl) +void Compiler::ParseVirtualCall(DolphinX::ExtCallDeclSpec decl) { // Parse a C++ virtual function call - _ASSERTE(GetLiteralCount() == 0); + _ASSERTE(LiteralCount == 0); _ASSERTE(m_literalLimit <= 256); NextToken(); TypeDescriptor args[ARGLIMIT]; - TEXTRANGE retTypeRange = ThisTokenRange(); + TEXTRANGE retTypeRange = ThisTokenRange; ParseExtCallArgument(args[0]); if (!m_ok) return; // Temporary bodge until VM call prim can handle variant return type correctly - if (args[0].type == DolphinX::ExtCallArgVARIANT) + if (args[0].type == DolphinX::ExtCallArgType::Variant) { - args[0].type = DolphinX::ExtCallArgSTRUCT; + args[0].type = DolphinX::ExtCallArgType::Struct; // Because VARIANT is not in the base image, cannot be used as a return type // until ActiveX Automation Package has been loaded @@ -2290,23 +2288,23 @@ void Compiler::ParseVirtualCall(DolphinX::ExtCallDeclSpecs decl) args[0].parm = Oop(structClass); } - m_primitiveIndex=DolphinX::VirtualCallPrim; + m_primitiveIndex = static_cast(DolphinX::ExtCallPrimitive::VirtualCall); m_compiledMethodClass=GetVMPointers().ClassExternalMethod; - int argcount; - long vfnIndex; + argcount_t argcount; + intptr_t vfnIndex; - if (ThisToken() != SmallIntegerConst) + if (ThisToken != TokenType::SmallIntegerConst) CompileError(CErrExpectVfn); else { // Virtual function number - vfnIndex = ThisTokenInteger(); + vfnIndex = ThisTokenInteger; if (vfnIndex < 1 || vfnIndex > 1024) CompileError(CErrBadVfn); // Implicit arg for this pointer (the receiver) - args[1].type = DolphinX::ExtCallArgLPVOID; + args[1].type = DolphinX::ExtCallArgType::LPVoid; args[1].parm = 0; // Now create an array of argument types @@ -2326,7 +2324,7 @@ void Compiler::mangleDescriptorReturnType(TypeDescriptor& retType, const TEXTRAN { if (retType.parm) { - if (retType.type == DolphinX::ExtCallArgSTRUCT) + if (retType.type == DolphinX::ExtCallArgType::Struct) { // We can save the interpreter work by compiling down this info now, thereby allowing // for improved run-time performance @@ -2335,9 +2333,9 @@ void Compiler::mangleDescriptorReturnType(TypeDescriptor& retType, const TEXTRAN if (byteSize != 0) { if (byteSize <= 4) - retType.type = DolphinX::ExtCallArgSTRUCT4; + retType.type = DolphinX::ExtCallArgType::Struct32; else if (byteSize <= 8) - retType.type = DolphinX::ExtCallArgSTRUCT8; + retType.type = DolphinX::ExtCallArgType::Struct64; } } } @@ -2349,35 +2347,34 @@ void Compiler::mangleDescriptorReturnType(TypeDescriptor& retType, const TEXTRAN } } -DolphinX::ExternalMethodDescriptor& Compiler::buildDescriptorLiteral(TypeDescriptor types[], int argcount, DolphinX::ExtCallDeclSpecs decl, LPUTF8 szProcName) +DolphinX::ExternalMethodDescriptor& Compiler::buildDescriptorLiteral(TypeDescriptor types[], argcount_t argcount, DolphinX::ExtCallDeclSpec decl, LPUTF8 szProcName) { _ASSERTE(szProcName); - _ASSERTE(argcount >= 0 && argcount < 256); - int argsLen=argcount; + argcount_t argsLen=argcount; { - for (int i=1;i<=argcount;i++) + for (size_t i=1;i<=argcount;i++) { if (types[i].parm) argsLen++; } } - unsigned procNameSize = strlen((LPCSTR)szProcName)+1; - unsigned size = sizeof(DolphinX::ExternalMethodDescriptor) + argsLen + procNameSize; - int index=AddToFrameUnconditional(Oop(m_piVM->NewByteArray(size)), LastTokenRange()); + size_t procNameSize = strlen((LPCSTR)szProcName)+1; + size_t size = sizeof(DolphinX::ExternalMethodDescriptor) + argsLen + procNameSize; + size_t index=AddToFrameUnconditional(Oop(m_piVM->NewByteArray(size)), LastTokenRange); // This must be the first literal in the frame! _ASSERTE(index==0); POTE argArray=(POTE)m_literalFrame[index]; - BYTE* pb = FetchBytesOf(argArray); + uint8_t* pb = FetchBytesOf(argArray); DolphinX::ExternalMethodDescriptor& argsEtc = *(DolphinX::ExternalMethodDescriptor*)pb; //memset(&argsEtc, 0xFF, size); - argsEtc.m_descriptor.m_callConv = decl; + argsEtc.m_descriptor.m_callConv = (uint8_t)decl; mangleDescriptorReturnType(types[0], types[0].range); - argsEtc.m_descriptor.m_return = types[0].type; - argsEtc.m_descriptor.m_returnParm = types[0].parm; + argsEtc.m_descriptor.m_return = (uint8_t)types[0].type; + argsEtc.m_descriptor.m_returnParm = (uint8_t)types[0].parm; // At the moment we build the descriptor in argument order, but the literal @@ -2386,49 +2383,49 @@ DolphinX::ExternalMethodDescriptor& Compiler::buildDescriptorLiteral(TypeDescrip // the reverse order that they are on the Smalltalk stack - i.e. pop from // Smalltalk, push onto machine stack) argsLen=0; - for (int i=1; m_ok && i<=argcount; i++) + for (size_t i=1; m_ok && i<=argcount; i++) { // Any types with a literal argument are added to frame (only ExtCallArgSTRUCT at present) if (types[i].parm) { - int frameIndex = AddToFrame(types[i].parm, types[i].range); + size_t frameIndex = AddToFrame(types[i].parm, types[i].range); _ASSERTE(frameIndex < 256); - argsEtc.m_descriptor.m_args[argsLen++] = frameIndex; + argsEtc.m_descriptor.m_args[argsLen++] = static_cast(frameIndex); } - argsEtc.m_descriptor.m_args[argsLen++] = types[i].type; + argsEtc.m_descriptor.m_args[argsLen++] = (uint8_t)types[i].type; } _ASSERTE(argsLen < 256 && argsLen >= argcount); - argsEtc.m_descriptor.m_argsLen = argsLen; + argsEtc.m_descriptor.m_argsLen = static_cast(argsLen); // Shove the procName (store ordinal as string too) on the end strcpy_s((char*)argsEtc.m_descriptor.m_args+argsLen, procNameSize, (LPCSTR)szProcName); return argsEtc; } -void Compiler::ParseLibCall(DolphinX::ExtCallDeclSpecs decl, int callPrim) +void Compiler::ParseLibCall(DolphinX::ExtCallDeclSpec decl, DolphinX::ExtCallPrimitive callPrim) { - if (decl > DolphinX::ExtCallCDecl) + if (decl > DolphinX::ExtCallDeclSpec::CDecl) { CompileError(CErrUnsupportedCallConv); return; } - _ASSERTE(decl == DolphinX::ExtCallStdCall || decl == DolphinX::ExtCallCDecl); + _ASSERTE(decl == DolphinX::ExtCallDeclSpec::StdCall || decl == DolphinX::ExtCallDeclSpec::CDecl); // Parse an external library call - _ASSERTE(GetLiteralCount()==0); + _ASSERTE(LiteralCount==0); NextToken(); TypeDescriptor args[ARGLIMIT]; - TEXTRANGE retTypeRange = ThisTokenRange(); + TEXTRANGE retTypeRange = ThisTokenRange; ParseExtCallArgument(args[0]); if (!m_ok) return; // Temporary bodge until VM call prim can handle variant return type correctly - if (args[0].type == DolphinX::ExtCallArgVARIANT) + if (args[0].type == DolphinX::ExtCallArgType::Variant) { - args[0].type = DolphinX::ExtCallArgSTRUCT; + args[0].type = DolphinX::ExtCallArgType::Struct; // Because VARIANT is not in the base image, cannot be used as a return type // until ActiveX Automation Package has been loaded @@ -2443,18 +2440,18 @@ void Compiler::ParseLibCall(DolphinX::ExtCallDeclSpecs decl, int callPrim) } // Function name or ordinal - m_primitiveIndex=callPrim; + m_primitiveIndex = static_cast(callPrim); m_compiledMethodClass=GetVMPointers().ClassExternalMethod; - int argcount; + argcount_t argcount; - TokenType tok = ThisToken(); + TokenType tok = ThisToken; // Function names must be ASCII, or an ordinal - if (tok != AnsiStringConst && tok != NameConst && tok != SmallIntegerConst) + if (tok != TokenType::AnsiStringConst && tok != TokenType::NameConst && tok != TokenType::SmallIntegerConst) CompileError(CErrExpectFnName); else { - Str procName = ThisTokenText(); + Str procName = ThisTokenText; // Now create an array of argument types // Now create an array of argument types @@ -2483,20 +2480,20 @@ POTE Compiler::FindExternalClass(const Str& strClass, const TEXTRANGE& range) if (structClass == Nil()) { CompileError(range, CErrUndefinedClass); - return NULL; + return nullptr; } if (!m_piVM->IsAClass(structClass)) { CompileError(range, CErrInvalidStructArg); - return NULL; + return nullptr; } STBehavior& behavior = *(STBehavior*)GetObj(structClass); if (behavior.instSpec.pointers && behavior.instSpec.fixedFields < 1) { CompileError(range, CErrInvalidStructArg); - return NULL; + return nullptr; } return structClass; @@ -2510,11 +2507,11 @@ void Compiler::ParseExternalClass(const Str& strClass, TypeDescriptor& descripto STBehavior& behavior = *(STBehavior*)GetObj(structClass); if (ThisTokenIsBinary('*')) { - descriptor.range.m_stop = ThisTokenRange().m_stop; + descriptor.range.m_stop = ThisTokenRange.m_stop; NextToken(); if (ThisTokenIsBinary('*')) { - descriptor.range.m_stop = ThisTokenRange().m_stop; + descriptor.range.m_stop = ThisTokenRange.m_stop; NextToken(); if (behavior.instSpec.indirect) // One level of indirection implied, cannot have 3 @@ -2522,7 +2519,7 @@ void Compiler::ParseExternalClass(const Str& strClass, TypeDescriptor& descripto else { // Double indirections always use LPPVOID type - descriptor.type = DolphinX::ExtCallArgLPPVOID; + descriptor.type = DolphinX::ExtCallArgType::LPPVoid; descriptor.parm = 0; } } @@ -2531,7 +2528,7 @@ void Compiler::ParseExternalClass(const Str& strClass, TypeDescriptor& descripto if (behavior.instSpec.indirect) { // One level of indirection already implied, totalling two - descriptor.type = DolphinX::ExtCallArgLPPVOID; + descriptor.type = DolphinX::ExtCallArgType::LPPVoid; descriptor.parm = 0; } else @@ -2549,135 +2546,135 @@ void Compiler::ParseExternalClass(const Str& strClass, TypeDescriptor& descripto // No explicit indirection, but there may be implicit if (behavior.instSpec.indirect) - descriptor.type = DolphinX::ExtCallArgLP; + descriptor.type = DolphinX::ExtCallArgType::LPStruct; else - descriptor.type = DolphinX::ExtCallArgSTRUCT; + descriptor.type = DolphinX::ExtCallArgType::Struct; descriptor.parm = Oop(structClass); } } } -DolphinX::ExtCallArgTypes Compiler::TypeForStructPointer(POTE oteStructClass) +DolphinX::ExtCallArgType Compiler::TypeForStructPointer(POTE oteStructClass) { const VMPointers& pointers = GetVMPointers(); POTE oteUnkClass = pointers.ClassIUnknown; return (oteUnkClass != pointers.Nil && m_piVM->InheritsFrom(oteStructClass, oteUnkClass)) - ? DolphinX::ExtCallArgCOMPTR - : DolphinX::ExtCallArgLP; + ? DolphinX::ExtCallArgType::ComPtr + : DolphinX::ExtCallArgType::LPStruct; } // Answers true if an argument type was parsed, else false. Advances over argument if parsed. void Compiler::ParseExtCallArgument(TypeDescriptor& answer) { - switch(ThisToken()) + switch(ThisToken) { - case NameConst: + case TokenType::NameConst: { // Table of arg types // N.B. THIS SHOULD MATCH THE DolphinX::ExtCallArgTypes ENUM... struct ArgTypeDefn { LPUTF8 m_szName; - DolphinX::ExtCallArgTypes m_type; + DolphinX::ExtCallArgType m_type; LPUTF8 m_szIndirectClass; }; static ArgTypeDefn argTypes[] = { - { (LPUTF8)"sdword", DolphinX::ExtCallArgSDWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"dword", DolphinX::ExtCallArgDWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"intptr", DolphinX::ExtCallArgINTPTR, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"uintptr", DolphinX::ExtCallArgUINTPTR, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"lpvoid", DolphinX::ExtCallArgLPVOID, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"handle", DolphinX::ExtCallArgHANDLE, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"lppvoid", DolphinX::ExtCallArgLPPVOID, NULL }, - { (LPUTF8)"lpstr", DolphinX::ExtCallArgLPSTR, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"bool", DolphinX::ExtCallArgBOOL, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"void", DolphinX::ExtCallArgVOID, (LPUTF8)DolphinX::ExtCallArgLPVOID}, - { (LPUTF8)"double", DolphinX::ExtCallArgDOUBLE, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"float", DolphinX::ExtCallArgFLOAT, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"hresult", DolphinX::ExtCallArgHRESULT, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"ntstatus", DolphinX::ExtCallArgNTSTATUS, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"char", DolphinX::ExtCallArgCHAR, (LPUTF8)DolphinX::ExtCallArgLPSTR}, - { (LPUTF8)"byte", DolphinX::ExtCallArgBYTE, (LPUTF8)DolphinX::ExtCallArgLPVOID}, - { (LPUTF8)"sbyte", DolphinX::ExtCallArgSBYTE, (LPUTF8)DolphinX::ExtCallArgLPVOID}, - { (LPUTF8)"word", DolphinX::ExtCallArgWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"sword", DolphinX::ExtCallArgSWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"oop", DolphinX::ExtCallArgOOP, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"lpwstr", DolphinX::ExtCallArgLPWSTR, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"bstr", DolphinX::ExtCallArgBSTR, (LPUTF8)DolphinX::ExtCallArgLPPVOID }, - { (LPUTF8)"qword", DolphinX::ExtCallArgQWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"sqword", DolphinX::ExtCallArgSQWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"ote", DolphinX::ExtCallArgOTE, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"variant", DolphinX::ExtCallArgVARIANT, (LPUTF8)"VARIANT" }, - { (LPUTF8)"varbool", DolphinX::ExtCallArgVARBOOL, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"guid", DolphinX::ExtCallArgGUID, (LPUTF8)"REFGUID" }, - { (LPUTF8)"date", DolphinX::ExtCallArgDATE, (LPUTF8)"DATE" }, + { (LPUTF8)"sdword", DolphinX::ExtCallArgType::Int32, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"dword", DolphinX::ExtCallArgType::UInt32, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"intptr", DolphinX::ExtCallArgType::IntPtr, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"uintptr", DolphinX::ExtCallArgType::UIntPtr, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"lpvoid", DolphinX::ExtCallArgType::LPVoid, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"handle", DolphinX::ExtCallArgType::Handle, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"lppvoid", DolphinX::ExtCallArgType::LPPVoid, nullptr }, + { (LPUTF8)"lpstr", DolphinX::ExtCallArgType::LPStr, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"bool", DolphinX::ExtCallArgType::Bool, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"void", DolphinX::ExtCallArgType::Void, (LPUTF8)DolphinX::ExtCallArgType::LPVoid}, + { (LPUTF8)"double", DolphinX::ExtCallArgType::Double, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"float", DolphinX::ExtCallArgType::Float, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"hresult", DolphinX::ExtCallArgType::HResult, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"ntstatus", DolphinX::ExtCallArgType::NTStatus, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"char", DolphinX::ExtCallArgType::Char, (LPUTF8)DolphinX::ExtCallArgType::LPStr}, + { (LPUTF8)"byte", DolphinX::ExtCallArgType::UInt8, (LPUTF8)DolphinX::ExtCallArgType::LPVoid}, + { (LPUTF8)"sbyte", DolphinX::ExtCallArgType::Int8, (LPUTF8)DolphinX::ExtCallArgType::LPVoid}, + { (LPUTF8)"word", DolphinX::ExtCallArgType::UInt16, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"sword", DolphinX::ExtCallArgType::Int16, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"oop", DolphinX::ExtCallArgType::Oop, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"lpwstr", DolphinX::ExtCallArgType::LPWStr, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"bstr", DolphinX::ExtCallArgType::Bstr, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid }, + { (LPUTF8)"qword", DolphinX::ExtCallArgType::UInt64, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"sqword", DolphinX::ExtCallArgType::Int64, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"ote", DolphinX::ExtCallArgType::Ote, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"variant", DolphinX::ExtCallArgType::Variant, (LPUTF8)"VARIANT" }, + { (LPUTF8)"varbool", DolphinX::ExtCallArgType::VarBool, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"guid", DolphinX::ExtCallArgType::Guid, (LPUTF8)"REFGUID" }, + { (LPUTF8)"date", DolphinX::ExtCallArgType::Date, (LPUTF8)"DATE" }, //(LPUTF8) Convert a few class types to the special types to save space and time - { (LPUTF8)"ExternalAddress", DolphinX::ExtCallArgLPVOID, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"ExternalHandle", DolphinX::ExtCallArgHANDLE, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"BSTR", DolphinX::ExtCallArgBSTR, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"VARIANT", DolphinX::ExtCallArgVARIANT, (LPUTF8)"VARIANT" }, - { (LPUTF8)"SDWORD", DolphinX::ExtCallArgSDWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"DWORD", DolphinX::ExtCallArgDWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"LPVOID", DolphinX::ExtCallArgLPVOID, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"DOUBLE", DolphinX::ExtCallArgDOUBLE, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"FLOAT", DolphinX::ExtCallArgFLOAT, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"HRESULT", DolphinX::ExtCallArgHRESULT, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"NTSTATUS", DolphinX::ExtCallArgNTSTATUS, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"BYTE", DolphinX::ExtCallArgBYTE, (LPUTF8)DolphinX::ExtCallArgLPVOID}, - { (LPUTF8)"SBYTE", DolphinX::ExtCallArgSBYTE, (LPUTF8)DolphinX::ExtCallArgLPVOID}, - { (LPUTF8)"WORD", DolphinX::ExtCallArgWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"SWORD", DolphinX::ExtCallArgSWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"LPWSTR", DolphinX::ExtCallArgLPWSTR, (LPUTF8)DolphinX::ExtCallArgLPPVOID}, - { (LPUTF8)"QWORD", DolphinX::ExtCallArgQWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"ULARGE_INTEGER", DolphinX::ExtCallArgQWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"SQWORD", DolphinX::ExtCallArgSQWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"LARGE_INTEGER", DolphinX::ExtCallArgSQWORD, (LPUTF8)DolphinX::ExtCallArgLPVOID }, - { (LPUTF8)"GUID", DolphinX::ExtCallArgGUID, (LPUTF8)"REFGUID" }, - { (LPUTF8)"IID", DolphinX::ExtCallArgGUID, (LPUTF8)"REFGUID" }, - { (LPUTF8)"CLSID", DolphinX::ExtCallArgGUID, (LPUTF8)"REFGUID" }, - { (LPUTF8)"VARIANT_BOOL", DolphinX::ExtCallArgVARBOOL, (LPUTF8)DolphinX::ExtCallArgLPVOID }, + { (LPUTF8)"ExternalAddress", DolphinX::ExtCallArgType::LPVoid, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"ExternalHandle", DolphinX::ExtCallArgType::Handle, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"BSTR", DolphinX::ExtCallArgType::Bstr, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"VARIANT", DolphinX::ExtCallArgType::Variant, (LPUTF8)"VARIANT" }, + { (LPUTF8)"SDWORD", DolphinX::ExtCallArgType::Int32, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"DWORD", DolphinX::ExtCallArgType::UInt32, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"LPVOID", DolphinX::ExtCallArgType::LPVoid, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"DOUBLE", DolphinX::ExtCallArgType::Double, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"FLOAT", DolphinX::ExtCallArgType::Float, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"HRESULT", DolphinX::ExtCallArgType::HResult, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"NTSTATUS", DolphinX::ExtCallArgType::NTStatus, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"BYTE", DolphinX::ExtCallArgType::UInt8, (LPUTF8)DolphinX::ExtCallArgType::LPVoid}, + { (LPUTF8)"SBYTE", DolphinX::ExtCallArgType::Int8, (LPUTF8)DolphinX::ExtCallArgType::LPVoid}, + { (LPUTF8)"WORD", DolphinX::ExtCallArgType::UInt16, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"SWORD", DolphinX::ExtCallArgType::Int16, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"LPWSTR", DolphinX::ExtCallArgType::LPWStr, (LPUTF8)DolphinX::ExtCallArgType::LPPVoid}, + { (LPUTF8)"QWORD", DolphinX::ExtCallArgType::UInt64, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"ULARGE_INTEGER", DolphinX::ExtCallArgType::UInt64, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"SQWORD", DolphinX::ExtCallArgType::Int64, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"LARGE_INTEGER", DolphinX::ExtCallArgType::Int64, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, + { (LPUTF8)"GUID", DolphinX::ExtCallArgType::Guid, (LPUTF8)"REFGUID" }, + { (LPUTF8)"IID", DolphinX::ExtCallArgType::Guid, (LPUTF8)"REFGUID" }, + { (LPUTF8)"CLSID", DolphinX::ExtCallArgType::Guid, (LPUTF8)"REFGUID" }, + { (LPUTF8)"VARIANT_BOOL", DolphinX::ExtCallArgType::VarBool, (LPUTF8)DolphinX::ExtCallArgType::LPVoid }, }; - answer.range = ThisTokenRange(); - Str strToken = ThisTokenText(); + answer.range = ThisTokenRange; + Str strToken = ThisTokenText; NextToken(); // Scan the table - for (int i=0; i < sizeof(argTypes)/sizeof(ArgTypeDefn);i++) + for (size_t i=0; i < sizeof(argTypes)/sizeof(ArgTypeDefn);i++) { if (strToken == argTypes[i].m_szName) { answer.type = argTypes[i].m_type; answer.parm = 0; - if (ThisToken() == Binary && !ThisTokenIsBinary('>')) + if (ThisToken == TokenType::Binary && !ThisTokenIsBinary('>')) { // At least a single indirection to a standard type uint8_t ch; while ((ch = PeekAtChar()) != '>' && isAnsiBinaryChar(ch)) Step(); - Str strModifier = ThisTokenText(); + Str strModifier = ThisTokenText; int indirections = strModifier == (LPUTF8)"**" ? 2 : strModifier == (LPUTF8)"*" ? 1 : 0; if (indirections == 0) { - CompileError(TEXTRANGE(ThisTokenRange().m_start, CharPosition()), CErrBadExtTypeQualifier); + CompileError(TEXTRANGE(ThisTokenRange.m_start, CharPosition), CErrBadExtTypeQualifier); } - answer.range.m_stop = ThisTokenRange().m_stop; + answer.range.m_stop = ThisTokenRange.m_stop; NextToken(); LPUTF8 szClass = argTypes[i].m_szIndirectClass; // Indirection to a built-in type? - if (szClass <= LPUTF8(DolphinX::ExtCallArgSTRUCT)) + if (szClass <= LPUTF8(DolphinX::ExtCallArgType::Struct)) { - if (!szClass || (indirections > 1 && szClass == LPUTF8(DolphinX::ExtCallArgLPPVOID))) + if (!szClass || (indirections > 1 && szClass == LPUTF8(DolphinX::ExtCallArgType::LPPVoid))) // Cannot indirect this type - CompileError(TEXTRANGE(answer.range.m_start, LastTokenRange().m_stop), CErrNotIndirectable, (Oop)NewUtf8String(strToken)); + CompileError(TEXTRANGE(answer.range.m_start, LastTokenRange.m_stop), CErrNotIndirectable, (Oop)NewUtf8String(strToken)); if (indirections > 1) - answer.type = DolphinX::ExtCallArgLPPVOID; + answer.type = DolphinX::ExtCallArgType::LPPVoid; else - answer.type = DolphinX::ExtCallArgTypes(int(szClass)); + answer.type = DolphinX::ExtCallArgType(reinterpret_cast(szClass) & UINT8_MAX); answer.parm = 0; } else @@ -2689,7 +2686,7 @@ void Compiler::ParseExtCallArgument(TypeDescriptor& answer) // Indirection to a recognised struct class if (indirections > 1) { - answer.type = DolphinX::ExtCallArgLPPVOID; + answer.type = DolphinX::ExtCallArgType::LPPVoid; answer.parm = 0; } else @@ -2722,7 +2719,7 @@ void Compiler::ParseExtCallArgument(TypeDescriptor& answer) NextToken(); } -void Compiler::ParseBlock(int textPosition) +void Compiler::ParseBlock(textpos_t textPosition) { PushNewScope(textPosition); @@ -2733,16 +2730,16 @@ void Compiler::ParseBlock(int textPosition) GenNop(); // Parse the block arguments - int nArgs = ParseBlockArguments(textPosition); + argcount_t nArgs = ParseBlockArguments(textPosition); - int stop = -1; + textpos_t stop = textpos_t::npos; if (m_ok) { // Block copy instruction has an implicit jump - int blockCopyMark = GenInstruction(BlockCopy); + ip_t blockCopyMark = GenInstruction(BlockCopy); m_bytecodes[blockCopyMark].pScope = m_pCurrentScope; // Block copy has 6 extension bytes, most filled in later - GenData(nArgs); + GenData(static_cast(nArgs)); GenData(0); GenData(0); GenData(0); @@ -2753,41 +2750,41 @@ void Compiler::ParseBlock(int textPosition) // Generate the block's body ParseBlockStatements(); - int endOfBlockPos = GenReturn(ReturnBlockStackTop); + ip_t endOfBlockPos = GenReturn(ReturnBlockStackTop); m_bytecodes[endOfBlockPos].pScope = m_pCurrentScope; // Generate text map entry for the Return - AddTextMap(endOfBlockPos, textPosition, ThisTokenRange().m_stop); + AddTextMap(endOfBlockPos, textPosition, ThisTokenRange.m_stop); // Fill in the target of the block copy's implicit jump (which will be the following Nop) - const int endOfBlockNopPos = GenNop(); + const ip_t endOfBlockNopPos = GenNop(); m_bytecodes[endOfBlockNopPos].addJumpTo(); m_bytecodes[blockCopyMark].makeJumpTo(endOfBlockNopPos); - if (ThisToken() == CloseSquare) + if (ThisToken == TokenType::CloseSquare) { - stop = ThisTokenRange().m_stop; + stop = ThisTokenRange.m_stop; NextToken(); } else { - stop = LastTokenRange().m_stop; + stop = LastTokenRange.m_stop; if (m_ok) CompileError(TEXTRANGE(textPosition, stop), CErrBlockNotClosed); } } - PopScope(stop < 0 ? LastTokenRange().m_stop : stop); + PopScope(stop != textpos_t::npos ? LastTokenRange.m_stop : stop); } -int Compiler::ParseBlockArguments(const int blockStart) +argcount_t Compiler::ParseBlockArguments(const textpos_t blockStart) { - int argcount=0; + argcount_t argcount=0; while (m_ok && ThisTokenIsSpecial(':')) { - if (NextToken()==NameConst) + if (NextToken()== TokenType::NameConst) { // Get temporary name - AddArgument(ThisTokenText(), ThisTokenRange()); + AddArgument(ThisTokenText, ThisTokenRange); argcount++; } else @@ -2799,7 +2796,7 @@ int Compiler::ParseBlockArguments(const int blockStart) if (ThisTokenIsBinary(TEMPSDELIMITER)) NextToken(); else - CompileError(TEXTRANGE(blockStart, LastTokenRange().m_stop), CErrBlockArgListNotClosed); + CompileError(TEXTRANGE(blockStart, LastTokenRange.m_stop), CErrBlockArgListNotClosed); } return argcount; } @@ -2813,16 +2810,16 @@ POTE Compiler::ParseArray() OOPVECTOR elems; elems.reserve(16); - int arrayStart = ThisTokenRange().m_start; + textpos_t arrayStart = ThisTokenRange.m_start; NextToken(); - while (m_ok && !ThisTokenIsClosing()) + while (m_ok && !ThisTokenIsClosing) { - switch(ThisToken()) + switch(ThisToken) { - case SmallIntegerConst: + case TokenType::SmallIntegerConst: { - Oop oopElement = m_piVM->NewSignedInteger(ThisTokenInteger()); + Oop oopElement = m_piVM->NewSignedInteger(ThisTokenInteger); elems.push_back(oopElement); m_piVM->AddReference(oopElement); m_piVM->MakeImmutable(oopElement, TRUE); @@ -2830,20 +2827,20 @@ POTE Compiler::ParseArray() } break; - case LargeIntegerConst: - case ScaledDecimalConst: + case TokenType::LargeIntegerConst: + case TokenType::ScaledDecimalConst: { // Result of NewNumber already has ref. count - Oop oopElem = NewNumber(ThisTokenText()); + Oop oopElem = NewNumber(ThisTokenText); m_piVM->MakeImmutable(oopElem, TRUE); elems.push_back(oopElem); NextToken(); } break; - case FloatingConst: + case TokenType::FloatingConst: { - Oop oopFloat = reinterpret_cast(m_piVM->NewFloat(ThisTokenFloat())); + Oop oopFloat = reinterpret_cast(m_piVM->NewFloat(ThisTokenFloat)); elems.push_back(oopFloat); m_piVM->AddReference(oopFloat); m_piVM->MakeImmutable(oopFloat, TRUE); @@ -2851,24 +2848,24 @@ POTE Compiler::ParseArray() } break; - case NilConst: + case TokenType::NilConst: elems.push_back(reinterpret_cast(Nil())); NextToken(); break; - case TrueConst: + case TokenType::TrueConst: elems.push_back(reinterpret_cast(GetVMPointers().True)); NextToken(); break; - case FalseConst: + case TokenType::FalseConst: elems.push_back(reinterpret_cast(GetVMPointers().False)); NextToken(); break; - case NameConst: + case TokenType::NameConst: { - POTE oteElement = InternSymbol(ThisTokenText()); + POTE oteElement = InternSymbol(ThisTokenText); Oop oopElement = reinterpret_cast(oteElement); elems.push_back(oopElement); m_piVM->AddReference(oopElement); @@ -2876,14 +2873,14 @@ POTE Compiler::ParseArray() } break; - case SymbolConst: - case NameColon: + case TokenType::SymbolConst: + case TokenType::NameColon: { - Str name = ThisTokenText(); + Str name = ThisTokenText; while (isIdentifierFirst(PeekAtChar())) { NextToken(); - name += ThisTokenText(); + name += ThisTokenText; } Oop oopSymbol = reinterpret_cast(InternSymbol(name)); elems.push_back(oopSymbol); @@ -2892,10 +2889,10 @@ POTE Compiler::ParseArray() } break; - case ArrayBegin: - case Binary: + case TokenType::ArrayBegin: + case TokenType::Binary: { - if (ThisToken()==ArrayBegin || ThisTokenIsBinary('(')) + if (ThisToken== TokenType::ArrayBegin || ThisTokenIsBinary('(')) { POTE array = ParseArray(); if (m_ok) @@ -2922,37 +2919,37 @@ POTE Compiler::ParseArray() Step(); } while (isAnsiBinaryChar(PeekAtChar())); - oopElement = reinterpret_cast(InternSymbol(ThisTokenText())); + oopElement = reinterpret_cast(InternSymbol(ThisTokenText)); NextToken(); } else if (isdigit(ch)) { NextToken(); - TokenType tokenType = ThisToken(); - if (tokenType == SmallIntegerConst) + TokenType tokenType = ThisToken; + if (tokenType == TokenType::SmallIntegerConst) { - oopElement = m_piVM->NewSignedInteger(-ThisTokenInteger()); + oopElement = m_piVM->NewSignedInteger(-ThisTokenInteger); NextToken(); } - else if (tokenType == LargeIntegerConst || tokenType == ScaledDecimalConst) + else if (tokenType == TokenType::LargeIntegerConst || tokenType == TokenType::ScaledDecimalConst) { Str valuetext = (LPUTF8)"-"; - valuetext += ThisTokenText(); + valuetext += ThisTokenText; oopElement = NewNumber(valuetext.c_str()); // Return value has an elevated ref. count which we assume here elems.push_back(oopElement); NextToken(); break; } - else if (tokenType == FloatingConst) + else if (tokenType == TokenType::FloatingConst) { - oopElement = reinterpret_cast(m_piVM->NewFloat(-ThisTokenFloat())); + oopElement = reinterpret_cast(m_piVM->NewFloat(-ThisTokenFloat)); NextToken(); } } else { - oopElement = reinterpret_cast(InternSymbol(ThisTokenText())); + oopElement = reinterpret_cast(InternSymbol(ThisTokenText)); NextToken(); } @@ -2963,25 +2960,25 @@ POTE Compiler::ParseArray() while (isAnsiBinaryChar(PeekAtChar())) Step(); - Oop oopSymbol = reinterpret_cast(InternSymbol(ThisTokenText())); + Oop oopSymbol = reinterpret_cast(InternSymbol(ThisTokenText)); elems.push_back(oopSymbol); m_piVM->AddReference(oopSymbol); NextToken(); break; } - case CharConst: + case TokenType::CharConst: { - Oop oopChar = reinterpret_cast(m_piVM->NewCharacter(static_cast(ThisTokenInteger()))); + Oop oopChar = reinterpret_cast(m_piVM->NewCharacter(static_cast(ThisTokenInteger))); m_piVM->AddReference(oopChar); elems.push_back(oopChar); NextToken(); } break; - case AnsiStringConst: + case TokenType::AnsiStringConst: { - LPUTF8 szLiteral = ThisTokenText(); + LPUTF8 szLiteral = ThisTokenText; POTE oteString = *szLiteral ? NewAnsiString(szLiteral) : GetVMPointers().EmptyString; @@ -2993,9 +2990,9 @@ POTE Compiler::ParseArray() } break; - case Utf8StringConst: + case TokenType::Utf8StringConst: { - LPUTF8 szLiteral = ThisTokenText(); + LPUTF8 szLiteral = ThisTokenText; POTE oteString = *szLiteral ? NewUtf8String(szLiteral) : GetVMPointers().EmptyString; @@ -3007,7 +3004,7 @@ POTE Compiler::ParseArray() } break; - case ExprConstBegin: + case TokenType::ExprConstBegin: { Oop oopConst = ParseConstExpression(); elems.push_back(oopConst); @@ -3018,7 +3015,7 @@ POTE Compiler::ParseArray() } break; - case ByteArrayBegin: + case TokenType::ByteArrayBegin: { Oop oopBytes = reinterpret_cast(ParseByteArray()); if (m_ok) @@ -3039,7 +3036,7 @@ POTE Compiler::ParseArray() if (m_ok) { - if (ThisToken() == CloseParen) + if (ThisToken == TokenType::CloseParen) { POTE arrayPointer; @@ -3050,10 +3047,10 @@ POTE Compiler::ParseArray() else { // Gather new literals into a new array - const int elemcount = elems.size(); + const size_t elemcount = elems.size(); arrayPointer = m_piVM->NewArray(elemcount); STVarObject& array = *(STVarObject*)GetObj(arrayPointer); - for (int i=0; i < elemcount; i++) + for (size_t i=0; i < elemcount; i++) { Oop object = elems[i]; // We've already inc'd ref count of the elements @@ -3069,7 +3066,7 @@ POTE Compiler::ParseArray() return arrayPointer; } else - CompileError(TEXTRANGE(arrayStart, LastTokenRange().m_stop), CErrArrayNotClosed); + CompileError(TEXTRANGE(arrayStart, LastTokenRange.m_stop), CErrArrayNotClosed); } // It failed, so destroy all the new bits and pieces @@ -3086,48 +3083,38 @@ POTE Compiler::ParseByteArray() // to the frame itself. // A byte array may be any length. // - int maxelemcount=128; // A convenient start size though we can expand beyond this if necessary - BYTE* elems=static_cast(malloc(maxelemcount*sizeof(BYTE))); - int elemcount=0; - - int start = ThisTokenRange().m_start; + std::vector elems; + textpos_t start = ThisTokenRange.m_start; NextToken(); - while (m_ok && !ThisTokenIsClosing()) + while (m_ok && !ThisTokenIsClosing) { - if (elemcount>=maxelemcount) + switch(ThisToken) { - _ASSERTE(maxelemcount > 0); - maxelemcount *= 2; - elems = (BYTE*)realloc(elems, maxelemcount*sizeof(BYTE)); - } - - switch(ThisToken()) - { - case SmallIntegerConst: + case TokenType::SmallIntegerConst: { - long intVal = ThisTokenInteger(); - if (intVal < 0 || intVal > 255) + intptr_t intVal = ThisTokenInteger; + if (intVal < 0 || intVal > UINT8_MAX) { CompileError(CErrBadValueInByteArray); NextToken(); break; } - elems[elemcount++] = static_cast(intVal); + elems.push_back(static_cast(intVal)); NextToken(); } break; - case LargeIntegerConst: + case TokenType::LargeIntegerConst: { - Oop li = NewNumber(ThisTokenText()); + Oop li = NewNumber(ThisTokenText); if (IsIntegerObject(li)) { - int nVal = IntegerValueOf(li); - if (nVal < 0 || nVal > 255) + intptr_t nVal = IntegerValueOf(li); + if (nVal < 0 || nVal > UINT8_MAX) CompileError(CErrBadValueInByteArray); else - elems[elemcount++] = static_cast(ThisTokenInteger()); + elems.push_back(static_cast(ThisTokenInteger)); NextToken(); break; } @@ -3149,17 +3136,16 @@ POTE Compiler::ParseByteArray() POTE arrayPointer=0; if (m_ok) { - if (ThisToken() == CloseSquare) + if (ThisToken == TokenType::CloseSquare) { - arrayPointer=m_piVM->NewByteArray(elemcount); - BYTE* pb = FetchBytesOf(arrayPointer); - memcpy(pb, elems, elemcount); + arrayPointer = m_piVM->NewByteArray(elems.size()); + uint8_t* pb = FetchBytesOf(arrayPointer); + memcpy(pb, elems.data(), elems.size()); NextToken(); } else - CompileError(TEXTRANGE(start, LastTokenRange().m_stop), CErrByteArrayNotClosed); + CompileError(TEXTRANGE(start, LastTokenRange.m_stop), CErrByteArrayNotClosed); } - free(elems); return arrayPointer; } @@ -3180,17 +3166,17 @@ Oop Compiler::ParseConstExpression() pCompiler->SetVMInterface(m_piVM); Oop result; - unsigned len; + size_t len; __try { _ASSERTE(m_compilerObject && m_notifier); - DWORD flags = m_flags & ~DebugMethod; + CompilerFlags flags = m_flags & ~CompilerFlags::DebugMethod; POTE oteSelf = m_piVM->IsAMetaclass(m_class) ? reinterpret_cast(GetObj(m_class))->instanceClass: m_class; Oop contextOop = Oop(oteSelf); - TEXTRANGE tokRange = ThisTokenRange(); - POTE oteMethod = pCompiler->CompileExpression(GetText(), m_compilerObject, m_notifier, contextOop, FLAGS(flags), len, tokRange.m_stop+1); - if (pCompiler->m_ok && pCompiler->ThisToken() != CloseParen) + TEXTRANGE tokRange = ThisTokenRange; + POTE oteMethod = pCompiler->CompileExpression(Text, m_compilerObject, m_notifier, contextOop, flags, len, tokRange.m_stop+1); + if (pCompiler->m_ok && pCompiler->ThisToken != TokenType::CloseParen) { CompileError(TEXTRANGE(tokRange.m_start, tokRange.m_stop+len), CErrStaticExprNotClosed); } @@ -3201,8 +3187,8 @@ Oop Compiler::ParseConstExpression() // Add all the literals in the expression to the literal frame of this method as this // allows normal references search to work in IDE - const int loopEnd = pCompiler->GetLiteralCount(); - for (int i=0; i < loopEnd;i++) + const size_t loopEnd = pCompiler->LiteralCount; + for (size_t i=0; i < loopEnd;i++) { Oop oopLiteral = exprMethod.aLiterals[i]; _ASSERTE(oopLiteral); @@ -3213,12 +3199,12 @@ Oop Compiler::ParseConstExpression() m_piVM->IsKindOf(oopLiteral, GetVMPointers().ClassArray))) { - AddToFrame(oopLiteral, LastTokenRange()); + AddToFrame(oopLiteral, LastTokenRange); } } m_piVM->AddReference((Oop)oteMethod); - result = this->EvaluateExpression(GetText(), tokRange.m_stop+1, tokRange.m_stop + len - 1, oteMethod, contextOop, Nil()); + result = this->EvaluateExpression(Text, tokRange.m_stop+1, tokRange.m_stop + len - 1, oteMethod, contextOop, Nil()); m_piVM->RemoveReference((Oop)oteMethod); } else @@ -3226,7 +3212,7 @@ Oop Compiler::ParseConstExpression() } __finally { - m_ok = pCompiler->Ok(); + m_ok = pCompiler->Ok; pCompiler->Release(); } @@ -3235,9 +3221,9 @@ Oop Compiler::ParseConstExpression() return result; } -Oop Compiler::EvaluateExpression(LPUTF8 source, int start, int end, POTE oteMethod, Oop contextOop, POTE pools) +Oop Compiler::EvaluateExpression(LPUTF8 source, textpos_t start, textpos_t end, POTE oteMethod, Oop contextOop, POTE pools) { - Str exprSource(source, start, end - start + 1); + Str exprSource(source, static_cast(start), static_cast(end - start + 1)); return EvaluateExpression(exprSource.c_str(), oteMethod, contextOop, pools); } @@ -3266,18 +3252,18 @@ void Compiler::GetInstVars() // instance variable names. // STVarObject& array=*(STVarObject*)GetObj(arrayPointer); - const int len=FetchWordLengthOf(arrayPointer); + const size_t len=FetchWordLengthOf(arrayPointer); // Too many inst vars? - if (len > 255) + if (len > UINT8_MAX) CompileError(CompileTextRange(), CErrBadContext); // We know how many inst vars there are in advance of compilation, and this // array does not, therefore, need to be dynamic m_instVars.resize(len); - for (int i=0; i(pb); } @@ -3307,11 +3293,11 @@ void Compiler::GetContext(POTE workspacePools) else { STVarObject& pools = *(STVarObject*)GetObj(m_oopWorkspacePools); - const MWORD len=FetchWordLengthOf(m_oopWorkspacePools); + const size_t len=FetchWordLengthOf(m_oopWorkspacePools); if (len == 0) m_oopWorkspacePools = Nil(); else - for (MWORD i=0;iIsKindOf(Oop(oop), GetVMPointers().ClassBlockClosure) != 0; } -void Compiler::AssertValidIpForTextMapEntry(int ip, bool bFinal) +void Compiler::AssertValidIpForTextMapEntry(ip_t ip, bool bFinal) { - if (ip == -1) return; - _ASSERTE(ip >= 0 && ip < GetCodeSize()); + if (ip == ip_t::npos) return; + _ASSERTE(ip <= LastIp); const BYTECODE& bc = m_bytecodes[ip]; - if (bc.isData()) + if (bc.IsData) { - _ASSERTE(ip > 0); + _ASSERTE(ip > ip_t::zero); const BYTECODE& prev = m_bytecodes[ip-1]; - _ASSERTE(prev.isOpCode()); + _ASSERTE(prev.IsOpCode); _ASSERTE((bc.byte == PopStoreTemp && (prev.byte == IncrementTemp || prev.byte == DecrementTemp)) || (bc.byte == StoreTemp && (prev.byte == IncrementPushTemp || prev.byte == DecrementPushTemp))); } else { - _ASSERTE(bc.byte == Nop || bc.pScope != NULL); + _ASSERTE(bc.byte == Nop || bc.pScope != nullptr); // Must be a message send, store (assignment), return, push of the empty block, // or the first instruction in a block - int prevIP = ip - 1; - while (prevIP >= 0 && (m_bytecodes[prevIP].isData() || m_bytecodes[prevIP].byte == Nop)) - prevIP--; - const BYTECODE* prev = prevIP < 0 ? NULL : &m_bytecodes[prevIP]; - bool isFirstInBlock = prev != NULL && (prev->byte == BlockCopy - || (bc.pScope == NULL - ? bc.byte == Nop && prev != NULL && prev->isUnconditionalJump() - : bc.pScope->GetRealScope()->IsBlock() - && (bc.pScope->GetRealScope()->GetInitialIP() == ip + ip_t prevIP = ip - 1; + while (prevIP >= ip_t::zero && (m_bytecodes[prevIP].IsData || m_bytecodes[prevIP].byte == Nop)) + --prevIP; + const BYTECODE* prev = prevIP < ip_t::zero ? nullptr : &m_bytecodes[prevIP]; + bool isFirstInBlock = prev != nullptr && (prev->byte == BlockCopy + || (bc.pScope == nullptr + ? bc.byte == Nop && prev != nullptr && prev->IsUnconditionalJump + : bc.pScope->RealScope->IsBlock + && (bc.pScope->RealScope->InitialIP == ip || bc.pScope != prev->pScope - || bc.pScope->GetRealScope() != prev->pScope->GetRealScope()))); - if (bFinal && WantDebugMethod()) + || bc.pScope->RealScope != prev->pScope->RealScope))); + if (bFinal && WantDebugMethod) { // If not at the start of a method or block, then a text map entry should only occur after a Break // or (when stripping unreachable code) if the byte immediately follows an unconditional return/jump - _ASSERTE(ip == 0 + _ASSERTE(ip == ip_t::zero || isFirstInBlock - || bc.isConditionalJump() - || (bc.isShortPushConst() && IsBlock(m_literalFrame[bc.indexOfShortPushConst()])) + || bc.IsConditionalJump + || (bc.IsShortPushConst && IsBlock(m_literalFrame[bc.indexOfShortPushConst()])) || (bc.byte == PushConst && IsBlock(m_literalFrame[m_bytecodes[ip + 1].byte])) - || (prev->isBreak() || (!bc.isJumpTarget() && (prev->isReturn() || prev->isLongJump())))); + || (prev->IsBreak || (!bc.IsJumpTarget && (prev->IsReturn || prev->IsLongJump)))); } - _ASSERTE(bc.isSend() - || bc.isConditionalJump() - || bc.isStore() - || bc.isReturn() - || (bc.isShortPushConst() && IsBlock(m_literalFrame[bc.indexOfShortPushConst()])) - || (bc.byte == PushConst && IsBlock(m_literalFrame[m_bytecodes[ip+1].byte])) + _ASSERTE(bc.IsSend + || bc.IsConditionalJump + || bc.IsStore + || bc.IsReturn + || (bc.IsShortPushConst && IsBlock(m_literalFrame[bc.indexOfShortPushConst()])) + || (bc.byte == PushConst && IsBlock(m_literalFrame[m_bytecodes[ip + 1].byte])) || (isFirstInBlock) - || (bc.isConditionalJump()) + || (bc.IsConditionalJump) || (bc.byte == IncrementTemp || bc.byte == DecrementTemp) || (bc.byte == IncrementStackTop || bc.byte == DecrementStackTop) || (bc.byte == IncrementPushTemp|| bc.byte == DecrementPushTemp) @@ -3400,27 +3386,27 @@ void Compiler::AssertValidIpForTextMapEntry(int ip, bool bFinal) void Compiler::VerifyTextMap(bool bFinal) { //_CrtCheckMemory(); - const int size = m_textMaps.size(); - for (int i=0; i= 0 && bc.target < size); + _ASSERTE(bc.IsJumpInstruction); + _ASSERTE(bc.target <= end); const BYTECODE& target = m_bytecodes[bc.target]; - _ASSERTE(!target.isData()); + _ASSERTE(!target.IsData); _ASSERTE(target.jumpsTo > 0); } } @@ -3429,53 +3415,53 @@ void Compiler::VerifyJumps() POTE Compiler::GetTextMapObject() { - const int size = m_textMaps.size(); + const size_t size = m_textMaps.size(); POTE arrayPointer=m_piVM->NewArray(size*3); STVarObject& array = *(STVarObject*)GetObj(arrayPointer); - int arrayIndex = 0; - for (int i=0; i(ip) + 1); + array.fields[arrayIndex++] = IntegerObjectOf(static_cast(textMap.start) + 1); + array.fields[arrayIndex++] = IntegerObjectOf(static_cast(textMap.stop) + 1); } return arrayPointer; } inline void Compiler::BreakPoint() { - if (WantDebugMethod()) + if (WantDebugMethod) GenInstruction(Break); } -int Compiler::AddTextMap(int ip, const TEXTRANGE& range) +size_t Compiler::AddTextMap(ip_t ip, const TEXTRANGE& range) { return AddTextMap(ip, range.m_start, range.m_stop); } // Add a new TEXTMAP encoding the current char position and code position // These need to be added in IP order. -int Compiler::AddTextMap(int ip, int textStart, int textStop) +size_t Compiler::AddTextMap(ip_t ip, const textpos_t textStart, const textpos_t textStop) { if (!m_ok) return -1; - _ASSERTE(ip < GetCodeSize()); + _ASSERTE(ip <= LastIp); // textStart can be equal to text length in order to specify an empty interval at the end of the method - _ASSERTE(textStart >= 0 && textStart <= GetTextLength()); - _ASSERTE(textStop >= -1 && textStop < GetTextLength()); - if (!WantTextMap()) return -1; - _ASSERTE(m_bytecodes[ip].isOpCode()); + _ASSERTE((intptr_t)textStart >= 0 && static_cast(textStart) <= TextLength); + _ASSERTE((intptr_t)textStop >= -1 && static_cast(textStop) < TextLength); + if (!WantTextMap) return -1; + _ASSERTE(m_bytecodes[ip].IsOpCode); _ASSERTE(m_bytecodes[ip].byte != Nop); m_textMaps.push_back(TEXTMAP(ip, textStart, textStop)); VerifyTextMap(); return m_textMaps.size() - 1; } -void Compiler::InsertTextMapEntry(int ip, int textStart, int textStop) +void Compiler::InsertTextMapEntry(ip_t ip, textpos_t textStart, textpos_t textStop) { - if (!WantTextMap()) return; + if (!WantTextMap) return; const TEXTMAPLIST::const_iterator end = m_textMaps.end(); TEXTMAPLIST::iterator it = m_textMaps.begin(); @@ -3488,7 +3474,7 @@ void Compiler::InsertTextMapEntry(int ip, int textStart, int textStop) m_textMaps.insert(it, TEXTMAP(ip, textStart, textStop)); } -Compiler::TEXTMAPLIST::iterator Compiler::FindTextMapEntry(int ip) +Compiler::TEXTMAPLIST::iterator Compiler::FindTextMapEntry(ip_t ip) { const TEXTMAPLIST::const_iterator end = m_textMaps.end(); for (TEXTMAPLIST::iterator it = m_textMaps.begin(); it != end; it++) @@ -3501,16 +3487,16 @@ Compiler::TEXTMAPLIST::iterator Compiler::FindTextMapEntry(int ip) return m_textMaps.end(); } -bool Compiler::RemoveTextMapEntry(int ip) +bool Compiler::RemoveTextMapEntry(ip_t ip) { - if (!WantTextMap()) return true; + if (!WantTextMap) return true; TEXTMAPLIST::iterator it = FindTextMapEntry(ip); if (it != m_textMaps.end()) { const TEXTMAP& tm = (*it); const BYTECODE& bc = m_bytecodes[ip]; - int i = it - m_textMaps.begin(); + ptrdiff_t i = it - m_textMaps.begin(); m_textMaps.erase(it); return true; @@ -3519,15 +3505,15 @@ bool Compiler::RemoveTextMapEntry(int ip) return false; } -bool Compiler::VoidTextMapEntry(int ip) +bool Compiler::VoidTextMapEntry(ip_t ip) { - if (!WantTextMap()) return true; + if (!WantTextMap) return true; TEXTMAPLIST::iterator it = FindTextMapEntry(ip); if (it != m_textMaps.end()) { TEXTMAP& tm = (*it); - tm.ip = -1; + tm.ip = ip_t::npos; return true; } else @@ -3537,15 +3523,14 @@ bool Compiler::VoidTextMapEntry(int ip) POTE Compiler::GetTempsMapObject() { - int nScopes = m_allScopes.size(); + const size_t nScopes = m_allScopes.size(); POTE arrayPointer=m_piVM->NewArray(nScopes); STVarObject& array = *(STVarObject*)GetObj(arrayPointer); - int arrayIndex = 0; - const int loopEnd = nScopes; - for (int i=0; iStorePointerWithValue(array.fields+i, Oop(pScope->BuildTempMapEntry(m_piVM))); + m_piVM->StorePointerWithValue(array.fields+i, reinterpret_cast(pScope->BuildTempMapEntry(m_piVM))); } return arrayPointer; } @@ -3569,7 +3554,7 @@ STDMETHODIMP_(POTE) Compiler::CompileForClass(IUnknown* piVM, Oop compilerOop, c m_piVM = (IDolphin*)piVM; // Check argument types are correct - if (!m_piVM->IsBehavior(Oop(aClass)) || szSource == NULL) + if (!m_piVM->IsBehavior(Oop(aClass)) || szSource == nullptr) return Nil(); POTE resultPointer = Nil(); @@ -3581,17 +3566,17 @@ STDMETHODIMP_(POTE) Compiler::CompileForClass(IUnknown* piVM, Oop compilerOop, c __try { - POTE methodPointer = CompileForClassHelper((LPUTF8)szSource, compilerOop, notifier, aClass, flags); + POTE methodPointer = CompileForClassHelper((LPUTF8)szSource, compilerOop, notifier, aClass, static_cast(flags)); resultPointer = m_piVM->NewArray(3); STVarObject& result = *(STVarObject*)GetObj(resultPointer); m_piVM->StorePointerWithValue(&(result.fields[0]), Oop(methodPointer)); - if (WantTextMap()) + if (WantTextMap) m_piVM->StorePointerWithValue(&(result.fields[1]), Oop(GetTextMapObject())); - if (WantTempsMap()) + if (WantTempsMap) m_piVM->StorePointerWithValue(&(result.fields[2]), Oop(GetTempsMapObject())); } __except(DolphinExceptionFilter(m_piVM, GetExceptionInformation())) @@ -3619,7 +3604,7 @@ STDMETHODIMP_(POTE) Compiler::CompileForEval(IUnknown* piVM, Oop compilerOop, co m_piVM = (IDolphin*)piVM; // Check argument types are correct - if (!m_piVM->IsBehavior(Oop(aClass)) || szSource == NULL) + if (!m_piVM->IsBehavior(Oop(aClass)) || szSource == nullptr) return Nil(); POTE resultPointer = Nil(); @@ -3628,14 +3613,14 @@ STDMETHODIMP_(POTE) Compiler::CompileForEval(IUnknown* piVM, Oop compilerOop, co CHECKREFERENCES #endif - wchar_t* prevLocale = NULL; + wchar_t* prevLocale = nullptr; __try { #ifdef USE_VM_DLL prevLocale = _wsetlocale(LC_ALL, L"C"); if (prevLocale[0] == L'C' && prevLocale[1] == 0) { - prevLocale = NULL; + prevLocale = nullptr; } else { @@ -3645,17 +3630,17 @@ STDMETHODIMP_(POTE) Compiler::CompileForEval(IUnknown* piVM, Oop compilerOop, co __try { - POTE methodPointer = CompileForEvaluationHelper((LPUTF8)szSource, compilerOop, notifier, aClass, aWorkspacePool, flags); + POTE methodPointer = CompileForEvaluationHelper((LPUTF8)szSource, compilerOop, notifier, aClass, aWorkspacePool, static_cast(flags)); resultPointer = m_piVM->NewArray(3); STVarObject& result = *(STVarObject*)GetObj(resultPointer); m_piVM->StorePointerWithValue(&(result.fields[0]), Oop(methodPointer)); - if (WantTextMap()) + if (WantTextMap) m_piVM->StorePointerWithValue(&(result.fields[1]), Oop(GetTextMapObject())); - if (WantTempsMap()) + if (WantTempsMap) m_piVM->StorePointerWithValue(&(result.fields[2]), Oop(GetTempsMapObject())); } __except(DolphinExceptionFilter(m_piVM, GetExceptionInformation())) @@ -3672,7 +3657,7 @@ STDMETHODIMP_(POTE) Compiler::CompileForEval(IUnknown* piVM, Oop compilerOop, co __finally { #ifdef USE_VM_DLL - if (prevLocale != NULL) + if (prevLocale != nullptr) { _wsetlocale(LC_ALL, prevLocale); free(prevLocale); @@ -3701,14 +3686,14 @@ Oop Compiler::Notification(int errorCode, const TEXTRANGE& range, va_list extras POTE argsPointer = m_piVM->NewArray(10); STVarObject& args = *(STVarObject*)GetObj(argsPointer); args.fields[0] = IntegerObjectOf(errorCode); - args.fields[1] = IntegerObjectOf(GetLineNo()); + args.fields[1] = IntegerObjectOf(LineNo); - args.fields[2] = IntegerObjectOf(range.m_start); - args.fields[3] = IntegerObjectOf(range.m_stop); - int offset = GetTextOffset(); - args.fields[4] = IntegerObjectOf(offset); + args.fields[2] = IntegerObjectOf(static_cast(range.m_start)); + args.fields[3] = IntegerObjectOf(static_cast(range.m_stop)); + textpos_t offset = TextOffset; + args.fields[4] = IntegerObjectOf(static_cast(offset)); - POTE sourceString = NewUtf8String(GetText()); + POTE sourceString = NewUtf8String(Text); m_piVM->StorePointerWithValue(&args.fields[5], Oop(sourceString)); LPUTF8 selector = m_selector.c_str(); @@ -3748,27 +3733,26 @@ Oop Compiler::Notification(int errorCode, const TEXTRANGE& range, va_list extras void Compiler::_CompileErrorV(int code, const TEXTRANGE& range, va_list extras) { m_ok=false; - if (!WantSyntaxCheckOnly()) + if (!WantSyntaxCheckOnly) { - if (m_flags & Boot) - { - Str erroneousText = GetTextRange(range); - fprintf(stdout, "ERROR %d in %s>>%s line %d,(%d..%d): %s\n\r", code, GetClassName().c_str(), m_selector.c_str(), GetLineNo(), range.m_start, range.m_stop, - erroneousText.c_str()); - fprintf(stdout, (LPCSTR)GetText()); - } - else + if (!(m_flags & CompilerFlags::Boot)) { _ASSERTE(m_compilerObject && m_notifier); - Notification(code, range, extras); } + else + { + Str erroneousText = GetTextRange(range); + fprintf(stdout, "ERROR %d in %s>>%s line %d,(%Id..%Id): %s\n\r", code, GetClassName().c_str(), m_selector.c_str(), LineNo, range.m_start, range.m_stop, + erroneousText.c_str()); + fprintf(stdout, (LPCSTR)Text); + } } } void Compiler::Warning(int code, Oop extra) { - WarningV(ThisTokenRange(), code, extra, 0); + WarningV(ThisTokenRange, code, extra, 0); } void Compiler::Warning(const TEXTRANGE& range, int code, Oop extra) @@ -3778,18 +3762,9 @@ void Compiler::Warning(const TEXTRANGE& range, int code, Oop extra) void Compiler::WarningV(const TEXTRANGE& range, int code, ...) { - if (!WantSyntaxCheckOnly()) + if (!WantSyntaxCheckOnly) { - if (m_flags & Boot) - { - char buf[1024]; - VERIFY(wsprintf(buf, "WARNING %s>>%s line %d: %d\n", GetClassName().c_str(), m_selector.c_str(), GetLineNo(), code)>=0); - OutputDebugString(buf); - //((CIstApp*)AfxGetApp())->OutputErrorStringToCurrentDoc(buf); - OutputDebugString((LPCSTR)GetText()); - OutputDebugString("\n\r"); - } - else + if (!(m_flags & CompilerFlags::Boot)) { _ASSERTE(m_compilerObject); va_list extras; @@ -3797,6 +3772,15 @@ void Compiler::WarningV(const TEXTRANGE& range, int code, ...) Notification(code, range, extras); va_end(extras); } + else + { + char buf[1024]; + VERIFY(wsprintf(buf, "WARNING %s>>%s line %d: %d\n", GetClassName().c_str(), m_selector.c_str(), LineNo, code) >= 0); + OutputDebugString(buf); + //((CIstApp*)AfxGetApp())->OutputErrorStringToCurrentDoc(buf); + OutputDebugString((LPCSTR)Text); + OutputDebugString("\n\r"); + } } } @@ -3830,16 +3814,16 @@ TempVarDecl* Compiler::DeclareTemp(const Str& strName, const TEXTRANGE& range) return pNewVar; } -void Compiler::PopScope(int textStop) +void Compiler::PopScope(textpos_t textStop) { - _ASSERTE(m_pCurrentScope != NULL); + _ASSERTE(m_pCurrentScope != nullptr); m_pCurrentScope->SetTextStop(textStop); - m_pCurrentScope = m_pCurrentScope->GetOuter(); + m_pCurrentScope = m_pCurrentScope->Outer; } -void Compiler::PushNewScope(int textStart, bool bOptimized) +void Compiler::PushNewScope(textpos_t textStart, bool bOptimized) { - int start = textStart < 0 ? ThisTokenRange().m_start : textStart; + textpos_t start = textStart < (textpos_t)0 ? ThisTokenRange.m_start : textStart; LexicalScope* pNewScope = new LexicalScope(m_pCurrentScope, start, bOptimized); m_allScopes.push_back(pNewScope); m_pCurrentScope = pNewScope; @@ -3853,23 +3837,23 @@ void Compiler::PushNewScope(int textStart, bool bOptimized) } } -void Compiler::PushOptimizedScope(int textStart) +void Compiler::PushOptimizedScope(textpos_t textStart) { PushNewScope(textStart, true); } -inline BYTE MakeOuterTempRef(int blockDepth, int index) +inline BYTE MakeOuterTempRef(size_t blockDepth, int index) { _ASSERTE(index < OuterTempMaxIndex); _ASSERTE(blockDepth <= OuterTempMaxDepth); - return static_cast((blockDepth << 5) | index); + return static_cast((blockDepth << 5) | index); } -int Compiler::GenTempRefInstruction(int instruction, TempVarRef* pRef) +ip_t Compiler::GenTempRefInstruction(uint8_t instruction, TempVarRef* pRef) { - int scopeDepth = pRef->GetEstimatedDistance(); - _ASSERTE(scopeDepth >= 0 && scopeDepth < 256); - int pos = GenInstructionExtended(instruction, static_cast(scopeDepth)); + unsigned scopeDepth = pRef->GetEstimatedDistance(); + _ASSERTE(scopeDepth <= UINT8_MAX); + ip_t pos = GenInstructionExtended(instruction, static_cast(scopeDepth)); // Placeholder for index (not yet known) GenData(0); m_bytecodes[pos].pVarRef = pRef; @@ -3877,46 +3861,46 @@ int Compiler::GenTempRefInstruction(int instruction, TempVarRef* pRef) return pos; } -int Compiler::GenPushCopiedValue(TempVarDecl* pDecl) +size_t Compiler::GenPushCopiedValue(TempVarDecl* pDecl) { - int index = pDecl->GetIndex(); - _ASSERTE(index >= 0); - int bytesGenerated = 0; + size_t index = pDecl->Index; + _ASSERTE(index != -1); + size_t bytesGenerated = 0; - switch(pDecl->GetVarType()) + switch(pDecl->VarType) { - case tvtUnaccessed: - InternalError(__FILE__, __LINE__, pDecl->GetTextRange(), - "Unaccessed copied value '%s'", pDecl->GetName().c_str()); + case TempVarType::Unaccessed: + InternalError(__FILE__, __LINE__, pDecl->TextRange, + "Unaccessed copied value '%s'", pDecl->Name.c_str()); break; - case tvtCopy: // Copies are pushed back on the stack on block activation - case tvtStack: // A stack variable accessed only from its local scope - case tvtCopied: // This is the type of a stack variable that has been copied + case TempVarType::Copy: // Copies are pushed back on the stack on block activation + case TempVarType::Stack: // A stack variable accessed only from its local scope + case TempVarType::Copied: // This is the type of a stack variable that has been copied { - int insertedAt; + ip_t insertedAt; if (index < NumShortPushTemps) { - insertedAt = GenInstruction(ShortPushTemp, static_cast(index)); + insertedAt = GenInstruction(ShortPushTemp, static_cast(index)); bytesGenerated = 1; } else { - insertedAt = GenInstructionExtended(PushTemp, static_cast(index)); + insertedAt = GenInstructionExtended(PushTemp, static_cast(index)); bytesGenerated = 2; } #ifdef _DEBUG // This fake temp ref is only needed for diagnostic purposes (the refs having been processed already) - TempVarRef* pVarRef = pDecl->GetScope()->AddTempRef(pDecl, vrtRead, pDecl->GetTextRange()); + TempVarRef* pVarRef = pDecl->Scope->AddTempRef(pDecl, VarRefType::Read, pDecl->TextRange); m_bytecodes[insertedAt].pVarRef = pVarRef; #endif break; } - case tvtShared: - InternalError( __FILE__, __LINE__, pDecl->GetTextRange(), - "Can't copy shared temp '%s'", pDecl->GetName().c_str()); + case TempVarType::Shared: + InternalError( __FILE__, __LINE__, pDecl->TextRange, + "Can't copy shared temp '%s'", pDecl->Name.c_str()); break; default: diff --git a/Core/DolphinVM/Compiler/compiler.h b/Core/DolphinVM/Compiler/compiler.h index 37968a918e..1e0b463a77 100755 --- a/Core/DolphinVM/Compiler/compiler.h +++ b/Core/DolphinVM/Compiler/compiler.h @@ -29,6 +29,9 @@ typedef std::valarray POTEARRAY; #include "..\disassembler.h" #endif +#include "EnumHelpers.h" +ENABLE_BITMASK_OPERATORS(CompilerFlags) + /////////////////////// #define LITERALLIMIT 65536 // maximum number of literals permitted. Limited by the byte code set, but in @@ -71,41 +74,66 @@ END_COM_MAP() void SetVMInterface(IDolphin* piVM) { m_piVM = piVM; } - POTE CompileExpression(LPUTF8 userexpression, Oop compiler, Oop notifier, Oop contextOop, FLAGS flags, unsigned& len, int startAt); + POTE CompileExpression(LPUTF8 userexpression, Oop compiler, Oop notifier, Oop contextOop, CompilerFlags flags, size_t& len, textpos_t startAt); Oop EvaluateExpression(LPUTF8 text, POTE method, Oop contextOop, POTE pools); - Oop EvaluateExpression(LPUTF8 source, int start, int end, POTE oteMethod, Oop contextOop, POTE pools); + Oop EvaluateExpression(LPUTF8 source, textpos_t start, textpos_t end, POTE oteMethod, Oop contextOop, POTE pools); // External interface requirements void GetContext(POTE workspacePools); void GetInstVars(); POTE NewMethod(); - POTE __stdcall NewCompiledMethod(POTE classPointer, unsigned numBytes, const STMethodHeader& hdr); - Str GetSelector() const; + POTE __stdcall NewCompiledMethod(POTE classPointer, size_t numBytes, const STMethodHeader& hdr); + + __declspec(property(get = get_Selector)) Str Selector; + Str get_Selector() const { return m_selector; } + POTE GetTextMapObject(); POTE GetTempsMapObject(); - bool Ok() const; - int GetLiteralCount() const; + __declspec(property(get = get_Ok)) bool Ok; + bool get_Ok() const { return m_ok; } + + __declspec(property(get = get_LiteralCount)) size_t LiteralCount; + size_t get_LiteralCount() const { return m_literalFrame.size(); } void Warning(int code, Oop extra=0); void Warning(const TEXTRANGE& range, int code, Oop extra=0); void WarningV(const TEXTRANGE& range, int code, ...); - bool IsInteractive() const; + + __declspec(property(get = get_IsInteractive)) bool IsInteractive; + bool get_IsInteractive() const { return (!!(m_flags & CompilerFlags::Interactive)) && !WantSyntaxCheckOnly; } private: // Flags - bool WantSyntaxCheckOnly() const; - bool WantOptimize() const; - bool WantTextMap() const; - bool WantTempsMap() const; - bool WantDebugMethod() const; + __declspec(property(get= get_WantOptimize)) bool WantOptimize; + bool get_WantOptimize() const { return !(m_flags & CompilerFlags::NoOptimize); } + __declspec(property(get= get_WantTextMap)) bool WantTextMap; + bool get_WantTextMap() const { return !!(m_flags & CompilerFlags::TextMap); } + __declspec(property(get= get_WantTempsMap)) bool WantTempsMap; + bool get_WantTempsMap() const { return !!(m_flags & CompilerFlags::TempsMap); } + __declspec(property(get= get_WantDebugMethod)) bool WantDebugMethod; + bool get_WantDebugMethod() const { return !!(m_flags & CompilerFlags::DebugMethod); } + __declspec(property(get= get_WantSyntaxCheckOnly)) bool WantSyntaxCheckOnly; + bool get_WantSyntaxCheckOnly() const { return !!(m_flags & CompilerFlags::SyntaxCheckOnly); } + + __declspec(property(get = get_CodeSize)) size_t CodeSize; + size_t Compiler::get_CodeSize() const + { + return m_bytecodes.size(); + } + + __declspec(property(get = get_ArgumentCount)) argcount_t ArgumentCount; + argcount_t get_ArgumentCount() const + { + return GetMethodScope()->ArgumentCount; + } - POTE CompileForClassHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aClass, FLAGS flags=Default); - POTE CompileForEvaluationHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aBehavior, POTE workspacePools, FLAGS flags=Default); + POTE CompileForClassHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aClass, CompilerFlags flags= CompilerFlags::Default); + POTE CompileForEvaluationHelper(LPUTF8 compiletext, Oop compiler, Oop notifier, POTE aBehavior, POTE workspacePools, CompilerFlags=CompilerFlags::Default); - void SetFlagsAndText(FLAGS flags, LPUTF8 text, int offset); - void PrepareToCompile(FLAGS flags, LPUTF8 text, int offset, POTE classPointer, Oop compiler, Oop notifier, POTE workspacePools, POTE compiledMethodClass, Oop context=0); + void SetFlagsAndText(CompilerFlags flags, LPUTF8 text, textpos_t offset); + void PrepareToCompile(CompilerFlags flags, LPUTF8 text, textpos_t offset, POTE classPointer, Oop compiler, Oop notifier, POTE workspacePools, POTE compiledMethodClass, Oop context=0); virtual void _CompileErrorV(int code, const TEXTRANGE& range, va_list extras); Oop Notification(int errorCode, const TEXTRANGE& range, va_list extras); void InternalError(const char* szFile, int line, const TEXTRANGE&, const char* szMsg, ...); @@ -123,59 +151,58 @@ END_COM_MAP() POTE InternSymbol(const Str&) const; // Lookup - int FindNameAsSpecialMessage(const Str&) const; + uint8_t FindNameAsSpecialMessage(const Str&) const; bool IsPseudoVariable(const Str&) const; - int FindNameAsInstanceVariable(const Str&) const; - TempVarRef* AddTempRef(const Str& strName, VarRefType refType, const TEXTRANGE& refRange, int expressionEnd); + size_t FindNameAsInstanceVariable(const Str&) const; + TempVarRef* AddTempRef(const Str& strName, VarRefType refType, const TEXTRANGE& refRange, textpos_t expressionEnd); - enum StaticType { STATICCANCEL=-1, STATICNOTFOUND, STATICVARIABLE, STATICCONSTANT }; + enum class StaticType { STATICCANCEL=-1, STATICNOTFOUND, STATICVARIABLE, STATICCONSTANT }; StaticType FindNameAsStatic(const Str&, POTE&, bool autoDefine=false); - void WarnIfRestrictedSelector(int start); + void WarnIfRestrictedSelector(textpos_t start); // Code generation - int GetCodeSize() const; - int AddToFrameUnconditional(Oop object, const TEXTRANGE&); - int AddToFrame(Oop object, const TEXTRANGE&); - int AddStringToFrame(POTE string, const TEXTRANGE&); + size_t AddToFrameUnconditional(Oop object, const TEXTRANGE&); + size_t AddToFrame(Oop object, const TEXTRANGE&); + size_t AddStringToFrame(POTE string, const TEXTRANGE&); POTE AddSymbolToFrame(LPUTF8, const TEXTRANGE&); POTE AddSymbolToFrame(const char*, const TEXTRANGE&); - void InsertByte(int pos, BYTE value, BYTE flags, LexicalScope* pScope); - void RemoveByte(int pos); - void RemoveBytes(int start, int stop); - int RemoveInstruction(int pos); - int GenByte(BYTE value, BYTE flags, LexicalScope* pScope); - int GenData(BYTE value); - int GenInstruction(BYTE basic, BYTE offset=0); - int GenInstructionExtended(BYTE basic, BYTE extension); - int GenLongInstruction(BYTE basic, WORD extension); - void UngenInstruction(int pos); - void UngenData(int pos, LexicalScope* pScope); + void InsertByte(ip_t pos, uint8_t value, BYTECODE::FLAGS flags, LexicalScope* pScope); + void RemoveByte(ip_t pos); + void RemoveBytes(ip_t start, size_t count); + size_t RemoveInstruction(ip_t pos); + ip_t GenByte(uint8_t value, BYTECODE::FLAGS flags, LexicalScope* pScope); + ip_t GenData(uint8_t value); + ip_t GenInstruction(uint8_t basic, uint8_t offset=0); + ip_t GenInstructionExtended(uint8_t basic, uint8_t extension); + ip_t GenLongInstruction(uint8_t basic, uint16_t extension); + void UngenInstruction(ip_t pos); + void UngenData(ip_t pos, LexicalScope* pScope); - int GenNop(); - int GenDup(); - int GenPopStack(); + ip_t GenNop(); + ip_t GenDup(); + ip_t GenPopStack(); - void GenInteger(int val, const TEXTRANGE&); + void GenInteger(intptr_t val, const TEXTRANGE&); Oop GenNumber(LPUTF8 textvalue, const TEXTRANGE&); void GenNumber(Oop, const TEXTRANGE&); - void GenConstant(int index); + void GenConstant(size_t index); void GenLiteralConstant(Oop object, const TEXTRANGE&); void GenStatic(const POTE oteStatic, const TEXTRANGE&); - int GenMessage(const Str& pattern, int argumentCount, int messageStart); + ip_t GenMessage(const Str& pattern, argcount_t argumentCount, textpos_t messageStart); - int GenJumpInstruction(BYTE basic); - int GenJump(BYTE basic, int location); - void SetJumpTarget(int jump, int target); + ip_t GenJumpInstruction(uint8_t basic); + ip_t GenJump(uint8_t basic, ip_t location); + void SetJumpTarget(ip_t jump, ip_t target); - int GenTempRefInstruction(int instruction, TempVarRef* pRef); - int GenPushCopiedValue(TempVarDecl*); + ip_t GenTempRefInstruction(uint8_t instruction, TempVarRef* pRef); + size_t GenPushCopiedValue(TempVarDecl*); void GenPushSelf(); void GenPushVariable(const Str&, const TEXTRANGE&); - int GenPushTemp(TempVarRef*); - int GenPushInstVar(BYTE index); + ip_t GenPushTemp(TempVarRef*); + ip_t GenPushInstVar(uint8_t index); void GenPushStaticVariable(const Str&, const TEXTRANGE&); void GenPushStaticConstant(POTE oteBinding, const TEXTRANGE& range); void GenPushConstant(Oop objectPointer, const TEXTRANGE& range); @@ -183,47 +210,47 @@ END_COM_MAP() void GenPopAndStoreTemp(TempVarRef*); - int GenStore(const Str&, const TEXTRANGE&, int assignedExpressionStop); - int GenStoreTemp(TempVarRef*); - int GenStoreInstVar(BYTE index); - int GenStaticStore(const Str&, const TEXTRANGE&, int assignedExpressionStop); + ip_t GenStore(const Str&, const TEXTRANGE&, textpos_t assignedExpressionStop); + ip_t GenStoreTemp(TempVarRef*); + ip_t GenStoreInstVar(uint8_t index); + ip_t GenStaticStore(const Str&, const TEXTRANGE&, textpos_t assignedExpressionStop); - int GenReturn(BYTE retOp); - int GenFarReturn(); + ip_t GenReturn(uint8_t retOp); + ip_t GenFarReturn(); // Pass 2 and optimization - int Pass2(); + unsigned Pass2(); void RemoveNops(); void Optimize(); - int CombinePairs(); - int CombinePairs1(); - int CombinePairs2(); - int OptimizePairs(); - int OptimizeJumps(); - int InlineReturns(); - int ShortenJumps(); + unsigned CombinePairs(); + unsigned CombinePairs1(); + unsigned CombinePairs2(); + unsigned OptimizePairs(); + unsigned OptimizeJumps(); + unsigned InlineReturns(); + unsigned ShortenJumps(); void FixupJumps(); - void FixupJump(int); + void FixupJump(ip_t); // Recursive Decent Parsing POTE ParseMethod(); POTE ParseEvalExpression(TokenType); void ParseMessagePattern(); void ParseArgument(); - int ParseTemporaries(); - int ParseStatements(TokenType, bool popResults = true); + tempcount_t ParseTemporaries(); + unsigned ParseStatements(TokenType, bool popResults = true); void ParseBlockStatements(); void ParseStatement(); void ParseExpression(); void ParseAssignment(const Str&, const TEXTRANGE&); - void ParseTerm(int textPosition); - void ParseBinaryTerm(int textPosition); - void ParseBraceArray(int textPosition); - void ParseContinuation(int exprMark, int textPosition); - int ParseKeyContinuation(int exprMark, int textPosition); - int ParseBinaryContinuation(int exprMark, int textPosition); - int ParseUnaryContinuation(int exprMark, int textPosition); + void ParseTerm(textpos_t textPosition); + void ParseBinaryTerm(textpos_t textPosition); + void ParseBraceArray(textpos_t textPosition); + void ParseContinuation(ip_t exprMark, textpos_t textPosition); + ip_t ParseKeyContinuation(ip_t exprMark, textpos_t textPosition); + ip_t ParseBinaryContinuation(ip_t exprMark, textpos_t textPosition); + ip_t ParseUnaryContinuation(ip_t exprMark, textpos_t textPosition); void MaybePatchNegativeNumber(); void MaybePatchLiteralMessage(); @@ -233,99 +260,113 @@ END_COM_MAP() struct LibCallType { LPUTF8 szCallType; - DolphinX::ExtCallDeclSpecs nCallType; + DolphinX::ExtCallDeclSpec nCallType; }; - static LibCallType callTypes[DolphinX::NumCallConventions]; + static LibCallType callTypes[4]; LibCallType* ParseCallingConvention(const Str&); - void ParseLibCall(DolphinX::ExtCallDeclSpecs decl, int callPrim); - void ParseVirtualCall(DolphinX::ExtCallDeclSpecs decl); + void ParseLibCall(DolphinX::ExtCallDeclSpec decl, DolphinX::ExtCallPrimitive callPrim); + void ParseVirtualCall(DolphinX::ExtCallDeclSpec decl); struct TypeDescriptor { - DolphinX::ExtCallArgTypes type; + DolphinX::ExtCallArgType type; Oop parm; TEXTRANGE range; }; - int ParseExtCallArgs(TypeDescriptor args[]); + argcount_t ParseExtCallArgs(TypeDescriptor args[]); void ParseExtCallArgument(TypeDescriptor& out); void ParseExternalClass(const Str&, TypeDescriptor&); POTE FindExternalClass(const Str&, const TEXTRANGE&); - DolphinX::ExtCallArgTypes TypeForStructPointer(POTE oteStructClass); - DolphinX::ExternalMethodDescriptor& buildDescriptorLiteral(TypeDescriptor args[], int argcount, DolphinX::ExtCallDeclSpecs decl, LPUTF8 procName); + DolphinX::ExtCallArgType TypeForStructPointer(POTE oteStructClass); + DolphinX::ExternalMethodDescriptor& buildDescriptorLiteral(TypeDescriptor args[], argcount_t argcount, DolphinX::ExtCallDeclSpec decl, LPUTF8 procName); void mangleDescriptorReturnType(TypeDescriptor& retType, const TEXTRANGE&); - bool IsAtMethodScope() const; - bool IsInBlock() const; - bool IsInOptimizedBlock() const; + __declspec(property(get=get_IsAtMethodScope)) bool IsAtMethodScope; + bool get_IsAtMethodScope() const + { + _ASSERTE(m_pCurrentScope != nullptr); + return m_pCurrentScope == GetMethodScope(); + } + + __declspec(property(get = get_IsInBlock)) bool IsInBlock; + bool get_IsInBlock() const + { + return m_pCurrentScope->IsInBlock; + } - void ParseBlock(const int textPosition); - int ParseBlockArguments(const int textPosition); + __declspec(property(get = get_IsInOptimizedBlock)) bool IsInOptimizedBlock; + bool get_IsInOptimizedBlock() const + { + return m_pCurrentScope->IsOptimizedBlock; + } + + void ParseBlock(const textpos_t textPosition); + argcount_t ParseBlockArguments(const textpos_t textPosition); bool ParseIfTrue(const TEXTRANGE&); bool ParseIfFalse(const TEXTRANGE&); bool ParseAndCondition(const TEXTRANGE&); bool ParseOrCondition(const TEXTRANGE&); bool ParseIfNilBlock(bool noPop); - int ParseIfNotNilBlock(); - bool ParseIfNil(const TEXTRANGE&, int); - bool ParseIfNotNil(const TEXTRANGE&, int); - template bool ParseWhileLoop(const int mark, const TEXTRANGE& receiverRange); - template bool ParseWhileLoopBlock(const int mark, const TEXTRANGE& tokenRange, const TEXTRANGE& receiverRange); - bool ParseRepeatLoop(const int mark, const TEXTRANGE& receiverRange); - bool ParseTimesRepeatLoop(const TEXTRANGE&, const int textStart); - void ParseToByNumberDo(int toPointer, Oop oopStep, bool bNegativeStep); - bool ParseToDoBlock(int, int toPointer); - bool ParseToByDoBlock(int, int toPointer, int byPointer=0); + bool ParseIfNotNilBlock(); + bool ParseIfNil(const TEXTRANGE&, textpos_t); + bool ParseIfNotNil(const TEXTRANGE&, textpos_t); + template bool ParseWhileLoop(const ip_t mark, const TEXTRANGE& receiverRange); + template bool ParseWhileLoopBlock(const ip_t mark, const TEXTRANGE& tokenRange, const TEXTRANGE& receiverRange); + bool ParseRepeatLoop(const ip_t mark, const TEXTRANGE& receiverRange); + bool ParseTimesRepeatLoop(const TEXTRANGE&, const textpos_t textStart); + void ParseToByNumberDo(ip_t toPointer, Oop oopStep, bool bNegativeStep); + bool ParseToDoBlock(textpos_t, ip_t toPointer); + bool ParseToByDoBlock(textpos_t, ip_t toPointer, ip_t byPointer=ip_t::zero); bool ParseZeroArgOptimizedBlock(); - int ParseOptimizeBlock(int argc); + void ParseOptimizeBlock(argcount_t argc); - void InlineOptimizedBlock(int nStart, int nStop); + void InlineOptimizedBlock(ip_t nStart, ip_t nStop); enum class LoopReceiverType { NiladicBlock, NonNiladicBlock, EmptyBlock, Other }; - LoopReceiverType InlineLoopBlock(const int loopmark, const TEXTRANGE&); - int PatchBlocks(); - int PatchBlockAt(int i); - void MakeCleanBlockAt(int i); + LoopReceiverType InlineLoopBlock(const ip_t loopmark, const TEXTRANGE&); + unsigned PatchBlocks(); + size_t PatchBlockAt(ip_t i); + void MakeCleanBlockAt(ip_t i); POTE ParseArray(); POTE ParseByteArray(); Oop ParseConstExpression(); - template int PriorInstruction() const; + template ip_t PriorInstruction() const; bool LastIsPushNil() const; - bool LastIsPushSmallInteger(int& value) const; + bool LastIsPushSmallInteger(intptr_t& value) const; Oop LastIsPushNumber() const; - Oop IsPushLiteral(int pos) const; + Oop IsPushLiteral(ip_t pos) const; // Temporaries TempVarDecl* AddTemporary(const Str& name, const TEXTRANGE& range, bool isArg); TempVarDecl* AddArgument(const Str& name, const TEXTRANGE& range); TempVarRef* AddOptimizedTemp(const Str& name, const TEXTRANGE& range=TEXTRANGE()); - void RenameTemporary(int temporary, LPUTF8 newName, const TEXTRANGE& range); + void RenameTemporary(size_t temporary, LPUTF8 newName, const TEXTRANGE& range); void CheckTemporaryName(const Str&, const TEXTRANGE&, bool isArg); - void PushNewScope(int textStart, bool bOptimized=false); - void PushOptimizedScope(int textStart=-1); - void PopScope(int textStop); - void PopOptimizedScope(int textStop); + void PushNewScope(textpos_t textStart, bool bOptimized=false); + void PushOptimizedScope(textpos_t textStart=textpos_t::npos); + void PopScope(textpos_t textStop); + void PopOptimizedScope(textpos_t textStop); LexicalScope* GetMethodScope() const; void DetermineTempUsage(); TempVarDecl* DeclareTemp(const Str& strName, const TEXTRANGE& range); - void FixupTempRef(int i); - int FixupTempRefs(); + void FixupTempRef(ip_t i); + unsigned FixupTempRefs(); int FixupTempsAndBlocks(); void PatchOptimizedScopes(); void PatchCleanBlockLiterals(POTE oteMethod); - int GetArgumentCount() const; // text map - int AddTextMap(int ip, const TEXTRANGE&); - int AddTextMap(int ip, int textStart, int textStop); - bool AdjustTextMapEntry(int ip, int newIP); - void InsertTextMapEntry(int ip, int textStart, int textStop); - bool RemoveTextMapEntry(int ip); - bool VoidTextMapEntry(int ip); + size_t AddTextMap(ip_t ip, const TEXTRANGE&); + size_t AddTextMap(ip_t ip, textpos_t textStart, textpos_t textStop); + bool AdjustTextMapEntry(ip_t ip, ip_t newIP); + void InsertTextMapEntry(ip_t ip, textpos_t textStart, textpos_t textStop); + bool RemoveTextMapEntry(ip_t ip); + bool VoidTextMapEntry(ip_t ip); #ifdef _DEBUG - void AssertValidIpForTextMapEntry(int ip, bool bFinal); + void AssertValidIpForTextMapEntry(ip_t ip, bool bFinal); void VerifyTextMap(bool bFinal = false); void VerifyJumps(); bool IsBlock(Oop oop); @@ -335,7 +376,7 @@ END_COM_MAP() public: // Methods required by Disassembler - BYTE GetBytecode(size_t ip) { return m_bytecodes[ip].byte; } + BYTE GetBytecode(ip_t ip) const { return m_bytecodes[ip].byte; } Str GetSpecialSelector(size_t index); std::wstring GetLiteralAsString(size_t index) { return DebugPrintString(m_literalFrame[index]); } Str GetInstVar(size_t index) { return m_instVars[index]; } @@ -383,19 +424,25 @@ END_COM_MAP() // Parse state bool m_ok; // Parse still ok? bool m_instVarsInitialized; - enum SendType { SendOther, SendSelf, SendSuper }; - FLAGS m_flags; // Compiler flags + enum class SendType { SendOther, SendSelf, SendSuper }; + CompilerFlags m_flags; // Compiler flags SendType m_sendType; // true if current message is to super // Dynamic array of bytecodes BYTECODES m_bytecodes; - int m_codePointer; // Code insert position + ip_t m_codePointer; // Code insert position + + __declspec(property(get = GetLastIp)) ip_t LastIp; + ip_t GetLastIp() const + { + return static_cast(CodeSize - 1); + } // Dynamic array of literals typedef std::vector OOPVECTOR; OOPVECTOR m_literalFrame; // Literal frame - int m_literalLimit; + size_t m_literalLimit; // Fixed size array of instance vars (determined from class) typedef std::valarray STRINGARRAY; @@ -411,23 +458,23 @@ END_COM_MAP() Str m_selector; // The current message selector - unsigned m_primitiveIndex; // Index of primitive or zero + uintptr_t m_primitiveIndex; // Index of primitive or zero Oop m_compilerObject; // The object which was the receiver of the primCompile:... message to start compilation struct TEXTMAP { - int ip; - int start; - int stop; + ip_t ip; + textpos_t start; + textpos_t stop; - TEXTMAP(int ip, int start, int stop) { this->ip = ip; this->start = start; this->stop = stop; } - TEXTMAP() { ip = start = stop = -1; } + TEXTMAP(const ip_t ip, const textpos_t start, const textpos_t stop) { this->ip = ip; this->start = start; this->stop = stop; } + TEXTMAP() : ip((ip_t)-1), start((textpos_t)-1), stop((textpos_t)-1) { } }; typedef std::vector TEXTMAPLIST; TEXTMAPLIST m_textMaps; - TEXTMAPLIST::iterator FindTextMapEntry(int ip); + TEXTMAPLIST::iterator FindTextMapEntry(ip_t ip); POTE m_compiledMethodClass; // Class of compiled method to generate Oop m_notifier; // Notifier object to send compilerError:... callbacks to @@ -438,43 +485,21 @@ OBJECT_ENTRY_AUTO(__uuidof(DolphinCompiler), Compiler) /////////////////////// // Inlines -inline bool Compiler::WantSyntaxCheckOnly() const { return (m_flags & SyntaxCheckOnly)!=0; } -inline bool Compiler::IsInteractive() const { return ((m_flags & Interactive)!=0) && !WantSyntaxCheckOnly(); } -inline bool Compiler::WantOptimize() const { return (m_flags & NoOptimize)==0; } -inline bool Compiler::WantTextMap() const { return (m_flags & TextMap)!=0; } -inline bool Compiler::WantDebugMethod() const { return (m_flags & DebugMethod)!=0; } -inline bool Compiler::WantTempsMap() const { return (m_flags & TempsMap)!=0; } -inline Str Compiler::GetSelector() const { return m_selector; } -inline bool Compiler::Ok() const { return m_ok; } -inline int Compiler::GetLiteralCount() const { return m_literalFrame.size(); } - -inline int Compiler::GetCodeSize() const -{ - return m_bytecodes.size(); -} - -inline int Compiler::GetArgumentCount() const -{ - return GetMethodScope()->GetArgumentCount(); -} - -/////////////////////////////////////////////////////////////////////////////// // Insert a data byte at the code pointer, returning the position at which // the date byte was inserted. -inline int Compiler::GenData(BYTE value) +inline ip_t Compiler::GenData(uint8_t value) { - return GenByte(value, BYTECODE::IsData, NULL); + return GenByte(value, BYTECODE::FLAGS::IsData, nullptr); } -inline void Compiler::UngenData(int pos, LexicalScope* pScope) +inline void Compiler::UngenData(ip_t pos, LexicalScope* pScope) { - _ASSERTE(pos < GetCodeSize()); #ifdef _DEBUG { BYTECODE& bc = m_bytecodes[pos]; - _ASSERTE(bc.isData()); - _ASSERTE(!bc.isJumpSource()); + _ASSERTE(bc.IsData); + _ASSERTE(!bc.IsJumpSource); } #endif m_bytecodes[pos].makeNop(pScope); @@ -482,51 +507,35 @@ inline void Compiler::UngenData(int pos, LexicalScope* pScope) // Insert an instruction at the code pointer, returning the position at which // the instruction was inserted. -inline int Compiler::GenInstruction(BYTE basic, BYTE offset) +inline ip_t Compiler::GenInstruction(uint8_t basic, uint8_t offset) { _ASSERTE(offset == 0 || ((int)basic+offset) < FirstDoubleByteInstruction); - _ASSERTE(m_pCurrentScope != NULL); - return GenByte(basic + offset, BYTECODE::IsOpCode, m_pCurrentScope); + _ASSERTE(m_pCurrentScope != nullptr); + return GenByte(basic + offset, BYTECODE::FLAGS::IsOpCode, m_pCurrentScope); } -inline int Compiler::GenNop() +inline ip_t Compiler::GenNop() { return GenInstruction(Nop); } -inline int Compiler::GenDup() +inline ip_t Compiler::GenDup() { return GenInstruction(DuplicateStackTop); } -inline int Compiler::GenPopStack() +inline ip_t Compiler::GenPopStack() { return GenInstruction(PopStackTop); } -inline int Compiler::GenStoreTemp(TempVarRef* pTemp) +inline ip_t Compiler::GenStoreTemp(TempVarRef* pTemp) { return GenTempRefInstruction(LongStoreOuterTemp, pTemp); } /////////////////////////////////////////////////////////////////////////////// -inline bool Compiler::IsInBlock() const -{ - return m_pCurrentScope->IsInBlock(); -} - -inline bool Compiler::IsAtMethodScope() const -{ - _ASSERTE(m_pCurrentScope != NULL); - return m_pCurrentScope == GetMethodScope(); -} - -inline bool Compiler::IsInOptimizedBlock() const -{ - return m_pCurrentScope->IsOptimizedBlock(); -} - inline LexicalScope* Compiler::GetMethodScope() const { _ASSERTE(!m_allScopes.empty()); @@ -565,9 +574,9 @@ inline POTE Compiler::InternSymbol(const Str& str) const return InternSymbol(str.c_str()); } -inline void Compiler::RemoveByte(int ip) +inline void Compiler::RemoveByte(ip_t ip) { - _ASSERTE(m_bytecodes[ip].isData()); // Should be using RemoveInstruction for op code bytes + _ASSERTE(m_bytecodes[ip].IsData); // Should be using RemoveInstruction for op code bytes RemoveBytes(ip, 1); } diff --git a/Core/DolphinVM/Compiler/disasm.cpp b/Core/DolphinVM/Compiler/disasm.cpp index e4a64d4641..c714e7ba0c 100755 --- a/Core/DolphinVM/Compiler/disasm.cpp +++ b/Core/DolphinVM/Compiler/disasm.cpp @@ -34,16 +34,16 @@ void Compiler::disassemble(wostream& stream) LexicalScope* currentScope = m_allScopes[0]; int currentDepth = 0; stream << std::endl; - size_t i=0; - const size_t size = GetCodeSize(); - BytecodeDisassembler disassembler(*this); - while (i < size) + ip_t ip=ip_t::zero; + const ip_t last = LastIp; + BytecodeDisassembler disassembler(*this); + while (ip <= LastIp) { - disassembler.EmitIp(i, stream); - size_t len = disassembler.EmitRawBytes(i, stream); + disassembler.EmitIp(ip, stream); + size_t len = disassembler.EmitRawBytes(ip, stream); // Scope changing, and getting deeper? - LexicalScope* newScope = m_bytecodes[i].pScope; + LexicalScope* newScope = m_bytecodes[ip].pScope; stream << newScope << L' '; char padChar = ' '; @@ -55,13 +55,13 @@ void Compiler::disassemble(wostream& stream) { padChar = '-'; } - currentScope = m_bytecodes[i].pScope; + currentScope = m_bytecodes[ip].pScope; currentDepth = newDepth; } // If next is in outer scope, want to print closing bracket now - bool lastInstr = i + len >= size; - int nextDepth = lastInstr ? 0 : m_bytecodes[i + len].pScope->GetLogicalDepth(); + bool lastInstr = ip + len > last; + int nextDepth = lastInstr ? 0 : m_bytecodes[ip + len].pScope->GetLogicalDepth(); // If not on last bytecode, and scope will change, close the bracket if (nextDepth < currentDepth) @@ -79,14 +79,14 @@ void Compiler::disassemble(wostream& stream) stream << padChar; } - const TEXTMAPLIST::iterator it = FindTextMapEntry(i); + const TEXTMAPLIST::iterator it = FindTextMapEntry(ip); if (it != m_textMaps.end()) stream << L'`'; else stream << L' '; - disassembler.EmitDecodedInstructionAt(i, stream); - i += len; + disassembler.EmitDecodedInstructionAt(ip, stream); + ip += len; } stream << std::endl; } @@ -105,3 +105,9 @@ std::wstring Compiler::DebugPrintString(Oop oop) return result; } + +std::wostream& __stdcall operator<<(std::wostream& stream, const std::string& str) +{ + USES_CONVERSION; + return stream << static_cast(A2W(str.c_str())); +} diff --git a/Core/DolphinVM/Compiler/lexer.cpp b/Core/DolphinVM/Compiler/lexer.cpp index 6434f97a42..70b4314d0b 100644 --- a/Core/DolphinVM/Compiler/lexer.cpp +++ b/Core/DolphinVM/Compiler/lexer.cpp @@ -27,17 +27,17 @@ static const uint8_t LITERAL = '#'; Lexer::Lexer() { - m_base = 0; + m_base = textpos_t::start; m_buffer = (LPUTF8)""; m_cc = '\0'; - m_cp = NULL; + m_cp = nullptr; m_integer = 0; - m_lastTokenRange = { 0, 0 }; + m_lastTokenRange = { textpos_t::start, textpos_t::start }; m_lineno = 0; - m_thisTokenRange = { 0, 0 }; - m_token = NULL; - m_tokenType = None; - tp = NULL; + m_thisTokenRange = { textpos_t::start, textpos_t::start }; + m_token = nullptr; + m_tokenType = TokenType::None; + tp = nullptr; m_locale = _create_locale(LC_ALL, "C"); m_piVM = nullptr; } @@ -50,7 +50,7 @@ Lexer::~Lexer() void Lexer::CompileError(int code, Oop extra) { - CompileErrorV(ThisTokenRange(), code, extra, 0); + CompileErrorV(ThisTokenRange, code, extra, 0); } void Lexer::CompileError(const TEXTRANGE& range, int code, Oop extra) @@ -66,15 +66,15 @@ void Lexer::CompileErrorV(const TEXTRANGE& range, int code, ...) va_end(extras); } -void Lexer::SetText(const uint8_t* compiletext, int offset) +void Lexer::SetText(const uint8_t* compiletext, textpos_t offset) { - m_tokenType = None; + m_tokenType = TokenType::None; m_buffer = compiletext; m_cp = m_buffer.c_str(); m_token = new uint8_t[m_buffer.size() + 1]; m_lineno = 1; m_base = offset; - AdvanceCharPtr(offset); + AdvanceCharPtr(static_cast(offset)); } // ANSI Binary chars are ... @@ -131,7 +131,7 @@ inline void Lexer::SkipBlanks() void Lexer::SkipComments() { - int commentStart = CharPosition(); + textpos_t commentStart = CharPosition; while (m_cc == COMMENTDELIM) { uint8_t ch; @@ -143,7 +143,7 @@ void Lexer::SkipComments() if (!ch) { // Break out at EOF - CompileError(TEXTRANGE(commentStart, CharPosition()), LErrCommentNotClosed); + CompileError(TEXTRANGE(commentStart, CharPosition), LErrCommentNotClosed); } const uint8_t* ep = m_cp; @@ -157,7 +157,7 @@ inline bool issign(uint8_t ch) return ch == '-' || ch == '+'; } -double Lexer::ThisTokenFloat() const +double Lexer::get_ThisTokenFloat() const { _CRT_DOUBLE result; int retval = _atodbl_l(&result, (LPSTR)m_token, m_locale); @@ -175,7 +175,7 @@ void Lexer::ScanFloat() uint8_t ch = NextChar(); if (isdigit(PeekAtChar())) { - m_tokenType = FloatingConst; + m_tokenType = TokenType::FloatingConst; do { @@ -231,7 +231,7 @@ int Lexer::DigitValue(uint8_t ch) const void Lexer::ScanInteger(int radix) { m_integer = 0; - m_tokenType = SmallIntegerConst; + m_tokenType = TokenType::SmallIntegerConst; int digit = DigitValue(PeekAtChar()); int maxval = INT_MAX / radix; @@ -240,7 +240,7 @@ void Lexer::ScanInteger(int radix) { *tp++ = NextChar(); - if (m_tokenType == SmallIntegerConst) + if (m_tokenType == TokenType::SmallIntegerConst) { if (m_integer < maxval || (m_integer == maxval && digit <= INT_MAX % radix)) { @@ -249,7 +249,7 @@ void Lexer::ScanInteger(int radix) } else // It will have to be left to Smalltalk to calc the large integer value - m_tokenType = LargeIntegerConst; + m_tokenType = TokenType::LargeIntegerConst; } digit = DigitValue(PeekAtChar()); @@ -276,7 +276,7 @@ void Lexer::ScanExponentInteger() { *tp++ = NextChar(); } while (isdigit(PeekAtChar())); - m_tokenType = LargeIntegerConst; + m_tokenType = TokenType::LargeIntegerConst; } else { @@ -304,7 +304,7 @@ void Lexer::ScanNumber() { case 'r': { - if (m_tokenType != SmallIntegerConst) + if (m_tokenType != TokenType::SmallIntegerConst) return; if (m_integer >= 2 && m_integer <= 36) @@ -333,7 +333,7 @@ void Lexer::ScanNumber() while (isdigit(PeekAtChar())) *tp++ = NextChar(); - m_tokenType = ScaledDecimalConst; + m_tokenType = TokenType::ScaledDecimalConst; break; case '.': @@ -349,7 +349,7 @@ void Lexer::ScanNumber() while (isdigit(PeekAtChar())) *tp++ = NextChar(); - m_tokenType = ScaledDecimalConst; + m_tokenType = TokenType::ScaledDecimalConst; } break; @@ -365,7 +365,7 @@ void Lexer::ScanNumber() } // Read string up to terminating quote, ignoring embedded double quotes -Lexer::TokenType Lexer::ScanString(int stringStart) +Lexer::TokenType Lexer::ScanString(textpos_t stringStart) { uint8_t ch; bool isAscii = true; @@ -374,7 +374,7 @@ Lexer::TokenType Lexer::ScanString(int stringStart) ch = NextChar(); if (!ch) { - CompileError(TEXTRANGE(stringStart, CharPosition()), LErrStringNotClosed); + CompileError(TEXTRANGE(stringStart, CharPosition), LErrStringNotClosed); } else { @@ -393,7 +393,7 @@ Lexer::TokenType Lexer::ScanString(int stringStart) } } while (ch); - return isAscii ? AnsiStringConst : Utf8StringConst; + return isAscii ? TokenType::AnsiStringConst : TokenType::Utf8StringConst; } void Lexer::ScanName() @@ -401,13 +401,13 @@ void Lexer::ScanName() while (isIdentifierSubsequent(NextChar())) *tp++ = m_cc; *tp = 0; - LPUTF8 tok = ThisTokenText(); + LPUTF8 tok = ThisTokenText; if (!strcmp((LPCSTR)tok, "true")) - m_tokenType = TrueConst; + m_tokenType = TokenType::TrueConst; else if (!strcmp((LPCSTR)tok, "false")) - m_tokenType = FalseConst; + m_tokenType = TokenType::FalseConst; else if (!strcmp((LPCSTR)tok, "nil")) - m_tokenType = NilConst; + m_tokenType = TokenType::NilConst; } void Lexer::ScanQualifiedName() @@ -415,9 +415,9 @@ void Lexer::ScanQualifiedName() LPUTF8 endLastWord = tp; *tp++ = m_cc; ScanName(); - if (m_tokenType != NameConst) + if (m_tokenType != TokenType::NameConst) { - m_tokenType = NameConst; + m_tokenType = TokenType::NameConst; } else { @@ -430,9 +430,9 @@ void Lexer::ScanQualifiedName() void Lexer::ScanIdentifierOrKeyword() { - m_tokenType = NameConst; + m_tokenType = TokenType::NameConst; ScanName(); - if (m_tokenType == NameConst && m_cc == '.' && isLetter(PeekAtChar())) + if (m_tokenType == TokenType::NameConst && m_cc == '.' && isLetter(PeekAtChar())) ScanQualifiedName(); else { @@ -441,7 +441,7 @@ void Lexer::ScanIdentifierOrKeyword() if (m_cc == ':' && PeekAtChar() != '=') { *tp++ = m_cc; - m_tokenType = NameColon; + m_tokenType = TokenType::NameColon; } else { @@ -452,7 +452,7 @@ void Lexer::ScanIdentifierOrKeyword() void Lexer::ScanSymbol() { - uint8_t* lastColon = NULL; + uint8_t* lastColon = nullptr; while (isIdentifierFirst(m_cc)) { *tp++ = m_cc; @@ -470,7 +470,7 @@ void Lexer::ScanSymbol() } } - if (lastColon != NULL && *(tp - 1) != ':') + if (lastColon != nullptr && *(tp - 1) != ':') { m_cp = m_cp - (tp - lastColon); tp = lastColon + 1; @@ -499,30 +499,30 @@ void Lexer::ScanLiteral() if (isIdentifierFirst(m_cc)) { ScanSymbol(); - m_tokenType = SymbolConst; + m_tokenType = TokenType::SymbolConst; } else if (isAnsiBinaryChar(m_cc)) { ScanBinary(); - m_tokenType = SymbolConst; + m_tokenType = TokenType::SymbolConst; } else if (m_cc == STRINGDELIM) { // Quoted Symbol - ScanString(CharPosition()); - m_tokenType = SymbolConst; + ScanString(CharPosition); + m_tokenType = TokenType::SymbolConst; } else if (m_cc == '(') { - m_tokenType = ArrayBegin; + m_tokenType = TokenType::ArrayBegin; } else if (m_cc == '[') { - m_tokenType = ByteArrayBegin; + m_tokenType = TokenType::ByteArrayBegin; } else if (m_cc == LITERAL) @@ -530,13 +530,13 @@ void Lexer::ScanLiteral() // Second hash, so should be a constant expression ##(xxx) NextChar(); if (m_cc != '(') - CompileError(TEXTRANGE(CharPosition(), CharPosition()), LErrExpectExtendedLiteral); - m_tokenType = ExprConstBegin; + CompileError(TEXTRANGE(CharPosition, CharPosition), LErrExpectExtendedLiteral); + m_tokenType = TokenType::ExprConstBegin; } else { - m_thisTokenRange.m_stop = CharPosition(); + m_thisTokenRange.m_stop = CharPosition; CompileError(LErrExpectConst); } } @@ -551,7 +551,7 @@ Lexer::TokenType Lexer::NextToken() SkipComments(); // Start remembering this token - int start = CharPosition(); + textpos_t start = CharPosition; m_thisTokenRange.m_start = start; tp = m_token; @@ -563,7 +563,7 @@ Lexer::TokenType Lexer::NextToken() { // Hit EOF straightaway - so be careful not to write another Null term into the token // as this would involve writing off the end of the token buffer - m_tokenType = Eof; + m_tokenType = TokenType::Eof; m_thisTokenRange.m_stop = start; m_thisTokenRange.m_start = start + 1; } @@ -583,7 +583,7 @@ Lexer::TokenType Lexer::NextToken() { Step(); ScanNumber(); - if (m_tokenType == SmallIntegerConst) + if (m_tokenType == TokenType::SmallIntegerConst) m_integer *= -1; } else if (ch == LITERAL) @@ -593,7 +593,7 @@ Lexer::TokenType Lexer::NextToken() else if (ch == STRINGDELIM) { - int stringStart = CharPosition(); + textpos_t stringStart = CharPosition; // String constant; remove quote tp--; m_tokenType = ScanString(stringStart); @@ -606,58 +606,58 @@ Lexer::TokenType Lexer::NextToken() else if (ch == '^') { - m_tokenType = Return; + m_tokenType = TokenType::Return; } else if (ch == ':') { if (PeekAtChar() == '=') { - m_tokenType = Assignment; + m_tokenType = TokenType::Assignment; *tp++ = NextChar(); } else - m_tokenType = Special; + m_tokenType = TokenType::Special; } else if (ch == ')') { - m_tokenType = CloseParen; + m_tokenType = TokenType::CloseParen; } else if (ch == '.') { - m_tokenType = CloseStatement; + m_tokenType = TokenType::CloseStatement; } else if (ch == ']') { - m_tokenType = CloseSquare; + m_tokenType = TokenType::CloseSquare; } else if (ch == '}') { - m_tokenType = CloseBrace; + m_tokenType = TokenType::CloseBrace; } else if (ch == ';') { - m_tokenType = Cascade; + m_tokenType = TokenType::Cascade; } else if (IsASingleBinaryChar(ch)) { // Single binary expressions - m_tokenType = Binary; + m_tokenType = TokenType::Binary; } else if (isAnsiBinaryChar(ch)) { - m_tokenType = Binary; + m_tokenType = TokenType::Binary; } else { - int pos = CharPosition(); + textpos_t pos = CharPosition; int cp = ReadUtf8(ch); CompileError(TEXTRANGE(pos, pos), LErrBadChar, (Oop)m_piVM->NewCharacter(cp < 0 ? 0xFFFD : cp)); } @@ -665,7 +665,7 @@ Lexer::TokenType Lexer::NextToken() *tp = '\0'; } - m_thisTokenRange.m_stop = CharPosition(); + m_thisTokenRange.m_stop = CharPosition; return m_tokenType; } @@ -720,7 +720,7 @@ int Lexer::ReadUtf8(uint8_t ch) void Lexer::ScanLiteralCharacter() { - m_tokenType = CharConst; + m_tokenType = TokenType::CharConst; m_integer = 0; // This is one of the few places we need to be aware of UTF-8 encoding. Generally the only chars that are significant to the compiler are @@ -732,7 +732,7 @@ void Lexer::ScanLiteralCharacter() if (codePoint == 0) { // Reached EOF - int pos = CharPosition(); + textpos_t pos = CharPosition; m_thisTokenRange.m_stop = pos; CompileError(LErrExpectChar); return; @@ -779,7 +779,7 @@ void Lexer::ScanLiteralCharacter() codePoint = ReadHexCodePoint(); if (codePoint < 0) { - int pos = CharPosition(); + textpos_t pos = CharPosition; m_thisTokenRange.m_stop = pos; CompileError(LErrExpectCodePoint); return; @@ -792,7 +792,7 @@ void Lexer::ScanLiteralCharacter() if (codePoint > MaxCodePoint || U_IS_UNICODE_NONCHAR(codePoint)) { - int pos = CharPosition(); + textpos_t pos = CharPosition; m_thisTokenRange.m_stop = pos; CompileError(LErrBadCodePoint); } @@ -1025,7 +1025,7 @@ unsigned long Lexer::strtoxl( number = LONG_MAX; } - if (endptr != NULL) + if (endptr != nullptr) /* store pointer to char that stopped the scan */ *endptr = p; diff --git a/Core/DolphinVM/Compiler/lexer.h b/Core/DolphinVM/Compiler/lexer.h index c1c6ab56fe..999eab90e8 100644 --- a/Core/DolphinVM/Compiler/lexer.h +++ b/Core/DolphinVM/Compiler/lexer.h @@ -8,6 +8,7 @@ The Smalltalk lexical analyser /////////////////////// #include "Str.h" +#include "textrange.h" /////////////////////// @@ -33,7 +34,7 @@ class Lexer protected: // The current lexical token - enum TokenType + enum class TokenType { // Type for parsing None, NameConst, NameColon, @@ -49,9 +50,9 @@ class Lexer uint8_t Step(); void PushBack(uint8_t ch); - VOID StepBack(int n); + void StepBack(size_t n); TokenType NextToken(); - TokenType ScanString(int); + TokenType ScanString(textpos_t); void ScanNumber(); int DigitValue(uint8_t ch) const; void ScanInteger(int radix); @@ -65,19 +66,65 @@ class Lexer void ScanSymbol(); void ScanBinary(); - TokenType ThisToken() const; - void SetTokenType(TokenType tok); - bool AtEnd() const; - LPUTF8 ThisTokenText() const; - long ThisTokenInteger() const; - double ThisTokenFloat() const; + __declspec(property(get = get_ThisToken, put=put_ThisToken)) TokenType ThisToken; + Lexer::TokenType get_ThisToken() const + { + return m_tokenType; + } + void put_ThisToken(TokenType tok) + { + m_tokenType = tok; + } + + __declspec(property(get = get_AtEnd)) bool AtEnd; + bool get_AtEnd() const + { + return m_tokenType == TokenType::Eof; + } + + __declspec(property(get = get_ThisTokenText)) LPUTF8 ThisTokenText; + LPUTF8 get_ThisTokenText() const + { + return m_token; + } + + __declspec(property(get = get_ThisTokenInteger)) intptr_t ThisTokenInteger; + intptr_t get_ThisTokenInteger() const + { + return m_integer; + } + + __declspec(property(get = get_ThisTokenFloat)) double ThisTokenFloat; + double get_ThisTokenFloat() const; + bool ThisTokenIsBinary(const char) const; bool ThisTokenIsSpecial(const char) const; - bool ThisTokenIsClosing() const; - bool ThisTokenIsAssignment() const; - bool ThisTokenIsReturn() const; - bool ThisTokenIsNumber() const; - + + __declspec(property(get = get_ThisTokenIsClosing)) bool ThisTokenIsClosing; + bool get_ThisTokenIsClosing() const + { + return m_tokenType >= TokenType::CloseParen && m_tokenType <= TokenType::Eof; + } + + __declspec(property(get = get_ThisTokenIsAssignment)) bool ThisTokenIsAssignment; + bool get_ThisTokenIsAssignment() const + { + return m_tokenType == TokenType::Assignment; + } + + __declspec(property(get = get_ThisTokenIsReturn)) bool ThisTokenIsReturn; + bool get_ThisTokenIsReturn() const + { + return m_tokenType == TokenType::Return; + } + + __declspec(property(get = get_ThisTokenIsNumber)) bool ThisTokenIsNumber; + bool get_ThisTokenIsNumber() const + { + return m_tokenType >= TokenType::SmallIntegerConst && m_tokenType <= TokenType::ScaledDecimalConst; + } + + void CompileError(const TEXTRANGE& range, int code, Oop extra=0); void CompileError(int code, Oop extra=0); void CompileErrorV(const TEXTRANGE& range, int code, ...); @@ -86,16 +133,13 @@ class Lexer enum { MaxCodePoint = 0x10FFFF }; virtual void _CompileErrorV(int code, const TEXTRANGE& range, va_list)=0; - uint8_t PeekAtChar(int lookAhead=0) const; - //bool CanBeSmallInteger(long valueLong) const; bool IsASingleBinaryChar(uint8_t ch) const; - //bool IsDigitInRadix(char ch, int radix) const; TEXTRANGE CompileTextRange() const { - return TEXTRANGE(0, GetTextLength()-1); + return TEXTRANGE(textpos_t::start, EndOfText); } //****************************************************************************** @@ -115,69 +159,83 @@ class Lexer void SkipBlanks(); void SkipComments(); - void SetText(const uint8_t* compiletext, int offset); + void SetText(const uint8_t* compiletext, textpos_t offset); - LPUTF8 GetText() const + __declspec(property(get = get_Text)) LPUTF8 Text; + LPUTF8 get_Text() const { return m_buffer.c_str(); } Str GetTextRange(const TEXTRANGE& r) { - return m_buffer.substr(r.m_start, r.m_stop - r.m_start + 1); + return m_buffer.substr(static_cast(r.m_start), r.Span); } - int GetTextOffset() const + __declspec(property(get = get_TextOffset)) textpos_t TextOffset; + textpos_t get_TextOffset() const { return m_base; } - int GetParsedLength() const + __declspec(property(get = get_ParsedLength)) size_t ParsedLength; + size_t get_ParsedLength() const { - return m_cp - GetText() - GetTextOffset(); + return m_cp - Text - static_cast(TextOffset); } - const TEXTRANGE& ThisTokenRange() const + __declspec(property(get = get_ThisTokenRange)) const TEXTRANGE& ThisTokenRange; + const TEXTRANGE& get_ThisTokenRange() const { return m_thisTokenRange; } - const TEXTRANGE& LastTokenRange() const + __declspec(property(get = get_LastTokenRange)) const TEXTRANGE& LastTokenRange; + const TEXTRANGE& get_LastTokenRange() const { return m_lastTokenRange; } - int ErrorPosition() const + __declspec(property(get = get_ErrorPosition)) textpos_t ErrorPosition; + textpos_t get_ErrorPosition() const { - return AtEnd() ? ThisTokenRange().m_stop : LastTokenRange().m_stop; + return AtEnd ? ThisTokenRange.m_stop : LastTokenRange.m_stop; } - int GetTextLength() const + __declspec(property(get=get_TextLength)) size_t TextLength; + size_t get_TextLength() const { return m_buffer.size(); } - const uint8_t* GetCharPtr() const + __declspec(property(get = get_EndOfText)) textpos_t EndOfText; + textpos_t get_EndOfText() const { - return m_cp; + return static_cast(m_buffer.size() - 1); } - char GetNextChar() const + __declspec(property(get = get_CharPtr)) const uint8_t* CharPtr; + const uint8_t* get_CharPtr() const { - return *m_cp; + return m_cp; } - int GetLineNo() const + __declspec(property(get = get_LineNo)) int LineNo; + int get_LineNo() const { return m_lineno; } - void AdvanceCharPtr(int offset) + void AdvanceCharPtr(size_t offset) { m_cp += offset; } - int CharPosition() const; + __declspec(property(get = get_CharPosition)) textpos_t CharPosition; + textpos_t get_CharPosition() const + { + return static_cast((m_cp - m_buffer.c_str()) - 1); + } IDolphin* m_piVM; @@ -190,7 +248,7 @@ class Lexer private: // The current token TokenType m_tokenType; - long m_integer; + intptr_t m_integer; uint8_t* m_token; uint8_t* tp; @@ -199,7 +257,7 @@ class Lexer const uint8_t* m_cp; uint8_t m_cc; int m_lineno; - int m_base; + textpos_t m_base; TEXTRANGE m_thisTokenRange; TEXTRANGE m_lastTokenRange; @@ -210,59 +268,14 @@ class Lexer /////////////////////////////////////////////////////////////////////////////// // Inlines -inline Lexer::TokenType Lexer::ThisToken() const -{ - return m_tokenType; -} - -inline bool Lexer::AtEnd() const -{ - return m_tokenType == Eof; -} - -inline LPUTF8 Lexer::ThisTokenText() const -{ - return m_token; -} - -inline long Lexer::ThisTokenInteger() const -{ - return m_integer; -} - -inline bool Lexer::ThisTokenIsAssignment() const -{ - return m_tokenType == Assignment; -} - -inline bool Lexer::ThisTokenIsReturn() const -{ - return m_tokenType == Return; -} - inline bool Lexer::ThisTokenIsBinary(const char match) const { - return m_tokenType==Binary && m_token[0] == match && m_token[1] == 0; + return m_tokenType== TokenType::Binary && m_token[0] == match && m_token[1] == 0; } inline bool Lexer::ThisTokenIsSpecial(const char match) const { - return m_tokenType==Special && m_token[0] == match && m_token[1] == 0; -} - -inline bool Lexer::ThisTokenIsClosing() const -{ - return m_tokenType >= CloseParen && m_tokenType <= Eof; -} - -inline bool Lexer::ThisTokenIsNumber() const -{ - return m_tokenType >= SmallIntegerConst && m_tokenType <= ScaledDecimalConst; -} - -inline void Lexer::SetTokenType(TokenType tok) -{ - m_tokenType = tok; + return m_tokenType== TokenType::Special && m_token[0] == match && m_token[1] == 0; } inline uint8_t Lexer::NextChar() @@ -280,7 +293,7 @@ inline uint8_t Lexer::Step() { *tp++ = ch; *tp = 0; - m_thisTokenRange.m_stop++; + ++m_thisTokenRange.m_stop; } return ch; } @@ -290,11 +303,6 @@ inline uint8_t Lexer::PeekAtChar(int lookAhead) const return m_cp[lookAhead]; } -inline int Lexer::CharPosition() const -{ - return (m_cp - m_buffer.c_str()) - 1; -} - inline void Lexer::PushBack(uint8_t ch) { _ASSERTE(m_cp>m_buffer.c_str()); @@ -312,12 +320,12 @@ inline void Lexer::PushBack(uint8_t ch) } // N.B. This routine assumes it is not stepping back over line ends -inline void Lexer::StepBack(int n) +inline void Lexer::StepBack(size_t n) { m_cp -= n; m_cc = *m_cp; m_thisTokenRange.m_stop -= n; - m_token[m_thisTokenRange.m_stop - m_thisTokenRange.m_start + 1] = 0; + m_token[m_thisTokenRange.Span] = 0; } //****************************************************************************** diff --git a/Core/DolphinVM/Compiler/optimizer.cpp b/Core/DolphinVM/Compiler/optimizer.cpp index 71c668c1c2..e816285c52 100755 --- a/Core/DolphinVM/Compiler/optimizer.cpp +++ b/Core/DolphinVM/Compiler/optimizer.cpp @@ -16,7 +16,7 @@ Smalltalk compiler bytecode optimizer. #define CHECKREFERENCES #ifdef _DEBUG -static int compilationTrace = 0; +static int compilationTrace = 1; #elif !defined(USE_VM_DLL) #undef NDEBUG @@ -25,19 +25,19 @@ static int compilationTrace = 0; #define _ASSERTE assert #endif -const int BlockCopyInstructionLength = 7; +const size_t BlockCopyInstructionLength = 7; ////////////////////////////////////////////////// // Some helpers for optimisation ////////////////////////////////////////////////// -inline int Compiler::Pass2() +inline unsigned Compiler::Pass2() { // Optimise generated code - int blockCount = FixupTempsAndBlocks(); + unsigned blockCount = FixupTempsAndBlocks(); RemoveNops(); - if (WantOptimize()) + if (WantOptimize) Optimize(); FixupJumps(); return blockCount; @@ -45,12 +45,12 @@ inline int Compiler::Pass2() void Compiler::RemoveNops() { - int i=0; - while (i= 0 && bc.target < GetCodeSize())); + _ASSERTE(bc.IsOpCode); + _ASSERTE(!bc.IsJumpSource || (bc.target >= ip_t::zero && bc.target <= LastIp)); VerifyTextMap(); @@ -63,7 +63,7 @@ void Compiler::RemoveNops() break; default: - i += bc.instructionLength(); + i += bc.InstructionLength; break; } } @@ -117,39 +117,39 @@ void Compiler::Optimize() // optimization when removing jumps, and to correctly // remove multi-byte instructions, which was not always done // before -inline int Compiler::RemoveInstruction(int ip) +inline size_t Compiler::RemoveInstruction(ip_t ip) { - _ASSERTE(ip < GetCodeSize()); + _ASSERTE(ip <= LastIp); BYTECODE& bc = m_bytecodes[ip]; // We should be removing an instruction - _ASSERTE(bc.isOpCode()); + _ASSERTE(bc.IsOpCode); #ifdef _DEBUG { const TEXTMAPLIST::iterator it = FindTextMapEntry(ip); if (it != m_textMaps.end()) { - int prevIP = ip - 1; - while (prevIP >= 0 && (m_bytecodes[prevIP].isData() || m_bytecodes[prevIP].byte == Nop)) - prevIP--; - const BYTECODE* prev = prevIP < 0 ? NULL : &m_bytecodes[prevIP]; - bool isFirstInBlock = bc.pScope != NULL && bc.pScope->IsBlock() - && (bc.pScope->GetInitialIP() == ip || prev->byte == BlockCopy || bc.pScope != prev->pScope); - _ASSERTE(ip == 0 || isFirstInBlock); + ip_t prevIP = ip - 1; + while (prevIP >= ip_t::zero && (m_bytecodes[prevIP].IsData || m_bytecodes[prevIP].byte == Nop)) + --prevIP; + const BYTECODE* prev = prevIP < ip_t::zero ? nullptr : &m_bytecodes[prevIP]; + bool isFirstInBlock = bc.pScope != nullptr && bc.pScope->IsBlock + && (bc.pScope->InitialIP == ip || (prev != nullptr && (prev->byte == BlockCopy || bc.pScope != prev->pScope))); + _ASSERTE(ip == ip_t::zero || isFirstInBlock); } } #endif // We're about to remove an unreachable jump, so we want to inform // its jump target in case that can be optimized away too - if (bc.isJumpSource()) + if (bc.IsJumpSource) { - _ASSERTE(bc.target < GetCodeSize()); + _ASSERTE(bc.target <= LastIp); BYTECODE& target = m_bytecodes[bc.target]; target.removeJumpTo(); } - int len = bc.instructionLength(); + size_t len = bc.InstructionLength; RemoveBytes(ip, len); return len; @@ -159,22 +159,22 @@ inline int Compiler::RemoveInstruction(int ip) // Remove a sequence of bytes from the code array // Adjusts any jumps that occur over the boundary // This is very slow if the bytecode array is large -void Compiler::RemoveBytes(int ip, int count) +void Compiler::RemoveBytes(ip_t ip, size_t count) { - _ASSERTE(ip >= 0 && count > 0); - int size = GetCodeSize(); - const int next = ip + count; - _ASSERTE(ip >=0 && next <= size); + _ASSERTE(ip >= ip_t::zero && count > 0); + ip_t last = LastIp; + const ip_t next = ip + count; + _ASSERTE(next <= last+1); const BYTECODE& bc = m_bytecodes[ip]; WORD jumpsTo = bc.jumpsTo; const BYTECODES::iterator begin = m_bytecodes.begin(); - m_bytecodes.erase(begin + ip, begin + next); + m_bytecodes.erase(begin + static_cast(ip), begin + static_cast(next)); - size -= count; - if (ip < size) + last -= count; + if (ip <= last) { - _ASSERTE(jumpsTo == 0 || m_bytecodes[ip].isOpCode()); + _ASSERTE(jumpsTo == 0 || m_bytecodes[ip].IsOpCode); // Following byte may become jump target m_bytecodes[ip].jumpsTo += jumpsTo; } @@ -187,17 +187,17 @@ void Compiler::RemoveBytes(int ip, int count) // Adjust any jumps to targets past the removal point as the target will have shuffled up { - for (int i = 0; i < size;) + for (ip_t i = ip_t::zero; i < last;) { BYTECODE& bc = m_bytecodes[i]; - _ASSERTE(bc.isOpCode()); - if (bc.isJumpSource()) + _ASSERTE(bc.IsOpCode); + if (bc.IsJumpSource) { - _ASSERTE(bc.target < size + count); + _ASSERTE(bc.target <= last + count); // This is a jump. Does it cross the boundary if (bc.target >= next) bc.target -= count; // Yes, adjust absolute target - _ASSERTE(bc.target >= 0); + _ASSERTE(bc.target >= ip_t::zero); } i += lengthOfByteCode(bc.byte); @@ -206,17 +206,17 @@ void Compiler::RemoveBytes(int ip, int count) // Adjust ip of any TextMaps { - const int textMapCount = m_textMaps.size(); - for (int i = 0; i < textMapCount; i++) + const size_t textMapCount = m_textMaps.size(); + for (size_t i = 0; i < textMapCount; i++) { TEXTMAP& textMap = m_textMaps[i]; // If the text map entry is in the range of removed bytes, adjust it to point at the next instruction // If the text map is for a later instruction, then adjust its ip to keep pointing at the same (moved up) instruction - int mapIp = textMap.ip; + ip_t mapIp = textMap.ip; if (mapIp > ip) { textMap.ip = mapIp < next ? ip : mapIp - count; - _ASSERTE(textMap.ip >= 0 && textMap.ip < size); + _ASSERTE(textMap.ip <= last); AssertValidIpForTextMapEntry(textMap.ip, false); } } @@ -229,12 +229,12 @@ inline int decodeOuterTempRef(BYTE byte, int& index) return byte >> OuterTempIndexBits; } -bool Compiler::AdjustTextMapEntry(int ip, int newIP) +bool Compiler::AdjustTextMapEntry(ip_t ip, ip_t newIP) { - if (!WantTextMap()) return true; + if (!WantTextMap) return true; - const int count = m_textMaps.size(); - for (int i = 0; i < count; i++) + const size_t count = m_textMaps.size(); + for (size_t i = 0; i < count; i++) { TEXTMAP& textMap = m_textMaps[i]; if (textMap.ip == ip) @@ -246,25 +246,26 @@ bool Compiler::AdjustTextMapEntry(int ip, int newIP) return false; } -int Compiler::OptimizePairs() +unsigned Compiler::OptimizePairs() { // Optimize pairs of instructions. // Returns a count of the optimizations done. - int count=0, i=0; - while (i < GetCodeSize()) + unsigned count = 0; + ip_t i = ip_t::zero; + while (i <= LastIp) { VerifyTextMap(); BYTECODE& bytecode1=m_bytecodes[i]; - const int len1 = bytecode1.instructionLength(); - const int next = i+len1; - if (next >= GetCodeSize()) + const size_t len1 = bytecode1.InstructionLength; + const ip_t next = i+len1; + if (next > LastIp) break; // bytecode1 is last instruction BYTECODE& bytecode2=m_bytecodes[next]; - _ASSERTE(bytecode1.isOpCode() && bytecode2.isOpCode()); + _ASSERTE(bytecode1.IsOpCode && bytecode2.IsOpCode); // We can't perform any of these optimizations if the second byte code is a jump target - if (!bytecode2.isJumpTarget()) + if (!bytecode2.IsJumpTarget) { BYTE byte1 = bytecode1.byte; BYTE byte2 = bytecode2.byte; @@ -274,7 +275,7 @@ int Compiler::OptimizePairs() // by a return special but only if the second is not a jump // target. // - if (bytecode1.isPseudoPush() && byte2 == ReturnMessageStackTop) + if (bytecode1.IsPseudoPush && byte2 == ReturnMessageStackTop) { // Can avoid need to modify text map if we remove the push and adjust the return instruction bytecode2.byte = FirstPseudoReturn + (byte1 - FirstPseudoPush); @@ -284,7 +285,7 @@ int Compiler::OptimizePairs() } // We must perform same optimisation in debug code to keep the text maps synchronised - else if (bytecode1.isPseudoPush() && byte2 == Break && m_bytecodes[next+1].byte == ReturnMessageStackTop) + else if (bytecode1.IsPseudoPush && byte2 == Break && m_bytecodes[next+1].byte == ReturnMessageStackTop) { m_bytecodes[next+1].byte = FirstPseudoReturn + (byte1 - FirstPseudoPush); RemoveInstruction(i); @@ -304,7 +305,7 @@ int Compiler::OptimizePairs() } // Quite a lot of pushes are redundant, and can be removed... - else if (bytecode1.isPush()) + else if (bytecode1.IsPush) { // A push immediately followed by a pop that is not immediately // jumped to can be replaced by nothing. @@ -315,7 +316,7 @@ int Compiler::OptimizePairs() (byte1==ShortPushNil && byte2 == LongJumpIfNotNil) ) { - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); if (byte2 != PopStackTop) VoidTextMapEntry(next); RemoveInstruction(i); @@ -325,9 +326,9 @@ int Compiler::OptimizePairs() } // Push followed by pseudo return is redundant, and can be removed leaving on the return - else if (bytecode2.isPseudoReturn()) + else if (bytecode2.IsPseudoReturn) { - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); RemoveInstruction(i); count++; continue; // Continue optimization on the pseudo return now move to i @@ -337,7 +338,7 @@ int Compiler::OptimizePairs() { // If push true followed by jump if true (which is not a jump target) // then equivalent to an unconditional jump - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); VoidTextMapEntry(i+1); bytecode2.byte = LongJump; RemoveInstruction(i); // Remove the push ... @@ -348,7 +349,7 @@ int Compiler::OptimizePairs() { // If push false followed by jump if false (which is not a jump target) // then equivalent to an unconditional jump - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); VoidTextMapEntry(i+1); bytecode2.byte = LongJump; RemoveInstruction(i); // Remove the push ... @@ -359,7 +360,7 @@ int Compiler::OptimizePairs() { // If push nil followed by jump if nil (which is not a jump target) // then equivalent to an unconditional jump - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); VoidTextMapEntry(i+1); bytecode2.byte = LongJump; RemoveInstruction(i); // Remove the push ... @@ -454,7 +455,7 @@ int Compiler::OptimizePairs() { if (byte2 == SpecialSendIdentical) { - _ASSERTE(!bytecode1.isJumpSource()); + _ASSERTE(!bytecode1.IsJumpSource); bytecode2.byte = IsZero; RemoveInstruction(i); count++; @@ -464,7 +465,7 @@ int Compiler::OptimizePairs() //else if (byte2 == SendArithmeticAdd || byte2 == SendArithmeticSub) //{ // // Subtract or add zero is, of course, redundant - // _ASSERTE(!bytecode1.isJumpSource()); + // _ASSERTE(!bytecode1.IsJumpSource); // RemoveInstruction(i+1); // RemoveInstruction(i); // count++; @@ -474,7 +475,7 @@ int Compiler::OptimizePairs() } // Check for unreachable code (remember the following byte is known not to be a jump target) - else if (bytecode1.isReturn() || bytecode1.isLongJump()) + else if (bytecode1.IsReturn || bytecode1.IsLongJump) { VerifyJumps(); VoidTextMapEntry(next); @@ -485,13 +486,13 @@ int Compiler::OptimizePairs() continue; } - else if (bytecode1.isExtendedStore()) + else if (bytecode1.IsExtendedStore) { // A store instruction followed by a pop that is not immediately // jumped to can be coerced (heh heh) into a pop and store. if (byte2==PopStackTop) { - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); if (byte1 == StoreOuterTemp) { // Remove the popStack @@ -529,9 +530,9 @@ int Compiler::OptimizePairs() // Now there may be a shorter form of instruction that // we can use - _ASSERTE(m_bytecodes[i+1].isData()); + _ASSERTE(m_bytecodes[i+1].IsData); - _ASSERTE(i+1 < GetCodeSize()); + _ASSERTE(i+1 <= LastIp); int index = m_bytecodes[i+1].byte; if (bytecode1.byte == PopStoreInstVar && index < NumShortPopStoreInstVars) { @@ -551,7 +552,7 @@ int Compiler::OptimizePairs() } // Same as above for the next ShortStoreTemp instruction - else if (bytecode1.isShortStoreTemp()) + else if (bytecode1.IsShortStoreTemp) { if (byte2 == PopStackTop) { @@ -564,9 +565,9 @@ int Compiler::OptimizePairs() } } - else if (byte1 == SpecialSendIsNil && bytecode2.isJumpSource()) + else if (byte1 == SpecialSendIsNil && bytecode2.IsJumpSource) { - _ASSERTE(bytecode2.instructionLength() == 3); + _ASSERTE(bytecode2.InstructionLength == 3); if (byte2 == LongJumpIfTrue) { bytecode2.byte = LongJumpIfNil; @@ -589,9 +590,9 @@ int Compiler::OptimizePairs() continue; // A new instruction will now be at i to be considered, so don't advance } } - else if (byte1 == SpecialSendNotNil && bytecode2.isJumpSource()) + else if (byte1 == SpecialSendNotNil && bytecode2.IsJumpSource) { - _ASSERTE(bytecode2.instructionLength() == 3); + _ASSERTE(bytecode2.InstructionLength == 3); if (byte2 == LongJumpIfTrue) { bytecode2.byte = LongJumpIfNotNil; @@ -616,7 +617,7 @@ int Compiler::OptimizePairs() if (byte2 == ReturnMessageStackTop) { // A Dup immediately before a Return ToS is redundant - _ASSERTE(!bytecode2.isJumpTarget()); + _ASSERTE(!bytecode2.IsJumpTarget); bytecode1.byte = ReturnMessageStackTop; count++; // Leave the other return to be removed as unreachable code @@ -628,15 +629,15 @@ int Compiler::OptimizePairs() BYTECODE& target = m_bytecodes[bytecode2.target]; if (target.byte == PopStackTop && target.jumpsTo == 1) { - int nilBranch = next + bytecode2.instructionLength(); + ip_t nilBranch = next + bytecode2.InstructionLength; BYTECODE& bytecode3 = m_bytecodes[nilBranch]; - if (bytecode3.byte = PopStackTop) + if (bytecode3.byte == PopStackTop) { // Remove Dup and Pop from first branch, and retarget jump over to next after the pop target.removeJumpTo(); m_bytecodes[++bytecode2.target].addJumpTo(); - _ASSERTE(!m_bytecodes[nilBranch].isJumpTarget()); + _ASSERTE(!m_bytecodes[nilBranch].IsJumpTarget); // Remove Pop from nil branch RemoveInstruction(nilBranch); // Remove Dup @@ -647,7 +648,7 @@ int Compiler::OptimizePairs() } } } - else if ((bytecode1.isShortPopStoreTemp() && bytecode2.isShortPushTemp()) + else if ((bytecode1.IsShortPopStoreTemp && bytecode2.IsShortPushTemp) && (bytecode1.indexOfShortPopStoreTemp() == bytecode2.indexOfShortPushTemp())) { // Replace a PopStore[n], Push[n], sequence with a store @@ -669,12 +670,12 @@ int Compiler::OptimizePairs() count++; continue; // A new instruction will now be at i to be considered, so don't advance } - else if (bytecode1.isLongConditionalJump() && bytecode2.isLongJump() + else if (bytecode1.IsLongConditionalJump && bytecode2.IsLongJump && bytecode1.target == next + 3) { // Conditional jump over unconditional jump can be replaced with // inverted conditional jump to unconditional jump's target - BYTE invertedJmp; + uint8_t invertedJmp; switch (bytecode1.byte) { case LongJumpIfTrue: @@ -708,7 +709,7 @@ int Compiler::OptimizePairs() // A store into a temp followed by a return from method is redundant, even if // either is a jump target - if (bytecode1.isStoreStackTemp() && bytecode2.isReturn()) + if (bytecode1.IsStoreStackTemp && bytecode2.IsReturn) { // bytecode1 is a Store (assignment) and might have a text map entry (the Store for // an ifNotNil: block will not). @@ -723,9 +724,9 @@ int Compiler::OptimizePairs() VerifyJumps(); - // Bytecode may have been replaced, so move to next based on the one there now - _ASSERTE(m_bytecodes[i].isOpCode()); - const int len = m_bytecodes[i].instructionLength(); + // m_bytecodes may have been replaced, so move to next based on the one there now + _ASSERTE(m_bytecodes[i].IsOpCode); + const size_t len = m_bytecodes[i].InstructionLength; i += len; } return count; @@ -735,31 +736,32 @@ int Compiler::OptimizePairs() // here generates incorrect code for CombinePairs1 and it fails to spot Push Temp;Send Zero Args pairs. #pragma optimize("g", off) -int Compiler::CombinePairs() +unsigned Compiler::CombinePairs() { return CombinePairs1() + CombinePairs2(); } // Combine pairs of instructions into the more favoured macro instructions. This should be done // before CombinePairs2(). Returns a count of the optimizations done. -int Compiler::CombinePairs1() +unsigned Compiler::CombinePairs1() { - int count=0, i=0; - while (i < GetCodeSize()) + unsigned count = 0; + ip_t i=ip_t::zero; + while (i <= LastIp) { VerifyTextMap(); BYTECODE& bytecode1=m_bytecodes[i]; - const int len1 = bytecode1.instructionLength(); + const size_t len1 = bytecode1.InstructionLength; - const int next = i+len1; - if (next >= GetCodeSize()) + const ip_t next = i+len1; + if (next > LastIp) break; // bytecode1 is last instruction BYTECODE& bytecode2=m_bytecodes[next]; - _ASSERTE(bytecode1.isOpCode() && bytecode2.isOpCode()); + _ASSERTE(bytecode1.IsOpCode && bytecode2.IsOpCode); // We can't perform any of these optimizations if the second byte code is a jump target - if (!bytecode2.isJumpTarget()) + if (!bytecode2.IsJumpTarget) { const BYTE byte1 = bytecode1.byte; const BYTE byte2 = bytecode2.byte; @@ -772,10 +774,10 @@ int Compiler::CombinePairs1() { if (byte2 == Send) { - _ASSERTE(m_bytecodes[next+1].isData()); - int m = m_bytecodes[next+1].byte; + _ASSERTE(m_bytecodes[next+1].IsData); + uint8_t m = m_bytecodes[next+1].byte; _ASSERTE(SendXLiteralBits == 5); - int argCount = m >> SendXLiteralBits; + uint8_t argCount = m >> SendXLiteralBits; if (argCount == 0) { // Push Self will become the Send Self instruction @@ -787,7 +789,7 @@ int Compiler::CombinePairs1() RemoveByte(next+1); } } - else if (bytecode2.isShortSendWithNoArgs()) + else if (bytecode2.IsShortSendWithNoArgs) { _ASSERTE(len1 == 1); VERIFY(AdjustTextMapEntry(next, i)); @@ -809,11 +811,11 @@ int Compiler::CombinePairs1() } // Look for opportunities to combine push temp with subsequent zero arg send - else if (bytecode1.isShortPushTemp()) + else if (bytecode1.IsShortPushTemp) { int n = bytecode1.indexOfShortPushTemp(); - if (bytecode2.isShortSendWithNoArgs()) + if (bytecode2.IsShortSendWithNoArgs) { // Push Temp has become the Send Temp instruction VERIFY(AdjustTextMapEntry(next, i)); @@ -829,10 +831,10 @@ int Compiler::CombinePairs1() } else if (byte2 == Send) { - _ASSERTE(m_bytecodes[next+1].isData()); - int m = m_bytecodes[next+1].byte; + _ASSERTE(m_bytecodes[next+1].IsData); + uint8_t m = m_bytecodes[next+1].byte; _ASSERTE(SendXLiteralBits <= 5); - int argCount = m >> SendXLiteralBits; + uint8_t argCount = m >> SendXLiteralBits; if (argCount == 0) { // Push Temp will become the Send Temp instruction @@ -856,11 +858,11 @@ int Compiler::CombinePairs1() // byte2 cannot possibly be the last instruction BYTECODE& bytecode3=m_bytecodes[next+1]; - if (!bytecode3.isJumpTarget()) + if (!bytecode3.IsJumpTarget) { - if (bytecode3.isShortPopStoreTemp()) + if (bytecode3.IsShortPopStoreTemp) { - int m = bytecode3.indexOfShortPopStoreTemp(); + uint8_t m = bytecode3.indexOfShortPopStoreTemp(); if (m == n) { VERIFY(AdjustTextMapEntry(next, i)); @@ -873,9 +875,9 @@ int Compiler::CombinePairs1() count++; } } - else if (bytecode3.isShortStoreTemp()) + else if (bytecode3.IsShortStoreTemp) { - int m = bytecode3.indexOfShortStoreTemp(); + uint8_t m = bytecode3.indexOfShortStoreTemp(); if (m == n) { bytecode1.byte = byte2 == IncrementStackTop ? IncrementPushTemp : DecrementPushTemp; @@ -891,7 +893,7 @@ int Compiler::CombinePairs1() } else if (bytecode3.byte == PopStoreTemp || bytecode3.byte == StoreTemp) { - int m = m_bytecodes[next+2].byte; + uint8_t m = m_bytecodes[next+2].byte; if (m == n) { bytecode1.byte = bytecode3.byte == PopStoreTemp @@ -910,24 +912,24 @@ int Compiler::CombinePairs1() } else if (byte1 == PushTemp) { - _ASSERTE(m_bytecodes[i+1].isData()); - int n = m_bytecodes[i+1].byte; + _ASSERTE(m_bytecodes[i+1].IsData); + uint8_t n = m_bytecodes[i+1].byte; if (byte2 == Send) { if (n <= MAXFORBITS(3)) { - _ASSERTE(m_bytecodes[next+1].isData()); + _ASSERTE(m_bytecodes[next+1].IsData); _ASSERTE(SendXLiteralBits <= 5); - int m = m_bytecodes[next+1].byte; - int argCount = m >> SendXLiteralBits; + uint8_t m = m_bytecodes[next+1].byte; + uint8_t argCount = m >> SendXLiteralBits; if (argCount == 0) { DebugBreak(); } } } - else if (bytecode2.isShortSendWithNoArgs()) + else if (bytecode2.IsShortSendWithNoArgs) { if (n <= MAXFORBITS(3)) { @@ -950,7 +952,7 @@ int Compiler::CombinePairs1() // byte2 cannot possibly be the last instruction BYTECODE& bytecode3=m_bytecodes[next+1]; - if (!bytecode3.isJumpTarget()) + if (!bytecode3.IsJumpTarget) { if (bytecode3.byte == PopStoreTemp || bytecode3.byte == StoreTemp) { @@ -978,9 +980,9 @@ int Compiler::CombinePairs1() } } - // Bytecode may have been replaced, so move to next based on the one there now - _ASSERTE(m_bytecodes[i].isOpCode()); - const int len = m_bytecodes[i].instructionLength(); + // m_bytecodes may have been replaced, so move to next based on the one there now + _ASSERTE(m_bytecodes[i].IsOpCode); + const size_t len = m_bytecodes[i].InstructionLength; i += len; } return count; @@ -988,27 +990,28 @@ int Compiler::CombinePairs1() // Combine pairs of instructions into the less favoured macro instructions. This should be done // after CombinePairs1(). Returns a count of the optimizations done. -int Compiler::CombinePairs2() +unsigned Compiler::CombinePairs2() { - int count=0, i=0; - while (i < GetCodeSize()) + unsigned count = 0; + ip_t i = ip_t::zero; + while (i <= LastIp) { VerifyTextMap(); BYTECODE& bytecode1=m_bytecodes[i]; - const int len1 = bytecode1.instructionLength(); + const size_t len1 = bytecode1.InstructionLength; - const int next = i+len1; - if (next >= GetCodeSize()) + const ip_t next = i+len1; + if (next > LastIp) break; // bytecode1 is last instruction BYTECODE& bytecode2=m_bytecodes[next]; - _ASSERTE(bytecode1.isOpCode() && bytecode2.isOpCode()); + _ASSERTE(bytecode1.IsOpCode && bytecode2.IsOpCode); BYTE byte1 = bytecode1.byte; BYTE byte2 = bytecode2.byte; // We can't perform any of these optimizations if the second byte code is a jump target - if (!bytecode2.isJumpTarget()) + if (!bytecode2.IsJumpTarget) { if (byte1 == PopStackTop) { @@ -1038,7 +1041,7 @@ int Compiler::CombinePairs2() count++; } - else if (bytecode2.isShortPushTemp() && (bytecode2.indexOfShortPushTemp() < NumShortPopPushTemps)) + else if (bytecode2.IsShortPushTemp && (bytecode2.indexOfShortPushTemp() < NumShortPopPushTemps)) { // Pop followed by a push of a temp is common in a sequence of statements where // messages are sent to a temp @@ -1052,7 +1055,7 @@ int Compiler::CombinePairs2() else if (byte1 == ShortPushSelf) { - if (bytecode2.isPushTemp()) + if (bytecode2.IsPushTemp) { // A pair of push self and then pushing a temp is very common, being the prelude // to sending a one (or more) arg message to self @@ -1091,24 +1094,24 @@ int Compiler::CombinePairs2() // Look for opportunities to combine pairs of push temp instructions into one // Pairs of temp pushes are common before sending 1 or more argument messages - else if (bytecode1.isShortPushTemp()) + else if (bytecode1.IsShortPushTemp) { int n = bytecode1.indexOfShortPushTemp(); if (byte2 == PushTemp) { - _ASSERTE(m_bytecodes[next+1].isData()); - int m = m_bytecodes[next+1].byte; + _ASSERTE(m_bytecodes[next+1].IsData); + uint8_t m = m_bytecodes[next+1].byte; if (m < MAXFORBITS(4)) { bytecode1.byte = PushTempPair; RemoveBytes(next, 1); - _ASSERTE(m_bytecodes[next].isData()); + _ASSERTE(m_bytecodes[next].IsData); m_bytecodes[next].byte = n << 4 | m; count++; } } - else if (bytecode2.isShortPushTemp()) + else if (bytecode2.IsShortPushTemp) { int m = bytecode2.indexOfShortPushTemp(); _ASSERTE(n <= MAXFORBITS(4)); @@ -1122,16 +1125,16 @@ int Compiler::CombinePairs2() else if (byte1 == PushTemp) { - _ASSERTE(m_bytecodes[i+1].isData()); + _ASSERTE(m_bytecodes[i+1].IsData); int n = m_bytecodes[i+1].byte; - if (bytecode2.isPushTemp()) + if (bytecode2.IsPushTemp) { if (n <= MAXFORBITS(4)) { if (byte2 == PushTemp) { - _ASSERTE(m_bytecodes[next+1].isData()); + _ASSERTE(m_bytecodes[next+1].IsData); int m = m_bytecodes[next+1].byte; if (m <= MAXFORBITS(4)) { @@ -1143,7 +1146,7 @@ int Compiler::CombinePairs2() } else { - _ASSERTE(bytecode2.isShortPushTemp()); + _ASSERTE(bytecode2.IsShortPushTemp); int m = bytecode2.indexOfShortPushTemp(); _ASSERTE(n <= MAXFORBITS(4)); _ASSERTE(m <= MAXFORBITS(4)); @@ -1157,9 +1160,9 @@ int Compiler::CombinePairs2() } } - // Bytecode may have been replaced, so move to next based on the one there now - _ASSERTE(m_bytecodes[i].isOpCode()); - const int len = m_bytecodes[i].instructionLength(); + // m_bytecodes may have been replaced, so move to next based on the one there now + _ASSERTE(m_bytecodes[i].IsOpCode); + const size_t len = m_bytecodes[i].InstructionLength; i += len; } return count; @@ -1169,78 +1172,79 @@ int Compiler::CombinePairs2() void Compiler::FixupJumps() { - const int loopEnd = GetCodeSize(); - int i=0; + const ip_t last = LastIp; + ip_t i = ip_t::zero; LexicalScope* pCurrentScope = GetMethodScope(); - pCurrentScope->SetInitialIP(0); + pCurrentScope->InitialIP = ip_t::zero; - while (iSetFinalIP(i-1); + pCurrentScope->FinalIP = i-1; pCurrentScope = m_bytecodes[i].pScope; - _ASSERTE(pCurrentScope != NULL); + _ASSERTE(pCurrentScope != nullptr); // Patch up the initialIP of the scope for the temps map pCurrentScope->MaybeSetInitialIP(i); } - _ASSERTE(m_bytecodes[i].isOpCode()); - int len = m_bytecodes[i].instructionLength(); + _ASSERTE(m_bytecodes[i].IsOpCode); + size_t len = m_bytecodes[i].InstructionLength; i += len; // Code size cannot shrink - _ASSERTE(GetCodeSize() == loopEnd); + _ASSERTE(LastIp == last); } - pCurrentScope->SetFinalIP(GetCodeSize()-1); - _ASSERTE(GetMethodScope()->GetFinalIP() == GetCodeSize()-1); + pCurrentScope->FinalIP = LastIp; + _ASSERTE(GetMethodScope()->FinalIP == LastIp); } -int Compiler::OptimizeJumps() +unsigned Compiler::OptimizeJumps() { // Run through seeing if any jumps can be removed or retargeted. // Return a count of the number of jumps replaced. // - int count=0, i=0; - while (i= 0 && currentTarget < GetCodeSize()); + ip_t currentTarget = bytecode.target; + _ASSERTE(currentTarget <= LastIp); BYTECODE& target = m_bytecodes[currentTarget]; - _ASSERTE(target.isJumpTarget()); + _ASSERTE(target.IsJumpTarget); BYTE targetByte = target.byte; - int distance = currentTarget-i; - int offset = distance - len; - if (!offset) + intptr_t distance = static_cast(currentTarget) - static_cast(i); + intptr_t offset = distance - len; + if (offset == 0) { _ASSERTE(bytecode.byte != BlockCopy); @@ -1261,7 +1265,7 @@ int Compiler::OptimizeJumps() continue; // Go round again at same IP } - if (target.isJumpSource()) + if (target.IsJumpSource) { if (target.byte == LongJump) { @@ -1270,8 +1274,8 @@ int Compiler::OptimizeJumps() { // Any jump to an unconditional jump can be redirected to its // eventual target. - int eventualtarget=target.target; - _ASSERTE(eventualtarget >= 0 && eventualtarget < GetCodeSize()); + ip_t eventualtarget=target.target; + _ASSERTE(eventualtarget <= LastIp); target.removeJumpTo(); // We're no longer jumping to original target SetJumpTarget(i, eventualtarget); count++; @@ -1283,36 +1287,36 @@ int Compiler::OptimizeJumps() // Unconditional jump to a conditional jump can be replaced // with a conditional jump (of the same type) to the same target // and an unconditional jump to the location after the original cond jump target - _ASSERTE(target.isLongConditionalJump()); + _ASSERTE(target.IsLongConditionalJump); _ASSERTE(len == 3); bytecode.byte = target.byte; - int eventualtarget = target.target; - _ASSERTE(eventualtarget >= 0 && eventualtarget < GetCodeSize()); + ip_t eventualtarget = target.target; + _ASSERTE(eventualtarget <= LastIp); target.removeJumpTo(); // We're no longer jumping to original target SetJumpTarget(i, eventualtarget); m_codePointer = i + len; m_pCurrentScope = bytecode.pScope; GenJump(LongJump, currentTarget+3); - m_pCurrentScope = NULL; + m_pCurrentScope = nullptr; count++; continue; // Reconsider this jump as may be in a chain } } - else if (target.isPush()) + else if (target.IsPush) { // If jumping to push followed by pop, can skip to the next instruction // This is quite a common result of conditional expressions // Can't be last byte (wouldn't make sense, as need a return) - int next = currentTarget + target.instructionLength(); - _ASSERTE(next < GetCodeSize()); + ip_t next = currentTarget + target.InstructionLength; + _ASSERTE(next <= LastIp); BYTECODE& nextAfterTarget=m_bytecodes[next]; if (nextAfterTarget.byte == PopStackTop) { - _ASSERTE(nextAfterTarget.instructionLength() == 1); + _ASSERTE(nextAfterTarget.InstructionLength == 1); // Yup its a jump to a no-op, so retarget to following byte target.removeJumpTo(); - _ASSERTE(next+1 < GetCodeSize()); // Again, must be at least a ret to follow + _ASSERTE(next+1 <= LastIp); // Again, must be at least a ret to follow SetJumpTarget(i, next+1); count++; continue; // Reconsider this jump as may be in a chain @@ -1327,45 +1331,46 @@ int Compiler::OptimizeJumps() return count; } -int Compiler::InlineReturns() +unsigned Compiler::InlineReturns() { // Jumps to return instructions can be replaced by the return instruction // Note that this is done last in optimisation as quite often such jumps // can be removed altogether due to elimination of unreachable/redundant code. // - int count=0, i=0; - while (i= 0 && currentTarget < GetCodeSize()); + ip_t currentTarget = bytecode.target; + _ASSERTE(currentTarget <= LastIp); BYTECODE& target = m_bytecodes[currentTarget]; - _ASSERTE(target.isJumpTarget()); + _ASSERTE(target.IsJumpTarget); BYTE targetByte = target.byte; // Unconditional Jumps to return instructions can be replaced with the return instruction if (bytecode.byte == LongJump) { - if (target.isReturn()) + if (target.IsReturn) { // All return instructions must be 1 byte long - _ASSERTE(target.instructionLength() == 1); + _ASSERTE(target.InstructionLength == 1); len = 1; bytecode.byte = targetByte; target.removeJumpTo(); bytecode.makeNonJump(); - if (WantTextMap()) + if (WantTextMap) { // N.B. We need to copy the text map entry for the target TEXTMAP tm = *FindTextMapEntry(currentTarget); @@ -1376,10 +1381,10 @@ int Compiler::InlineReturns() count++; } // We need to perform the same optimisation in debug methods to ensure the text maps match - else if (targetByte == Break && m_bytecodes[currentTarget+1].isReturn()) + else if (targetByte == Break && m_bytecodes[currentTarget+1].IsReturn) { // All return instructions must be 1 byte long - _ASSERTE(target.instructionLength() == 1); + _ASSERTE(target.InstructionLength == 1); const BYTECODE& returnOp = m_bytecodes[currentTarget+1]; @@ -1389,14 +1394,14 @@ int Compiler::InlineReturns() // and therefore there is no code inline in the method to jump over. We have to special case // this to avoid creating inconsistent text maps. You would think the code sequence '[[]]' // would never appear in a method, but EventsCollection>>triggerEvent: contains it! - if (!(returnOp.byte == ReturnBlockStackTop && m_bytecodes[i+len].pScope->GetRealScope()->IsEmptyBlock())) + if (!(returnOp.byte == ReturnBlockStackTop && m_bytecodes[i+len].pScope->RealScope->IsEmptyBlock)) { len = 2; bytecode.byte = Break; target.removeJumpTo(); bytecode.makeNonJump(); m_bytecodes[i+1].makeOpCode(m_bytecodes[currentTarget+1].byte, bytecode.pScope); - if (WantTextMap()) + if (WantTextMap) { // N.B. We need to copy the text map entry for the target TEXTMAPLIST::const_iterator it = FindTextMapEntry(currentTarget+1); @@ -1409,17 +1414,17 @@ int Compiler::InlineReturns() } else if (targetByte == PopStackTop) { - if (m_bytecodes[currentTarget+1].isReturn())//.byte == ReturnSelf) + if (m_bytecodes[currentTarget+1].IsReturn)//.byte == ReturnSelf) { // All return instructions must be 1 byte long - _ASSERTE(target.instructionLength() == 1); + _ASSERTE(target.InstructionLength == 1); len = 2; bytecode.byte = targetByte; target.removeJumpTo(); bytecode.makeNonJump(); m_bytecodes[i+1].makeOpCode(m_bytecodes[currentTarget+1].byte, bytecode.pScope); - if (WantTextMap()) + if (WantTextMap) { // N.B. We need to copy the text map entry for the return after the target TEXTMAPLIST::const_iterator it = FindTextMapEntry(currentTarget+1); @@ -1430,10 +1435,10 @@ int Compiler::InlineReturns() count++; } else if (m_bytecodes[currentTarget+1].byte == Break - && m_bytecodes[currentTarget+2].isReturn()) //.byte == ReturnSelf) + && m_bytecodes[currentTarget+2].IsReturn) //.byte == ReturnSelf) { // All return instructions must be 1 byte long - _ASSERTE(target.instructionLength() == 1); + _ASSERTE(target.InstructionLength == 1); len = 3; bytecode.byte = targetByte; @@ -1441,7 +1446,7 @@ int Compiler::InlineReturns() bytecode.makeNonJump(); m_bytecodes[i+1].makeOpCode(Break, bytecode.pScope); m_bytecodes[i+2].makeOpCode(m_bytecodes[currentTarget+2].byte, bytecode.pScope); - if (WantTextMap()) + if (WantTextMap) { // N.B. We need to copy the text map entry for the return after the target TEXTMAPLIST::const_iterator it = FindTextMapEntry(currentTarget+2); @@ -1451,21 +1456,21 @@ int Compiler::InlineReturns() count++; } } - else if (target.isPseudoPush()) + else if (target.IsPseudoPush) { // Inline jump to Push [Self|True|False|Nil]; Return sequence - if (m_bytecodes[currentTarget+1].isReturnStackTop()) + if (m_bytecodes[currentTarget+1].IsReturnStackTop) { // All return instructions must be 1 byte long - _ASSERTE(target.instructionLength() == 1); + _ASSERTE(target.InstructionLength == 1); len = 2; bytecode.byte = targetByte; target.removeJumpTo(); bytecode.makeNonJump(); m_bytecodes[i+1].makeOpCode(m_bytecodes[currentTarget+1].byte, bytecode.pScope); - if (WantTextMap()) + if (WantTextMap) { // N.B. We need to copy the text map entry for the return after the target TEXTMAPLIST::const_iterator it = FindTextMapEntry(currentTarget+1); @@ -1475,10 +1480,10 @@ int Compiler::InlineReturns() RemoveByte(i+2); count++; } - else if (m_bytecodes[currentTarget+1].byte == Break && m_bytecodes[currentTarget+2].isReturnStackTop()) + else if (m_bytecodes[currentTarget+1].byte == Break && m_bytecodes[currentTarget+2].IsReturnStackTop) { // All return instructions must be 1 byte long - _ASSERTE(target.instructionLength() == 1); + _ASSERTE(target.InstructionLength == 1); len = 3; bytecode.byte = targetByte; @@ -1486,7 +1491,7 @@ int Compiler::InlineReturns() bytecode.makeNonJump(); m_bytecodes[i+1].makeOpCode(Break, bytecode.pScope); m_bytecodes[i+2].makeOpCode(m_bytecodes[currentTarget+2].byte, bytecode.pScope); - if (WantTextMap()) + if (WantTextMap) { // N.B. We need to copy the text map entry for the return after the target TEXTMAPLIST::const_iterator it = FindTextMapEntry(currentTarget+2); @@ -1502,7 +1507,7 @@ int Compiler::InlineReturns() // other is a jump target. Note that we do this after inlining any returns to ensure that // we inline the 'correct' return (the correct one is the one associated with the right text // map entry). T - else if (bytecode.isReturn() && i + len < GetCodeSize() && bytecode.byte == m_bytecodes[i+len].byte) + else if (bytecode.IsReturn && i + len <= LastIp && bytecode.byte == m_bytecodes[i+len].byte) { VERIFY(VoidTextMapEntry(i)); BYTE duplicateReturn = bytecode.byte; @@ -1524,16 +1529,16 @@ int Compiler::InlineReturns() // allow us to take account of the size of the current extension for forward jumps, as otherwise we may // miss an opportunity to optimize jumps which are currently near, but could be short if it were not for // the extension byte of the Near Jump -inline static bool isInShortJumpRange(int distance, unsigned extensionBytes) +inline static bool isInShortJumpRange(intptr_t distance, size_t extensionBytes) { - int offset = distance - 2; // Allow for the instruction itself + intptr_t offset = distance - 2; // Allow for the instruction itself return offset >= 0 && (offset - extensionBytes) < NumShortJumps; } // Answer whether the supplied distance is within the possible jump range from the jump // instruction. assuming that the current instruction has 'extensionBytes' bytes of extensions. // -inline static bool isInNearJumpRange(int distance, unsigned extensionBytes) +inline static bool isInNearJumpRange(intptr_t distance, unsigned extensionBytes) { #if defined(_DEBUG) && !defined(USE_VM_DLL) if (distance == 0) @@ -1543,9 +1548,9 @@ inline static bool isInNearJumpRange(int distance, unsigned extensionBytes) // If the jump instruction is at 1, then the IP after interpreting it will be 3 // so the offsets will be distance - 2 - int offset = distance - 2; + intptr_t offset = distance - 2; - return offset < 0 ? + return offset < 0? // We must take account of the size of the Near Jump instruction (2) when deciding whether a // Near jump is possible since the offset always starts from the next instruction (i.e. // offset 0 is the next instruction). The offset accounts for the opcode, but not the extension @@ -1558,41 +1563,42 @@ inline static bool isInNearJumpRange(int distance, unsigned extensionBytes) // Is distance within the range of jumps possible from the current long jump instruction (accounting for // the size of the instruction). -inline static bool isInLongJumpRange(int distance) +inline static bool isInLongJumpRange(intptr_t distance) { - int offset = distance - 3; + intptr_t offset = distance - 3; return offset >= MaxBackwardsLongJump && offset <= MaxForwardsLongJump; } -int Compiler::ShortenJumps() +unsigned Compiler::ShortenJumps() { // Run through seeing if any shorter jumps can be used. Return a count // of the number of jumps shortened. // - int count=0, i=0; - while (i= 0 && bytecode.target < GetCodeSize()); + _ASSERTE(bytecode.target >= ip_t::zero && bytecode.target <= LastIp); BYTECODE& target = m_bytecodes[bytecode.target]; - _ASSERTE(target.isJumpTarget()); - BYTE targetByte = target.byte; - int distance = bytecode.target - i; + _ASSERTE(target.IsJumpTarget); + uint8_t targetByte = target.byte; + intptr_t distance = static_cast(bytecode.target) - static_cast(i); switch (bytecode.byte) { ////////////////////////////////////////////////////////////////////////////////// // Single byte Short jumps. Obviously these cannot be shorted further case ShortJump: - _ASSERTE(!target.isReturn()); + _ASSERTE(!target.IsReturn); case ShortJumpIfFalse: break; @@ -1601,7 +1607,7 @@ int Compiler::ShortenJumps() case NearJump: // Unconditional Jumps to return instructions can be replaced with the return instruction - _ASSERTE(!target.isReturn()); + _ASSERTE(!target.IsReturn); if (isInShortJumpRange(distance, 1)) // Account for extension { // Can shorten to short jump @@ -1635,7 +1641,7 @@ int Compiler::ShortenJumps() case LongJump: // Unconditional Jumps to return instructions should have been replaced with the // return instruction - _ASSERTE(!target.isReturn()); + _ASSERTE(!target.IsReturn); if (isInNearJumpRange(distance, 2)) { // Can shorten to near jump @@ -1697,7 +1703,7 @@ int Compiler::ShortenJumps() _ASSERTE(0); } } - int len = m_bytecodes[i].instructionLength(); + size_t len = m_bytecodes[i].InstructionLength; i += len; } return count; @@ -1711,13 +1717,13 @@ int Compiler::ShortenJumps() // not read by fetching). In the case of the short instructions the VM adds an additional 1 to the jump offset // to extend the range of jumps that can be handled by a short jump (since jump 0 is effectively jump to the // next instruction, which is not much use) - i.e. the zero based offset in the instruction is converted to 1 based. -void Compiler::FixupJump(int pos) +void Compiler::FixupJump(ip_t pos) { // Fixes up the jump at pos - const int targetIP = m_bytecodes[pos].target; - _ASSERTE(targetIP >= 0 && targetIP < GetCodeSize()); - _ASSERTE(m_bytecodes[targetIP].isJumpTarget()); // Otherwise optimization could have gone wrong - int distance=targetIP - pos; + const ip_t targetIP = m_bytecodes[pos].target; + _ASSERTE(targetIP <= LastIp); + _ASSERTE(m_bytecodes[targetIP].IsJumpTarget); // Otherwise optimization could have gone wrong + intptr_t distance=static_cast(targetIP) - static_cast(pos); switch (m_bytecodes[pos].byte) { @@ -1726,30 +1732,30 @@ void Compiler::FixupJump(int pos) { // Short jumps _ASSERTE(isInShortJumpRange(distance,0)); - int offset = distance - 2; // IP advanced over instruction, and VM adds 1 too to + intptr_t offset = distance - 2; // IP advanced over instruction, and VM adds 1 too to // extend the useful range of short jumps (no point jumping // to the next instruction) - _ASSERTE(pos+distance < GetCodeSize()); - m_bytecodes[pos].byte += offset; + _ASSERTE(pos+distance <= LastIp); + m_bytecodes[pos].byte += static_cast(offset); } break; case NearJump: case NearJumpIfFalse: - _ASSERTE(!WantOptimize() || !isInShortJumpRange(distance, 1)); // Why not optimized? + _ASSERTE(!WantOptimize || !isInShortJumpRange(distance, 1)); // Why not optimized? case NearJumpIfTrue: case NearJumpIfNil: case NearJumpIfNotNil: { // Unconditional jump _ASSERTE(isInNearJumpRange(distance, 1)); - int offset = distance - 2; // IP inc'd for instruction and extension byte + intptr_t offset = distance - 2; // IP inc'd for instruction and extension byte - _ASSERTE(!WantOptimize() || offset != 0); // Why not optimized out? + _ASSERTE(!WantOptimize || offset != 0); // Why not optimized out? _ASSERTE(offset >= -128 && offset <= 127); - _ASSERTE(pos+distance < GetCodeSize()); - m_bytecodes[pos+1].byte = offset; + _ASSERTE(pos+distance <= LastIp); + m_bytecodes[pos+1].byte = static_cast(offset); } break; @@ -1765,29 +1771,29 @@ void Compiler::FixupJump(int pos) #define MASK_BYTE(op) (op) #endif // Unconditional jump - _ASSERTE(!WantOptimize() || !isInNearJumpRange(distance,2)); // Why not optimized? - int offset = distance - 3; // IP inc'd for instruction, and extension bytes + _ASSERTE(!WantOptimize || !isInNearJumpRange(distance,2)); // Why not optimized? + ptrdiff_t offset = distance - 3; // IP inc'd for instruction, and extension bytes if (offset < MaxBackwardsLongJump || offset > MaxForwardsLongJump) { CompileError(CErrMethodTooLarge); } - _ASSERTE(pos+distance < GetCodeSize()); - m_bytecodes[pos+1].byte = BYTE(MASK_BYTE(offset)); - m_bytecodes[pos + 2].byte = BYTE(MASK_BYTE(offset >> 8)); + _ASSERTE(pos+distance <= LastIp); + m_bytecodes[pos+1].byte = static_cast(MASK_BYTE(offset)); + m_bytecodes[pos + 2].byte = static_cast(MASK_BYTE(offset >> 8)); } break; case BlockCopy: { // BlockCopy contains an implicit jump - int offset = distance - BlockCopyInstructionLength; // IP inc'd for instruction, and extension bytes + intptr_t offset = distance - BlockCopyInstructionLength; // IP inc'd for instruction, and extension bytes if (offset < MaxBackwardsLongJump || offset > MaxForwardsLongJump) { CompileError(CErrMethodTooLarge); } - _ASSERTE(pos+distance < GetCodeSize()); - m_bytecodes[pos + 5].byte = BYTE(MASK_BYTE(offset)); - m_bytecodes[pos + 6].byte = BYTE(MASK_BYTE(offset >> 8)); + _ASSERTE(pos+distance <= LastIp); + m_bytecodes[pos + 5].byte =static_cast(MASK_BYTE(offset)); + m_bytecodes[pos + 6].byte =static_cast(MASK_BYTE(offset >> 8)); } break; @@ -1808,19 +1814,19 @@ POTE Compiler::NewMethod() // Must do this before generate the bytecodes as the textmaps may be offset if packed VerifyTextMap(true); - if (!m_ok || WantSyntaxCheckOnly()) + if (!m_ok || WantSyntaxCheckOnly) return m_piVM->NilPointer(); int blockCount = Pass2(); - _ASSERTE(sizeof(STMethodHeader) == sizeof(MWORD)); - _ASSERTE(GetLiteralCount()<=LITERALLIMIT); + _ASSERTE(sizeof(STMethodHeader) == sizeof(uintptr_t)); + _ASSERTE(LiteralCount<=LITERALLIMIT); // As we keep the class of the method in the method, we no longer need to store the super // class as an extra literal STMethodHeader hdr; - *(MWORD*)&hdr = 0; + *(uintptr_t*)&hdr = 0; // Set the needsContext flag if any literal blocks (non-optimized) are used // within this method. @@ -1835,19 +1841,19 @@ POTE Compiler::NewMethod() // Need this in case we choose to gen some code m_pCurrentScope = pMethodScope; _ASSERTE(pMethodScope->GetCopiedTemps().size() == 0); - int numEnvTemps = pMethodScope->GetSharedTempsCount(); - bool bHasFarReturn = pMethodScope->HasFarReturn(); + tempcount_t numEnvTemps = pMethodScope->SharedTempsCount; + bool bHasFarReturn = pMethodScope->HasFarReturn; bool bNeedsContext = bHasFarReturn || numEnvTemps > 0; - BYTE byte1=m_bytecodes[0].byte; - BYTE byte2=Nop; - BYTE byte3=Nop; - int len = GetCodeSize(); + uint8_t byte0=m_bytecodes[ip_t::zero].byte; + uint8_t byte1=Nop; + uint8_t byte2=Nop; + size_t len = CodeSize; if (len > 1) { - byte2 = m_bytecodes[1].byte; + byte1 = m_bytecodes[ip_t::one].byte; if (len > 2) - byte3=m_bytecodes[2].byte; + byte2=m_bytecodes[ip_t::two].byte; } if (m_primitiveIndex!=0) @@ -1856,89 +1862,89 @@ POTE Compiler::NewMethod() // This is not a valid assertion, since primitive methods // can have any form of Smalltalk backup code //_ASSERTE(!hdr.m_needsContextFlag); - MakeQuickMethod(hdr, STPrimitives(m_primitiveIndex)); + MakeQuickMethod(hdr, static_cast(m_primitiveIndex)); //classRequired=true; } - else if (m_bytecodes[0].isPseudoReturn()) + else if (m_bytecodes[ip_t::zero].IsPseudoReturn) { //_ASSERTE(!bNeedsContext); Not a valid assertion, since could have a block after the return at the top // Primitive return of self, true, false, nil - MakeQuickMethod(hdr, STPrimitives(PRIMITIVE_RETURN_SELF + (byte1 - FirstPseudoReturn))); + MakeQuickMethod(hdr, static_cast(PRIMITIVE_RETURN_SELF + (byte0 - FirstPseudoReturn))); // We go ahead and generate the bytes anyway, as they'll fit in a SmallInteger and // may be of interest for debugging/browsing - _ASSERTE(GetCodeSize() < sizeof(MWORD)); + _ASSERTE(CodeSize < sizeof(uintptr_t)); } - else if (byte1 == ShortPushConst && byte2 == ReturnMessageStackTop) + else if (byte0 == ShortPushConst && byte1 == ReturnMessageStackTop) { // Primitive return of literal zero _ASSERTE(!bNeedsContext); - _ASSERTE(GetLiteralCount()>0); + _ASSERTE(LiteralCount>0); MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); // Note that in this case the literal may be a clean block, in which case the code size // may well be greater than will fit in a SmallInteger - // _ASSERTE(GetCodeSize() < sizeof(MWORD)); + // _ASSERTE(CodeSize < sizeof(uintptr_t)); } - else if (m_bytecodes[0].isShortPushConst() && byte2 == ReturnMessageStackTop && GetCodeSize() == 2) + else if (m_bytecodes[ip_t::zero].IsShortPushConst && byte1 == ReturnMessageStackTop && CodeSize == 2) { // Primitive return of literal zero from a ##() expression that generated literal frame entries _ASSERTE(!bNeedsContext); - _ASSERTE(GetLiteralCount()>1); - int index = m_bytecodes[0].indexOfShortPushConst(); + _ASSERTE(LiteralCount>1); + int index = m_bytecodes[ip_t::zero].indexOfShortPushConst(); Oop tmp = m_literalFrame[0]; m_literalFrame[0] = m_literalFrame[index]; m_literalFrame[index] = tmp; - m_bytecodes[0].byte = ShortPushConst; + m_bytecodes[ip_t::zero].byte = ShortPushConst; MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); } - else if (byte1 == ShortPushStatic && byte2 == ReturnMessageStackTop) + else if (byte0 == ShortPushStatic && byte1 == ReturnMessageStackTop) { // Primitive return of literal zero _ASSERTE(!bNeedsContext); - _ASSERTE(GetLiteralCount()>0); + _ASSERTE(LiteralCount>0); MakeQuickMethod(hdr, PRIMITIVE_RETURN_STATIC_ZERO); // Note that in this case the literal may be a clean block, in which case the code size // may well be greater than will fit in a SmallInteger - // _ASSERTE(GetCodeSize() < sizeof(MWORD)); + // _ASSERTE(CodeSize < sizeof(uintptr_t)); } - else if (m_bytecodes[0].isShortPushStatic() && byte2 == ReturnMessageStackTop && GetCodeSize() == 2) + else if (m_bytecodes[ip_t::zero].IsShortPushStatic && byte1 == ReturnMessageStackTop && CodeSize == 2) { // Primitive return of literal zero from a ##() expression that generated literal frame entries _ASSERTE(!bNeedsContext); - _ASSERTE(GetLiteralCount()>1); - int index = m_bytecodes[0].indexOfShortPushStatic(); + _ASSERTE(LiteralCount>1); + int index = m_bytecodes[ip_t::zero].indexOfShortPushStatic(); Oop tmp = m_literalFrame[0]; m_literalFrame[0] = m_literalFrame[index]; m_literalFrame[index] = tmp; - m_bytecodes[0].byte = ShortPushStatic; + m_bytecodes[ip_t::zero].byte = ShortPushStatic; MakeQuickMethod(hdr, PRIMITIVE_RETURN_STATIC_ZERO); } - else if (m_bytecodes[0].isShortPushInstVar() && byte2 == ReturnMessageStackTop && GetArgumentCount() == 0) + else if (m_bytecodes[ip_t::zero].IsShortPushInstVar && byte1 == ReturnMessageStackTop && ArgumentCount == 0) { // instance variable accessor method (<=15) _ASSERTE(!bNeedsContext); MakeQuickMethod(hdr, PRIMITIVE_RETURN_INSTVAR); // Convert to long form to simplify the interpreter's code to exec. this quick method. - byte2 = m_bytecodes[0].indexOfPushInstVar(); - m_bytecodes[0].byte = PushInstVar; - m_codePointer = 1; - GenData(byte2); + byte1 = m_bytecodes[ip_t::zero].indexOfPushInstVar(); + m_bytecodes[ip_t::zero].byte = PushInstVar; + m_codePointer = ip_t::one; + GenData(byte1); m_codePointer++; - byte3 = ReturnMessageStackTop; + byte2 = ReturnMessageStackTop; // We must adjust the debug info to account for the longer (two byte) first instruction //_ASSERTE(m_allScopes.size() == 1); Some inlined scopes may have been optimised away - _ASSERTE(pMethodScope->GetFinalIP() == 1); - pMethodScope->SetFinalIP(2); + _ASSERTE(pMethodScope->FinalIP == ip_t::one); + pMethodScope->FinalIP = ip_t::two; // We must go ahead and generate the bytes anyway as they are needed by the interpreter to // determine which inst. var to push (they'll fit in a SmallInteger anyway) - _ASSERTE(GetCodeSize() == 3); + _ASSERTE(CodeSize == 3); } - else if (isPushInstVarX(byte1, byte2) && byte3 == ReturnMessageStackTop && GetArgumentCount() == 0) + else if (isPushInstVarX(byte0, byte1) && byte2 == ReturnMessageStackTop && ArgumentCount == 0) { // instance variable accessor method (>15) _ASSERTE(!bNeedsContext); @@ -1946,17 +1952,17 @@ POTE Compiler::NewMethod() // We must go ahead and generate the bytes anyway as they are needed by the interpreter to // determine which inst. var to push (they'll fit in a SmallInteger anyway) - _ASSERTE(GetCodeSize() == 3); + _ASSERTE(CodeSize == 3); } - else if (byte2 == ReturnMessageStackTop && m_bytecodes[0].isShortPushImmediate()) + else if (byte1 == ReturnMessageStackTop && m_bytecodes[ip_t::zero].IsShortPushImmediate) { - _ASSERTE(GetCodeSize() == 2 || !WantOptimize()); - _ASSERTE(m_bytecodes[1].isOpCode()); + _ASSERTE(CodeSize == 2 || !WantOptimize); + _ASSERTE(m_bytecodes[ip_t::one].IsOpCode); MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); _ASSERTE(m_primitiveIndex == 0); - Oop literalInt = IntegerObjectOf(byte1-ShortPushMinusOne-1); - if (GetLiteralCount() > 0) + Oop literalInt = IntegerObjectOf(byte0-ShortPushMinusOne-1); + if (LiteralCount > 0) { m_literalFrame.push_back(m_literalFrame[0]); m_literalFrame[0] = literalInt; @@ -1964,14 +1970,14 @@ POTE Compiler::NewMethod() else AddToFrameUnconditional(literalInt, TEXTRANGE()); } - else if (byte1 == PushImmediate && byte3 == ReturnMessageStackTop) + else if (byte0 == PushImmediate && byte2 == ReturnMessageStackTop) { - _ASSERTE(GetCodeSize() == 3 || !WantOptimize()); - _ASSERTE(m_bytecodes[2].isOpCode()); + _ASSERTE(CodeSize == 3 || !WantOptimize); + _ASSERTE(m_bytecodes[ip_t::two].IsOpCode); MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); _ASSERTE(m_primitiveIndex == 0); - SBYTE immediateByte = SBYTE(byte2); - if (GetLiteralCount() > 0) + int8_t immediateByte = static_cast(byte1); + if (LiteralCount > 0) { m_literalFrame.push_back(m_literalFrame[0]); m_literalFrame[0] = IntegerObjectOf(immediateByte); @@ -1979,14 +1985,14 @@ POTE Compiler::NewMethod() else AddToFrameUnconditional(IntegerObjectOf(immediateByte), TEXTRANGE()); } - else if (byte1 == LongPushImmediate && m_bytecodes[3].byte == ReturnMessageStackTop) + else if (byte0 == LongPushImmediate && m_bytecodes[ip_t::three].byte == ReturnMessageStackTop) { - _ASSERTE(GetCodeSize() >= 4); - _ASSERTE(m_bytecodes[3].isOpCode()); + _ASSERTE(CodeSize >= 4); + _ASSERTE(m_bytecodes[ip_t::three].IsOpCode); MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); _ASSERTE(m_primitiveIndex == 0); - SWORD immediateWord = SWORD(byte3 << 8) + byte2; - if (GetLiteralCount() > 0) + int16_t immediateWord = static_cast(byte2 << 8) + byte1; + if (LiteralCount > 0) { m_literalFrame.push_back(m_literalFrame[0]); m_literalFrame[0] = IntegerObjectOf(immediateWord); @@ -1994,20 +2000,21 @@ POTE Compiler::NewMethod() else AddToFrameUnconditional(IntegerObjectOf(immediateWord), TEXTRANGE()); // We can save space by replacing the LongPushImmediate instruction with 2-byte argument with a single byte push const 0 - m_bytecodes[0].byte = ShortPushConst; - RemoveBytes(1, 2); + m_bytecodes[ip_t::zero].byte = ShortPushConst; + RemoveBytes(ip_t::one, 2); } - else if (byte1 == ExLongPushImmediate && m_bytecodes[ExLongPushImmediateInstructionSize].byte == ReturnMessageStackTop) + else if (byte0 == ExLongPushImmediate && m_bytecodes[static_cast(ExLongPushImmediateInstructionSize)].byte == ReturnMessageStackTop) { - _ASSERTE(GetCodeSize() >= 4); - _ASSERTE(m_bytecodes[ExLongPushImmediateInstructionSize].isOpCode()); + _ASSERTE(CodeSize >= 4); + const ip_t longPush = static_cast(ExLongPushImmediateInstructionSize); + _ASSERTE(m_bytecodes[longPush].IsOpCode); MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); _ASSERTE(m_primitiveIndex == 0); - SDWORD immediateValue = static_cast((m_bytecodes[ExLongPushImmediateInstructionSize-1].byte << 24) - | (m_bytecodes[ExLongPushImmediateInstructionSize - 2].byte << 16) - | (m_bytecodes[ExLongPushImmediateInstructionSize - 3].byte << 8) - | m_bytecodes[ExLongPushImmediateInstructionSize - 4].byte); - if (GetLiteralCount() > 0) + int32_t immediateValue = static_cast((m_bytecodes[longPush - 1].byte << 24) + | (m_bytecodes[longPush - 2].byte << 16) + | (m_bytecodes[longPush - 3].byte << 8) + | m_bytecodes[longPush - 4].byte); + if (LiteralCount > 0) { m_literalFrame.push_back(m_literalFrame[0]); m_literalFrame[0] = IntegerObjectOf(immediateValue); @@ -2015,17 +2022,17 @@ POTE Compiler::NewMethod() else AddToFrameUnconditional(IntegerObjectOf(immediateValue), TEXTRANGE()); // We can save space by replacing the ExLongPushImmediate instruction with 4-byte argument with a single byte push const 0 - m_bytecodes[0].byte = ShortPushConst; - RemoveBytes(1, ExLongPushImmediateInstructionSize-1); + m_bytecodes[ip_t::zero].byte = ShortPushConst; + RemoveBytes(ip_t::one, ExLongPushImmediateInstructionSize-1); } - else if (byte1 == PushChar && byte3 == ReturnMessageStackTop) + else if (byte0 == PushChar && byte2 == ReturnMessageStackTop) { - _ASSERTE(GetCodeSize() == 3 || !WantOptimize()); - _ASSERTE(m_bytecodes[2].isOpCode()); + _ASSERTE(CodeSize == 3 || !WantOptimize); + _ASSERTE(m_bytecodes[ip_t::two].IsOpCode); MakeQuickMethod(hdr, PRIMITIVE_RETURN_LITERAL_ZERO); _ASSERTE(m_primitiveIndex == 0); - Oop oopChar = reinterpret_cast(m_piVM->NewCharacter(byte2)); - if (GetLiteralCount() > 0) + Oop oopChar = reinterpret_cast(m_piVM->NewCharacter(byte1)); + if (LiteralCount > 0) { m_literalFrame.push_back(m_literalFrame[0]); m_literalFrame[0] = oopChar; @@ -2033,13 +2040,13 @@ POTE Compiler::NewMethod() else AddToFrameUnconditional(oopChar, TEXTRANGE()); } - else if ((byte1 == ShortPushTemp && GetArgumentCount() == 1 && GetCodeSize() <= sizeof(MWORD)) - && ((byte2 == PopStoreInstVar && m_bytecodes[3].byte == ReturnSelf) - ||(m_bytecodes[1].isShortPopStoreInstVar() && byte3 == ReturnSelf))) + else if ((byte0 == ShortPushTemp && ArgumentCount == 1 && CodeSize <= sizeof(uintptr_t)) + && ((byte1 == PopStoreInstVar && m_bytecodes[ip_t::three].byte == ReturnSelf) + ||(m_bytecodes[ip_t::one].IsShortPopStoreInstVar && byte2 == ReturnSelf))) { // instance variable set method _ASSERTE(!bNeedsContext); - _ASSERTE((byte1 & 1) != 0); // First must be odd, as VM assumes will be a packed method + _ASSERTE((byte0 & 1) != 0); // First must be odd, as VM assumes will be a packed method MakeQuickMethod(hdr, PRIMITIVE_SET_INSTVAR); @@ -2062,35 +2069,35 @@ POTE Compiler::NewMethod() hdr.envTempCount = numEnvTemps + 1; } - _ASSERTE(pMethodScope->GetStackSize() <= TEMPORARYLIMIT); - _ASSERTE(GetArgumentCount() <= ARGLIMIT); - hdr.stackTempCount = pMethodScope->GetStackTempCount(); - hdr.argumentCount = GetArgumentCount(); + _ASSERTE(pMethodScope->StackSize <= TEMPORARYLIMIT); + _ASSERTE(ArgumentCount <= ARGLIMIT); + hdr.stackTempCount = static_cast(pMethodScope->StackTempCount); + hdr.argumentCount = static_cast(ArgumentCount); // Allocate CompiledMethod and install the header - POTE method = NewCompiledMethod(m_compiledMethodClass, GetCodeSize(), hdr); + POTE method = NewCompiledMethod(m_compiledMethodClass, CodeSize, hdr); STCompiledMethod& cmpldMethod = *(STCompiledMethod*)GetObj(method); // May have been changed above - byte1 = m_bytecodes[0].byte; + byte0 = m_bytecodes[ip_t::zero].byte; // Install bytecodes - if (!WantDebugMethod() //&& blockCount == 0 - && (GetCodeSize() < sizeof(MWORD) - || (GetCodeSize() == sizeof(MWORD) && ((byte1 & 1) != 0)))) + if (!WantDebugMethod //&& blockCount == 0 + && (CodeSize < sizeof(uintptr_t) + || (CodeSize == sizeof(uintptr_t) && ((byte0 & 1) != 0)))) { Oop bytes = IntegerObjectOf(0); BYTE* pByteCodes = (BYTE*)&bytes; // IX86 is a little endian machine, so first must be odd for SmallInteger flag - if ((byte1 & 1) == 0) + if ((byte0 & 1) == 0) { *pByteCodes++ = Nop; // Must adjust the debug info maps to account for the leading Nop // Method scope expands for leading Nop - pMethodScope->SetFinalIP(pMethodScope->GetFinalIP() + 1); + pMethodScope->FinalIP = pMethodScope->FinalIP + 1; // Should only be here for 3 byte methods, so don't nested scopes are unlikely, but possible - const int count = m_allScopes.size(); - for (int i = 1; i < count; i++) + const size_t count = m_allScopes.size(); + for (size_t i = 1; i < count; i++) { LexicalScope* pScope = m_allScopes[i]; pScope->IncrementIPs(); @@ -2098,22 +2105,22 @@ POTE Compiler::NewMethod() // Adjust ip of any TextMaps { - const int loopEnd = m_textMaps.size(); - for (int i = 0; i < loopEnd; i++) + const size_t loopEnd = m_textMaps.size(); + for (size_t i = 0; i < loopEnd; i++) m_textMaps[i].ip++; } } - const int loopEnd = GetCodeSize(); - for (int i=0; i(i)].byte; m_piVM->StorePointerWithValue(&cmpldMethod.byteCodes, bytes); } else { BYTE* pByteCodes = FetchBytesOf(POTE(cmpldMethod.byteCodes)); - const int loopEnd = GetCodeSize(); - for (int i=0; i(i)] = m_bytecodes[i].byte; m_piVM->MakeImmutable(cmpldMethod.byteCodes, TRUE); } @@ -2122,22 +2129,22 @@ POTE Compiler::NewMethod() PatchCleanBlockLiterals(method); // Install literals - const int loopEnd = GetLiteralCount(); - for (int i=0; iStorePointerWithValue(&cmpldMethod.aLiterals[i], oopLiteral); } - m_piVM->StorePointerWithValue((Oop*)&cmpldMethod.selector, Oop(NewUtf8String(GetSelector()))); + m_piVM->StorePointerWithValue((Oop*)&cmpldMethod.selector, Oop(NewUtf8String(Selector))); m_piVM->StorePointerWithValue((Oop*)&cmpldMethod.methodClass, Oop(m_class)); #if defined(_DEBUG) { char buf[512]; wsprintf(buf, "Compiling %s>>%s for %s, %s\n", GetClassName().c_str(), m_selector.c_str(), - WantDebugMethod() ? "debug" : "release", m_ok ? "succeeded" : "failed"); + WantDebugMethod ? "debug" : "release", m_ok ? "succeeded" : "failed"); OutputDebugString(buf); if (m_ok && compilationTrace > 0) @@ -2158,11 +2165,11 @@ POTE Compiler::NewMethod() void Compiler::PatchCleanBlockLiterals(POTE oteMethod) { - const int count = m_allScopes.size(); - for (int i = 1; i < count; i++) + const size_t count = m_allScopes.size(); + for (size_t i = 1; i < count; i++) { LexicalScope* pScope = m_allScopes[i]; - if (pScope->IsCleanBlock()) + if (pScope->IsCleanBlock) { pScope->PatchBlockLiteral(m_piVM, oteMethod); } @@ -2191,7 +2198,7 @@ int Compiler::FixupTempsAndBlocks() LexicalScope* pScope = (*sit); pScope->CopyTemps(this); - if (!pScope->IsOptimizedBlock()) + if (!pScope->IsOptimizedBlock) { pScope->AllocTempIndices(this); } @@ -2223,9 +2230,9 @@ int Compiler::FixupTempsAndBlocks() // when copying temps. void Compiler::PatchOptimizedScopes() { - const int count = m_allScopes.size(); + const size_t count = m_allScopes.size(); _ASSERTE(count >= 1); - for (int i = 1; i < count; i++) + for (size_t i = 1; i < count; i++) { LexicalScope* pScope = m_allScopes[i]; pScope->PatchOptimized(this); @@ -2234,13 +2241,13 @@ void Compiler::PatchOptimizedScopes() void Compiler::DetermineTempUsage() { - const int count = GetCodeSize(); - for (int i = 0; i < count;) + const ip_t last = LastIp; + for (ip_t i = ip_t::zero; i <= last;) { const BYTECODE& bytecode1 = m_bytecodes[i]; - int len1 = bytecode1.instructionLength(); + size_t len1 = bytecode1.InstructionLength; - _ASSERTE(!bytecode1.isPushTemp()); + _ASSERTE(!bytecode1.IsPushTemp); switch(bytecode1.byte) { @@ -2268,14 +2275,14 @@ void Compiler::DetermineTempUsage() } } -int Compiler::FixupTempRefs() +unsigned Compiler::FixupTempRefs() { - int fixed=0; - const int count = GetCodeSize(); - for (int i = 0; i < count;) + unsigned fixed=0; + const ip_t last = LastIp; + for (ip_t i = ip_t::zero; i <= last;) { const BYTECODE& bytecode1 = m_bytecodes[i]; - const int len1 = bytecode1.instructionLength(); + const size_t len1 = bytecode1.InstructionLength; switch(bytecode1.byte) { @@ -2299,113 +2306,113 @@ int Compiler::FixupTempRefs() return fixed; } -void Compiler::FixupTempRef(int i) +void Compiler::FixupTempRef(ip_t i) { BYTECODE& byte1 = m_bytecodes[i]; BYTECODE& byte2 = m_bytecodes[i+1]; BYTECODE& byte3 = m_bytecodes[i+2]; - _ASSERTE(byte1.isOpCode()); - _ASSERTE(byte2.isData()); - _ASSERTE(byte3.isData()); + _ASSERTE(byte1.IsOpCode); + _ASSERTE(byte2.IsData); + _ASSERTE(byte3.IsData); TempVarRef* pVarRef = byte1.pVarRef; - _ASSERTE(pVarRef != NULL); - TempVarDecl* pDecl = pVarRef->GetDecl(); - int index = pDecl->GetIndex(); - _ASSERTE(index >= 0 && index < 255); + _ASSERTE(pVarRef != nullptr); + TempVarDecl* pDecl = pVarRef->Decl; + size_t index = pDecl->Index; + _ASSERTE(index != -1 && index < UINT8_MAX); // Temp refs should by now be pointing at real decls in unoptimized scopes - _ASSERTE(!pDecl->GetScope()->IsOptimizedBlock()); + _ASSERTE(!pDecl->Scope->IsOptimizedBlock); bool bIsPush = byte1.byte == LongPushOuterTemp; - TempVarType varType = pDecl->GetVarType(); + TempVarType varType = pDecl->VarType; switch(varType) { - case tvtCopy: - case tvtStack: - case tvtCopied: + case TempVarType::Copy: + case TempVarType::Stack: + case TempVarType::Copied: if (bIsPush) { if (index < NumShortPushTemps) { - byte1.byte = ShortPushTemp + index; + byte1.byte = ShortPushTemp + static_cast(index); byte2.makeNop(byte1.pScope); } else { byte1.byte = PushTemp; - byte2.byte = index; + byte2.byte = static_cast(index); } } else { if (index < NumShortStoreTemps) { - byte1.byte = ShortStoreTemp + index; + byte1.byte = ShortStoreTemp + static_cast(index); byte2.makeNop(byte1.pScope); } else { byte1.byte = StoreTemp; - byte2.byte = index; + byte2.byte = static_cast(index); } } byte3.makeNop(byte1.pScope); break; - case tvtShared: + case TempVarType::Shared: { - int outer = pVarRef->GetActualDistance(); - _ASSERTE(outer >= 0 && outer < 256); - TempVarDecl* pDecl = pVarRef->GetDecl(); - _ASSERTE(pDecl == pVarRef->GetDecl()->GetActualDecl()); + unsigned outer = pVarRef->GetActualDistance(); + _ASSERTE(outer <= UINT8_MAX); + TempVarDecl* pDecl = pVarRef->Decl; + _ASSERTE(pDecl == pVarRef->Decl->ActualDecl); if (outer > 0) - pVarRef->GetScope()->SetReferencesOuterTempsIn(pDecl->GetScope()); + pVarRef->Scope->SetReferencesOuterTempsIn(pDecl->Scope); - _ASSERTE(index < pDecl->GetScope()->GetSharedTempsCount()); + _ASSERTE(index < pDecl->Scope->SharedTempsCount); if (outer < 2 && index < NumPushContextTemps && bIsPush) { - byte1.byte = (outer == 0 ? ShortPushContextTemp : ShortPushOuterTemp) + index; + byte1.byte = (outer == 0 ? ShortPushContextTemp : ShortPushOuterTemp) + static_cast(index); byte2.makeNop(byte1.pScope); byte3.makeNop(byte1.pScope); } else if (outer <= OuterTempMaxDepth && index <= OuterTempMaxIndex) { byte1.byte = bIsPush ? PushOuterTemp : StoreOuterTemp; - byte2.byte = (outer << OuterTempIndexBits) | index; + byte2.byte = (outer << OuterTempIndexBits) | static_cast(index); byte3.makeNop(byte1.pScope); } else { byte2.byte = outer; - byte3.byte = index; + byte3.byte = static_cast(index); } } break; - case tvtUnaccessed: + case TempVarType::Unaccessed: default: { - TempVarDecl* pDecl = pVarRef->GetDecl(); - InternalError(__FILE__, __LINE__, pVarRef->GetTextRange(), + TempVarDecl* pDecl = pVarRef->Decl; + InternalError(__FILE__, __LINE__, pVarRef->TextRange, "Invalid temp variable state %d for '%s'", - pVarRef->GetVarType(), pVarRef->GetName().c_str()); + pVarRef->VarType, pVarRef->Name.c_str()); } break; }; } -int Compiler::PatchBlocks() +unsigned Compiler::PatchBlocks() { - int i=0; - int blockCount = 0; - while (i < GetCodeSize()) + ip_t i=ip_t::zero; + unsigned blockCount = 0; + while (i <= LastIp) { VerifyTextMap(true); - BYTECODE& bytecode1 = m_bytecodes[i]; - int len1 = bytecode1.instructionLength(); + const BYTECODE& bytecode1 = m_bytecodes[i]; + size_t len1 = bytecode1.InstructionLength; switch(bytecode1.byte) { @@ -2427,25 +2434,25 @@ int Compiler::PatchBlocks() // Push any copied values in reverse order for the block at the specified position in the bytecodes // Answers the number of extra bytes generated to push copied values. These are generated // before the block. -int Compiler::PatchBlockAt(int i) +size_t Compiler::PatchBlockAt(ip_t i) { BYTECODE& byte1 = m_bytecodes[i]; _ASSERTE(byte1.byte == BlockCopy); LexicalScope* pScope = byte1.pScope; - _ASSERTE(pScope != NULL); + _ASSERTE(pScope != nullptr); // Self and far return flags should have been propagated by now - _ASSERTE(!pScope->NeedsSelf() || pScope->GetOuter()->NeedsSelf()); - _ASSERTE(!pScope->HasFarReturn() || pScope->GetOuter()->HasFarReturn()); + _ASSERTE(!pScope->NeedsSelf || pScope->Outer->NeedsSelf); + _ASSERTE(!pScope->HasFarReturn || pScope->Outer->HasFarReturn); - if (pScope->IsCleanBlock()) + if (pScope->IsCleanBlock) { MakeCleanBlockAt(i); return 0; } // From now on we don't want this instruction to appear to be part of this block's scope - LexicalScope* pOuter = pScope->GetOuter(); - _ASSERTE(pOuter != NULL); + LexicalScope* pOuter = pScope->Outer; + _ASSERTE(pOuter != nullptr); byte1.pScope = pOuter; // BlockCopy @@ -2455,21 +2462,21 @@ int Compiler::PatchBlockAt(int i) // +4 nCopiedTemps // +5 jumpOffset1 // jumpOffset2 - _ASSERTE(m_bytecodes[i+1].byte == pScope->GetArgumentCount()); - m_bytecodes[i+2].byte = pScope->GetStackTempCount(); + _ASSERTE(m_bytecodes[i+1].byte == pScope->ArgumentCount); + m_bytecodes[i+2].byte = static_cast(pScope->StackTempCount); // Note that the env size includes the env temps and copied temps - int nEnvSize = pScope->GetSharedTempsCount(); - _ASSERTE(nEnvSize < 128); - int needsOuter = pScope->NeedsOuter(); - m_bytecodes[i+3].byte = (nEnvSize << 1) | needsOuter; + tempcount_t nEnvSize = pScope->SharedTempsCount; + _ASSERTE(nEnvSize <= INT8_MAX); + bool needsOuter = pScope->NeedsOuter; + m_bytecodes[i+3].byte = static_cast((nEnvSize << 1) | (needsOuter ? 1 : 0)); - int nCopied = pScope->GetCopiedValuesCount(); - _ASSERTE(nCopied < 128); - m_bytecodes[i+4].byte = (nCopied << 1) | (pScope->NeedsSelf() ?1:0); + tempcount_t nCopied = pScope->CopiedValuesCount; + _ASSERTE(nCopied <= INT8_MAX); + m_bytecodes[i+4].byte = static_cast((nCopied << 1) | (pScope->NeedsSelf ?1:0)); // This text map is needed by the Debugger to remap the initial IP of block frames. - int blockStart = pScope->GetTextRange().m_start; + textpos_t blockStart = pScope->TextRange.m_start; InsertTextMapEntry(i + BlockCopyInstructionLength, blockStart, blockStart-1); if (nCopied == 0) @@ -2478,48 +2485,49 @@ int Compiler::PatchBlockAt(int i) //////////////////////////////////////////////////////////////////////////////////////// // Generate push temp instructions for all values to be copied from enclosing scope // - _ASSERTE(m_codePointer == GetCodeSize()); - _ASSERTE(!byte1.isJumpTarget()); + _ASSERTE(m_codePointer == LastIp+1); + _ASSERTE(!byte1.IsJumpTarget); m_codePointer = i; - m_pCurrentScope = pOuter->GetRealScope(); + m_pCurrentScope = pOuter->RealScope; - int extraBytes = 0; + size_t extraBytes = 0; DECLLIST& copiedTemps = pScope->GetCopiedTemps(); const DECLLIST::reverse_iterator loopEnd = copiedTemps.rend(); for (DECLLIST::reverse_iterator it = copiedTemps.rbegin(); it != loopEnd; it++) { TempVarDecl* pCopy = (*it); - TempVarDecl* pCopyFrom = pCopy->GetOuter(); - _ASSERTE(pCopyFrom != NULL && !pCopyFrom->GetScope()->IsOptimizedBlock()); - if (pCopyFrom == NULL || pCopyFrom->GetScope() != m_pCurrentScope) - InternalError(__FILE__, __LINE__, pCopy->GetTextRange(), "Copied temp '%s' not found in outer scope", pCopy->GetName().c_str()); + TempVarDecl* pCopyFrom = pCopy->Outer; + _ASSERTE(pCopyFrom != nullptr && !pCopyFrom->Scope->IsOptimizedBlock); + if (pCopyFrom == nullptr || pCopyFrom->Scope != m_pCurrentScope) + InternalError(__FILE__, __LINE__, pCopy->TextRange, "Copied temp '%s' not found in outer scope", pCopy->Name.c_str()); // Its a copied value, so must be local to this environment extraBytes += GenPushCopiedValue(pCopyFrom); } - m_pCurrentScope = NULL; + m_pCurrentScope = nullptr; - m_codePointer = GetCodeSize(); + // TODO: Is this right? Looks to be off by one + m_codePointer = LastIp + 1; return extraBytes; } -void Compiler::MakeCleanBlockAt(int i) +void Compiler::MakeCleanBlockAt(ip_t i) { BYTECODE& byte1 = m_bytecodes[i]; - _ASSERTE(byte1.byte = BlockCopy); - _ASSERTE(byte1.instructionLength() == BlockCopyInstructionLength); - int initIP = i + BlockCopyInstructionLength; + _ASSERTE(byte1.byte == BlockCopy); + _ASSERTE(byte1.InstructionLength == BlockCopyInstructionLength); + ip_t initIP = i + BlockCopyInstructionLength; BYTECODE& firstInBlock = m_bytecodes[initIP]; - BYTECODE& secondInBlock = m_bytecodes[initIP + firstInBlock.instructionLength()]; + BYTECODE& secondInBlock = m_bytecodes[initIP + firstInBlock.InstructionLength]; LexicalScope* pScope = byte1.pScope; - _ASSERTE(pScope->IsBlock()); + _ASSERTE(pScope->IsBlock); - LexicalScope* pOuter = pScope->GetOuter(); - _ASSERTE(pOuter != NULL); + LexicalScope* pOuter = pScope->Outer; + _ASSERTE(pOuter != nullptr); byte1.pScope = pOuter; // If a Clean block, then we can patch out the block copy replacing it @@ -2527,16 +2535,16 @@ void Compiler::MakeCleanBlockAt(int i) // over the blocks bytecodes. const VMPointers& vmPointers = GetVMPointers(); - POTE blockPointer = WantDebugMethod() ? vmPointers.EmptyDebugBlock : vmPointers.EmptyBlock; - bool isEmptyBlock = pScope->IsEmptyBlock(); + POTE blockPointer = WantDebugMethod ? vmPointers.EmptyDebugBlock : vmPointers.EmptyBlock; + bool isEmptyBlock = pScope->IsEmptyBlock; bool useEmptyBlock = isEmptyBlock && blockPointer != Nil() // We don't want to generate empty block form for the empty block itself - && this->GetTextLength() != 2; + && this->TextLength != 2; if (useEmptyBlock) { - _ASSERTE(!firstInBlock.isJumpTarget()); - _ASSERTE(!secondInBlock.isJumpTarget()); + _ASSERTE(!firstInBlock.IsJumpTarget); + _ASSERTE(!secondInBlock.IsJumpTarget); } else { @@ -2549,24 +2557,24 @@ void Compiler::MakeCleanBlockAt(int i) pScope->SetCleanBlockLiteral(blockPointer); } - int index = AddToFrame(reinterpret_cast(blockPointer), pScope->GetTextRange()); + size_t index = AddToFrame(reinterpret_cast(blockPointer), pScope->TextRange); if (index < NumShortPushConsts) // In range of short instructions ? { - byte1.byte = ShortPushConst + index; + byte1.byte = ShortPushConst + static_cast(index); UngenData(i+1, byte1.pScope); UngenData(i+2, byte1.pScope); } - else if (index < 256) // In range of single extended instructions ? + else if (index <= UINT8_MAX) // In range of single extended instructions ? { byte1.byte = PushConst; - m_bytecodes[i+1].byte = index; + m_bytecodes[i+1].byte = static_cast(index); UngenData(i+2, byte1.pScope); } else { byte1.byte = LongPushConst; - m_bytecodes[i+1].byte = index & 0xFF; - m_bytecodes[i+2].byte = index >> 8; + m_bytecodes[i+1].byte = index & UINT8_MAX; + m_bytecodes[i+2].byte = (index >> 8) & UINT8_MAX; } // The block copy is no longer a jump, being replaced by byte 4 (or not at all if empty) @@ -2575,12 +2583,12 @@ void Compiler::MakeCleanBlockAt(int i) initIP = i; if (useEmptyBlock) { - int j=i+3; + ip_t j=i+3; for(;jGetTextRange().m_start; + textpos_t blockStart = pScope->TextRange.m_start; InsertTextMapEntry(initIP, blockStart, blockStart-1); } } diff --git a/Core/DolphinVM/Compiler/str.h b/Core/DolphinVM/Compiler/str.h index 5de6a8ee54..8a23522424 100644 --- a/Core/DolphinVM/Compiler/str.h +++ b/Core/DolphinVM/Compiler/str.h @@ -6,7 +6,7 @@ A simple String class (again) Now mapped onto the Standard Template Library string class (BSM, Sep 2002) */ #pragma once - +#include "EnumHelpers.h" #include typedef std::basic_string, std::allocator> Str; @@ -19,7 +19,7 @@ inline Str MakeString(IDolphin* piVM, const POTE stringPointer) else { _ASSERTE(IsAString(stringPointer)); - MWORD stringLen=FetchByteLengthOf(stringPointer); + size_t stringLen=FetchByteLengthOf(stringPointer); BYTE* bytes = FetchBytesOf(stringPointer); return Str((const uint8_t*)bytes, stringLen); } @@ -31,8 +31,8 @@ inline Str MakeString(IDolphin* piVM, const POTE stringPointer) // Expand this string to have (insert) for every occurence of (ch) inline void InsertStringFor(Str& str, const uint8_t* insert, uint8_t ch) { - unsigned i=0; - int insertlen = strlen((const char*)insert); + size_t i=0; + size_t insertlen = strlen((const char*)insert); while (i < str.size() && (i = str.find(ch, i)) != Str::npos) { str.replace(i, 1, insert, insertlen); @@ -40,19 +40,8 @@ inline void InsertStringFor(Str& str, const uint8_t* insert, uint8_t ch) } } -struct TEXTRANGE -{ - int m_start; - int m_stop; - - TEXTRANGE(int start=0, int stop=-1) : m_start(start), m_stop(stop) - {} - - int span() const { return m_stop - m_start + 1; } -}; - -inline std::wostream& operator<<(std::wostream& stream, const std::string& str) +inline std::wostream& operator<<(std::wostream& stream, const Str& str) { USES_CONVERSION; - return stream << static_cast(A2W(str.c_str())); + return stream << static_cast(A2W(reinterpret_cast(str.c_str()))); } diff --git a/Core/DolphinVM/DolphinSmalltalk.idl b/Core/DolphinVM/DolphinSmalltalk.idl index f2a65ede91..9bfcc18b4b 100644 --- a/Core/DolphinVM/DolphinSmalltalk.idl +++ b/Core/DolphinVM/DolphinSmalltalk.idl @@ -13,16 +13,31 @@ import "ocidl.idl"; //typedef unsigned int *PUINT; //#include "winver.h" -typedef signed char SBYTE; -typedef unsigned char BYTE; -typedef short SWORD; -typedef long SDWORD; -typedef SDWORD NTSTATUS; - -typedef UINT_PTR MWORD; +// Unfortunately we can't include stdint.h without getting a lot of errors from definitions we don't need +//#define _VCRUNTIME_H +//#include + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; + +#ifdef _M_X64 +typedef int64_t intptr_t; +typedef uint64_t uintptr_t; +#else +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +#endif + +// SDWORD is used in the definition of the original Dolphin COM interfaces. We can't change this now. +typedef int32_t SDWORD; cpp_quote("#if !defined(POTE_DEFINED)") -typedef MWORD Oop; +typedef uintptr_t Oop; typedef void* POTE; cpp_quote("#define POTE_DEFINED") cpp_quote("#endif") @@ -221,6 +236,15 @@ library DolphinVM POTE NewUtf8String([in]LPCSTR szValue, [in, defaultvalue(-1)]int len); }; + cpp_quote("#ifndef INTPTR_MAX") + cpp_quote("#define DEFINED_INTPTR_MAX") +#ifdef _M_X64 + cpp_quote("#define INTPTR_MAX 9223372036854775807i64") +#else + cpp_quote("#define INTPTR_MAX 2147483647i32") +#endif + cpp_quote("#endif") + // Please do not rely on any of the internal representation exposed by these inline // functions, as it may change in future. cpp_quote("__inline STVarObject* GetObj(POTE ote)") @@ -233,18 +257,18 @@ library DolphinVM cpp_quote(" return objectPointer & 1;") cpp_quote("}") - cpp_quote("__inline SDWORD IntegerValueOf(Oop objectPointer)") + cpp_quote("__inline intptr_t IntegerValueOf(Oop objectPointer)") cpp_quote("{") cpp_quote(" // Use cast to ensure shift is signed arithmetic") - cpp_quote(" return ((SDWORD)(objectPointer)) >> 1;") + cpp_quote(" return ((intptr_t)(objectPointer)) >> 1;") cpp_quote("}") - cpp_quote("__inline Oop IntegerObjectOf(SDWORD value) ") + cpp_quote("__inline Oop IntegerObjectOf(intptr_t value) ") cpp_quote("{") cpp_quote(" return (Oop)(((value) << 1) | 1);") cpp_quote("}") - cpp_quote("__inline BOOL IsIntegerValue(SDWORD valueWord)") + cpp_quote("__inline BOOL IsIntegerValue(intptr_t valueWord)") cpp_quote("{") cpp_quote(" return (valueWord >= MinSmallInteger && valueWord <= MaxSmallInteger);") cpp_quote("}") @@ -255,21 +279,26 @@ library DolphinVM cpp_quote(" return pObj->fields;") cpp_quote("}") - cpp_quote("__inline MWORD FetchByteLengthOf(POTE ote)") + cpp_quote("__inline size_t FetchByteLengthOf(POTE ote)") cpp_quote("{") - cpp_quote(" return (((MWORD*)ote)[2]) & 0x7FFFFFFF;") + cpp_quote(" return (((size_t*)ote)[2]) & INTPTR_MAX;") cpp_quote("}") - cpp_quote("__inline MWORD FetchWordLengthOf(POTE ote)") + cpp_quote("__inline size_t FetchWordLengthOf(POTE ote)") cpp_quote("{") - cpp_quote(" return FetchByteLengthOf(ote)/sizeof(MWORD);") + cpp_quote(" return FetchByteLengthOf(ote)/sizeof(uintptr_t);") cpp_quote("}") cpp_quote("__inline BOOL IsAString(const POTE ote)") cpp_quote("{") - cpp_quote(" return (((MWORD*)ote)[3] & 0x12) == 0x10;") + cpp_quote(" return (((uintptr_t*)ote)[3] & 0x12) == 0x10;") cpp_quote("}") + cpp_quote("#ifdef DEFINED_INTPTR_MAX") + cpp_quote(" #undef INTPTR_MAX") + cpp_quote(" #undef DEFINED_INTPTR_MAX") + cpp_quote("#endif") + [ object, uuid(B7EEF77A-71B9-11D3-97BC-0080C8D59432), @@ -406,3 +435,4 @@ library DolphinVM interface IDolphinStart; }; }; + diff --git a/Core/DolphinVM/DolphinX.h b/Core/DolphinVM/DolphinX.h index 377b2b32b0..5911578a4d 100644 --- a/Core/DolphinVM/DolphinX.h +++ b/Core/DolphinVM/DolphinX.h @@ -9,45 +9,45 @@ namespace DolphinX { enum { LibCallArgArray }; // External call primitives - enum { CallbackPrim=0, VirtualCallPrim=80, AsyncLibCallPrim=48, LibCallPrim=96 }; + enum class ExtCallPrimitive : uint8_t { Callback=0, VirtualCall=80, AsyncLibCall=48, LibCall=96 }; // Calling conventions (fastcall not supported) - enum ExtCallDeclSpecs { ExtCallStdCall, ExtCallCDecl, ExtCallThisCall, ExtCallFastCall, NumCallConventions }; + enum class ExtCallDeclSpec : uint8_t { StdCall, CDecl, ThisCall, FastCall, NumCallConventions }; // Argument types // Note that differentiation between signed and unsigned types is only // really relevant to return values if using SmallIntegers // VOID is only supported as a return type - enum ExtCallArgTypes { - ExtCallArgVOID =0, - ExtCallArgLPVOID, //1 - ExtCallArgCHAR, //2 - ExtCallArgBYTE, //3 - ExtCallArgSBYTE, //4 - ExtCallArgWORD, //5 - ExtCallArgSWORD, //6 - ExtCallArgDWORD, //7 - ExtCallArgSDWORD, //8 - ExtCallArgBOOL, //9 - ExtCallArgHANDLE, //10 - ExtCallArgDOUBLE, //11 - ExtCallArgLPSTR, //12 - ExtCallArgOOP, //13 - ExtCallArgFLOAT, //14 - ExtCallArgLPPVOID, //15 - ExtCallArgHRESULT, //16 - ExtCallArgLPWSTR, //17 OLECHAR*, Unicode string - ExtCallArgQWORD, //18 Unsigned 64-bit LARGE_INTEGER - ExtCallArgSQWORD, //19 Signed 64-bit LARGE_INTEGER - ExtCallArgOTE, //20 Same as Oop, but disallows immediate objects - ExtCallArgBSTR, //21 VB String - ExtCallArgVARIANT, //22 VB Variant type - ExtCallArgDATE, //23 VB Date type - ExtCallArgVARBOOL, //24 VB Boolean type - ExtCallArgGUID, //25 GUID (128-bit unique number) - ExtCallArgUINTPTR, //26 - ExtCallArgINTPTR, //27 - ExtCallArgNTSTATUS, //28 + enum class ExtCallArgType : uint8_t { + Void =0, + LPVoid, //1 + Char, //2 + UInt8, //3 + Int8, //4 + UInt16, //5 + Int16, //6 + UInt32, //7 + Int32, //8 + Bool, //9 + Handle, //10 + Double, //11 + LPStr, //12 + Oop, //13 + Float, //14 + LPPVoid, //15 + HResult, //16 + LPWStr, //17 OLECHAR*, Unicode string + UInt64, //18 Unsigned 64-bit LARGE_INTEGER + Int64, //19 Signed 64-bit LARGE_INTEGER + Ote, //20 Same as Oop, but disallows immediate objects + Bstr, //21 VB String + Variant, //22 VB Variant type + Date, //23 VB Date type + VarBool, //24 VB Boolean type + Guid, //25 GUID (128-bit unique number) + UIntPtr, //26 + IntPtr, //27 + NTStatus, //28 //29 //30 //31 @@ -69,12 +69,12 @@ namespace DolphinX { //47 //48 //49 - ExtCallArgSTRUCT=50, //50 Was 26 - ExtCallArgSTRUCT4, //51 Was 27 - ExtCallArgSTRUCT8, //52 Was 28 - ExtCallArgLP, //53 Was 29 - ExtCallArgLPP, //54 Was 30 - ExtCallArgCOMPTR, //55 Was 31 + Struct=50, //50 Was 26 + Struct32, //51 Was 27 + Struct64, //52 Was 28 + LPStruct, //53 Was 29 + LPPStruct, //54 Was 30 + ComPtr, //55 Was 31 ExtCallArgMax=63 }; @@ -86,11 +86,11 @@ namespace DolphinX { struct CallDescriptor { - BYTE m_callConv; - BYTE m_argsLen; - BYTE m_returnParm; - BYTE m_return; - BYTE m_args[]; + uint8_t m_callConv; + uint8_t m_argsLen; + uint8_t m_returnParm; + uint8_t m_return; + uint8_t m_args[]; }; struct ExternalMethodDescriptor diff --git a/Core/DolphinVM/EnumHelpers.h b/Core/DolphinVM/EnumHelpers.h new file mode 100644 index 0000000000..0038055124 --- /dev/null +++ b/Core/DolphinVM/EnumHelpers.h @@ -0,0 +1,133 @@ +#pragma once + +template struct EnableBitOperators : std::false_type { }; + +template +typename std::enable_if::value, T>::type +operator |(const T lhs, const T rhs) +{ + using underlying = typename std::underlying_type::type; + return static_cast ( + static_cast(lhs) | + static_cast(rhs) + ); +} + +template +typename std::enable_if::value, T>::type +operator &(const T lhs, const T rhs) +{ + using underlying = typename std::underlying_type::type; + return static_cast ( + static_cast(lhs) & + static_cast(rhs) + ); +} + +template +typename std::enable_if::value, T>::type +operator ~(const T rhs) +{ + using underlying = typename std::underlying_type::type; + return static_cast ( + ~static_cast(rhs) + ); +} + +template +typename std::enable_if::value, bool>::type +operator !(const T rhs) +{ + using underlying = typename std::underlying_type::type; + return static_cast(rhs) == 0; +} + +#define ENABLE_BITMASK_OPERATORS(x) \ + template<> struct EnableBitOperators : std::true_type { }; + +/////////////////////////////////////////////////////////////////////////////// +// Integer types +// + +template struct EnableIntOperators : std::false_type { }; + +// operator++() - prefix +template +typename std::enable_if::value, T>::type +operator++(T& x) +{ + using underlying = typename std::underlying_type::type; + return x = static_cast(static_cast(x) + 1); +} + +// operator++(int) - postfix +template +typename std::enable_if::value, T>::type +operator++(T& x, int) +{ + using underlying = typename std::underlying_type::type; + T current = x; + x = static_cast(static_cast(x) + 1); + return current; +} + +template +typename std::enable_if::value, T>::type& +operator--(T& x) +{ + _ASSERTE(x > T::npos); + using underlying = typename std::underlying_type::type; + auto r = static_cast(x) - 1; + return x = static_cast(r); +} + +template +typename std::enable_if::value, T>::type& +operator--(T& x, int) +{ + _ASSERTE(x > T::npos); + using underlying = typename std::underlying_type::type; + T current = x; + auto r = static_cast(x) - 1; + x = static_cast(r); + return current; +} + +template +typename std::enable_if::value, T>::type& +operator+=(T& x, const I offset) +{ + using underlying = typename std::underlying_type::type; + return x = static_cast(static_cast(x) + offset); +} + +template +typename std::enable_if::value, T>::type& +operator-=(T& x, const I offset) +{ + using underlying = typename std::underlying_type::type; + underlying r = static_cast(x) - offset; + _ASSERTE(r >= static_cast(T::npos)); + return x = static_cast(r); +} + +template +const typename std::enable_if::value, T>::type +operator+(const T x, const I y) +{ + using underlying = typename std::underlying_type::type; + return static_cast(static_cast(x) + static_cast(y)); +} + +template +const typename std::enable_if::value, T>::type +operator-(const T x, const I y) +{ + using underlying = typename std::underlying_type::type; + underlying r = static_cast(x) - static_cast(y); + _ASSERTE(r >= static_cast(T::npos)); + return static_cast(r); +} + +#define ENABLE_INT_OPERATORS(x) \ + template<> struct EnableIntOperators : std::true_type { }; diff --git a/Core/DolphinVM/InProcStub/StdAfx.h b/Core/DolphinVM/InProcStub/StdAfx.h index cd580ab5ef..a9affb0e60 100644 --- a/Core/DolphinVM/InProcStub/StdAfx.h +++ b/Core/DolphinVM/InProcStub/StdAfx.h @@ -13,8 +13,10 @@ #define _ATL_DEBUG_INTERFACES #endif +#include + #define UMDF_USING_NTSTATUS -typedef long NTSTATUS; +typedef int32_t NTSTATUS; #include #include diff --git a/Core/DolphinVM/InProcToGo/StdAfx.h b/Core/DolphinVM/InProcToGo/StdAfx.h index cd580ab5ef..a9affb0e60 100644 --- a/Core/DolphinVM/InProcToGo/StdAfx.h +++ b/Core/DolphinVM/InProcToGo/StdAfx.h @@ -13,8 +13,10 @@ #define _ATL_DEBUG_INTERFACES #endif +#include + #define UMDF_USING_NTSTATUS -typedef long NTSTATUS; +typedef int32_t NTSTATUS; #include #include diff --git a/Core/DolphinVM/STMethodHeader.h b/Core/DolphinVM/STMethodHeader.h index 85e57bb513..6e89e85b9d 100644 --- a/Core/DolphinVM/STMethodHeader.h +++ b/Core/DolphinVM/STMethodHeader.h @@ -28,10 +28,10 @@ typedef enum { typedef struct STMethodHeader { - BYTE isInt : 1; // MUST be 1 (to avoid treatment as object) - BYTE isPrivate : 1; - BYTE envTempCount : 6; // Note that this is actually count+1 - BYTE stackTempCount; - BYTE argumentCount; - BYTE primitiveIndex; + uint8_t isInt : 1; // MUST be 1 (to avoid treatment as object) + uint8_t isPrivate : 1; + uint8_t envTempCount : 6; // Note that this is actually count+1 + uint8_t stackTempCount; + uint8_t argumentCount; + uint8_t primitiveIndex; } STMethodHeader; diff --git a/Core/DolphinVM/decode.cpp b/Core/DolphinVM/decode.cpp index f3f5c94344..c47c3e3265 100755 --- a/Core/DolphinVM/decode.cpp +++ b/Core/DolphinVM/decode.cpp @@ -63,6 +63,14 @@ static void printChars(wostream& stream, const char16_t* pwsz, size_t len) // stream.unlock(); } + +std::wostream& __stdcall operator<<(std::wostream& stream, const std::string& str) +{ + Utf16StringBuf buf(CP_UTF8, str.c_str(), str.size()); + printChars(stream, buf, buf.Count); + return stream; +} + // Helper to dump characters to the tracestream // Unprintable characters are printed in hex wostream& operator<<(wostream& stream, const StringOTE* oteChars) @@ -246,19 +254,19 @@ wostream& operator<<(wostream& st, const LargeIntegerOTE* ote) LargeInteger* li = ote->m_location; st << L"a LargeInteger(" << std::hex << setfill(L'0'); - const int size = ote->getWordSize(); + const size_t size = ote->getWordSize(); if (size < MaxWords) { - for (int i = size - 1; i >= 0; i--) + for (ptrdiff_t i = size - 1; i >= 0; i--) st << setw(8) << li->m_digits[i] << L' '; } else { // Dump only the top and bottom 10 words with middle ellipsis - for (int i = size - 1; i >= size - (MaxWords/2); i--) + for (size_t i = size - 1; i >= size - (MaxWords/2); i--) st << setw(8) << li->m_digits[i] << L' '; st << L"... "; - for (int i = (MaxWords/2)-1; i >= 0; i--) + for (ptrdiff_t i = (MaxWords/2)-1; i >= 0; i--) st << setw(8) << li->m_digits[i] << L' '; } @@ -327,7 +335,7 @@ wostream& operator<<(wostream& st, const CharOTE* ote) st << L'$'; SMALLINTEGER code = ObjectMemoryIntegerValueOf(ch->m_code); - MWORD codeUnit = code & 0xffffff; + char32_t codeUnit = code & 0xffffff; if (__isascii(codeUnit)) { if (isgraph(codeUnit)) @@ -341,17 +349,17 @@ wostream& operator<<(wostream& st, const CharOTE* ote) { case StringEncoding::Ansi: { - MWORD codePoint = Interpreter::m_ansiToUnicodeCharMap[code & 0xFF]; + char16_t codePoint = Interpreter::m_ansiToUnicodeCharMap[codeUnit & 0xff]; if (iswgraph(codePoint)) { - return st << static_cast(codePoint); + return st << static_cast(codePoint); } break; } case StringEncoding::Utf16: - if (iswgraph(codeUnit)) + if (iswgraph(static_cast(codeUnit))) { - return st << static_cast(codeUnit); + return st << static_cast(codeUnit); } break; @@ -359,9 +367,9 @@ wostream& operator<<(wostream& st, const CharOTE* ote) break; case StringEncoding::Utf32: - if (U_IS_BMP(codeUnit) && iswgraph(codeUnit)) + if (U_IS_BMP(codeUnit) && iswgraph(static_cast(codeUnit))) { - return st << static_cast(codeUnit); + return st << static_cast(codeUnit); } break; @@ -409,7 +417,7 @@ wostream& operator<<(wostream& st, const HandleOTE* ote) wostream& operator<<(wostream& st, const ArrayOTE* ote) { if (ote->isNil()) return st << L"nil"; - int size = ote->pointersSize(); + size_t size = ote->pointersSize(); st << L"#("; if (size > 0) { @@ -418,9 +426,9 @@ wostream& operator<<(wostream& st, const ArrayOTE* ote) return st << L"***Bad Array: " << (void*)array; else { - int size = ote->pointersSize(); - int end = min(40, size); - for (int i = 0; i < end; i++) + size_t size = ote->pointersSize(); + size_t end = min(40, size); + for (size_t i = 0; i < end; i++) st << reinterpret_cast(array->m_elements[i]) << L" "; if (end < size) st << L"..."; @@ -629,14 +637,14 @@ static void DumpIP(BYTE* ip, CompiledMethod* pMethod, wostream& logStream) } else { - int offsetFromBeginningOfByteCodesObject = ip - ObjectMemory::ByteAddressOfObject(pMethod->m_byteCodes); + ptrdiff_t offsetFromBeginningOfByteCodesObject = ip - ObjectMemory::ByteAddressOfObject(pMethod->m_byteCodes); logStream << LPVOID(ip) << L" (" << std::dec << offsetFromBeginningOfByteCodesObject << L')'; } } logStream << std::endl; } -static void DumpStack(Oop* sp, Process* pProcess, wostream& logStream, unsigned nDepth) +static void DumpStack(Oop* sp, Process* pProcess, wostream& logStream, size_t nDepth) { if (IsBadReadPtr(sp, sizeof(Oop))) logStream << L"***Bad stack pointer: " << PVOID(sp) << std::endl; @@ -650,11 +658,11 @@ static void DumpStack(Oop* sp, Process* pProcess, wostream& logStream, unsigned else { // A short stack trace - unsigned i = 0; - unsigned nSlots = sp - pProcess->m_stack; - if (nSlots > nDepth) + size_t i = 0; + ptrdiff_t nSlots = sp - pProcess->m_stack; + if (static_cast(nSlots) > nDepth) { - unsigned nHalfDepth = nDepth / 2; + size_t nHalfDepth = nDepth / 2; while (sp >= pProcess->m_stack && i < nHalfDepth) { DumpStackEntry(sp, pProcess, logStream); @@ -674,11 +682,13 @@ static void DumpStack(Oop* sp, Process* pProcess, wostream& logStream, unsigned } } else + { while (sp >= pProcess->m_stack) { DumpStackEntry(sp, pProcess, logStream); sp--; } + } logStream << L"" << std::endl; } @@ -698,7 +708,7 @@ static void DumpBP(Oop* bp, Process* pProcess, wostream& logStream) } else { - int index = pProcess->indexOfSP(bp); + SMALLUNSIGNED index = pProcess->indexOfSP(bp); logStream << bp << L" (" << std::dec << index << L')'; } } @@ -714,7 +724,7 @@ wostream& operator<<(wostream& stream, StackFrame *pFrame) Oop* bp = pFrame->basePointer(); MethodOTE* oteMethod = pFrame->m_method; CompiledMethod* method = oteMethod->m_location; - int ip = ObjectMemoryIntegerValueOf(pFrame->m_ip); + SMALLINTEGER ip = ObjectMemoryIntegerValueOf(pFrame->m_ip); if (ip != 0) ip += isIntegerObject(method->m_byteCodes) ? 1 : -(int(ObjectByteSize) - 1); @@ -787,7 +797,7 @@ wostream& operator<<(wostream& stream, StackFrame *pFrame) if (ctx != NULL) { - const unsigned envTempCount = oteContext->pointersSize() - Context::FixedSize; + const size_t envTempCount = oteContext->pointersSize() - Context::FixedSize; for (i = 0; i < envTempCount; i++) stream << L" env temp[" << std::dec << i << L"]: " << reinterpret_cast(ctx->m_tempFrame[i]) << std::endl; } @@ -1006,7 +1016,7 @@ void AppendAllInstVarNames(ClassDescriptionOTE* oteClass, std::vector& i { ArrayOTE* oteNamesArray = pClass->m_instanceVariables; Array* pNames = oteNamesArray->m_location; - for (MWORD i = 0; i < oteNamesArray->pointersSize(); i++) + for (size_t i = 0; i < oteNamesArray->pointersSize(); i++) { // TODO: Use Utf8String _ASSERTE(ObjectMemory::isKindOf(pNames->m_elements[i], Pointers.ClassAnsiString)); @@ -1065,7 +1075,7 @@ class DisassemblyContext private: CompiledMethod* method; - unsigned cBytes; + size_t cBytes; BYTE* pBytes; Oop* literalFrame; vector instVarNames; @@ -1095,7 +1105,7 @@ void Interpreter::decodeMethod(CompiledMethod* method, wostream* pstream) stream << std::endl; DisassemblyContext info(method); - BytecodeDisassembler disassembler(info); + BytecodeDisassembler disassembler(info); const size_t size = ObjectMemoryIsIntegerObject(method->m_byteCodes) ? sizeof(SMALLINTEGER) @@ -1111,7 +1121,7 @@ void Interpreter::decodeMethod(CompiledMethod* method, wostream* pstream) void Interpreter::decodeMethodAt(CompiledMethod* method, unsigned ip, wostream& stream) { DisassemblyContext info(method); - BytecodeDisassembler disassembler(info); + BytecodeDisassembler disassembler(info); disassembler.DisassembleAt(ip, stream); stream.flush(); } @@ -1149,7 +1159,7 @@ void Interpreter::checkStack(Oop* sp) */ if (abs(executionTrace) > 3) { ProcessOTE* oteActive = m_registers.m_oteActiveProcess; - MWORD size = oteActive->getSize(); + size_t size = oteActive->getSize(); m_registers.ResizeProcess(); ObjectMemory::checkReferences(); oteActive->setSize(size); diff --git a/Core/DolphinVM/disassembler.h b/Core/DolphinVM/disassembler.h index a43995e2c9..a7a501450e 100644 --- a/Core/DolphinVM/disassembler.h +++ b/Core/DolphinVM/disassembler.h @@ -8,9 +8,9 @@ enum JumpType { Jump, JumpIfTrue, JumpIfFalse, JumpIfNil, JumpIfNotNil }; #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif -std::wostream& operator<<(std::wostream& stream, const std::string& str); +std::wostream& __stdcall operator<<(std::wostream& stream, const std::string& str); -template class BytecodeDisassembler +template class BytecodeDisassembler { T& context; public: @@ -19,7 +19,7 @@ template class BytecodeDisassembler {} //void Disassemble(T context, std::wostream& stream); - size_t DisassembleAt(size_t ip, std::wostream& stream) + size_t DisassembleAt(I ip, std::wostream& stream) { EmitIp(ip, stream); size_t len = EmitRawBytes(ip, stream); @@ -31,25 +31,25 @@ template class BytecodeDisassembler size_t GetCodeSize() { return context.GetCodeSize(); } - BYTE GetBytecode(size_t ip) { + uint8_t GetBytecode(I ip) { return context.GetBytecode(ip); } public: - void EmitIp(size_t ip, std::wostream& stream) + void EmitIp(I ip, std::wostream& stream) { // Print one-based ip as this is how they are disassembled in the image - stream << std::dec << setw(5) << (ip + 1) << L":"; + stream << std::dec << setw(5) << static_cast(ip + 1) << L":"; } - size_t EmitRawBytes(size_t ip, std::wostream& stream) + size_t EmitRawBytes(I ip, std::wostream& stream) { - int len = lengthOfByteCode(GetBytecode(ip)); + size_t len = lengthOfByteCode(GetBytecode(ip)); stream << std::hex << uppercase << setfill(L'0'); - int j; + size_t j; for (j = 0; j < min(len, 3); j++) { - stream << L' ' << setw(2) << static_cast(GetBytecode(ip + j)); + stream << L' ' << setw(2) << static_cast(GetBytecode(ip + j)); } if (len > 3) { @@ -64,9 +64,9 @@ template class BytecodeDisassembler return len; } - void BytecodeDisassembler::EmitDecodedInstructionAt(size_t ip, std::wostream& stream) + void BytecodeDisassembler::EmitDecodedInstructionAt(I ip, std::wostream& stream) { - const BYTE opcode = GetBytecode(ip); + const uint8_t opcode = GetBytecode(ip); switch (opcode) { @@ -307,8 +307,8 @@ template class BytecodeDisassembler case ShortJump + 6: case ShortJump + 7: { - BYTE offset = opcode - ShortJump; - PrintJumpInstruction(ip, stream, Jump, offset, offset + ip + 1 + 1); + int8_t offset = opcode - ShortJump; + PrintJumpInstruction(ip, stream, Jump, offset, offset + static_cast(ip) + 1 + 1); } break; @@ -321,8 +321,8 @@ template class BytecodeDisassembler case ShortJumpIfFalse + 6: case ShortJumpIfFalse + 7: { - BYTE offset = opcode - ShortJumpIfFalse; - PrintJumpInstruction(ip, stream, JumpIfFalse, offset, offset + ip + 1 + 1); + int8_t offset = opcode - ShortJumpIfFalse; + PrintJumpInstruction(ip, stream, JumpIfFalse, offset, offset + static_cast(ip) + 1 + 1); } break; @@ -355,11 +355,10 @@ template class BytecodeDisassembler case ShortSpecialSend + 26: case ShortSpecialSend + 27: case ShortSpecialSend + 28: - case ShortSpecialSend + 29: case ShortSpecialSend + 30: case ShortSpecialSend + 31: { - stream << L"Special Send #" << context.GetSpecialSelector(opcode - ShortSpecialSend).c_str(); + stream << L"Special Send #" << context.GetSpecialSelector(opcode - ShortSpecialSend); } break; @@ -439,7 +438,7 @@ template class BytecodeDisassembler case PushOuterTemp: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); stream << L"Push Outer[" << std::dec << static_cast(operand >> 5); PrintTempInstruction(ip, stream, "]", (operand & 0x1F)); } @@ -463,7 +462,7 @@ template class BytecodeDisassembler case StoreOuterTemp: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); stream << L"Store Outer[" << std::dec << static_cast(operand >> 5); PrintTempInstruction(ip, stream, "]", (operand & 0x1F)); } @@ -483,7 +482,7 @@ template class BytecodeDisassembler case PopStoreOuterTemp: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); stream << L"Pop Outer[" << std::dec << static_cast(operand >> 5); PrintTempInstruction(ip, stream, "]", operand & 0x1F); } @@ -494,7 +493,7 @@ template class BytecodeDisassembler break; case PushImmediate: - PrintPushImmediate(ip, stream, static_cast(GetBytecode(ip + 1)), 1); + PrintPushImmediate(ip, stream, static_cast(GetBytecode(ip + 1)), 1); break; case PushChar: @@ -503,14 +502,14 @@ template class BytecodeDisassembler case Send: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); PrintSendInstruction(ip, stream, operand & SendXMaxLiteral, operand >> SendXLiteralBits); } break; case Supersend: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); stream << L"Super "; PrintSendInstruction(ip, stream, operand & SendXMaxLiteral, operand >> SendXLiteralBits); } @@ -522,14 +521,14 @@ template class BytecodeDisassembler case NearJumpIfNil: case NearJumpIfNotNil: { - SBYTE offset = static_cast(GetBytecode(ip + 1)); - PrintJumpInstruction(ip, stream, (JumpType)(opcode - NearJump), offset, ip + offset + 2); + int8_t offset = static_cast(GetBytecode(ip + 1)); + PrintJumpInstruction(ip, stream, (JumpType)(opcode - NearJump), offset, static_cast(ip) + offset + 2); } break; case SendTempWithNoArgs: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); PrintTempInstruction(ip, stream, "Push", operand >> SendXLiteralBits); stream << L"; "; PrintSendInstruction(ip, stream, operand & SendXMaxLiteral, 0); @@ -546,7 +545,7 @@ template class BytecodeDisassembler case PushTempPair: { - BYTE operand = GetBytecode(ip + 1); + uint8_t operand = GetBytecode(ip + 1); PrintTempInstruction(ip, stream, "Push", operand >> 4); PrintTempInstruction(ip + 1, stream, "; Push", operand & 0xF); } @@ -554,19 +553,19 @@ template class BytecodeDisassembler // Three bytes from here on ... case LongPushConst: - PrintStaticInstruction(ip, stream, "Push Const", (GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1)); + PrintStaticInstruction(ip, stream, "Push Const", (static_cast(GetBytecode(ip + 2)) << 8) + GetBytecode(ip + 1)); break; case LongPushStatic: - PrintStaticInstruction(ip, stream, "Push Static", (GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1)); + PrintStaticInstruction(ip, stream, "Push Static", (static_cast(GetBytecode(ip + 2)) << 8) + GetBytecode(ip + 1)); break; case LongStoreStatic: - PrintStaticInstruction(ip, stream, "Store Static", (GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1)); + PrintStaticInstruction(ip, stream, "Store Static", (static_cast(GetBytecode(ip + 2)) << 8) + GetBytecode(ip + 1)); break; case LongPushImmediate: - PrintPushImmediate(ip, stream, (SWORD)((GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1)), 2); + PrintPushImmediate(ip, stream, static_cast((GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1)), 2); break; case LongSend: @@ -585,8 +584,8 @@ template class BytecodeDisassembler case LongJumpIfNil: case LongJumpIfNotNil: { - SWORD offset = (SWORD)((GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1)); - PrintJumpInstruction(ip, stream, (JumpType)(opcode - LongJump), offset, ip + 3 + offset); + int16_t offset = static_cast((GetBytecode(ip + 2) << 8ui32) + GetBytecode(ip + 1)); + PrintJumpInstruction(ip, stream, static_cast(opcode - LongJump), offset, static_cast(ip) + 3 + offset); } break; @@ -639,22 +638,22 @@ template class BytecodeDisassembler stream << L"needs self, "; if (GetBytecode(ip + 3) & 1) stream << L"needs outer, "; - int length = (GetBytecode(ip + 6) << 8) + GetBytecode(ip + 5); + int length = (GetBytecode(ip + 6) << 8ui32) + GetBytecode(ip + 5); stream << L"length: " << length; } break; case ExLongSend: - PrintSendInstruction(ip, stream, (GetBytecode(ip + 3) << 8) + GetBytecode(ip + 2), GetBytecode(ip + 1)); + PrintSendInstruction(ip, stream, (GetBytecode(ip + 3) << 8ui32) + GetBytecode(ip + 2), GetBytecode(ip + 1)); break; case ExLongSupersend: stream << L"Super "; - PrintSendInstruction(ip, stream, (GetBytecode(ip + 3) << 8) + GetBytecode(ip + 2), GetBytecode(ip + 1)); + PrintSendInstruction(ip, stream, (GetBytecode(ip + 3) << 8ui32) + GetBytecode(ip + 2), GetBytecode(ip + 1)); break; case ExLongPushImmediate: - PrintPushImmediate(ip, stream, (GetBytecode(ip + 4) << 24) + (GetBytecode(ip + 3) << 16) + (GetBytecode(ip + 2) << 8) + GetBytecode(ip + 1), 4); + PrintPushImmediate(ip, stream, (GetBytecode(ip + 4) << 24ui32) + (GetBytecode(ip + 3) << 16ui32) + (GetBytecode(ip + 2) << 8ui32) + GetBytecode(ip + 1), 4); break; @@ -666,7 +665,7 @@ template class BytecodeDisassembler stream.flush(); } - void BytecodeDisassembler::PrintJumpInstruction(size_t ip, std::wostream& stream, JumpType jumpType, SWORD offset, size_t target) + void BytecodeDisassembler::PrintJumpInstruction(I ip, std::wostream& stream, JumpType jumpType, int16_t offset, size_t target) { const char* JumpNames[] = { "Jump", "Jump If True", "Jump If False", "Jump If Nil", "Jump If Not Nil" }; stream << JumpNames[jumpType] << L' '; @@ -677,28 +676,28 @@ template class BytecodeDisassembler stream << std::dec << static_cast(offset) << L" to " << (target + 1); } - void BytecodeDisassembler::PrintStaticInstruction(size_t ip, std::wostream& stream, const char* type, size_t index) + void BytecodeDisassembler::PrintStaticInstruction(I ip, std::wostream& stream, const char* type, size_t index) { stream << type << L" [" << std::dec << index << L"]: " << context.GetLiteralAsString(index); } - void BytecodeDisassembler::PrintInstVarInstruction(size_t ip, std::wostream& stream, const char* type, size_t index) + void BytecodeDisassembler::PrintInstVarInstruction(I ip, std::wostream& stream, const char* type, size_t index) { stream << type << L" InstVar[" << std::dec << index << L"]: " << context.GetInstVar(index).c_str(); } - void BytecodeDisassembler::PrintSendInstruction(size_t ip, std::wostream& stream, int index, int argumentCount) + void BytecodeDisassembler::PrintSendInstruction(I ip, std::wostream& stream, int index, int argumentCount) { wstring selector = context.GetLiteralAsString(index); stream << L"Send[" << std::dec << index << L"]: #" << selector << L" with " << argumentCount << (argumentCount == 1 ? L" arg" : L" args"); } - void BytecodeDisassembler::PrintTempInstruction(size_t ip, std::wostream& stream, const char* type, size_t index) + void BytecodeDisassembler::PrintTempInstruction(I ip, std::wostream& stream, const char* type, size_t index) { stream << type << L" Temp[" << std::dec << index << L"]"; } - void BytecodeDisassembler::PrintPushImmediate(size_t ip, std::wostream& stream, int value, int byteSize) + void BytecodeDisassembler::PrintPushImmediate(I ip, std::wostream& stream, int value, int byteSize) { stream << L"Push " << std::dec << value; if (byteSize > 0) diff --git a/Core/DolphinVM/extcall.cpp b/Core/DolphinVM/extcall.cpp index 5e042217de..a74f95634b 100644 --- a/Core/DolphinVM/extcall.cpp +++ b/Core/DolphinVM/extcall.cpp @@ -227,146 +227,146 @@ unsigned Interpreter::pushArgsAt(const ExternalDescriptor* descriptor, BYTE* lpP { BYTE arg = types->m_args[i++]; // Similar to primitiveDLL32Call return values, but VOID is not supported as a parameter type - switch(ExtCallArgTypes(arg)) + switch(ExtCallArgType(arg)) { - case ExtCallArgVOID: // Not a valid argument + case ExtCallArgType::Void: // Not a valid argument HARDASSERT(FALSE); pushNil(); lpParms += sizeof(MWORD); break; - case ExtCallArgLPVOID: + case ExtCallArgType::LPVoid: pushNewObject((OTE*)ExternalAddress::New(*(BYTE**)lpParms)); lpParms += sizeof(BYTE*); break; - case ExtCallArgCHAR: + case ExtCallArgType::Char: pushObject((OTE*)Character::NewUnicode(*reinterpret_cast(lpParms))); lpParms += sizeof(MWORD); break; - case ExtCallArgBYTE: + case ExtCallArgType::UInt8: pushSmallInteger(*lpParms); lpParms += sizeof(MWORD); break; - case ExtCallArgSBYTE: + case ExtCallArgType::Int8: pushSmallInteger(*reinterpret_cast(lpParms)); lpParms += sizeof(MWORD); break; - case ExtCallArgWORD: + case ExtCallArgType::UInt16: pushSmallInteger(*reinterpret_cast(lpParms)); lpParms += sizeof(MWORD); break; - case ExtCallArgSWORD: + case ExtCallArgType::Int16: pushSmallInteger(*reinterpret_cast(lpParms)); lpParms += sizeof(MWORD); break; - case ExtCallArgDWORD: + case ExtCallArgType::UInt32: pushUnsigned32(*reinterpret_cast(lpParms)); lpParms += sizeof(DWORD); break; - case ExtCallArgSDWORD: - case ExtCallArgHRESULT: - case ExtCallArgNTSTATUS: + case ExtCallArgType::Int32: + case ExtCallArgType::HResult: + case ExtCallArgType::NTStatus: pushSigned32(*reinterpret_cast(lpParms)); lpParms += sizeof(SDWORD); break; - case ExtCallArgBOOL: + case ExtCallArgType::Bool: pushBool(*reinterpret_cast(lpParms)); lpParms += sizeof(MWORD); break; - case ExtCallArgHANDLE: + case ExtCallArgType::Handle: pushHandle(*reinterpret_cast(lpParms)); lpParms += sizeof(HANDLE); break; - case ExtCallArgDOUBLE: + case ExtCallArgType::Double: push(*reinterpret_cast(lpParms)); // Yup, even doubles passed on main stack lpParms += sizeof(DOUBLE); break; - case ExtCallArgLPSTR: + case ExtCallArgType::LPStr: push(*reinterpret_cast(lpParms)); lpParms += sizeof(LPCSTR); break; - case ExtCallArgOOP: - case ExtCallArgOTE: + case ExtCallArgType::Oop: + case ExtCallArgType::Ote: push(*reinterpret_cast(lpParms)); lpParms += sizeof(Oop); break; - case ExtCallArgFLOAT: + case ExtCallArgType::Float: push(static_cast(*reinterpret_cast(lpParms))); // Yup, even doubles passed on main stack lpParms += sizeof(FLOAT); break; - case ExtCallArgLPPVOID: + case ExtCallArgType::LPPVoid: // Push an LPVOID* instance onto the stack pushNewObject(ExternalStructure::NewPointer(Pointers.ClassLPVOID, *(BYTE**)lpParms)); lpParms += sizeof(BYTE*); break; - case ExtCallArgLPWSTR: + case ExtCallArgType::LPWStr: push(*reinterpret_cast(lpParms)); lpParms += sizeof(LPWSTR); break; - case ExtCallArgQWORD: + case ExtCallArgType::UInt64: push(Integer::NewUnsigned64(*reinterpret_cast(lpParms))); lpParms += sizeof(ULARGE_INTEGER); break; - case ExtCallArgSQWORD: + case ExtCallArgType::Int64: push(Integer::NewSigned64(*reinterpret_cast(lpParms))); lpParms += sizeof(LONGLONG); break; - case ExtCallArgBSTR: + case ExtCallArgType::Bstr: push(*reinterpret_cast(lpParms)); lpParms += sizeof(BSTR); break; - case ExtCallArgVARIANT: + case ExtCallArgType::Variant: pushNewObject(ExternalStructure::New(Pointers.ClassVARIANT, lpParms)); lpParms += sizeof(VARIANT); break; - case ExtCallArgDATE: + case ExtCallArgType::Date: pushNewObject(ExternalStructure::New(Pointers.ClassDATE, lpParms)); lpParms += sizeof(DATE); break; - case ExtCallArgVARBOOL: + case ExtCallArgType::VarBool: pushBool(*reinterpret_cast(lpParms)); lpParms += sizeof(MWORD); // Note passes as 32-bit break; - case ExtCallArgGUID: + case ExtCallArgType::Guid: pushNewObject((OTE*)NewGUID(reinterpret_cast(lpParms))); lpParms += sizeof(GUID); break; - case ExtCallArgUINTPTR: + case ExtCallArgType::UIntPtr: pushUIntPtr(*reinterpret_cast(lpParms)); lpParms += sizeof(UINT_PTR); break; - case ExtCallArgINTPTR: + case ExtCallArgType::IntPtr: pushIntPtr(*reinterpret_cast(lpParms)); lpParms += sizeof(INT_PTR); break; - case ExtCallArgSTRUCT: + case ExtCallArgType::Struct: { arg = types->m_args[i++]; BehaviorOTE* behaviorPointer = reinterpret_cast(descriptor->m_literals[arg]); @@ -375,7 +375,7 @@ unsigned Interpreter::pushArgsAt(const ExternalDescriptor* descriptor, BYTE* lpP } break; - case ExtCallArgSTRUCT4: + case ExtCallArgType::Struct32: { arg = types->m_args[i++]; BehaviorOTE* behaviorPointer = reinterpret_cast(descriptor->m_literals[arg]); @@ -384,7 +384,7 @@ unsigned Interpreter::pushArgsAt(const ExternalDescriptor* descriptor, BYTE* lpP } break; - case ExtCallArgSTRUCT8: + case ExtCallArgType::Struct64: { arg = types->m_args[i++]; BehaviorOTE* behaviorPointer = reinterpret_cast(descriptor->m_literals[arg]); @@ -393,7 +393,7 @@ unsigned Interpreter::pushArgsAt(const ExternalDescriptor* descriptor, BYTE* lpP } break; - case ExtCallArgLP: + case ExtCallArgType::LPStruct: { arg = types->m_args[i++]; BehaviorOTE* behaviorPointer = reinterpret_cast(descriptor->m_literals[arg]); @@ -402,13 +402,13 @@ unsigned Interpreter::pushArgsAt(const ExternalDescriptor* descriptor, BYTE* lpP } break; - case ExtCallArgLPP: // Not a valid argument + case ExtCallArgType::LPPStruct: // Not a valid argument arg = types->m_args[i++]; pushNewObject(ExternalStructure::NewPointer(Pointers.ClassLPVOID, *(BYTE**)lpParms)); lpParms += sizeof(BYTE*); break; - case ExtCallArgCOMPTR: + case ExtCallArgType::ComPtr: { arg = types->m_args[i++]; IUnknown* punk = *(IUnknown**)lpParms; diff --git a/Core/DolphinVM/ist.h b/Core/DolphinVM/ist.h index 5b4a284d2d..aa6790c4c6 100755 --- a/Core/DolphinVM/ist.h +++ b/Core/DolphinVM/ist.h @@ -75,15 +75,19 @@ #pragma warning(pop) #include +typedef _Return_type_success_(return >= 0) int32_t NTSTATUS; +#define NTSTATUS_DEFINED +#define _NTDEF_ + #include "Environ.h" -typedef signed char SBYTE; -typedef short SWORD; -typedef long SDWORD; +typedef int8_t SBYTE; +typedef int16_t SWORD; +typedef int32_t SDWORD; // The basic word size of the machine -typedef UINT_PTR MWORD; -typedef INT_PTR SMALLINTEGER; // Optimized SmallInteger; same size as MWORD +typedef uintptr_t MWORD; +typedef intptr_t SMALLINTEGER; // Optimized SmallInteger; same size as MWORD typedef MWORD SMALLUNSIGNED; // Unsigned optimized SmallInteger; same size as MWORD typedef MWORD Oop; diff --git a/Core/DolphinVM/textrange.h b/Core/DolphinVM/textrange.h new file mode 100644 index 0000000000..ca24dd2491 --- /dev/null +++ b/Core/DolphinVM/textrange.h @@ -0,0 +1,19 @@ +#pragma once + +#include "EnumHelpers.h" + +enum class textpos_t : intptr_t { npos = -1, start }; +ENABLE_INT_OPERATORS(textpos_t) + +struct TEXTRANGE +{ + textpos_t m_start; + textpos_t m_stop; + + TEXTRANGE(textpos_t start = textpos_t::start, textpos_t stop = textpos_t::npos) : m_start(start), m_stop(stop) + {} + + __declspec(property(get = GetSpan)) intptr_t Span; + intptr_t GetSpan() const { return (intptr_t)m_stop - (intptr_t)m_start + 1; } +}; +