mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
be4ecb415b
Issue: https://gitee.com/openharmony/ark_js_runtime/issues/I4ZL8V Signed-off-by: luochuhao <luochuhao@huawei.com> Change-Id: I32bf175d4aea43dab2d408ea0347a14a4b5903cb
229 lines
7.0 KiB
C++
229 lines
7.0 KiB
C++
/*
|
|
* 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 <iostream>
|
|
#include <list>
|
|
#include <map>
|
|
#include <sys/mman.h>
|
|
#include <vector>
|
|
|
|
#include "code_generator.h"
|
|
#include "ecmascript/ecma_macros.h"
|
|
#include "ecmascript/js_thread.h"
|
|
#include "llvm_ir_builder.h"
|
|
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wshadow"
|
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
|
#elif defined(__GNUC__)
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wshadow"
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
#endif
|
|
|
|
#include "llvm-c/Analysis.h"
|
|
#include "llvm-c/Core.h"
|
|
#include "llvm-c/ExecutionEngine.h"
|
|
#include "llvm-c/Target.h"
|
|
#include "llvm-c/Transforms/PassManagerBuilder.h"
|
|
#include "llvm-c/Transforms/Scalar.h"
|
|
#include "llvm-c/Types.h"
|
|
#include "llvm/ExecutionEngine/Interpreter.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
|
#include "llvm/ExecutionEngine/MCJIT.h"
|
|
#include "llvm/Support/Host.h"
|
|
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic pop
|
|
#elif defined(__GNUC__)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
namespace panda::ecmascript::kungfu {
|
|
struct CodeInfo {
|
|
using ByteBuffer = std::vector<uint8_t>;
|
|
using BufferList = std::list<ByteBuffer>;
|
|
using StringList = std::list<std::string>;
|
|
CodeInfo()
|
|
{
|
|
machineCode_ = static_cast<uint8_t *>(mmap(nullptr, MAX_MACHINE_CODE_SIZE, protRWX, flags, -1, 0));
|
|
if (machineCode_ == reinterpret_cast<uint8_t *>(-1)) {
|
|
machineCode_ = nullptr;
|
|
}
|
|
if (machineCode_ != nullptr) {
|
|
ASAN_UNPOISON_MEMORY_REGION(machineCode_, MAX_MACHINE_CODE_SIZE);
|
|
}
|
|
}
|
|
~CodeInfo()
|
|
{
|
|
Reset();
|
|
if (machineCode_ != nullptr) {
|
|
ASAN_POISON_MEMORY_REGION(machineCode_, MAX_MACHINE_CODE_SIZE);
|
|
munmap(machineCode_, MAX_MACHINE_CODE_SIZE);
|
|
}
|
|
machineCode_ = nullptr;
|
|
}
|
|
|
|
uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName)
|
|
{
|
|
uint8_t *addr = nullptr;
|
|
if (codeBufferPos_ + size > MAX_MACHINE_CODE_SIZE) {
|
|
LOG_ECMA(INFO) << std::hex << "AllocaCodeSection failed alloc codeBufferPos_:" << codeBufferPos_
|
|
<< " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE;
|
|
return nullptr;
|
|
}
|
|
LOG_ECMA(INFO) << "AllocaCodeSection size:" << size;
|
|
codeSectionNames_.push_back(sectionName);
|
|
addr = machineCode_ + codeBufferPos_;
|
|
codeInfo_.push_back({addr, size});
|
|
codeBufferPos_ += size;
|
|
return addr;
|
|
}
|
|
|
|
uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName)
|
|
{
|
|
uint8_t *addr = nullptr;
|
|
dataSectionList_.push_back(std::vector<uint8_t>());
|
|
dataSectionList_.back().resize(size);
|
|
dataSectionNames_.push_back(sectionName);
|
|
std::cout << "AllocaDataSection " << sectionName << std::endl;
|
|
addr = static_cast<uint8_t *>(dataSectionList_.back().data());
|
|
if (!strcmp(sectionName, ".llvm_stackmaps")) {
|
|
LOG_ECMA(INFO) << "llvm_stackmaps : " << addr << " size:" << size;
|
|
stackMapsSection_ = addr;
|
|
stackMapsSize_ = size;
|
|
}
|
|
return addr;
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
stackMapsSection_ = nullptr;
|
|
codeInfo_.clear();
|
|
dataSectionList_.clear();
|
|
dataSectionNames_.clear();
|
|
codeSectionNames_.clear();
|
|
codeBufferPos_ = 0;
|
|
}
|
|
|
|
uint8_t *GetStackMapsSection() const
|
|
{
|
|
return stackMapsSection_;
|
|
}
|
|
|
|
size_t GetStackMapsSize() const
|
|
{
|
|
return stackMapsSize_;
|
|
}
|
|
|
|
std::vector<std::pair<uint8_t *, uintptr_t>> GetCodeInfo() const
|
|
{
|
|
return codeInfo_;
|
|
}
|
|
|
|
uint8_t *GetCodeBuff() const
|
|
{
|
|
return machineCode_;
|
|
}
|
|
|
|
size_t GetCodeSize() const
|
|
{
|
|
return codeBufferPos_;
|
|
}
|
|
|
|
private:
|
|
BufferList dataSectionList_ {};
|
|
StringList dataSectionNames_ {};
|
|
StringList codeSectionNames_ {};
|
|
uint8_t *machineCode_ {nullptr};
|
|
const size_t MAX_MACHINE_CODE_SIZE = (1 << 20); // 1M
|
|
static constexpr int protRWX = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise)
|
|
static constexpr int flags = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise)
|
|
size_t codeBufferPos_ {0};
|
|
/* <addr, size > for asssembler */
|
|
std::vector<std::pair<uint8_t *, uintptr_t>> codeInfo_ {};
|
|
/* stack map */
|
|
uint8_t *stackMapsSection_ {nullptr};
|
|
size_t stackMapsSize_ {0};
|
|
};
|
|
|
|
class LLVMAssembler {
|
|
public:
|
|
LLVMAssembler(LLVMModuleRef module, bool genFp = true);
|
|
virtual ~LLVMAssembler();
|
|
void Run();
|
|
const LLVMExecutionEngineRef &GetEngine()
|
|
{
|
|
return engine_;
|
|
}
|
|
void Disassemble(const std::map<uint64_t, std::string> &addr2name) const;
|
|
uint8_t *GetStackMapsSection() const
|
|
{
|
|
return codeInfo_.GetStackMapsSection();
|
|
}
|
|
|
|
size_t GetStackMapsSize() const
|
|
{
|
|
return codeInfo_.GetStackMapsSize();
|
|
}
|
|
|
|
uint8_t *GetCodeBuffer() const
|
|
{
|
|
return codeInfo_.GetCodeBuff();
|
|
}
|
|
|
|
size_t GetCodeSize() const
|
|
{
|
|
return codeInfo_.GetCodeSize();
|
|
}
|
|
|
|
void *GetFuncPtrFromCompiledModule(LLVMValueRef function)
|
|
{
|
|
return LLVMGetPointerToGlobal(engine_, function);
|
|
}
|
|
|
|
private:
|
|
void UseRoundTripSectionMemoryManager();
|
|
bool BuildMCJITEngine();
|
|
void BuildAndRunPasses();
|
|
void Initialize(bool genFp);
|
|
|
|
LLVMMCJITCompilerOptions options_ {};
|
|
LLVMModuleRef module_;
|
|
LLVMExecutionEngineRef engine_ {nullptr};
|
|
char *error_ {nullptr};
|
|
struct CodeInfo codeInfo_ {};
|
|
};
|
|
|
|
class LLVMIRGeneratorImpl : public CodeGeneratorImpl {
|
|
public:
|
|
explicit LLVMIRGeneratorImpl(LLVMModule *module) : module_(module) {}
|
|
~LLVMIRGeneratorImpl() = 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 JSMethod *method) override;
|
|
|
|
private:
|
|
LLVMModule *module_;
|
|
};
|
|
} // namespace panda::ecmascript::kungfu
|
|
#endif // ECMASCRIPT_COMPILER_LLVM_CODEGEN_H
|