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(), bool isStubCompiler = false); 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