#ifndef AirCode_h
#define AirCode_h
#if ENABLE(B3_JIT)
#include "AirArg.h"
#include "AirBasicBlock.h"
#include "AirSpecial.h"
#include "AirStackSlot.h"
#include "AirTmp.h"
#include "B3SparseCollection.h"
#include "RegisterAtOffsetList.h"
#include "StackAlignment.h"
namespace JSC { namespace B3 {
class Procedure;
#if COMPILER(GCC) && ASSERT_DISABLED
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
#endif // COMPILER(GCC) && ASSERT_DISABLED
namespace Air {
class BlockInsertionSet;
class CCallSpecial;
class Code {
WTF_MAKE_NONCOPYABLE(Code);
WTF_MAKE_FAST_ALLOCATED;
public:
~Code();
Procedure& proc() { return m_proc; }
JS_EXPORT_PRIVATE BasicBlock* addBlock(double frequency = 1);
JS_EXPORT_PRIVATE StackSlot* addStackSlot(
unsigned byteSize, StackSlotKind, B3::StackSlot* = nullptr);
StackSlot* addStackSlot(B3::StackSlot*);
Special* addSpecial(std::unique_ptr<Special>);
CCallSpecial* cCallSpecial();
Tmp newTmp(Arg::Type type)
{
switch (type) {
case Arg::GP:
return Tmp::gpTmpForIndex(m_numGPTmps++);
case Arg::FP:
return Tmp::fpTmpForIndex(m_numFPTmps++);
}
ASSERT_NOT_REACHED();
}
unsigned numTmps(Arg::Type type)
{
switch (type) {
case Arg::GP:
return m_numGPTmps;
case Arg::FP:
return m_numFPTmps;
}
ASSERT_NOT_REACHED();
}
unsigned callArgAreaSize() const { return m_callArgAreaSize; }
void requestCallArgAreaSize(unsigned size)
{
m_callArgAreaSize = std::max(
m_callArgAreaSize,
static_cast<unsigned>(WTF::roundUpToMultipleOf(stackAlignmentBytes(), size)));
}
unsigned frameSize() const { return m_frameSize; }
void setFrameSize(unsigned frameSize)
{
m_frameSize = frameSize;
}
const RegisterAtOffsetList& calleeSaveRegisters() const { return m_calleeSaveRegisters; }
RegisterAtOffsetList& calleeSaveRegisters() { return m_calleeSaveRegisters; }
void resetReachability();
void dump(PrintStream&) const;
unsigned size() const { return m_blocks.size(); }
BasicBlock* at(unsigned index) const { return m_blocks[index].get(); }
BasicBlock* operator[](unsigned index) const { return at(index); }
Vector<std::unique_ptr<BasicBlock>>& blockList() { return m_blocks; }
unsigned findFirstBlockIndex(unsigned index) const;
unsigned findNextBlockIndex(unsigned index) const;
BasicBlock* findNextBlock(BasicBlock*) const;
class iterator {
public:
iterator()
: m_code(nullptr)
, m_index(0)
{
}
iterator(const Code& code, unsigned index)
: m_code(&code)
, m_index(m_code->findFirstBlockIndex(index))
{
}
BasicBlock* operator*()
{
return m_code->at(m_index);
}
iterator& operator++()
{
m_index = m_code->findFirstBlockIndex(m_index + 1);
return *this;
}
bool operator==(const iterator& other) const
{
return m_index == other.m_index;
}
bool operator!=(const iterator& other) const
{
return !(*this == other);
}
private:
const Code* m_code;
unsigned m_index;
};
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, size()); }
const SparseCollection<StackSlot>& stackSlots() const { return m_stackSlots; }
SparseCollection<StackSlot>& stackSlots() { return m_stackSlots; }
const SparseCollection<Special>& specials() const { return m_specials; }
SparseCollection<Special>& specials() { return m_specials; }
template<typename Callback>
void forAllTmps(const Callback& callback) const
{
for (unsigned i = m_numGPTmps; i--;)
callback(Tmp::gpTmpForIndex(i));
for (unsigned i = m_numFPTmps; i--;)
callback(Tmp::fpTmpForIndex(i));
}
void addFastTmp(Tmp);
bool isFastTmp(Tmp tmp) const { return m_fastTmps.contains(tmp); }
void setLastPhaseName(const char* name)
{
m_lastPhaseName = name;
}
const char* lastPhaseName() const { return m_lastPhaseName; }
unsigned jsHash() const;
private:
friend class ::JSC::B3::Procedure;
friend class BlockInsertionSet;
Code(Procedure&);
Procedure& m_proc; SparseCollection<StackSlot> m_stackSlots;
Vector<std::unique_ptr<BasicBlock>> m_blocks;
SparseCollection<Special> m_specials;
HashSet<Tmp> m_fastTmps;
CCallSpecial* m_cCallSpecial { nullptr };
unsigned m_numGPTmps { 0 };
unsigned m_numFPTmps { 0 };
unsigned m_frameSize { 0 };
unsigned m_callArgAreaSize { 0 };
RegisterAtOffsetList m_calleeSaveRegisters;
const char* m_lastPhaseName;
};
} } }
#if COMPILER(GCC) && ASSERT_DISABLED
#pragma GCC diagnostic pop
#endif // COMPILER(GCC) && ASSERT_DISABLED
#endif // ENABLE(B3_JIT)
#endif // AirCode_h