| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- //-------------------------------------------------------------------------------------------------------
- // 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
- namespace IR {
- inline IRKind
- Instr::GetKind() const
- {
- return this->m_kind;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::IsEntryInstr
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::IsEntryInstr() const
- {
- return this->GetKind() == InstrKindEntry;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::AsEntryInstr
- ///
- /// Return this as an EntryInstr *
- ///
- ///----------------------------------------------------------------------------
- inline EntryInstr *
- Instr::AsEntryInstr()
- {
- AssertMsg(this->IsEntryInstr(), "Bad call to AsEntryInstr()");
- return reinterpret_cast<EntryInstr *>(this);
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::IsExitInstr
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::IsExitInstr() const
- {
- return this->GetKind() == InstrKindExit;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::AsExitInstr
- ///
- /// Return this as an ExitInstr *
- ///
- ///----------------------------------------------------------------------------
- inline ExitInstr *
- Instr::AsExitInstr()
- {
- AssertMsg(this->IsExitInstr(), "Bad call to AsExitInstr()");
- return reinterpret_cast<ExitInstr *>(this);
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::IsBranchInstr
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::IsBranchInstr() const
- {
- return this->GetKind() == InstrKindBranch;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::AsBranchInstr
- ///
- /// Return this as a BranchInstr *
- ///
- ///----------------------------------------------------------------------------
- inline BranchInstr *
- Instr::AsBranchInstr()
- {
- AssertMsg(this->IsBranchInstr(), "Bad call to AsBranchInstr()");
- return reinterpret_cast<BranchInstr *>(this);
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::IsLabelInstr
- ///
- ///----------------------------------------------------------------------------
- __forceinline bool
- Instr::IsLabelInstr() const
- {
- return this->GetKind() == InstrKindLabel || this->IsProfiledLabelInstr();
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::AsLabelInstr
- ///
- /// Return this as a LabelInstr *
- ///
- ///----------------------------------------------------------------------------
- inline LabelInstr *
- Instr::AsLabelInstr()
- {
- AssertMsg(this->IsLabelInstr(), "Bad call to AsLabelInstr()");
- return reinterpret_cast<LabelInstr *>(this);
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::AsMultiBrInstr
- ///
- /// Return this as a MultiBrInstr *
- ///
- ///----------------------------------------------------------------------------
- inline MultiBranchInstr *
- BranchInstr::AsMultiBrInstr()
- {
- AssertMsg(this->IsMultiBranch(), "Bad call to AsMultiBrInstr()");
- return static_cast<MultiBranchInstr *>(this);
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::IsPragmaInstr
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::IsPragmaInstr() const
- {
- return this->GetKind() == InstrKindPragma;
- }
- inline PragmaInstr *
- Instr::AsPragmaInstr()
- {
- AssertMsg(this->IsPragmaInstr(), "Bad call to AsPragmaInstr()");
- return reinterpret_cast<PragmaInstr *>(this);
- }
- inline bool
- Instr::IsJitProfilingInstr() const
- {
- return this->GetKind() == InstrKindJitProfiling;
- }
- inline JitProfilingInstr *
- Instr::AsJitProfilingInstr()
- {
- AssertMsg(this->IsJitProfilingInstr(), "Bad call to AsProfiledInstr()");
- return reinterpret_cast<JitProfilingInstr *>(this);
- }
- inline bool
- Instr::IsProfiledInstr() const
- {
- return this->GetKind() == InstrKindProfiled;
- }
- inline ProfiledInstr *
- Instr::AsProfiledInstr()
- {
- AssertMsg(this->IsProfiledInstr(), "Bad call to AsProfiledInstr()");
- return reinterpret_cast<ProfiledInstr *>(this);
- }
- inline bool
- Instr::IsProfiledLabelInstr() const
- {
- return this->GetKind() == InstrKindProfiledLabel;
- }
- inline ProfiledLabelInstr *
- Instr::AsProfiledLabelInstr()
- {
- AssertMsg(this->IsProfiledLabelInstr(), "Bad call to AsProfiledLabelInstr()");
- return reinterpret_cast<ProfiledLabelInstr *>(this);
- }
- inline bool
- Instr::IsByteCodeUsesInstr() const
- {
- return GetKind() == IR::InstrKindByteCodeUses;
- }
- inline ByteCodeUsesInstr *
- Instr::AsByteCodeUsesInstr()
- {
- AssertMsg(this->IsByteCodeUsesInstr(), "Bad call to AsByteCodeUsesInstr()");
- return (ByteCodeUsesInstr *)this;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::IsLowered
- ///
- /// Is this instr lowered to machine dependent opcode?
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::IsLowered() const
- {
- return m_opcode > Js::OpCode::MDStart;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::StartsBasicBlock
- ///
- /// Does this instruction mark the beginning of a basic block?
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::StartsBasicBlock() const
- {
- return this->IsLabelInstr() || this->IsEntryInstr();
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::EndsBasicBlock
- ///
- /// Does this instruction mark the end of a basic block?
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::EndsBasicBlock() const
- {
- return
- this->IsBranchInstr() ||
- this->IsExitInstr() ||
- this->m_opcode == Js::OpCode::Ret ||
- this->m_opcode == Js::OpCode::Throw ||
- this->m_opcode == Js::OpCode::RuntimeTypeError ||
- this->m_opcode == Js::OpCode::RuntimeReferenceError;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::HasFallThrough
- ///
- /// Can execution fall through to the next instruction?
- ///
- ///----------------------------------------------------------------------------
- inline bool
- Instr::HasFallThrough() const
- {
- return (!(this->IsBranchInstr() && const_cast<Instr*>(this)->AsBranchInstr()->IsUnconditional())
- && OpCodeAttr::HasFallThrough(this->m_opcode));
- }
- inline bool
- Instr::IsNewScObjectInstr() const
- {
- return this->m_opcode == Js::OpCode::NewScObject || this->m_opcode == Js::OpCode::NewScObjectNoCtor;
- }
- inline bool
- Instr::IsInvalidInstr() const
- {
- return this == (Instr*)InvalidInstrLayout;
- }
- inline Instr*
- Instr::GetInvalidInstr()
- {
- return (Instr*)InvalidInstrLayout;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::GetDst
- ///
- ///----------------------------------------------------------------------------
- inline Opnd *
- Instr::GetDst() const
- {
- return this->m_dst;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::GetSrc1
- ///
- ///----------------------------------------------------------------------------
- inline Opnd *
- Instr::GetSrc1() const
- {
- return this->m_src1;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::SetSrc1
- ///
- /// Makes a copy if opnd is in use...
- ///
- ///----------------------------------------------------------------------------
- inline Opnd *
- Instr::SetSrc1(Opnd * newSrc)
- {
- AssertMsg(this->m_src1 == NULL, "Trying to overwrite existing src.");
- newSrc = newSrc->Use(m_func);
- this->m_src1 = newSrc;
- return newSrc;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::GetSrc2
- ///
- ///----------------------------------------------------------------------------
- inline Opnd *
- Instr::GetSrc2() const
- {
- return this->m_src2;
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::SetSrc2
- ///
- /// Makes a copy if opnd is in use...
- ///
- ///----------------------------------------------------------------------------
- inline Opnd *
- Instr::SetSrc2(Opnd * newSrc)
- {
- AssertMsg(this->m_src2 == NULL, "Trying to overwrite existing src.");
- newSrc = newSrc->Use(m_func);
- this->m_src2 = newSrc;
- return newSrc;
- }
- // IsInlined - true if the function that contains the instr has been inlined
- inline bool
- Instr::IsInlined() const
- {
- return this->m_func->IsInlined();
- }
- ///----------------------------------------------------------------------------
- ///
- /// Instr::ForEachCallDirectArgOutInstrBackward
- ///
- /// Walks the ArgsOut of CallDirect backwards
- ///
- ///----------------------------------------------------------------------------
- template <typename Fn>
- inline bool
- Instr::ForEachCallDirectArgOutInstrBackward(Fn fn, uint argsOpndLength) const
- {
- Assert(this->m_opcode == Js::OpCode::CallDirect); // Right now we call this method only for partial inlining of split, match and exec. Can be modified for other uses also.
- // CallDirect src2
- IR::Opnd * linkOpnd = this->GetSrc2();
- // ArgOut_A_InlineSpecialized
- IR::Instr * tmpInstr = linkOpnd->AsSymOpnd()->m_sym->AsStackSym()->m_instrDef;
- Assert(tmpInstr->m_opcode == Js::OpCode::ArgOut_A_InlineSpecialized);
- // ArgOut_A_InlineSpecialized src2; link to actual argouts.
- linkOpnd = tmpInstr->GetSrc2();
- uint32 argCount = linkOpnd->AsSymOpnd()->m_sym->AsStackSym()->GetArgSlotNum();
- if (argCount != argsOpndLength)
- {
- return false;
- }
- while (linkOpnd->IsSymOpnd() && argCount > 0)
- {
- IR::SymOpnd *src2 = linkOpnd->AsSymOpnd();
- StackSym *sym = src2->m_sym->AsStackSym();
- Assert(sym->m_isSingleDef);
- IR::Instr *argInstr = sym->m_instrDef;
- Assert(argInstr->m_opcode == Js::OpCode::ArgOut_A);
- if (fn(argInstr, argCount - 1))
- {
- return true;
- }
- argCount--;
- linkOpnd = argInstr->GetSrc2();
- }
- return false;
- }
- ///----------------------------------------------------------------------------
- ///
- /// BranchInstr::SetTarget
- ///
- ///----------------------------------------------------------------------------
- inline void
- BranchInstr::SetTarget(LabelInstr * labelInstr)
- {
- Assert(!this->m_isMultiBranch);
- if (this->m_branchTarget)
- {
- this->m_branchTarget->RemoveLabelRef(this);
- }
- if (labelInstr)
- {
- labelInstr->AddLabelRef(this);
- }
- this->m_branchTarget = labelInstr;
- }
- inline void
- BranchInstr::ClearTarget()
- {
- if (this->IsMultiBranch())
- {
- this->AsMultiBrInstr()->ClearTarget();
- }
- else
- {
- this->SetTarget(nullptr);
- }
- }
- ///----------------------------------------------------------------------------
- ///
- /// BranchInstr::GetTarget
- ///
- ///----------------------------------------------------------------------------
- inline LabelInstr *
- BranchInstr::GetTarget() const
- {
- return this->m_branchTarget;
- }
- ///----------------------------------------------------------------------------
- ///
- /// BranchInstr::IsConditional
- ///
- ///----------------------------------------------------------------------------
- inline bool
- BranchInstr::IsConditional() const
- {
- return !this->IsUnconditional();
- }
- inline bool
- BranchInstr::IsMultiBranch() const
- {
- if (m_branchTarget)
- {
- Assert(!m_isMultiBranch);
- return false;
- }
- else
- {
- Assert(m_isMultiBranch);
- return true; // it's a multi branch instr
- }
- }
- ///----------------------------------------------------------------------------
- ///
- /// BranchInstr::IsUnconditional
- ///
- ///----------------------------------------------------------------------------
- inline bool
- BranchInstr::IsUnconditional() const
- {
- if (this->IsLowered())
- {
- return LowererMD::IsUnconditionalBranch(this);
- }
- else
- {
- return (this->m_opcode == Js::OpCode::Br || this->m_opcode == Js::OpCode::MultiBr);
- }
- }
- ///----------------------------------------------------------------------------
- ///
- /// MultiBranchInstr::AddtoDictionary
- /// - Adds the string to the list with the targetoffset
- /// In order for the dictionary to have the right value, MapBranchTargetAddress
- /// needs to be called to populate the dictionary and then it'll be patched up
- /// to the right values
- ///
- ///----------------------------------------------------------------------------
- inline void
- MultiBranchInstr::AddtoDictionary(uint32 offset, TBranchKey key, void* remoteVar)
- {
- Assert(this->m_kind == StrDictionary);
- Assert(key);
- auto dict = this->GetBranchDictionary();
- dict->AddEntry(offset, key, remoteVar);
- }
- inline void
- MultiBranchInstr::AddtoJumpTable(uint32 offset, uint32 jmpIndex)
- {
- Assert(this->m_kind == IntJumpTable || this->m_kind == SingleCharStrJumpTable);
- Assert(jmpIndex != -1);
- auto table = this->GetBranchJumpTable();
- table->jmpTable[jmpIndex] = (void*)offset;
- }
- inline void
- MultiBranchInstr::FixMultiBrDefaultTarget(uint32 targetOffset)
- {
- this->GetBranchJumpTable()->defaultTarget = (void *)targetOffset;
- }
- inline void
- MultiBranchInstr::CreateBranchTargetsAndSetDefaultTarget(int size, Kind kind, uint defaultTargetOffset)
- {
- AssertMsg(size != 0, "The dictionary/jumpTable size should not be zero");
- NativeCodeData::Allocator * allocator = this->m_func->GetNativeCodeDataAllocator();
- m_kind = kind;
- switch (kind)
- {
- case IntJumpTable:
- case SingleCharStrJumpTable:
- {
- JitArenaAllocator * jitAllocator = this->m_func->GetTopFunc()->m_alloc;
- BranchJumpTableWrapper * branchTargets = BranchJumpTableWrapper::New(jitAllocator, size);
- branchTargets->defaultTarget = (void *)defaultTargetOffset;
- this->m_branchTargets = branchTargets;
- break;
- }
- case StrDictionary:
- {
- BranchDictionaryWrapper * branchTargets = BranchDictionaryWrapper::New(allocator, size, m_func->IsOOPJIT() ? m_func->m_alloc : nullptr);
- branchTargets->defaultTarget = (void *)defaultTargetOffset;
- this->m_branchTargets = branchTargets;
- break;
- }
- default:
- Assert(false);
- };
- }
- inline MultiBranchInstr::BranchDictionaryWrapper *
- MultiBranchInstr::GetBranchDictionary()
- {
- return reinterpret_cast<MultiBranchInstr::BranchDictionaryWrapper *>(m_branchTargets);
- }
- inline MultiBranchInstr::BranchJumpTable *
- MultiBranchInstr::GetBranchJumpTable()
- {
- return reinterpret_cast<MultiBranchInstr::BranchJumpTable *>(m_branchTargets);
- }
- inline void
- MultiBranchInstr::ChangeLabelRef(LabelInstr * oldTarget, LabelInstr * newTarget)
- {
- if (oldTarget)
- {
- oldTarget->RemoveLabelRef(this);
- }
- if (newTarget)
- {
- newTarget->AddLabelRef(this);
- }
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::SetPC
- ///
- ///----------------------------------------------------------------------------
- inline void
- LabelInstr::SetPC(BYTE * pc)
- {
- this->m_pc.pc = pc;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::GetPC
- ///
- ///----------------------------------------------------------------------------
- inline BYTE *
- LabelInstr::GetPC(void) const
- {
- return this->m_pc.pc;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::ResetOffset
- ///
- ///----------------------------------------------------------------------------
- inline void
- LabelInstr::ResetOffset(uintptr_t offset)
- {
- AssertMsg(this->isInlineeEntryInstr, "As of now only InlineeEntryInstr overwrites the offset at encoder stage");
- this->m_pc.offset = offset;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::SetOffset
- ///
- ///----------------------------------------------------------------------------
- inline void
- LabelInstr::SetOffset(uintptr_t offset)
- {
- AssertMsg(this->m_pc.offset == 0, "Overwriting existing byte offset");
- this->m_pc.offset = offset;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::GetOffset
- ///
- ///----------------------------------------------------------------------------
- inline uintptr_t
- LabelInstr::GetOffset(void) const
- {
- return this->m_pc.offset;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::SetBasicBlock
- ///
- ///----------------------------------------------------------------------------
- inline void
- LabelInstr::SetBasicBlock(BasicBlock * block)
- {
- AssertMsg(this->m_block == nullptr || block == nullptr, "Overwriting existing block pointer");
- this->m_block = block;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::GetBasicBlock
- ///
- ///----------------------------------------------------------------------------
- inline BasicBlock *
- LabelInstr::GetBasicBlock(void) const
- {
- return this->m_block;
- }
- inline void
- LabelInstr::SetLoop(Loop* loop)
- {
- Assert(this->m_isLoopTop);
- this->m_loop = loop;
- }
- inline Loop*
- LabelInstr::GetLoop(void) const
- {
- Assert(this->m_isLoopTop);
- return this->m_loop;
- }
- ///----------------------------------------------------------------------------
- ///
- /// LabelInstr::UnlinkBasicBlock
- ///
- ///----------------------------------------------------------------------------
- inline void
- LabelInstr::UnlinkBasicBlock(void)
- {
- this->m_block = nullptr;
- }
- inline BOOL
- LabelInstr::IsUnreferenced(void) const
- {
- return labelRefs.Empty() && !m_hasNonBranchRef;
- }
- inline void
- LabelInstr::SetRegion(Region * region)
- {
- this->m_region = region;
- }
- inline Region *
- LabelInstr::GetRegion(void) const
- {
- return this->m_region;
- }
- } // namespace IR
|