• 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 #include "llvm-c/DebugInfo.h"
33 #include "llvm-c/Core.h"
34 
35 namespace panda::ecmascript::kungfu {
36 using OperandsVector = std::set<int>;
37 class BasicBlock;
38 class DebugInfo;
39 using BasicBlockMap = std::map<int, std::unique_ptr<BasicBlock>>;
40 class LLVMIRBuilder;
41 using HandleType = void(LLVMIRBuilder::*)(GateRef gate);
42 
43 enum class MachineRep {
44     K_NONE,
45     K_BIT,
46     K_WORD8,
47     K_WORD16,
48     K_WORD32,
49     K_WORD64,
50     // FP representations must be last, and in order of increasing size.
51     K_FLOAT32,
52     K_FLOAT64,
53     K_SIMD128,
54     K_PTR_1, // Tagged Pointer
55     K_META,
56 };
57 
58 class BasicBlock {
59 public:
BasicBlock(int id)60     explicit BasicBlock(int id) : id_(id)
61     {
62         predecessors_ = {};
63         successors_ = {};
64         impl_ = nullptr;
65     }
66 
GetId()67     int GetId() const
68     {
69         return id_;
70     }
71 
72     template<class T>
GetImpl()73     inline T *GetImpl() const
74     {
75         return static_cast<T *>(impl_);
76     }
77 
SetImpl(void * impl)78     inline void SetImpl(void *impl)
79     {
80         impl_ = impl;
81     }
82 
83     template<class T>
ResetImpl()84     inline void ResetImpl()
85     {
86         if (impl_) {
87             delete GetImpl<T>();
88             impl_ = nullptr;
89         }
90     }
91     ~BasicBlock() = default;
92 
93 private:
94     std::vector<BasicBlock *> predecessors_ {};
95     std::vector<BasicBlock *> successors_ {};
96     int id_ {-1};
97     void *impl_ {nullptr};
98 };
99 
100 struct NotMergedPhiDesc {
101     int predBBId;
102     GateRef operand;
103     LLVMValueRef phi;
104 };
105 
106 struct BasicBlockImpl {
107     LLVMBasicBlockRef lBB_ = nullptr;
108     LLVMBasicBlockRef continuation = nullptr;
109     bool started = false;
110     bool ended = false;
111     std::vector<NotMergedPhiDesc> unmergedPhis_;
112 };
113 
114 class LLVMModule {
115 public:
116     LLVMModule(NativeAreaAllocator* allocator, const std::string &name, bool logDbg, const std::string &triple);
117     ~LLVMModule();
118     void SetUpForCommonStubs();
119     void SetUpForBytecodeHandlerStubs();
120     void SetUpForBuiltinsStubs();
121     LLVMValueRef AddFunc(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile);
GetModule()122     LLVMModuleRef GetModule() const
123     {
124         return module_;
125     }
126     LLVMTypeRef GetFuncType(const CallSignature *stubDescriptor);
127 
128     LLVMTypeRef GenerateFuncType(const std::vector<LLVMValueRef> &params, const CallSignature *stubDescriptor);
129 
SetFunction(size_t index,LLVMValueRef func,bool isFastCall)130     void SetFunction(size_t index, LLVMValueRef func, bool isFastCall)
131     {
132         funcIndexMap_.emplace_back(std::make_tuple(index, func, isFastCall));
133     }
134 
GetFunction(size_t index)135     LLVMValueRef GetFunction(size_t index)
136     {
137         // next optimization can be performed
138         for (auto &it: funcIndexMap_) {
139             if (std::get<0>(it) == index) {
140                 return std::get<1>(it);
141             }
142         }
143         return nullptr;
144     }
145 
Is64Bit()146     bool Is64Bit() const
147     {
148         return is64Bit_;
149     }
150 
Is32Bit()151     bool Is32Bit() const
152     {
153         return !is64Bit_;
154     }
155 
GetFuncCount()156     size_t GetFuncCount() const
157     {
158         return funcIndexMap_.size();
159     }
160 
161     template<class Callback>
IteratefuncIndexMap(const Callback & cb)162     void IteratefuncIndexMap(const Callback &cb) const
163     {
164         for (auto record : funcIndexMap_) {
165             // 2: 3nd param
166             cb(std::get<0>(record), std::get<1>(record), std::get<2>(record));
167         }
168     }
169 
GetCSign(size_t index)170     const CallSignature *GetCSign(size_t index) const
171     {
172         return callSigns_[index];
173     }
174 
GetTripleStr()175     const std::string &GetTripleStr() const
176     {
177         return tripleStr_;
178     }
179 
GetCSigns()180     const std::vector<const CallSignature*> &GetCSigns() const
181     {
182         return callSigns_;
183     }
184 
GetContext()185     LLVMContextRef GetContext() const
186     {
187         return context_;
188     }
189 
GetDFileMD()190     LLVMMetadataRef GetDFileMD() const
191     {
192         return dFileMD_;
193     }
194 
GetDIBuilder()195     LLVMDIBuilderRef GetDIBuilder() const
196     {
197         return dBuilder_;
198     }
199 
200     LLVMValueRef GetDeoptFunction();
201 
GetDebugInfo()202     DebugInfo* GetDebugInfo() const
203     {
204         return debugInfo_;
205     }
206 
GetTriple()207     Triple GetTriple() const
208     {
209         return triple_;
210     }
211 
212     std::string GetFuncName(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile);
213 
214     static constexpr int kDeoptEntryOffset = 0;
215 
GetVoidT()216     LLVMTypeRef GetVoidT() const
217     {
218         return voidT_;
219     }
220 
GetInt1T()221     LLVMTypeRef GetInt1T() const
222     {
223         return int1T_;
224     }
225 
GetInt8T()226     LLVMTypeRef GetInt8T() const
227     {
228         return int8T_;
229     }
230 
GetInt16T()231     LLVMTypeRef GetInt16T() const
232     {
233         return int16T_;
234     }
235 
GetInt32T()236     LLVMTypeRef GetInt32T() const
237     {
238         return int32T_;
239     }
240 
GetInt64T()241     LLVMTypeRef GetInt64T() const
242     {
243         return int64T_;
244     }
245 
GetFloatT()246     LLVMTypeRef GetFloatT() const
247     {
248         return floatT_;
249     }
250 
GetDoubleT()251     LLVMTypeRef GetDoubleT() const
252     {
253         return doubleT_;
254     }
255 
GetTaggedPtrT()256     LLVMTypeRef GetTaggedPtrT() const
257     {
258         return taggedPtrT_;
259     }
260 
GetTaggedHPtrT()261     LLVMTypeRef GetTaggedHPtrT() const
262     {
263         return taggedHPtrT_;
264     }
265 
GetRawPtrT()266     LLVMTypeRef GetRawPtrT() const
267     {
268         return rawPtrT_;
269     }
270 private:
271     LLVMValueRef AddAndGetFunc(const CallSignature *stubDescriptor);
272     void InitialLLVMFuncTypeAndFuncByModuleCSigns();
273     LLVMTypeRef ConvertLLVMTypeFromVariableType(VariableType type);
274     LLVMTypeRef NewLType(MachineType machineType, GateType gateType);
275     // index:
276     //     stub scenario - sequence of function adding to llvmModule
277     //     aot scenario - method Id of function generated by panda files
278     std::vector<std::tuple<size_t, LLVMValueRef, bool>> funcIndexMap_;
279     std::vector<const CallSignature *> callSigns_;
280     LLVMModuleRef module_ {nullptr};
281     LLVMContextRef context_ {nullptr};
282     LLVMMetadataRef dFileMD_ {nullptr};
283     LLVMMetadataRef dUnitMD_ {nullptr};
284     LLVMDIBuilderRef dBuilder_ {nullptr};
285     DebugInfo* debugInfo_ {nullptr};
286 
287     LLVMTypeRef voidT_ {nullptr};
288     LLVMTypeRef int1T_ {nullptr};
289     LLVMTypeRef int8T_ {nullptr};
290     LLVMTypeRef int16T_ {nullptr};
291     LLVMTypeRef int32T_ {nullptr};
292     LLVMTypeRef int64T_ {nullptr};
293     LLVMTypeRef floatT_ {nullptr};
294     LLVMTypeRef doubleT_ {nullptr};
295     LLVMTypeRef taggedHPtrT_ {nullptr};
296     LLVMTypeRef taggedPtrT_ {nullptr};
297     LLVMTypeRef rawPtrT_ {nullptr};
298 
299     std::string tripleStr_;
300     bool is64Bit_ {false};
301     Triple triple_;
302 };
303 
304 
305 #define OPCODES(V)                                                                        \
306     V(Call, (GateRef gate, const std::vector<GateRef> &inList, OpCode op))                \
307     V(RuntimeCall, (GateRef gate, const std::vector<GateRef> &inList))                    \
308     V(RuntimeCallWithArgv, (GateRef gate, const std::vector<GateRef> &inList))            \
309     V(NoGcRuntimeCall, (GateRef gate, const std::vector<GateRef> &inList))                \
310     V(BytecodeCall, (GateRef gate, const std::vector<GateRef> &inList))                   \
311     V(Alloca, (GateRef gate))                                                             \
312     V(Block, (int id, const OperandsVector &predecessors))                                \
313     V(Goto, (int block, int bbout))                                                       \
314     V(Parameter, (GateRef gate))                                                          \
315     V(Constant, (GateRef gate, std::bitset<64> value))                                    \
316     V(ConstString, (GateRef gate, const ChunkVector<char> &str))                          \
317     V(RelocatableData, (GateRef gate, uint64_t value))                                    \
318     V(ZExtInt, (GateRef gate, GateRef e1))                                                \
319     V(SExtInt, (GateRef gate, GateRef e1))                                                \
320     V(FPExt, (GateRef gate, GateRef e1))                                                  \
321     V(FPTrunc, (GateRef gate, GateRef e1))                                                \
322     V(Load, (GateRef gate, GateRef base))                                                 \
323     V(Store, (GateRef gate, GateRef base, GateRef value))                                 \
324     V(IntRev, (GateRef gate, GateRef e1))                                                 \
325     V(Add, (GateRef gate, GateRef e1, GateRef e2))                                        \
326     V(Sub, (GateRef gate, GateRef e1, GateRef e2))                                        \
327     V(Mul, (GateRef gate, GateRef e1, GateRef e2))                                        \
328     V(FloatDiv, (GateRef gate, GateRef e1, GateRef e2))                                   \
329     V(IntDiv, (GateRef gate, GateRef e1, GateRef e2))                                     \
330     V(UDiv, (GateRef gate, GateRef e1, GateRef e2))                                       \
331     V(IntOr, (GateRef gate, GateRef e1, GateRef e2))                                      \
332     V(IntAnd, (GateRef gate, GateRef e1, GateRef e2))                                     \
333     V(IntXor, (GateRef gate, GateRef e1, GateRef e2))                                     \
334     V(IntLsr, (GateRef gate, GateRef e1, GateRef e2))                                     \
335     V(IntAsr, (GateRef gate, GateRef e1, GateRef e2))                                     \
336     V(Int32LessThanOrEqual, (GateRef gate, GateRef e1, GateRef e2))                       \
337     V(Cmp, (GateRef gate, GateRef e1, GateRef e2))                                        \
338     V(Branch, (GateRef gate, GateRef cmp, GateRef btrue, GateRef bfalse))                 \
339     V(Switch, (GateRef gate, GateRef input, const std::vector<GateRef> &outList))         \
340     V(SwitchCase, (GateRef gate, GateRef switchBranch, GateRef out))                      \
341     V(Phi, (GateRef gate, const std::vector<GateRef> &srcGates))                          \
342     V(Return, (GateRef gate, GateRef popCount, const std::vector<GateRef> &operands))     \
343     V(ReturnVoid, (GateRef gate))                                                         \
344     V(CastIntXToIntY, (GateRef gate, GateRef e1))                                         \
345     V(ChangeInt32ToDouble, (GateRef gate, GateRef e1))                                    \
346     V(ChangeUInt32ToDouble, (GateRef gate, GateRef e1))                                   \
347     V(ChangeDoubleToInt32, (GateRef gate, GateRef e1))                                    \
348     V(BitCast, (GateRef gate, GateRef e1))                                                \
349     V(IntLsl, (GateRef gate, GateRef e1, GateRef e2))                                     \
350     V(Mod, (GateRef gate, GateRef e1, GateRef e2))                                        \
351     V(ChangeTaggedPointerToInt64, (GateRef gate, GateRef e1))                             \
352     V(ChangeInt64ToTagged, (GateRef gate, GateRef e1))                                    \
353     V(DeoptCheck, (GateRef gate))                                                         \
354     V(TruncFloatToInt, (GateRef gate, GateRef e1))                                        \
355     V(AddWithOverflow, (GateRef gate, GateRef e1, GateRef e2))                            \
356     V(SubWithOverflow, (GateRef gate, GateRef e1, GateRef e2))                            \
357     V(MulWithOverflow, (GateRef gate, GateRef e1, GateRef e2))                            \
358     V(ExtractValue, (GateRef gate, GateRef e1, GateRef e2))                               \
359     V(Sqrt, (GateRef gate, GateRef e1))                                                   \
360     V(ReadSp, (GateRef gate))
361 
362 // runtime/common stub ID, opcodeOffset for bc stub
363 using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, LLVMValueRef>;
364 
365 class LLVMIRBuilder {
366 public:
367     LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
368                   LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg,
369                   CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot, const std::string &funcName);
370     ~LLVMIRBuilder();
371     void Build();
372 
373 private:
374     #define DECLAREVISITOPCODE(name, signature) void Visit##name signature;
OPCODES(DECLAREVISITOPCODE)375         OPCODES(DECLAREVISITOPCODE)
376     #undef DECLAREVISITOPCODE
377     #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(GateRef gate);
378         OPCODES(DECLAREHANDLEOPCODE)
379     #undef DECLAREHANDLEOPCODE
380 
381     bool IsPrologue(int bbId) const
382     {
383         return bbId == 0;
384     }
385     void LinkToLLVMCfg(int bbId, const OperandsVector &predecessors);
386     BasicBlock *EnsureBB(int id);
387     LLVMValueRef CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller);
388     LLVMValueRef GetCurrentSP();
389     LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder, LLVMMetadataRef meta);
390     void GenPrologue();
391     LLVMBasicBlockRef EnsureLBB(BasicBlock *bb) const;
392     BasicBlockImpl *EnsureBBImpl(BasicBlock *bb) const;
393     void SetToCfg(BasicBlock *bb) const;
394 
395     LLVMTypeRef GetMachineRepType(MachineRep rep) const;
396     int FindBasicBlock(GateRef gate) const;
397     void EndCurrentBlock() const;
398     void Finish();
399 
400     void ProcessPhiWorkList();
401     void InitializeHandlers();
402     std::string LLVMValueToString(LLVMValueRef val) const;
403 
404     LLVMTypeRef ConvertLLVMTypeFromGate(GateRef gate) const;
405     int64_t GetBitWidthFromMachineType(MachineType machineType) const;
406     LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offsetInByte, LLVMTypeRef rep);
407     LLVMValueRef CanonicalizeToInt(LLVMValueRef value) const;
408     LLVMValueRef CanonicalizeToPtr(LLVMValueRef value) const;
409     LLVMValueRef CanonicalizeToPtr(LLVMValueRef value, LLVMTypeRef ptrType) const;
410     LLVMValueRef GetCurrentFrameType(LLVMValueRef currentSpFrameAddr);
411     void SetFunctionCallConv();
412 
IsLogEnabled()413     bool IsLogEnabled() const
414     {
415         return enableLog_;
416     }
417     LLVMValueRef GetFunction(LLVMValueRef glue, const CallSignature *signature, LLVMValueRef rtbaseoffset,
418                              const std::string &realName = "") const;
419     LLVMValueRef GetCallee(const std::vector<GateRef> &inList, const CallSignature *signature,
420                            const std::string &realName = "");
421     LLVMValueRef GetFunctionFromGlobalValue(LLVMValueRef glue, const CallSignature *signature,
422                                             LLVMValueRef reloc) const;
423     bool IsInterpreted() const;
424     bool IsOptimized() const;
425     bool IsOptimizedJSFunction() const;
426     void SetGCLeafFunction(LLVMValueRef call);
427     void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call);
428     bool IsHeapPointerType(LLVMTypeRef valueType);
429 
GetVoidT()430     LLVMTypeRef GetVoidT() const
431     {
432         return llvmModule_->GetVoidT();
433     }
434 
GetInt1T()435     LLVMTypeRef GetInt1T() const
436     {
437         return llvmModule_->GetInt1T();
438     }
439 
GetInt8T()440     LLVMTypeRef GetInt8T() const
441     {
442         return llvmModule_->GetInt8T();
443     }
444 
GetInt16T()445     LLVMTypeRef GetInt16T() const
446     {
447         return llvmModule_->GetInt16T();
448     }
449 
GetInt32T()450     LLVMTypeRef GetInt32T() const
451     {
452         return llvmModule_->GetInt32T();
453     }
454 
GetInt64T()455     LLVMTypeRef GetInt64T() const
456     {
457         return llvmModule_->GetInt64T();
458     }
459 
GetFloatT()460     LLVMTypeRef GetFloatT() const
461     {
462         return llvmModule_->GetFloatT();
463     }
464 
GetDoubleT()465     LLVMTypeRef GetDoubleT() const
466     {
467         return llvmModule_->GetDoubleT();
468     }
469 
GetTaggedPtrT()470     LLVMTypeRef GetTaggedPtrT() const
471     {
472         return llvmModule_->GetTaggedPtrT();
473     }
474 
GetTaggedHPtrT()475     LLVMTypeRef GetTaggedHPtrT() const
476     {
477         return llvmModule_->GetTaggedHPtrT();
478     }
479 
GetRawPtrT()480     LLVMTypeRef GetRawPtrT() const
481     {
482         return llvmModule_->GetRawPtrT();
483     }
484 
485 private:
486     enum class CallInputs : size_t {
487         DEPEND = 0,
488         TARGET,
489         GLUE,
490         FIRST_PARAMETER
491     };
492     enum class CallExceptionKind : bool {
493         HAS_PC_OFFSET = true,
494         NO_PC_OFFSET = false
495     };
496 
GetDIBuilder()497     LLVMDIBuilderRef GetDIBuilder() const
498     {
499         return llvmModule_ == nullptr ? nullptr : llvmModule_->GetDIBuilder();
500     }
501 
502     unsigned GetPtrAddressSpace(LLVMValueRef v) const;
503     bool IsLInteger(LLVMValueRef v) const;
504     bool IsLPointer(LLVMValueRef v) const;
505     LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond);
506     LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond);
507     LLVMValueRef GetGlue(const std::vector<GateRef> &inList);
508     LLVMValueRef GetLeaveFrameOffset(LLVMValueRef glue);
509     LLVMValueRef GetRTStubOffset(LLVMValueRef glue, int index);
510     LLVMValueRef GetCoStubOffset(LLVMValueRef glue, int index);
511     LLVMValueRef GetBCStubOffset(LLVMValueRef glue);
512     LLVMValueRef GetBCDebugStubOffset(LLVMValueRef glue);
513     LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue);
514     LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue);
515     CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
516     void ComputeArgCountAndPCOffset(size_t &actualNumArgs, LLVMValueRef &pcOffset,
517                                     const std::vector<GateRef> &inList, CallExceptionKind kind);
518     void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
519     void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);
520     void SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder);
521     void UpdateLeaveFrame(LLVMValueRef glue);
522     LLVMTypeRef GetExperimentalDeoptTy();
523     LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module);
524     void GenDeoptEntry(LLVMModuleRef &module);
525     LLVMMetadataRef GetFunctionTypeMD(LLVMMetadataRef dFile);
526     bool SetDebugInfo(GateRef g, LLVMValueRef r);
527     LLVMValueRef ConvertToTagged(GateRef gate);
528     LLVMValueRef ConvertBoolToTaggedBoolean(GateRef gate);
529     LLVMValueRef ConvertInt32ToTaggedInt(GateRef gate);
530     LLVMValueRef ConvertInt32ToTaggedInt(LLVMValueRef value);
531     LLVMValueRef ConvertFloat64ToTaggedDouble(GateRef gate);
532     void SaveDeoptVregInfo(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift,
533                            GateRef gate);
534     void SaveDeoptVregInfoWithI64(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift,
535                            GateRef gate);
536     int LookupPredBB(GateRef start, int bbID);
537 
538     const CompilationConfig *compCfg_ {nullptr};
539     const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr};
540     const Circuit *circuit_ {nullptr};
541     GateAccessor acc_;
542     BasicBlock *currentBb_ {nullptr};
543     int lineNumber_ {0};
544 
545     LLVMModuleRef module_ {nullptr};
546     LLVMContextRef context_ {nullptr};
547     LLVMValueRef function_ {nullptr};
548     LLVMBuilderRef builder_ {nullptr};
549     std::map<GateId, int> instID2bbID_;
550     BasicBlockMap bbID2BB_;
551 
552     std::vector<BasicBlock *> phiRebuildWorklist_;
553     LLVMModule *llvmModule_ {nullptr};
554     std::unordered_map<GateRef, LLVMValueRef> gate2LValue_;
555     std::unordered_map<OpCode, HandleType> opHandlers_;
556     std::set<OpCode> illegalOpHandlers_;
557     int slotSize_ {-1};
558     LLVMTypeRef slotType_ {nullptr};
559     CallSignature::CallConv callConv_ = CallSignature::CallConv::CCallConv;
560     bool enableLog_ {false};
561     bool isFastCallAot_ {false};
562     LLVMMetadataRef dFuncMD_ {nullptr};
563 };
564 }  // namespace panda::ecmascript::kungfu
565 #endif  // ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H
566