• 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/compiler/ir_module.h"
32 #include "ecmascript/compiler/ir_builder.h"
33 #include "ecmascript/jspandafile/method_literal.h"
34 #include "llvm-c/DebugInfo.h"
35 #include "llvm-c/Core.h"
36 
37 namespace panda::ecmascript::kungfu {
38 class BasicBlock;
39 class DebugInfo;
40 using BasicBlockMap = std::map<int, std::unique_ptr<BasicBlock>>;
41 class LLVMIRBuilder;
42 using HandleType = void(LLVMIRBuilder::*)(GateRef gate);
43 
44 class BasicBlock {
45 public:
BasicBlock(int id)46     explicit BasicBlock(int id) : id_(id)
47     {
48         predecessors_ = {};
49         successors_ = {};
50         impl_ = nullptr;
51     }
52 
GetId()53     int GetId() const
54     {
55         return id_;
56     }
57 
58     template<class T>
GetImpl()59     inline T *GetImpl() const
60     {
61         return static_cast<T *>(impl_);
62     }
63 
SetImpl(void * impl)64     inline void SetImpl(void *impl)
65     {
66         impl_ = impl;
67     }
68 
69     template<class T>
ResetImpl()70     inline void ResetImpl()
71     {
72         if (impl_) {
73             delete GetImpl<T>();
74             impl_ = nullptr;
75         }
76     }
77     ~BasicBlock() = default;
78 
79 private:
80     std::vector<BasicBlock *> predecessors_ {};
81     std::vector<BasicBlock *> successors_ {};
82     int id_ {-1};
83     void *impl_ {nullptr};
84 };
85 
86 struct NotMergedPhiDesc {
87     int predBBId;
88     GateRef operand;
89     LLVMValueRef phi;
90 };
91 
92 struct BasicBlockImpl {
93     LLVMBasicBlockRef lBB_ = nullptr;
94     LLVMBasicBlockRef continuation = nullptr;
95     bool started = false;
96     bool ended = false;
97     std::vector<NotMergedPhiDesc> unmergedPhis_;
98 };
99 
100 class LLVMModule : public IRModule {
101 public:
102     LLVMModule(NativeAreaAllocator* allocator, const std::string &name, bool logDbg, const std::string &triple);
103     ~LLVMModule();
104     void SetUpForCommonStubs();
105     void SetUpForBytecodeHandlerStubs();
106     void SetUpForBuiltinsStubs();
107     LLVMValueRef AddFunc(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile);
GetModule()108     LLVMModuleRef GetModule() const
109     {
110         return module_;
111     }
112     LLVMTypeRef GetFuncType(const CallSignature *stubDescriptor);
113 
114     LLVMTypeRef GenerateFuncType(const std::vector<LLVMValueRef> &params, const CallSignature *stubDescriptor);
115 
SetFunction(size_t index,LLVMValueRef func,bool isFastCall)116     void SetFunction(size_t index, LLVMValueRef func, bool isFastCall)
117     {
118         funcIndexMap_.emplace_back(std::make_tuple(index, func, isFastCall));
119     }
120 
GetModuleKind()121     ModuleKind GetModuleKind() const override
122     {
123         return MODULE_LLVM;
124     }
125 
GetFunction(size_t index)126     LLVMValueRef GetFunction(size_t index)
127     {
128         // next optimization can be performed
129         for (auto &it: funcIndexMap_) {
130             if (std::get<0>(it) == index) {
131                 return std::get<1>(it);
132             }
133         }
134         return nullptr;
135     }
136 
GetFuncCount()137     size_t GetFuncCount() const
138     {
139         return funcIndexMap_.size();
140     }
141 
142     template<class Callback>
IteratefuncIndexMap(const Callback & cb)143     void IteratefuncIndexMap(const Callback &cb) const
144     {
145         for (auto record : funcIndexMap_) {
146             // 2: 3nd param
147             cb(std::get<0>(record), std::get<1>(record), std::get<2>(record));
148         }
149     }
150 
GetCSign(size_t index)151     const CallSignature *GetCSign(size_t index) const
152     {
153         return callSigns_[index];
154     }
155 
GetCSigns()156     const std::vector<const CallSignature*> &GetCSigns() const
157     {
158         return callSigns_;
159     }
160 
GetContext()161     LLVMContextRef GetContext() const
162     {
163         return context_;
164     }
165 
GetDFileMD()166     LLVMMetadataRef GetDFileMD() const
167     {
168         return dFileMD_;
169     }
170 
GetDIBuilder()171     LLVMDIBuilderRef GetDIBuilder() const
172     {
173         return dBuilder_;
174     }
175 
176     LLVMValueRef GetDeoptFunction();
177 
178     static constexpr int kDeoptEntryOffset = 0;
179 
GetVoidT()180     LLVMTypeRef GetVoidT() const
181     {
182         return voidT_;
183     }
184 
GetInt1T()185     LLVMTypeRef GetInt1T() const
186     {
187         return int1T_;
188     }
189 
GetInt8T()190     LLVMTypeRef GetInt8T() const
191     {
192         return int8T_;
193     }
194 
GetInt16T()195     LLVMTypeRef GetInt16T() const
196     {
197         return int16T_;
198     }
199 
GetInt32T()200     LLVMTypeRef GetInt32T() const
201     {
202         return int32T_;
203     }
204 
GetInt64T()205     LLVMTypeRef GetInt64T() const
206     {
207         return int64T_;
208     }
209 
GetFloatT()210     LLVMTypeRef GetFloatT() const
211     {
212         return floatT_;
213     }
214 
GetDoubleT()215     LLVMTypeRef GetDoubleT() const
216     {
217         return doubleT_;
218     }
219 
GetTaggedPtrT()220     LLVMTypeRef GetTaggedPtrT() const
221     {
222         return taggedPtrT_;
223     }
224 
GetTaggedHPtrT()225     LLVMTypeRef GetTaggedHPtrT() const
226     {
227         return taggedHPtrT_;
228     }
229 
GetRawPtrT()230     LLVMTypeRef GetRawPtrT() const
231     {
232         return rawPtrT_;
233     }
234 private:
235     LLVMValueRef AddAndGetFunc(const CallSignature *stubDescriptor);
236     void InitialLLVMFuncTypeAndFuncByModuleCSigns();
237     LLVMTypeRef ConvertLLVMTypeFromVariableType(VariableType type);
238     LLVMTypeRef NewLType(MachineType machineType, GateType gateType);
239     // index:
240     //     stub scenario - sequence of function adding to llvmModule
241     //     aot scenario - method Id of function generated by panda files
242     std::vector<std::tuple<size_t, LLVMValueRef, bool>> funcIndexMap_;
243     std::vector<const CallSignature *> callSigns_;
244     LLVMModuleRef module_ {nullptr};
245     LLVMContextRef context_ {nullptr};
246     LLVMMetadataRef dFileMD_ {nullptr};
247     LLVMMetadataRef dUnitMD_ {nullptr};
248     LLVMDIBuilderRef dBuilder_ {nullptr};
249 
250     LLVMTypeRef voidT_ {nullptr};
251     LLVMTypeRef int1T_ {nullptr};
252     LLVMTypeRef int8T_ {nullptr};
253     LLVMTypeRef int16T_ {nullptr};
254     LLVMTypeRef int32T_ {nullptr};
255     LLVMTypeRef int64T_ {nullptr};
256     LLVMTypeRef floatT_ {nullptr};
257     LLVMTypeRef doubleT_ {nullptr};
258     LLVMTypeRef taggedHPtrT_ {nullptr};
259     LLVMTypeRef taggedPtrT_ {nullptr};
260     LLVMTypeRef rawPtrT_ {nullptr};
261 };
262 
263 // runtime/common stub ID, opcodeOffset for bc stub
264 using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, LLVMValueRef>;
265 
266 class LLVMIRBuilder {
267 public:
268     LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
269                   LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg,
270                   CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot, const std::string &funcName,
271                   bool enableOptInlining = false, bool enableOptBranchProfiling = true);
272     ~LLVMIRBuilder();
273     void Build();
274 
275 private:
276     #define DECLAREVISITOPCODE(name, signature) void Visit##name signature;
OPCODES(DECLAREVISITOPCODE)277         OPCODES(DECLAREVISITOPCODE)
278     #undef DECLAREVISITOPCODE
279     #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(GateRef gate);
280         OPCODES(DECLAREHANDLEOPCODE)
281     #undef DECLAREHANDLEOPCODE
282 
283     bool IsPrologue(int bbId) const
284     {
285         return bbId == 0;
286     }
287     void LinkToLLVMCfg(int bbId, const OperandsVector &predecessors);
288     BasicBlock *EnsureBB(int id);
289     LLVMValueRef CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller);
290     LLVMValueRef GetCurrentSP();
291     LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder, LLVMMetadataRef meta);
292     void GenPrologue();
293     LLVMBasicBlockRef EnsureLBB(BasicBlock *bb) const;
294     BasicBlockImpl *EnsureBBImpl(BasicBlock *bb) const;
295     void SetToCfg(BasicBlock *bb) const;
296 
297     LLVMTypeRef GetMachineRepType(MachineRep rep) const;
298     int FindBasicBlock(GateRef gate) const;
299     void EndCurrentBlock() const;
300     void Finish();
301 
302     void ProcessPhiWorkList();
303     void InitializeHandlers();
304     std::string LLVMValueToString(LLVMValueRef val) const;
305 
306     LLVMTypeRef ConvertLLVMTypeFromGate(GateRef gate) const;
307     int64_t GetBitWidthFromMachineType(MachineType machineType) const;
308     LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offsetInByte, LLVMTypeRef rep);
309     LLVMValueRef CanonicalizeToInt(LLVMValueRef value) const;
310     LLVMValueRef CanonicalizeToPtr(LLVMValueRef value) const;
311     LLVMValueRef CanonicalizeToPtr(LLVMValueRef value, LLVMTypeRef ptrType) const;
312     LLVMValueRef GetCurrentFrameType(LLVMValueRef currentSpFrameAddr);
313     void SetFunctionCallConv();
314 
IsLogEnabled()315     bool IsLogEnabled() const
316     {
317         return enableLog_;
318     }
319     LLVMValueRef GetFunction(LLVMValueRef glue, const CallSignature *signature, LLVMValueRef rtbaseoffset,
320                              const std::string &realName = "") const;
321     LLVMValueRef GetCallee(const std::vector<GateRef> &inList, const CallSignature *signature,
322                            const std::string &realName = "");
323     void CollectExraCallSiteInfo(std::vector<LLVMValueRef> &values, LLVMValueRef pcOffset,
324                                  GateRef frameState);
325     LLVMValueRef GetFunctionFromGlobalValue(LLVMValueRef glue, const CallSignature *signature,
326                                             LLVMValueRef reloc) const;
327     bool IsInterpreted() const;
328     bool IsOptimized() const;
329     bool IsOptimizedJSFunction() const;
330     void SetGCLeafFunction(LLVMValueRef call);
331     void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call);
332     bool IsHeapPointerType(LLVMTypeRef valueType);
333 
GetVoidT()334     LLVMTypeRef GetVoidT() const
335     {
336         return llvmModule_->GetVoidT();
337     }
338 
GetInt1T()339     LLVMTypeRef GetInt1T() const
340     {
341         return llvmModule_->GetInt1T();
342     }
343 
GetInt8T()344     LLVMTypeRef GetInt8T() const
345     {
346         return llvmModule_->GetInt8T();
347     }
348 
GetInt16T()349     LLVMTypeRef GetInt16T() const
350     {
351         return llvmModule_->GetInt16T();
352     }
353 
GetInt32T()354     LLVMTypeRef GetInt32T() const
355     {
356         return llvmModule_->GetInt32T();
357     }
358 
GetInt64T()359     LLVMTypeRef GetInt64T() const
360     {
361         return llvmModule_->GetInt64T();
362     }
363 
GetFloatT()364     LLVMTypeRef GetFloatT() const
365     {
366         return llvmModule_->GetFloatT();
367     }
368 
GetDoubleT()369     LLVMTypeRef GetDoubleT() const
370     {
371         return llvmModule_->GetDoubleT();
372     }
373 
GetTaggedPtrT()374     LLVMTypeRef GetTaggedPtrT() const
375     {
376         return llvmModule_->GetTaggedPtrT();
377     }
378 
GetTaggedHPtrT()379     LLVMTypeRef GetTaggedHPtrT() const
380     {
381         return llvmModule_->GetTaggedHPtrT();
382     }
383 
GetRawPtrT()384     LLVMTypeRef GetRawPtrT() const
385     {
386         return llvmModule_->GetRawPtrT();
387     }
388 
389 private:
GetDIBuilder()390     LLVMDIBuilderRef GetDIBuilder() const
391     {
392         return llvmModule_ == nullptr ? nullptr : llvmModule_->GetDIBuilder();
393     }
394 
395     unsigned GetPtrAddressSpace(LLVMValueRef v) const;
396     bool IsLInteger(LLVMValueRef v) const;
397     bool IsLPointer(LLVMValueRef v) const;
398     LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond);
399     LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond);
400     LLVMValueRef GetGlue(const std::vector<GateRef> &inList);
401     LLVMValueRef GetLeaveFrameOffset(LLVMValueRef glue);
402     LLVMValueRef GetRTStubOffset(LLVMValueRef glue, int index);
403     LLVMValueRef GetCoStubOffset(LLVMValueRef glue, int index);
404     LLVMValueRef GetBCStubOffset(LLVMValueRef glue);
405     LLVMValueRef GetBCDebugStubOffset(LLVMValueRef glue);
406     LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue);
407     LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue);
408     CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
409     void ComputeArgCountAndExtraInfo(size_t &actualNumArgs, LLVMValueRef &pcOffset, GateRef &frameArgs,
410                                     const std::vector<GateRef> &inList, CallExceptionKind kind);
411     void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
412     void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);
413     void SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder);
414     void UpdateLeaveFrame(LLVMValueRef glue);
415     LLVMTypeRef GetExperimentalDeoptTy();
416     LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module);
417     void GenDeoptEntry(LLVMModuleRef &module);
418     LLVMMetadataRef GetFunctionTypeMD(LLVMMetadataRef dFile);
419     bool SetDebugInfo(GateRef g, LLVMValueRef r);
420     LLVMValueRef ConvertToTagged(GateRef gate);
421     LLVMValueRef ConvertBoolToTaggedBoolean(GateRef gate);
422     LLVMValueRef ConvertInt32ToTaggedInt(GateRef gate);
423     LLVMValueRef ConvertInt32ToTaggedInt(LLVMValueRef value);
424     LLVMValueRef ConvertFloat64ToTaggedDouble(GateRef gate);
425     void SaveDeoptVregInfo(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift,
426                            GateRef gate);
427     void SaveDeoptVregInfoWithI64(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift,
428                            GateRef gate);
429     int LookupPredBB(GateRef start, int bbID);
GetLValue(const GateRef g)430     LLVMValueRef GetLValue(const GateRef g)
431     {
432         return gate2LValue_[g];
433     }
Bind(const GateRef g,const LLVMValueRef lv)434     void Bind(const GateRef g, const LLVMValueRef lv)
435     {
436         gate2LValue_[g] = lv;
437     }
438 
439     const CompilationConfig *compCfg_ {nullptr};
440     const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr};
441     const Circuit *circuit_ {nullptr};
442     GateAccessor acc_;
443     BasicBlock *currentBb_ {nullptr};
444     int lineNumber_ {0};
445 
446     LLVMModuleRef module_ {nullptr};
447     LLVMContextRef context_ {nullptr};
448     LLVMValueRef function_ {nullptr};
449     LLVMBuilderRef builder_ {nullptr};
450     std::map<GateId, int> instID2bbID_;
451     BasicBlockMap bbID2BB_;
452 
453     std::vector<BasicBlock *> phiRebuildWorklist_;
454     LLVMModule *llvmModule_ {nullptr};
455     std::unordered_map<GateRef, LLVMValueRef> gate2LValue_;
456     std::unordered_map<OpCode, HandleType> opHandlers_;
457     std::set<OpCode> illegalOpHandlers_;
458     int slotSize_ {-1};
459     LLVMTypeRef slotType_ {nullptr};
460     CallSignature::CallConv callConv_ = CallSignature::CallConv::CCallConv;
461     bool enableLog_ {false};
462     bool isFastCallAot_ {false};
463     LLVMMetadataRef dFuncMD_ {nullptr};
464     bool enableOptInlining_ {false};
465     bool enableOptBranchProfiling_ {true};
466 };
467 }  // namespace panda::ecmascript::kungfu
468 #endif  // ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H
469