• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_LLVM_IR_BUILDER_H
17 #define ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H
18 
19 #include <map>
20 #include <memory>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "ecmascript/compiler/circuit.h"
25 #include "ecmascript/compiler/gate.h"
26 #include "ecmascript/compiler/stub_builder.h"
27 #include "ecmascript/compiler/call_signature.h"
28 #include "ecmascript/compiler/common_stubs.h"
29 #include "ecmascript/compiler/interpreter_stub.h"
30 #include "ecmascript/compiler/rt_call_signature.h"
31 #include "ecmascript/jspandafile/method_literal.h"
32 
33 #include "llvm-c/Core.h"
34 
35 namespace panda::ecmascript::kungfu {
36 using OperandsVector = std::set<int>;
37 class BasicBlock;
38 using BasicBlockMap = std::map<int, std::unique_ptr<BasicBlock>>;
39 class LLVMIRBuilder;
40 using HandleType = void(LLVMIRBuilder::*)(GateRef gate);
41 
42 enum class MachineRep {
43     K_NONE,
44     K_BIT,
45     K_WORD8,
46     K_WORD16,
47     K_WORD32,
48     K_WORD64,
49     // FP representations must be last, and in order of increasing size.
50     K_FLOAT32,
51     K_FLOAT64,
52     K_SIMD128,
53     K_PTR_1, // Tagged Pointer
54     K_META,
55 };
56 
57 class BasicBlock {
58 public:
BasicBlock(int id)59     explicit BasicBlock(int id) : id_(id)
60     {
61         predecessors_ = {};
62         successors_ = {};
63         impl_ = nullptr;
64     }
65 
GetId()66     int GetId() const
67     {
68         return id_;
69     }
70 
71     template<class T>
GetImpl()72     inline T *GetImpl() const
73     {
74         return static_cast<T *>(impl_);
75     }
76 
SetImpl(void * impl)77     inline void SetImpl(void *impl)
78     {
79         impl_ = impl;
80     }
81 
82     template<class T>
ResetImpl()83     inline void ResetImpl()
84     {
85         if (impl_) {
86             delete GetImpl<T>();
87             impl_ = nullptr;
88         }
89     }
90     ~BasicBlock() = default;
91 
92 private:
93     std::vector<BasicBlock *> predecessors_ {};
94     std::vector<BasicBlock *> successors_ {};
95     int id_ {-1};
96     void *impl_ {nullptr};
97 };
98 
99 struct NotMergedPhiDesc {
100     BasicBlock *pred;
101     GateRef operand;
102     LLVMValueRef phi;
103 };
104 
105 struct BasicBlockImpl {
106     LLVMBasicBlockRef lBB_ = nullptr;
107     LLVMBasicBlockRef continuation = nullptr;
108     bool started = false;
109     bool ended = false;
110     std::vector<NotMergedPhiDesc> unmergedPhis_;
111 };
112 
113 class LLVMModule {
114 public:
115     LLVMModule(const std::string &name, const std::string &triple, bool enablePGOProfiler = false);
116     ~LLVMModule();
117     void SetUpForCommonStubs();
118     void SetUpForBytecodeHandlerStubs();
119     void SetUpForBuiltinsStubs();
120     LLVMValueRef AddFunc(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile);
GetModule()121     LLVMModuleRef GetModule() const
122     {
123         return module_;
124     }
125     LLVMTypeRef GetFuncType(const CallSignature *stubDescriptor);
126 
127     LLVMTypeRef GenerateFuncType(const std::vector<LLVMValueRef> &params, const CallSignature *stubDescriptor);
128 
SetFunction(size_t index,LLVMValueRef func)129     void SetFunction(size_t index, LLVMValueRef func)
130     {
131         funcIndexMap_.emplace_back(std::make_pair(index, func));
132     }
133 
GetFunction(size_t index)134     LLVMValueRef GetFunction(size_t index)
135     {
136         // next optimization can be performed
137         for (auto &it: funcIndexMap_) {
138             if (it.first == index) {
139                 return it.second;
140             }
141         }
142         return nullptr;
143     }
144 
GetFuncCount()145     size_t GetFuncCount() const
146     {
147         return funcIndexMap_.size();
148     }
149 
150     template<class Callback>
IteratefuncIndexMap(const Callback & cb)151     void IteratefuncIndexMap(const Callback &cb) const
152     {
153         for (auto record : funcIndexMap_) {
154             cb(record.first, record.second);
155         }
156     }
157 
GetCSign(size_t index)158     const CallSignature *GetCSign(size_t index) const
159     {
160         return callSigns_[index];
161     }
162 
GetCompilationConfig()163     const CompilationConfig *GetCompilationConfig() const
164     {
165         return &cfg_;
166     }
167 
GetCSigns()168     const std::vector<const CallSignature*> &GetCSigns() const
169     {
170         return callSigns_;
171     }
172 
173     LLVMValueRef GetDeoptFunction() const;
174 
175     static constexpr int kDeoptEntryOffset = 0;
176 private:
177     LLVMValueRef AddAndGetFunc(const CallSignature *stubDescriptor);
178     void InitialLLVMFuncTypeAndFuncByModuleCSigns();
179     LLVMTypeRef ConvertLLVMTypeFromVariableType(VariableType type);
180     LLVMTypeRef NewLType(MachineType machineType, GateType gateType);
181     // index:
182     //     stub scenario - sequence of function adding to llvmModule
183     //     aot scenario - method Id of function generated by panda files
184     std::vector<std::pair<size_t, LLVMValueRef>> funcIndexMap_;
185     std::vector<const CallSignature *> callSigns_;
186     LLVMModuleRef module_;
187     CompilationConfig cfg_;
188 };
189 
190 
191 #define OPCODES(V)                                                                        \
192     V(Call, (GateRef gate, const std::vector<GateRef> &inList, OpCode op))                \
193     V(RuntimeCall, (GateRef gate, const std::vector<GateRef> &inList))                    \
194     V(RuntimeCallWithArgv, (GateRef gate, const std::vector<GateRef> &inList))            \
195     V(NoGcRuntimeCall, (GateRef gate, const std::vector<GateRef> &inList))                \
196     V(BytecodeCall, (GateRef gate, const std::vector<GateRef> &inList))                   \
197     V(Alloca, (GateRef gate))                                                             \
198     V(Block, (int id, const OperandsVector &predecessors))                                \
199     V(Goto, (int block, int bbout))                                                       \
200     V(Parameter, (GateRef gate))                                                          \
201     V(Constant, (GateRef gate, std::bitset<64> value))                                    \
202     V(RelocatableData, (GateRef gate, uint64_t value))                                    \
203     V(ZExtInt, (GateRef gate, GateRef e1))                                                \
204     V(SExtInt, (GateRef gate, GateRef e1))                                                \
205     V(FPExt, (GateRef gate, GateRef e1))                                                  \
206     V(FPTrunc, (GateRef gate, GateRef e1))                                                \
207     V(Load, (GateRef gate, GateRef base))                                                 \
208     V(Store, (GateRef gate, GateRef base, GateRef value))                                 \
209     V(IntRev, (GateRef gate, GateRef e1))                                                 \
210     V(Add, (GateRef gate, GateRef e1, GateRef e2))                                        \
211     V(Sub, (GateRef gate, GateRef e1, GateRef e2))                                        \
212     V(Mul, (GateRef gate, GateRef e1, GateRef e2))                                        \
213     V(FloatDiv, (GateRef gate, GateRef e1, GateRef e2))                                   \
214     V(IntDiv, (GateRef gate, GateRef e1, GateRef e2))                                     \
215     V(UDiv, (GateRef gate, GateRef e1, GateRef e2))                                       \
216     V(IntOr, (GateRef gate, GateRef e1, GateRef e2))                                      \
217     V(IntAnd, (GateRef gate, GateRef e1, GateRef e2))                                     \
218     V(IntXor, (GateRef gate, GateRef e1, GateRef e2))                                     \
219     V(IntLsr, (GateRef gate, GateRef e1, GateRef e2))                                     \
220     V(IntAsr, (GateRef gate, GateRef e1, GateRef e2))                                     \
221     V(Int32LessThanOrEqual, (GateRef gate, GateRef e1, GateRef e2))                       \
222     V(Cmp, (GateRef gate, GateRef e1, GateRef e2))                                        \
223     V(Branch, (GateRef gate, GateRef cmp, GateRef btrue, GateRef bfalse))                 \
224     V(Switch, (GateRef gate, GateRef input, const std::vector<GateRef> &outList))         \
225     V(SwitchCase, (GateRef gate, GateRef switchBranch, GateRef out))                      \
226     V(Phi, (GateRef gate, const std::vector<GateRef> &srcGates))                          \
227     V(Return, (GateRef gate, GateRef popCount, const std::vector<GateRef> &operands))     \
228     V(ReturnVoid, (GateRef gate))                                                         \
229     V(CastIntXToIntY, (GateRef gate, GateRef e1))                                         \
230     V(ChangeInt32ToDouble, (GateRef gate, GateRef e1))                                    \
231     V(ChangeUInt32ToDouble, (GateRef gate, GateRef e1))                                   \
232     V(ChangeDoubleToInt32, (GateRef gate, GateRef e1))                                    \
233     V(BitCast, (GateRef gate, GateRef e1))                                                \
234     V(IntLsl, (GateRef gate, GateRef e1, GateRef e2))                                     \
235     V(Mod, (GateRef gate, GateRef e1, GateRef e2))                                        \
236     V(ChangeTaggedPointerToInt64, (GateRef gate, GateRef e1))                             \
237     V(ChangeInt64ToTagged, (GateRef gate, GateRef e1))                                    \
238     V(Deopt, (GateRef gate))                                                              \
239     V(TruncFloatToInt, (GateRef gate, GateRef e1))                                        \
240 
241 // runtime/common stub ID, opcodeOffset for bc stub
242 using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, LLVMValueRef>;
243 class LLVMIRBuilder {
244 public:
245     explicit LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
246                            LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg,
247                            CallSignature::CallConv callConv, bool enableLog = false);
248     ~LLVMIRBuilder();
249     void Build();
250 
251 private:
252     #define DECLAREVISITOPCODE(name, signature) void Visit##name signature;
OPCODES(DECLAREVISITOPCODE)253         OPCODES(DECLAREVISITOPCODE)
254     #undef DECLAREVISITOPCODE
255     #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(GateRef gate);
256         OPCODES(DECLAREHANDLEOPCODE)
257     #undef DECLAREHANDLEOPCODE
258 
259     bool isPrologue(int bbId) const
260     {
261         return bbId == 0;
262     }
263     void LinkToLLVMCfg(int bbId, const OperandsVector &predecessors);
264     BasicBlock *EnsureBB(int id);
265     LLVMValueRef CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller);
266     LLVMValueRef GetCurrentSP();
267     LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder,
268         LLVMMetadataRef meta);
269     void GenPrologue();
270     LLVMBasicBlockRef EnsureLBB(BasicBlock *bb) const;
271     BasicBlockImpl *EnsureBBImpl(BasicBlock *bb) const;
272     void SetToCfg(BasicBlock *bb) const;
273 
274     LLVMTypeRef GetMachineRepType(MachineRep rep) const;
275     int FindBasicBlock(GateRef gate) const;
276     void EndCurrentBlock() const;
277     void Finish();
278 
279     void ProcessPhiWorkList();
280     void InitializeHandlers();
281     std::string LLVMValueToString(LLVMValueRef val) const;
282 
GetIntPtr()283     LLVMTypeRef GetIntPtr() const
284     {
285         if (compCfg_->Is32Bit()) {
286             return LLVMInt32Type();
287         }
288         return LLVMInt64Type();
289     }
290     LLVMTypeRef ConvertLLVMTypeFromGate(GateRef gate) const;
291     int64_t GetBitWidthFromMachineType(MachineType machineType) const;
292     LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep);
293     LLVMValueRef VectorAdd(LLVMValueRef e1Value, LLVMValueRef e2Value, LLVMTypeRef rep);
294     LLVMValueRef CanonicalizeToInt(LLVMValueRef value);
295     LLVMValueRef CanonicalizeToPtr(LLVMValueRef value);
296     LLVMValueRef GetCurrentFrameType(LLVMValueRef currentSpFrameAddr);
297     void SetFunctionCallConv();
298 
IsLogEnabled()299     bool IsLogEnabled() const
300     {
301         return enableLog_;
302     }
303     LLVMValueRef GetFunction(LLVMValueRef glue, const CallSignature *signature, LLVMValueRef rtbaseoffset,
304                              const std::string &realName = "") const;
305     LLVMValueRef GetFunctionFromGlobalValue(LLVMValueRef glue, const CallSignature *signature,
306         LLVMValueRef reloc) const;
307     bool IsInterpreted();
308     bool IsOptimized();
309     void SetGCLeafFunction(LLVMValueRef call);
310     void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call);
311     bool IsHeapPointerType(LLVMTypeRef valueType);
312 
313 private:
314     enum class CallInputs : size_t {
315         DEPEND = 0,
316         TARGET,
317         GLUE,
318         FIRST_PARAMETER
319     };
320     enum class CallExceptionKind : bool {
321         HAS_BC_OFFSET = true,
322         NO_BC_OFFSET = false
323     };
324     LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond);
325     LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond);
326     LLVMValueRef GetGlue(const std::vector<GateRef> &inList);
327     LLVMValueRef GetLeaveFrameOffset(LLVMValueRef glue);
328     LLVMValueRef GetRTStubOffset(LLVMValueRef glue, int index);
329     LLVMValueRef GetCoStubOffset(LLVMValueRef glue, int index);
330     LLVMValueRef GetBCStubOffset(LLVMValueRef glue);
331     LLVMValueRef GetBCDebugStubOffset(LLVMValueRef glue);
332     LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue);
333     LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue);
334     CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
335     void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector<GateRef> &inList,
336                                     CallExceptionKind kind);
337     void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
338     void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);
339     void SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder);
340     void UpdateLeaveFrame(LLVMValueRef glue);
341     LLVMTypeRef GetExperimentalDeoptTy();
342     LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module);
343     void GenDeoptEntry(LLVMModuleRef &module);
344     const CompilationConfig *compCfg_ {nullptr};
345     const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr};
346     const Circuit *circuit_ {nullptr};
347     GateAccessor acc_;
348     BasicBlock *currentBb_ {nullptr};
349     int lineNumber_ {0};
350 
351     LLVMModuleRef module_ {nullptr};
352     LLVMContextRef context_;
353     LLVMValueRef function_ {nullptr};
354     LLVMBuilderRef builder_ {nullptr};
355     std::map<GateId, int> instID2bbID_;
356     BasicBlockMap bbID2BB_;
357 
358     std::vector<BasicBlock *> phiRebuildWorklist_;
359     LLVMModule *llvmModule_ {nullptr};
360     std::unordered_map<GateRef, LLVMValueRef> gate2LValue_;
361     std::unordered_map<OpCode, HandleType> opHandlers_;
362     std::set<OpCode> illegalOpHandlers_;
363     int slotSize_;
364     LLVMTypeRef slotType_;
365     CallSignature::CallConv callConv_ = CallSignature::CallConv::CCallConv;
366     bool enableLog_ {false};
367 };
368 }  // namespace panda::ecmascript::kungfu
369 #endif  // PANDA_RUNTIME_ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H
370