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