• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params,
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