* 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_CODEGEN_H
#define ECMASCRIPT_ARKSTEED_CODEGEN_H
#include "ecmascript/arksteed/arksteed_assembler.h"
#include "ecmascript/arksteed/arksteed_graph.h"
#include "ecmascript/arksteed/arksteed_graph_labeller.h"
#include "ecmascript/arksteed/arksteed_opcode.h"
namespace panda::ecmascript::arksteed {
class ArkSteedSafepointTableBuilder;
class GapMoveResolver;
class ArkSteedCodeGenerator {
public:
ArkSteedCodeGenerator(ArkSteedAssembler *assembler, Graph *graph,
ArkSteedSafepointTableBuilder *safepointBuilder = nullptr)
: assembler_(assembler),
graph_(graph),
safepointBuilder_(safepointBuilder),
blockColorAssignment_(graph->GetChunk())
{}
void Generate();
private:
static int32_t ComputeFrameSize(Graph *graph);
void ProcessValueVertex(ValueVertex *valueVertex);
void ProcessNonControlVertex(NonControlVertex *vertex);
void ProcessControlVertex(ControlVertex *vertex);
void DeconstructPhisInSuccessor(BB *successor, int predecessorId);
void CollectPhiMoves(GapMoveResolver *resolver, BB *successor, int predecessorId,
ArkSteedRegList *registersSetByPhis, ArkDoubleRegList *doubleRegistersSetByPhis,
ChunkVector<std::pair<AllocatedState, ValueVertex *>> *constantMoves);
void CollectRegisterStateMoves(GapMoveResolver *resolver, BB *successor, int predecessorId,
const ArkSteedRegList ®istersSetByPhis,
const ArkDoubleRegList &doubleRegistersSetByPhis,
ChunkVector<std::pair<AllocatedState, ValueVertex *>> *constantMoves);
void LoadConstantToRegister(const ValueVertex *constVertex, ArkSteedRegister reg);
void ExecuteConstantPhiMove(const AllocatedState &dest, ValueVertex *constVertex,
const ArkSteedRegister *scratchGPR = nullptr);
void ExecuteGapMove(const InstructionOperand &dest, const InstructionOperand &src,
const ArkSteedRegister *scratchGPR = nullptr);
void StoreStubStackArgument(const Vertex *callVertex, int paramIdx, ArkSteedAssembler::MemoryOperand destMem);
int PrepareCommonStubStackArguments(const Vertex *callVertex, int argCount);
int PrepareRuntimeStubStackArguments(const Vertex *callVertex, int argCount, int runtimeId);
template <class VertexT>
void VisitNonControlVertex(VertexT *vertex);
template <class VertexT>
void VisitControlVertex(VertexT *vertex);
ArkSteedSafepointTableBuilder *GetSafepointBuilder() const
{
return safepointBuilder_;
}
void RecordComment(const char *msg);
void RecordBlockComment(BB *block);
void RecordVertexComment(Vertex *vertex);
void AppendVertexInputInfo(std::ostringstream *ss, Vertex *vertex);
void AppendVertexSuccessorInfo(std::ostringstream *ss, Vertex *vertex);
void RecordGapMoveComment(const InstructionOperand &src, const InstructionOperand &dest, PhiVertex *phi);
void RecordSpillComment();
int ComputeDeferredBlocks();
void ReorderDeferredBlocks(int deferredCount);
bool IsNextBlockInLayout(BB *target) const;
bool AllPredecessorsDeferred(BB *block) const;
bool AllSuccessorsDeferred(BB *block);
static constexpr const char *BLOCK_COLORS[] = {
"\033[33m",
"\033[36m",
"\033[35m",
"\033[32m",
"\033[31m",
"\033[34m",
};
static constexpr int NUM_BLOCK_COLORS = 6;
static constexpr const char *COLOR_RESET = "\033[0m";
void ComputeBlockColors();
void BuildBlockAdjacencyList(std::vector<std::vector<int>> *adjacentBlocks);
void AssignBlockColors(const std::vector<std::vector<int>> &adjacentBlocks);
int GetBlockColorIndex(int blockId) const;
const char *GetBlockColor(int blockId) const
{
return BLOCK_COLORS[GetBlockColorIndex(blockId)];
}
void SetCurrentBlockColor(int blockId)
{
currentBlockColor_ = GetBlockColor(blockId);
}
const char *GetCurrentBlockColor() const
{
return currentBlockColor_;
}
ArkSteedAssembler *assembler_;
Graph *graph_;
ArkSteedSafepointTableBuilder *safepointBuilder_;
const char *currentBlockColor_ = "";
BB *currentLayoutNextBlock_ = nullptr;
ChunkVector<int> blockColorAssignment_;
bool blockColorsComputed_ = false;
};
}
#endif