1 /** 2 * Copyright (c) 2021-2022 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/annotation.h" 20 #include "assembler/assembly-function.h" 21 #include "assembler/assembly-ins.h" 22 #include "ins_create_api.h" 23 #include "ir_interface.h" 24 #include "compiler/optimizer/pass.h" 25 #include "compiler/optimizer/ir/basicblock.h" 26 #include "compiler/optimizer/ir/graph.h" 27 #include "compiler/optimizer/ir/graph_visitor.h" 28 #include "utils/logger.h" 29 30 namespace panda::bytecodeopt { 31 32 using compiler::BasicBlock; 33 using compiler::Inst; 34 using compiler::Opcode; 35 36 void DoLda(compiler::Register reg, std::vector<pandasm::Ins> &result); 37 void DoSta(compiler::Register reg, std::vector<pandasm::Ins> &result); 38 39 class BytecodeGen : public compiler::Optimization, public compiler::GraphVisitor { 40 public: BytecodeGen(compiler::Graph * graph,pandasm::Function * function,const BytecodeOptIrInterface * iface,pandasm::Program * prog)41 explicit BytecodeGen(compiler::Graph *graph, pandasm::Function *function, 42 const BytecodeOptIrInterface *iface, pandasm::Program *prog) 43 : compiler::Optimization(graph), function_(function), ir_interface_(iface), program_(prog) 44 { 45 } 46 ~BytecodeGen() override = default; 47 bool RunImpl() override; GetPassName()48 const char *GetPassName() const override 49 { 50 return "BytecodeGen"; 51 } GetEncodedInstructions()52 std::vector<pandasm::Ins> GetEncodedInstructions() const 53 { 54 return res_; 55 } 56 57 void Reserve(size_t res_size = 0) 58 { 59 if (res_size > 0) { 60 result_.reserve(res_size); 61 } 62 } 63 GetStatus()64 bool GetStatus() const 65 { 66 return success_; 67 } 68 GetResult()69 const std::vector<pandasm::Ins> &GetResult() const 70 { 71 return result_; 72 } 73 GetResult()74 std::vector<pandasm::Ins> &&GetResult() 75 { 76 return std::move(result_); 77 } 78 LabelName(uint32_t id)79 static std::string LabelName(uint32_t id) 80 { 81 return "label_" + std::to_string(id); 82 } 83 EmitLabel(const std::string label)84 void EmitLabel(const std::string label) 85 { 86 pandasm::Ins l; 87 l.label = label; 88 l.set_label = true; 89 result_.emplace_back(l); 90 } 91 92 void EmitJump(const BasicBlock *bb); 93 94 void EncodeSpillFillData(const compiler::SpillFillData &sf); 95 void EncodeSta(compiler::Register reg, compiler::DataType::Type type); 96 void AddLineNumber(const Inst *inst, const size_t idx); 97 void AddColumnNumber(const Inst *inst, const uint32_t idx); 98 GetBlocksToVisit()99 const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override 100 { 101 return GetGraph()->GetBlocksRPO(); 102 } 103 static void VisitSpillFill(GraphVisitor *v, Inst *inst); 104 static void VisitConstant(GraphVisitor *v, Inst *inst); 105 static void VisitCatchPhi(GraphVisitor *visitor, Inst *inst); 106 107 static void VisitIf(GraphVisitor *v, Inst *inst_base); 108 static void VisitIfImm(GraphVisitor *v, Inst *inst_base); 109 static void VisitCast(GraphVisitor *v, Inst *inst_base); 110 static void IfImmZero(GraphVisitor *v, Inst *inst_base); 111 static void IfImmNonZero(GraphVisitor *v, Inst *inst_base); 112 static void IfImm64(GraphVisitor *v, Inst *inst_base); 113 static void VisitIntrinsic(GraphVisitor *v, Inst *inst_base); 114 static void VisitLoadString(GraphVisitor *v, Inst *inst_base); 115 static void VisitReturn(GraphVisitor *v, Inst *inst_base); 116 117 static void VisitCastValueToAnyType(GraphVisitor *v, Inst *inst_base); 118 119 static void VisitEcma(GraphVisitor *v, Inst *inst_base); 120 static void IfEcma(GraphVisitor *v, compiler::IfInst *inst); 121 122 #include "generated/codegen_visitors.inc" 123 124 #include "generated/insn_selection.h" 125 VisitDefault(Inst * inst)126 void VisitDefault(Inst *inst) override 127 { 128 LOG(ERROR, BYTECODE_OPTIMIZER) << "Opcode " << compiler::GetOpcodeString(inst->GetOpcode()) 129 << " not yet implemented in codegen"; 130 success_ = false; 131 } 132 133 #include "compiler/optimizer/ir/visitor.inc" 134 135 private: 136 void AppendCatchBlock(uint32_t type_id, const compiler::BasicBlock *try_begin, const compiler::BasicBlock *try_end, 137 const compiler::BasicBlock *catch_begin, const compiler::BasicBlock *catch_end = nullptr); 138 void VisitTryBegin(const compiler::BasicBlock *bb); 139 140 // TypeInfoIndex typeinfo adaption 141 using Literal = panda::pandasm::LiteralArray::Literal; 142 using TypeInfoComponents = std::vector<Literal>; 143 void AddTypeInfoIndexForArguments(TypeInfoComponents *elements) const; 144 void AddOrderAndTypeInfoIndex(int32_t order, TypeInfoIndex type, TypeInfoComponents *elements) const; 145 void AddTypeInfoIndexForIns(int32_t order, size_t id, TypeInfoComponents *elements) const; 146 void UpdateTypeInfoIndexAnnotation(const TypeInfoComponents *elements); GetProgram()147 pandasm::Program *GetProgram() const 148 { 149 return program_; 150 } 151 152 private: 153 pandasm::Function *function_; 154 const BytecodeOptIrInterface *ir_interface_; 155 pandasm::Program *program_; 156 157 std::vector<pandasm::Ins> res_; 158 std::vector<pandasm::Function::CatchBlock> catch_blocks_; 159 160 bool success_ {true}; 161 std::vector<pandasm::Ins> result_; 162 }; 163 164 } // namespace panda::bytecodeopt 165 166 #endif // PANDA_BYTECODE_OPT_CODEGEN_H 167