1 /* 2 * Copyright (c) 2021-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 ECMASCRIPT_COMPILER_LITECG_IR_BUILDER_H 17 #define ECMASCRIPT_COMPILER_LITECG_IR_BUILDER_H 18 19 #include <map> 20 #include <vector> 21 22 #include "ecmascript/compiler/circuit.h" 23 #include "ecmascript/compiler/gate.h" 24 #include "ecmascript/compiler/stub_builder.h" 25 #include "ecmascript/compiler/call_signature.h" 26 #include "ecmascript/compiler/interpreter_stub.h" 27 #include "ecmascript/compiler/rt_call_signature.h" 28 #include "ecmascript/compiler/ir_builder.h" 29 #include "ecmascript/compiler/ir_module.h" 30 #include "ecmascript/jspandafile/method_literal.h" 31 #include "lmir_builder.h" 32 #include "constantfold.h" 33 34 namespace panda::ecmascript::kungfu { 35 class LMIRModule : public IRModule { 36 public: 37 static constexpr int kDeoptEntryOffset = 0; LMIRModule(NativeAreaAllocator *allocator, const std::string &name, bool logDbg, const std::string &triple, bool isJit)38 LMIRModule(NativeAreaAllocator *allocator, const std::string &name, bool logDbg, const std::string &triple, 39 bool isJit) 40 : IRModule(allocator, logDbg, triple) 41 { 42 moduleName = name; 43 module = isJit ? nullptr : maple::litecg::CreateModuleWithName(name); 44 } 45 ~LMIRModule()46 ~LMIRModule() 47 { 48 if (module != nullptr) { 49 maple::litecg::ReleaseModule(module); 50 } 51 } 52 JitCreateLitecgModule()53 void JitCreateLitecgModule() 54 { 55 ASSERT(module == nullptr); 56 module = maple::litecg::CreateModuleWithName(moduleName); 57 } 58 GetModule()59 maple::litecg::Module *GetModule() 60 { 61 ASSERT(module != nullptr); 62 return module; 63 } 64 65 ModuleKind GetModuleKind() const override 66 { 67 return MODULE_LITECG; 68 } 69 SetFunction(size_t index, std::string funcName, bool isFastCall)70 void SetFunction(size_t index, std::string funcName, bool isFastCall) 71 { 72 funcIndexMap_.emplace_back(std::make_tuple(index, funcName, isFastCall)); 73 } 74 75 template <class Callback> IteratefuncIndexMap(const Callback &cb) const76 void IteratefuncIndexMap(const Callback &cb) const 77 { 78 for (auto record : funcIndexMap_) { 79 // 2: 3nd param 80 cb(std::get<0>(record), std::get<1>(record), std::get<2>(record)); 81 } 82 } 83 84 private: 85 std::string moduleName; 86 maple::litecg::Module *module; 87 std::vector<std::tuple<size_t, std::string, bool>> funcIndexMap_; 88 }; 89 90 class LiteCGIRBuilder { 91 public: 92 LiteCGIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit, LMIRModule *module, 93 const CompilationConfig *cfg, CallSignature::CallConv callConv, bool enableLog, 94 bool enableOptInlining, const panda::ecmascript::MethodLiteral *methodLiteral, 95 const JSPandaFile *jsPandaFile, const std::string &funcName); 96 ~LiteCGIRBuilder(); 97 void Build(); 98 99 private: 100 struct PhiDesc { 101 int predBBId; 102 GateRef operand; 103 maple::litecg::PregIdx phi; 104 }; 105 enum DerivedStatus { 106 IS_DERIVED, 107 IS_BASE, 108 UNKNOW 109 }; 110 const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr}; 111 const Circuit *circuit_ {nullptr}; 112 LMIRModule *lmirModule_ {nullptr}; 113 const CompilationConfig *compCfg_ {nullptr}; 114 CallSignature::CallConv callConv_ = CallSignature::CallConv::CCallConv; 115 bool enableLog_ {false}; 116 bool enableOptInlining_ {false}; 117 const panda::ecmascript::MethodLiteral *methodLiteral_ {nullptr}; 118 const JSPandaFile *jsPandaFile_ {nullptr}; 119 std::string funcName_; 120 GateAccessor acc_; 121 maple::litecg::LMIRBuilder *lmirBuilder_ {nullptr}; 122 std::unordered_map<GateRef, maple::litecg::LiteCGValue> gate2Expr_; 123 std::set<OpCode> illegalOpHandlers_; 124 std::map<GateId, int> instID2bbID_; 125 std::map<int, maple::litecg::BB *> bbID2BB_; 126 int slotSize_ {-1}; 127 maple::litecg::Type *slotType_ {nullptr}; 128 std::map<int, std::vector<PhiDesc>> bbID2unmergedPhis_; 129 std::map<int, std::vector<PhiDesc>> bbID2basePhis_; // use for collect all the base references 130 // derived phi reference gate to base phi preg map 131 std::map<GateRef, maple::litecg::PregIdx> derivedPhiGate2BasePhiPreg_; 132 std::map<GateRef, GateRef> derivedGate2BaseGate_; // derived reference gate to base reference gate map 133 std::map<GateRef, bool> derivedGateCache_; // cache whether the phi reference is derived, base or unknow 134 maple::ConstantFold cf_; 135 136 #define DECLAREVISITLOWEROPCODE(name, signature) void Visit##name signature; 137 OPCODES(DECLAREVISITLOWEROPCODE) 138 #undef DECLAREVISITLOWEROPCODE 139 #define DECLAREHANDLELOWEROPCODE(name, ignore) void Handle##name(GateRef gate); 140 OPCODES(DECLAREHANDLELOWEROPCODE) 141 #undef DECLAREHANDLELOWEROPCODE InsertUsedOpcodeSet(std::unordered_set<OpCode> &usedOpcodeSet, OpCode op)142 void InsertUsedOpcodeSet(std::unordered_set<OpCode> &usedOpcodeSet, OpCode op) 143 { 144 if (enableLog_) { 145 usedOpcodeSet.insert(op); 146 } 147 } 148 void SaveGate2Expr(GateRef gate, maple::litecg::Expr expr, bool isGlueAdd = false); 149 void SaveGate2Expr(GateRef gate, maple::litecg::PregIdx pregIdx1, maple::litecg::PregIdx pregIdx2); 150 maple::litecg::Expr GetExprFromGate(GateRef gate); 151 maple::litecg::Expr GetExprFromGate(GateRef gate, uint32_t index); 152 maple::litecg::Expr GetConstant(GateRef gate); 153 void BuildInstID2BBIDMap(); 154 maple::litecg::BB &GetOrCreateBB(int bbID); 155 maple::litecg::BB &GetFirstBB(); 156 maple::litecg::BB &CreateBB(); 157 void AddPhiDesc(int bbID, PhiDesc &desc, std::map<int, std::vector<PhiDesc>> &bbID2Phis); 158 DerivedStatus CheckDerivedPhi(GateRef gate, std::set<GateRef> &vis); 159 void FindBaseRefForPhi(GateRef gate, const std::vector<GateRef> &phiIns); 160 maple::litecg::Type *ConvertLiteCGTypeFromGate(GateRef gate, bool isSigned = true) const; 161 maple::litecg::IntCmpCondition ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const; 162 maple::litecg::FloatCmpCondition ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const; 163 void InitializeHandlers(); 164 maple::litecg::Expr GetGlue(const std::vector<GateRef> &inList); 165 maple::litecg::Expr GetRTStubOffset(maple::litecg::Expr glue, int index); 166 maple::litecg::Type *ConvertLiteCGTypeFromVariableType(VariableType type) const; 167 maple::litecg::Type *GenerateFuncType(const std::vector<maple::litecg::Expr> ¶ms, 168 const CallSignature *stubDescriptor); 169 maple::litecg::Type *GetFuncType(const CallSignature *stubDescriptor) const; 170 maple::litecg::Expr GetFunction(maple::litecg::BB &bb, maple::litecg::Expr glue, const CallSignature *signature, 171 maple::litecg::Expr rtbaseoffset, const std::string &realName = "") const; 172 bool IsOptimizedJSFunction() const; 173 bool IsOptimized() const; 174 CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const; 175 maple::litecg::Expr GetRTStubOffset(maple::litecg::Expr glue, int index) const; 176 maple::litecg::Expr GetCoStubOffset(maple::litecg::Expr glue, int index) const; 177 maple::litecg::Expr GetBaselineStubOffset(maple::litecg::Expr glue, int index) const; 178 maple::litecg::Expr GetCallee(maple::litecg::BB &bb, const std::vector<GateRef> &inList, 179 const CallSignature *signature, const std::string &realName); 180 maple::litecg::Expr CanonicalizeToPtr(maple::litecg::Expr expr, maple::litecg::Type *type); 181 maple::litecg::Expr CanonicalizeToInt(GateRef gate); 182 int64_t GetBitWidthFromMachineType(MachineType machineType) const; 183 int LookupPredBB(GateRef start, int bbID); 184 maple::litecg::Expr GetBuiltinsStubOffset(maple::litecg::Expr glue); 185 void UpdateLeaveFrame(maple::litecg::Expr glue); 186 maple::litecg::Expr GetLeaveFrameOffset(maple::litecg::Expr glue); 187 maple::litecg::Expr CallingFp(bool isCaller); 188 maple::litecg::Expr GetBaseOffset(GateRef gate, maple::litecg::Expr glue); 189 maple::litecg::Expr GetBCDebugStubOffset(maple::litecg::Expr glue); 190 maple::litecg::Expr GetBCStubOffset(maple::litecg::Expr glue); 191 maple::litecg::Type *GetExperimentalDeoptTy(); 192 maple::litecg::Function *GetExperimentalDeopt(); 193 void GenDeoptEntry(std::string funcName); 194 void SaveFrameTypeOnFrame(maple::litecg::BB &bb, FrameType frameType); 195 maple::litecg::Expr ConvertToTagged(GateRef gate); 196 maple::litecg::Expr ConvertInt32ToTaggedInt(maple::litecg::Expr value); 197 maple::litecg::Expr ConvertBoolToTaggedBoolean(GateRef gate); 198 maple::litecg::Expr ConvertFloat64ToTaggedDouble(GateRef gate); 199 void SaveDeoptVregInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, maple::litecg::BB &bb, 200 int32_t index, size_t curDepth, size_t shift, GateRef gate); 201 void SaveDeoptVregInfoWithI64(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, 202 maple::litecg::BB &bb, int32_t index, size_t curDepth, size_t shift, GateRef gate); 203 204 maple::litecg::ConvAttr ConvertCallAttr(const CallSignature::CallConv callConv); 205 void CollectExraCallSiteInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, 206 maple::litecg::Expr pcOffset, GateRef frameArgs); 207 void GenPrologue(maple::litecg::Function &function); 208 void AssistGenPrologue(const size_t reservedSlotsSize, FrameType frameType, maple::litecg::Function &function); 209 void SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var &value); 210 void SaveJSFuncOnOptJSFuncFrame(maple::litecg::Function &function, maple::litecg::Var &value, int funcIndex); 211 void SaveFrameTypeOnFrame(maple::litecg::Function &function, FrameType frameType); 212 bool IsInterpreted() const; 213 bool IsBaselineBuiltin() const; 214 void AddFunc(); 215 void CollectDerivedRefInfo(); 216 void HandleBB(const std::vector<GateRef> &bb, std::unordered_set<OpCode> &usedOpcodeSet); IsLogEnabled() const217 bool IsLogEnabled() const 218 { 219 return enableLog_; 220 } 221 void VisitBinaryOpWithOverflow(GateRef gate, GateRef e1, GateRef e2, maple::litecg::IntrinsicId intrinsicId); 222 }; 223 } // namespace panda::ecmascript::kungfu 224 #endif // ECMASCRIPT_COMPILER_LITECG_IR_BUILDER_H 225