• 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_CODEGEN_H
17 #define ECMASCRIPT_COMPILER_LLVM_CODEGEN_H
18 
19 #include "ecmascript/compiler/binary_section.h"
20 #include "ecmascript/compiler/code_generator.h"
21 
22 #if defined(__clang__)
23 #pragma clang diagnostic push
24 #pragma clang diagnostic ignored "-Wshadow"
25 #pragma clang diagnostic ignored "-Wunused-parameter"
26 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
27 #elif defined(__GNUC__)
28 #pragma GCC diagnostic push
29 #pragma GCC diagnostic ignored "-Wshadow"
30 #pragma GCC diagnostic ignored "-Wunused-parameter"
31 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
32 #endif
33 
34 #include "llvm-c/Core.h"
35 #include "llvm-c/ExecutionEngine.h"
36 #include "llvm/ExecutionEngine/JITEventListener.h"
37 
38 #if defined(__clang__)
39 #pragma clang diagnostic pop
40 #elif defined(__GNUC__)
41 #pragma GCC diagnostic pop
42 #endif
43 
44 namespace panda::ecmascript::kungfu {
45 class CompilerLog;
46 class MethodLogList;
47 class LLVMModule;
48 
49 enum class FPFlag : uint32_t {
50     ELIM_FP = 0,
51     RESERVE_FP = 1
52 };
53 
54 struct LOptions {
55     uint32_t optLevel : 2; // 2 bits for optimized level 0-4
56     uint32_t genFp : 1; // 1 bit for whether to generated frame pointer or not
57     uint32_t relocMode : 3; // 3 bits for relocation mode
58     // 3: default optLevel, 1: generating fp, 2: PIC mode
LOptionsLOptions59     LOptions() : optLevel(3), genFp(static_cast<uint32_t>(FPFlag::RESERVE_FP)), relocMode(2) {};
LOptionsLOptions60     LOptions(size_t level, FPFlag flag, size_t relocMode)
61         : optLevel(level), genFp(static_cast<uint32_t>(flag)), relocMode(relocMode) {};
62 };
63 
64 class LLVMAssembler : public Assembler {
65 public:
66     explicit LLVMAssembler(LLVMModule *lm, CodeInfo::CodeSpaceOnDemand &codeSpaceOnDemand,
67                            LOptions option = LOptions());
68     virtual ~LLVMAssembler();
69     void Run(const CompilerLog &log, bool fastCompileMode, bool isJit = false) override;
GetEngine()70     const LLVMExecutionEngineRef &GetEngine()
71     {
72         return engine_;
73     }
74     void Disassemble(const std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset,
75                      const CompilerLog &log, const MethodLogList &logList, std::ostringstream &codeStream) const;
76     static void Disassemble(const std::map<uintptr_t, std::string> *addr2name,
77                             const std::string& triple, uint8_t *buf, size_t size);
78     static int GetFpDeltaPrevFramSp(LLVMValueRef fn, const CompilerLog &log);
79     static kungfu::CalleeRegAndOffsetVec GetCalleeReg2Offset(LLVMValueRef fn, const CompilerLog &log);
80 
GetFuncPtrFromCompiledModule(LLVMValueRef function)81     void *GetFuncPtrFromCompiledModule(LLVMValueRef function)
82     {
83         return LLVMGetPointerToGlobal(engine_, function);
84     }
85 
SetObjFile(const llvm::object::ObjectFile * obj)86     void SetObjFile(const llvm::object::ObjectFile *obj)
87     {
88         objFile_ = obj;
89     }
90 private:
91     class AOTEventListener : public llvm::JITEventListener {
92       public:
AOTEventListener(LLVMAssembler * as)93         AOTEventListener(LLVMAssembler* as) : as_(as)
94         {
95         }
notifyObjectLoaded(ObjectKey key,const llvm::object::ObjectFile & objFile,const llvm::RuntimeDyld::LoadedObjectInfo & objInfo)96         void notifyObjectLoaded([[maybe_unused]] ObjectKey key, const llvm::object::ObjectFile &objFile,
97                                 [[maybe_unused]] const llvm::RuntimeDyld::LoadedObjectInfo &objInfo)
98         {
99             as_->SetObjFile(&objFile);
100         }
101       private:
GetAssembler()102         LLVMAssembler* GetAssembler() const
103         {
104             return as_;
105         }
106 
107         LLVMAssembler* as_ {nullptr};
108     };
109 
110     void UseRoundTripSectionMemoryManager(bool isJit);
111     bool BuildMCJITEngine();
112     void BuildAndRunPasses();
113     void BuildAndRunPassesFastMode();
114     void Initialize(LOptions option);
115     static void PrintInstAndStep(uint64_t &pc, uint8_t **byteSp, uintptr_t &numBytes, size_t instSize,
116                                  uint64_t textOffset, char *outString, std::ostringstream &codeStream,
117                                  bool logFlag = true);
118     uint64_t GetTextSectionIndex() const;
119 
120     LLVMMCJITCompilerOptions options_ {};
121     LLVMModule *llvmModule_ {nullptr};
122     LLVMModuleRef module_ {nullptr};
123     const llvm::object::ObjectFile* objFile_ {nullptr};
124     LLVMExecutionEngineRef engine_ {nullptr};
125     AOTEventListener listener_;
126     char *error_ {nullptr};
127 };
128 
129 class LLVMIRGeneratorImpl : public CodeGeneratorImpl {
130 public:
LLVMIRGeneratorImpl(LLVMModule * module,bool enableLog)131     LLVMIRGeneratorImpl(LLVMModule *module, bool enableLog)
132         : module_(module), enableLog_(enableLog) {}
133     ~LLVMIRGeneratorImpl() override = default;
134     void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index,
135                              const CompilationConfig *cfg) override;
136     void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
137         const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, const std::string &methodName,
138         const FrameType frameType, bool enableOptInlining, bool enableBranchProfiling) override;
139 
IsLogEnabled()140     bool IsLogEnabled() const
141     {
142         return enableLog_;
143     }
144 
145 private:
146     LLVMModule *module_;
147     bool enableLog_ {false};
148 };
149 }  // namespace panda::ecmascript::kungfu
150 #endif  // ECMASCRIPT_COMPILER_LLVM_CODEGEN_H
151