1 /* 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_BYTECODE_OPT_CODEGEN_H 17 #define PANDA_BYTECODE_OPT_CODEGEN_H 18 19 #include "assembler/assembly-function.h" 20 #include "assembler/assembly-ins.h" 21 #include "ins_create_api.h" 22 #include "ir_interface.h" 23 #include "compiler/optimizer/pass.h" 24 #include "compiler/optimizer/ir/basicblock.h" 25 #include "compiler/optimizer/ir/graph.h" 26 #include "compiler/optimizer/ir/graph_visitor.h" 27 #include "utils/logger.h" 28 #include "common.h" 29 30 namespace ark::bytecodeopt { 31 32 using compiler::BasicBlock; 33 using compiler::Inst; 34 using compiler::Opcode; 35 36 void DoLdaObj(compiler::Register reg, std::vector<pandasm::Ins> &result); 37 void DoLda(compiler::Register reg, std::vector<pandasm::Ins> &result); 38 void DoLda64(compiler::Register reg, std::vector<pandasm::Ins> &result); 39 void DoStaObj(compiler::Register reg, std::vector<pandasm::Ins> &result); 40 void DoSta(compiler::Register reg, std::vector<pandasm::Ins> &result); 41 void DoSta64(compiler::Register reg, std::vector<pandasm::Ins> &result); 42 void DoSta(compiler::DataType::Type type, compiler::Register reg, std::vector<pandasm::Ins> &result); 43 void DoLdaDyn(compiler::Register reg, std::vector<pandasm::Ins> &result); 44 void DoStaDyn(compiler::Register reg, std::vector<pandasm::Ins> &result); 45 46 // NOLINTNEXTLINE(fuchsia-multiple-inheritance) 47 class BytecodeGen : public compiler::Optimization, public compiler::GraphVisitor { 48 public: BytecodeGen(compiler::Graph * graph,pandasm::Function * function,const BytecodeOptIrInterface * iface)49 explicit BytecodeGen(compiler::Graph *graph, pandasm::Function *function, const BytecodeOptIrInterface *iface) 50 : compiler::Optimization(graph), function_(function), irInterface_(iface) 51 { 52 } 53 ~BytecodeGen() override = default; 54 NO_COPY_SEMANTIC(BytecodeGen); 55 NO_MOVE_SEMANTIC(BytecodeGen); 56 57 bool RunImpl() override; GetPassName()58 const char *GetPassName() const override 59 { 60 return "BytecodeGen"; 61 } GetEncodedInstructions()62 std::vector<pandasm::Ins> GetEncodedInstructions() const 63 { 64 return res_; 65 } 66 67 void Reserve(size_t resSize = 0) 68 { 69 if (resSize > 0) { 70 result_.reserve(resSize); 71 } 72 } 73 GetStatus()74 bool GetStatus() const 75 { 76 return success_; 77 } 78 GetResult()79 const std::vector<pandasm::Ins> &GetResult() const 80 { 81 return result_; 82 } 83 GetResult()84 std::vector<pandasm::Ins> &&GetResult() 85 { 86 return std::move(result_); 87 } 88 GetMaxReg()89 static compiler::Register GetMaxReg() 90 { 91 return compiler::GetInvalidReg() - 1; 92 } 93 LabelName(uint32_t id)94 static std::string LabelName(uint32_t id) 95 { 96 return "label_" + std::to_string(id); 97 } 98 EmitLabel(const std::string & label)99 void EmitLabel(const std::string &label) 100 { 101 pandasm::Ins l; 102 l.label = label; 103 l.setLabel = true; 104 result_.emplace_back(l); 105 } 106 107 void EmitJump(const BasicBlock *bb); 108 109 void EncodeSpillFillData(const compiler::SpillFillData &sf); 110 void EncodeSta(compiler::Register reg, compiler::DataType::Type type); 111 void AddLineNumber(const Inst *inst, size_t idx); 112 void AddColumnNumber(const Inst *inst, uint32_t idx); 113 void AddLineAndColumnNumber(const Inst *inst, size_t idx); 114 GetBlocksToVisit()115 const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override 116 { 117 return GetGraph()->GetBlocksRPO(); 118 } 119 static void VisitSpillFill(GraphVisitor *v, Inst *inst); 120 static void VisitConstant(GraphVisitor *v, Inst *inst); 121 static void VisitCallStatic(GraphVisitor *visitor, Inst *inst); 122 static void VisitCallVirtual(GraphVisitor *visitor, Inst *inst); 123 static void VisitInitObject(GraphVisitor *visitor, Inst *inst); 124 static void VisitCatchPhi(GraphVisitor *visitor, Inst *inst); 125 126 static void VisitIf(GraphVisitor *v, Inst *instBase); 127 static void VisitIfImm(GraphVisitor *v, Inst *instBase); 128 static void VisitCast(GraphVisitor *v, Inst *instBase); 129 static void IfImmZero(GraphVisitor *v, Inst *instBase); 130 static void IfImmNonZero(GraphVisitor *v, Inst *instBase); 131 static void IfImm64(GraphVisitor *v, Inst *instBase); 132 static void VisitIntrinsic(GraphVisitor *v, Inst *instBase); 133 static void CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId); 134 static void CallHandler(GraphVisitor *visitor, Inst *inst); 135 static void VisitStoreObject(GraphVisitor *v, Inst *instBase); 136 static void VisitStoreStatic(GraphVisitor *v, Inst *instBase); 137 static void VisitLoadObject(GraphVisitor *v, Inst *instBase); 138 static void VisitLoadStatic(GraphVisitor *v, Inst *instBase); 139 static void VisitLoadString(GraphVisitor *v, Inst *instBase); 140 static void VisitReturn(GraphVisitor *v, Inst *instBase); 141 static void VisitReturnAny(GraphVisitor *v, Inst *instBase); 142 143 static void VisitCastValueToAnyType(GraphVisitor *v, Inst *instBase); 144 145 static void VisitEcma(GraphVisitor *v, Inst *instBase); 146 static void IfEcma(GraphVisitor *v, compiler::IfInst *inst); 147 148 #include "generated/codegen_visitors.inc" 149 150 #include "generated/insn_selection.h" 151 VisitDefault(Inst * inst)152 void VisitDefault(Inst *inst) override 153 { 154 LOG(ERROR, BYTECODE_OPTIMIZER) << "Opcode " << compiler::GetOpcodeString(inst->GetOpcode()) 155 << " not yet implemented in codegen"; 156 success_ = false; 157 } 158 159 #include "compiler/optimizer/ir/visitor.inc" 160 161 private: 162 void AppendCatchBlock(uint32_t typeId, const compiler::BasicBlock *tryBegin, const compiler::BasicBlock *tryEnd, 163 const compiler::BasicBlock *catchBegin, const compiler::BasicBlock *catchEnd = nullptr); 164 void VisitTryBegin(const compiler::BasicBlock *bb); 165 166 private: 167 pandasm::Function *function_; 168 const BytecodeOptIrInterface *irInterface_; 169 170 std::vector<pandasm::Ins> res_; 171 std::vector<pandasm::Function::CatchBlock> catchBlocks_; 172 173 bool success_ {true}; 174 std::vector<pandasm::Ins> result_; 175 }; 176 177 } // namespace ark::bytecodeopt 178 179 #endif // PANDA_BYTECODE_OPT_CODEGEN_H 180