* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_COMPILER_LLVM_CODEGEN_H
#define ECMASCRIPT_COMPILER_LLVM_CODEGEN_H
#include "ecmascript/compiler/binary_section.h"
#include "ecmascript/compiler/code_generator.h"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include "llvm-c/Core.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
namespace panda::ecmascript::kungfu {
class CompilerLog;
class MethodLogList;
class LLVMModule;
enum class FPFlag : uint32_t {
ELIM_FP = 0,
RESERVE_FP = 1
};
struct LOptions {
uint32_t optLevel : 2;
uint32_t genFp : 1;
uint32_t relocMode : 3;
LOptions() : optLevel(3), genFp(static_cast<uint32_t>(FPFlag::RESERVE_FP)), relocMode(2) {};
LOptions(size_t level, FPFlag flag, size_t relocMode)
: optLevel(level), genFp(static_cast<uint32_t>(flag)), relocMode(relocMode) {};
};
class LLVMAssembler : public Assembler {
public:
explicit LLVMAssembler(LLVMModule *lm, CodeInfo::CodeSpaceOnDemand &codeSpaceOnDemand,
LOptions option = LOptions(), bool isStubCompiler = false);
virtual ~LLVMAssembler();
void Run(const CompilerLog &log, bool fastCompileMode, bool isJit = false) override;
const LLVMExecutionEngineRef &GetEngine()
{
return engine_;
}
void Disassemble(const std::map<uintptr_t, std::string> &addr2name, uint64_t textOffset,
const CompilerLog &log, const MethodLogList &logList, std::ostringstream &codeStream) const;
static void Disassemble(const std::map<uintptr_t, std::string> *addr2name,
const std::string& triple, uint8_t *buf, size_t size);
static int GetFpDeltaPrevFramSp(LLVMValueRef fn, const CompilerLog &log);
static kungfu::CalleeRegAndOffsetVec GetCalleeReg2Offset(LLVMValueRef fn, const CompilerLog &log);
void *GetFuncPtrFromCompiledModule(LLVMValueRef function)
{
return LLVMGetPointerToGlobal(engine_, function);
}
void SetObjFile(const llvm::object::ObjectFile *obj)
{
objFile_ = obj;
}
private:
class AOTEventListener : public llvm::JITEventListener {
public:
AOTEventListener(LLVMAssembler* as) : as_(as)
{
}
void notifyObjectLoaded([[maybe_unused]] ObjectKey key, const llvm::object::ObjectFile &objFile,
[[maybe_unused]] const llvm::RuntimeDyld::LoadedObjectInfo &objInfo)
{
as_->SetObjFile(&objFile);
}
private:
LLVMAssembler* GetAssembler() const
{
return as_;
}
LLVMAssembler* as_ {nullptr};
};
void UseRoundTripSectionMemoryManager(bool isJit);
bool BuildMCJITEngine();
void BuildAndRunPasses();
void BuildAndRunPassesFastMode();
void Initialize(LOptions option);
static void PrintInstAndStep(uint64_t &pc, uint8_t **byteSp, uintptr_t &numBytes, size_t instSize,
uint64_t textOffset, char *outString, std::ostringstream &codeStream,
bool logFlag = true);
uint64_t GetTextSectionIndex() const;
LLVMMCJITCompilerOptions options_ {};
LLVMModule *llvmModule_ {nullptr};
LLVMModuleRef module_ {nullptr};
const llvm::object::ObjectFile* objFile_ {nullptr};
LLVMExecutionEngineRef engine_ {nullptr};
AOTEventListener listener_;
char *error_ {nullptr};
};
class LLVMIRGeneratorImpl : public CodeGeneratorImpl {
public:
LLVMIRGeneratorImpl(LLVMModule *module, bool enableLog)
: module_(module), enableLog_(enableLog) {}
~LLVMIRGeneratorImpl() override = default;
void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index,
const CompilationConfig *cfg) override;
void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, const std::string &methodName,
const FrameType frameType, bool enableOptInlining, bool enableBranchProfiling) override;
bool IsLogEnabled() const
{
return enableLog_;
}
private:
LLVMModule *module_;
bool enableLog_ {false};
};
}
#endif