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 GetModuleKind()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)76 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 struct DeoptBBInfo { 111 maple::litecg::BB *deoptBB = nullptr; 112 maple::litecg::PregIdx deoptTypePreg = 0; 113 std::map<uint32_t, maple::litecg::BB*> deoptType2BB; 114 DeoptBBInfoDeoptBBInfo115 DeoptBBInfo(maple::litecg::BB *bb, maple::litecg::PregIdx preg) : deoptBB(bb), deoptTypePreg(preg) 116 {} 117 ~DeoptBBInfo() = default; 118 }; 119 const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr}; 120 const Circuit *circuit_ {nullptr}; 121 LMIRModule *lmirModule_ {nullptr}; 122 const CompilationConfig *compCfg_ {nullptr}; 123 CallSignature::CallConv callConv_ = CallSignature::CallConv::CCallConv; 124 bool enableLog_ {false}; 125 bool enableOptInlining_ {false}; 126 const panda::ecmascript::MethodLiteral *methodLiteral_ {nullptr}; 127 const JSPandaFile *jsPandaFile_ {nullptr}; 128 std::string funcName_; 129 GateAccessor acc_; 130 maple::litecg::LMIRBuilder *lmirBuilder_ {nullptr}; 131 std::unordered_map<GateRef, maple::litecg::LiteCGValue> gate2Expr_; 132 std::set<OpCode> illegalOpHandlers_; 133 std::map<GateId, int> instID2bbID_; 134 std::map<int, maple::litecg::BB *> bbID2BB_; 135 int slotSize_ {-1}; 136 maple::litecg::Type *slotType_ {nullptr}; 137 std::map<int, std::vector<PhiDesc>> bbID2unmergedPhis_; 138 std::map<int, std::vector<PhiDesc>> bbID2basePhis_; // use for collect all the base references 139 // derived phi reference gate to base phi preg map 140 std::map<GateRef, maple::litecg::PregIdx> derivedPhiGate2BasePhiPreg_; 141 std::map<GateRef, GateRef> derivedGate2BaseGate_; // derived reference gate to base reference gate map 142 std::map<GateRef, bool> derivedGateCache_; // cache whether the phi reference is derived, base or unknow 143 std::map<GateRef, DeoptBBInfo> deoptFrameState2BB_; 144 maple::ConstantFold cf_; 145 std::unordered_map<GateRef, maple::litecg::Expr> derivedrefGate; 146 147 #define DECLAREVISITLOWEROPCODE(name, signature) void Visit##name signature; 148 OPCODES(DECLAREVISITLOWEROPCODE) 149 #undef DECLAREVISITLOWEROPCODE 150 #define DECLAREHANDLELOWEROPCODE(name, ignore) void Handle##name(GateRef gate); OPCODES(DECLAREHANDLELOWEROPCODE)151 OPCODES(DECLAREHANDLELOWEROPCODE) 152 #undef DECLAREHANDLELOWEROPCODE 153 void InsertUsedOpcodeSet(std::unordered_set<OpCode> &usedOpcodeSet, OpCode op) 154 { 155 if (enableLog_) { 156 usedOpcodeSet.insert(op); 157 } 158 } 159 maple::litecg::LiteCGValue ConstantFoldExpr(maple::litecg::Expr expr, maple::litecg::BB &curBB); 160 void SaveGate2Expr(GateRef gate, maple::litecg::Expr expr, bool isGlueAdd = false); 161 void SaveGate2Expr(GateRef gate, maple::litecg::PregIdx pregIdx1, maple::litecg::PregIdx pregIdx2); 162 maple::litecg::Expr CreateExprFromLiteCGValue(const maple::litecg::LiteCGValue &value); 163 maple::litecg::Expr GetExprFromGate(GateRef gate); 164 maple::litecg::Expr GetExprFromGate(GateRef gate, uint32_t index); 165 maple::litecg::Expr GetConstant(GateRef gate); 166 void BuildInstID2BBIDMap(); 167 maple::litecg::BB &GetOrCreateBB(int bbID); 168 maple::litecg::BB &GetFirstBB(); 169 maple::litecg::BB &CreateBB(); 170 void AddPhiDesc(int bbID, PhiDesc &desc, std::map<int, std::vector<PhiDesc>> &bbID2Phis); 171 DerivedStatus CheckDerivedPhi(GateRef gate, std::set<GateRef> &vis); 172 void FindBaseRefForPhi(GateRef gate, const std::vector<GateRef> &phiIns); 173 maple::litecg::Type *ConvertLiteCGTypeFromGate(GateRef gate, bool isSigned = true) const; 174 maple::litecg::IntCmpCondition ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const; 175 maple::litecg::FloatCmpCondition ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const; 176 void InitializeHandlers(); 177 maple::litecg::Expr GetGlue(const std::vector<GateRef> &inList); 178 maple::litecg::Expr GetRTStubOffset(maple::litecg::Expr glue, int index); 179 maple::litecg::Type *ConvertLiteCGTypeFromVariableType(VariableType type) const; 180 maple::litecg::Type *GenerateFuncType(const std::vector<maple::litecg::Expr> ¶ms, 181 const CallSignature *stubDescriptor); 182 maple::litecg::Type *GetFuncType(const CallSignature *stubDescriptor) const; 183 maple::litecg::Expr GetFunction(maple::litecg::BB &bb, maple::litecg::Expr glue, const CallSignature *signature, 184 maple::litecg::Expr rtbaseoffset, const std::string &realName = "") const; 185 bool IsOptimizedJSFunction() const; 186 bool IsOptimized() const; 187 CallExceptionKind GetCallExceptionKind(OpCode op, size_t index = SIZE_MAX) const; 188 maple::litecg::Expr GetRTStubOffset(maple::litecg::Expr glue, int index) const; 189 maple::litecg::Expr GetCoStubOffset(maple::litecg::Expr glue, int index) const; 190 maple::litecg::Expr GetBaselineStubOffset(maple::litecg::Expr glue, int index) const; 191 maple::litecg::Expr GetCallee(maple::litecg::BB &bb, const std::vector<GateRef> &inList, 192 const CallSignature *signature, const std::string &realName); 193 maple::litecg::Expr CanonicalizeToPtr(maple::litecg::Expr expr, maple::litecg::Type *type); 194 maple::litecg::Expr CanonicalizeToInt(GateRef gate); 195 int64_t GetBitWidthFromMachineType(MachineType machineType) const; 196 int LookupPredBB(GateRef start, int bbID); 197 maple::litecg::Expr GetBuiltinsStubOffset(maple::litecg::Expr glue); 198 void UpdateLeaveFrame(maple::litecg::Expr glue); 199 maple::litecg::Expr GetLeaveFrameOffset(maple::litecg::Expr glue); 200 maple::litecg::Expr CallingFp(bool isCaller); 201 maple::litecg::Expr GetBaseOffset(GateRef gate, maple::litecg::Expr glue); 202 maple::litecg::Expr GetBCDebugStubOffset(maple::litecg::Expr glue); 203 maple::litecg::Expr GetBCStubOffset(maple::litecg::Expr glue); 204 maple::litecg::Type *GetExperimentalDeoptTy(); 205 maple::litecg::Function *GetExperimentalDeopt(); 206 void GenDeoptEntry(std::string funcName); 207 void SaveFrameTypeOnFrame(maple::litecg::BB &bb, FrameType frameType); 208 maple::litecg::Expr ConvertToTagged(GateRef gate); 209 maple::litecg::Expr ConvertInt32ToTaggedInt(maple::litecg::Expr value); 210 maple::litecg::Expr ConvertBoolToTaggedBoolean(GateRef gate); 211 maple::litecg::Expr ConvertFloat64ToTaggedDouble(GateRef gate); 212 void SaveDeoptVregInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, maple::litecg::BB &bb, 213 int32_t index, size_t curDepth, size_t shift, GateRef gate); 214 void SaveDeoptVregInfoWithI64(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, 215 maple::litecg::BB &bb, int32_t index, size_t curDepth, size_t shift, GateRef gate); 216 217 maple::litecg::ConvAttr ConvertCallAttr(const CallSignature::CallConv callConv); 218 void CollectExraCallSiteInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, 219 maple::litecg::Expr pcOffset, GateRef frameArgs); 220 void GenPrologue(maple::litecg::Function &function); 221 void AssistGenPrologue(const size_t reservedSlotsSize, FrameType frameType, maple::litecg::Function &function); 222 void SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var &value); 223 void SaveJSFuncOnOptJSFuncFrame(maple::litecg::Function &function, maple::litecg::Var &value, int funcIndex); 224 void SaveFrameTypeOnFrame(maple::litecg::Function &function, FrameType frameType); 225 bool IsInterpreted() const; 226 bool IsBaselineBuiltin() const; 227 void AddFunc(); 228 void CollectDerivedRefInfo(); 229 void HandleBB(const std::vector<GateRef> &bb, std::unordered_set<OpCode> &usedOpcodeSet); IsLogEnabled()230 bool IsLogEnabled() const 231 { 232 return enableLog_; 233 } 234 void VisitBinaryOpWithOverflow(GateRef gate, GateRef e1, GateRef e2, maple::litecg::IntrinsicId intrinsicId); 235 void AddDerivedrefGate(GateRef gate, maple::litecg::Expr result); 236 maple::litecg::Expr GetDerivedrefExpr(GateRef gate); 237 DeoptBBInfo &GetOrCreateDeoptBBInfo(GateRef gate); 238 }; 239 } // namespace panda::ecmascript::kungfu 240 #endif // ECMASCRIPT_COMPILER_LITECG_IR_BUILDER_H 241