* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_ARKSTEED_BB_H
#define ECMASCRIPT_ARKSTEED_BB_H
#include "ecmascript/arksteed/arksteed_assembler.h"
#include "ecmascript/arksteed/arksteed_opcode.h"
#include "ecmascript/mem/chunk.h"
#include "ecmascript/mem/chunk_containers.h"
#include "libpandabase/macros.h"
#include "utils/span.h"
namespace panda::ecmascript::arksteed {
class ControlVertex;
class NonControlVertex;
class ValueVertex;
class PhiVertex;
class MergePointFrameState;
class RegisterMergeState;
constexpr uint32_t INVALID_BLOCK_ID = static_cast<uint32_t>(-1);
class BB {
public:
NO_COPY_SEMANTIC(BB);
NO_MOVE_SEMANTIC(BB);
static BB *New(Chunk *chunk)
{
void *memory = chunk->Allocate(sizeof(BB));
ASSERT(memory != nullptr);
return new (memory) BB(chunk);
}
uint32_t GetId() const
{
return id_;
}
void SetId(uint32_t id)
{
id_ = id;
}
bool IsDeferred() const
{
return deferred_;
}
void SetDeferred(bool deferred)
{
deferred_ = deferred;
}
ControlVertex *GetControlVertex() const
{
return controlVertex_;
}
void SetControlVertex(ControlVertex *vertex)
{
controlVertex_ = vertex;
}
void AddPhiVertex(PhiVertex *vertex)
{
phis_.push_back(vertex);
}
void AddVertex(NonControlVertex *vertex)
{
vertices_.push_back(vertex);
}
void ReplaceVertices(const std::vector<NonControlVertex *> &newVertices)
{
vertices_.assign(newVertices.begin(), newVertices.end());
}
size_t GetVertexCount() const
{
return vertices_.size();
}
const ChunkVector<NonControlVertex *> &GetVertices() const
{
return vertices_;
}
ChunkVector<NonControlVertex *> &GetVertices()
{
return vertices_;
}
bool IsLoopHeader() const { return isLoopHeader_; }
void SetLoopHeader(bool v) { isLoopHeader_ = v; }
bool IsExceptionHandler() const { return isExceptionHandler_; }
void SetExceptionHandler(bool v) { isExceptionHandler_ = v; }
bool HasRegisterMerge() const { return registerMergeState_ != nullptr; }
RegisterMergeState *GetRegisterMergeState()
{
ASSERT(registerMergeState_ != nullptr);
return registerMergeState_;
}
void SetRegisterMergeState(RegisterMergeState *state) { registerMergeState_ = state; }
bool HasPhi() const { return !phis_.empty(); }
const ChunkVector<PhiVertex *> &GetPhis() const { return phis_; }
ChunkVector<PhiVertex *> &GetPhis() { return phis_; }
void AddPredecessor(BB *pred) { predecessors_.push_back(pred); }
Span<BB *> GetPredecessors() { return {predecessors_.data(), predecessors_.size()}; }
Span<const BB *const> GetPredecessors() const { return {predecessors_.data(), predecessors_.size()}; }
template <class Callback>
void ForEachPredecessor(Callback callback) const
{
for (const BB *predecessor : GetPredecessors()) {
callback(const_cast<BB *>(predecessor));
}
}
template <class Callback>
void ForEachSuccessor(Callback callback) const
{
ControlVertex *control = GetControlVertex();
if (auto *jump = control->TryCast<UnconditionalControlVertex>(); jump != nullptr) {
callback(jump->Target());
} else if (auto *branch = control->TryCast<BranchControlVertex>(); branch != nullptr) {
callback(branch->IfTrue());
callback(branch->IfFalse());
}
}
BB *GetPredecessor(uint32_t index) { return predecessors_[index]; }
const BB *GetPredecessor(uint32_t index) const { return predecessors_[index]; }
uint32_t PredecessorCount() const { return predecessorCount_; }
void SetPredecessorCount(uint32_t n) { predecessorCount_ = n; }
void SetSinglePredecessor(BB *predecessor) { predecessor_ = predecessor; }
Label *GetLabel()
{
return &label_;
}
int GetPredecessorId() const;
void SetPredecessorId(int id);
uint32_t GetFirstId() const;
uint32_t GetFirstNonPhiId() const;
uint32_t GetFirstNonGapMoveId() const;
private:
explicit BB(Chunk *chunk)
: id_(INVALID_BLOCK_ID),
deferred_(false),
controlVertex_(nullptr),
phis_(chunk),
vertices_(chunk),
predecessors_(chunk),
isLoopHeader_(false),
isExceptionHandler_(false),
registerMergeState_(nullptr),
predecessorCount_(0),
predecessor_(nullptr)
{}
uint32_t id_;
bool deferred_;
ControlVertex *controlVertex_;
ChunkVector<PhiVertex *> phis_;
ChunkVector<NonControlVertex *> vertices_;
ChunkVector<BB *> predecessors_;
bool isLoopHeader_;
bool isExceptionHandler_;
RegisterMergeState *registerMergeState_;
uint32_t predecessorCount_ = 0;
BB *predecessor_ = nullptr;
Label label_;
};
}
#endif