//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once using namespace JsUtil; /* * CaseNode - represents the case statements (not the case block) in the switch statement */ class CaseNode { private: uint32 offset; // offset - indicates the bytecode offset of the case instruction uint32 targetOffset; // targetOffset - indicates the bytecode offset of the target instruction (case block) IR::BranchInstr* caseInstr; // caseInstr - stores the case instruction IR::Opnd* lowerBound; // lowerBound - used for integer cases int32 GetIntConst(IR::Opnd* opnd) { Assert(IsIntConst(opnd)); return opnd->IsIntConstOpnd() ? opnd->AsIntConstOpnd()->AsInt32() : opnd->GetStackSym()->GetIntConstValue(); } bool IsIntConst(IR::Opnd* opnd) { return opnd->IsIntConstOpnd() || opnd->GetStackSym()->IsIntConst(); } bool IsStrConst(IR::Opnd* opnd) { return opnd->GetStackSym()->m_isStrConst; } public: CaseNode(IR::BranchInstr* caseInstr, uint32 offset, uint32 targetOffset, IR::Opnd* lowerBound = nullptr) : caseInstr(caseInstr), offset(offset), targetOffset(targetOffset), lowerBound(lowerBound) { } int32 GetUpperBoundIntConst() { AssertMsg(IsUpperBoundIntConst(), "Source2 operand is not an integer constant"); return GetIntConst(GetUpperBound()); } JITJavascriptString* GetUpperBoundStringConstLocal() { AssertMsg(IsUpperBoundStrConst(), "Upper bound operand is not a string constant"); return JITJavascriptString::FromVar(GetUpperBound()->GetStackSym()->GetConstAddress(true)); } JITJavascriptString* GetUpperBoundStrConst() { AssertMsg(IsUpperBoundStrConst(), "Upper bound operand is not a string constant"); return static_cast(GetUpperBound()->GetStackSym()->GetConstAddress(false)); } bool IsUpperBoundIntConst() { return IsIntConst(GetUpperBound()); } bool IsUpperBoundStrConst() { return IsStrConst(GetUpperBound()); } int32 GetLowerBoundIntConst() { AssertMsg(IsLowerBoundIntConst(), "LowerBound is not an integer constant"); return GetIntConst(lowerBound); } bool IsLowerBoundIntConst() { return IsIntConst(lowerBound); } bool IsLowerBoundStrConst() { return IsStrConst(lowerBound); } uint32 GetOffset() { return offset; } uint32 GetTargetOffset() { return targetOffset; } IR::Opnd* GetUpperBound() { return caseInstr->GetSrc2(); } IR::Opnd* GetLowerBound() { return lowerBound; } void SetLowerBound(IR::Opnd* lowerBound) { this->lowerBound = lowerBound; } IR::BranchInstr* GetCaseInstr() { return caseInstr; } }; template <> struct DefaultComparer { public: static int Compare(CaseNode* caseNode1, CaseNode* caseNode2); static bool Equals(CaseNode* x, CaseNode* y); static uint GetHashCode(CaseNode * caseNode); };