Add AOT Pass Manager

Modify aot compiler main process to pass manager, as to compile file by
file.

Add PassData to manage data interact between passes, PassRunner to
execute every pass that is registered on specific order.

Issue: I4SW05

Change-Id: I5b83b84880c7375e26e1c47e02c9943bfefc647a
Signed-off-by: Hailiang Hu <allenpas@huawei.com>
This commit is contained in:
Hailiang Hu 2022-02-08 17:25:05 +08:00
parent f037ce6928
commit e97de69528
7 changed files with 202 additions and 74 deletions

View File

@ -217,7 +217,10 @@ ohos_executable("ark_stub_opt") {
}
ohos_executable("ark_ts_aot") {
sources = [ "ts_aot_compiler.cpp" ]
sources = [
"aot_compiler.cpp",
"pass_manager.cpp",
]
configs = [
":include_llvm",

View File

@ -29,6 +29,7 @@
#include "libpandabase/utils/pandargs.h"
#include "libpandabase/utils/span.h"
#include "libpandafile/file.h"
#include "pass_manager.h"
namespace panda::ecmascript::kungfu {
void BlockSignals()
@ -104,7 +105,7 @@ int Main(const int argc, const char **argv)
runtimeOptions.SetShouldLoadBootPandaFiles(false);
runtimeOptions.SetShouldInitializeIntrinsics(false);
runtimeOptions.SetBootClassSpaces( {"ecmascript"} );
runtimeOptions.SetBootClassSpaces({"ecmascript"});
runtimeOptions.SetRuntimeType("ecmascript");
JSNApi::SetOptions(runtimeOptions);
static EcmaLanguageContext lcEcma;
@ -125,20 +126,13 @@ int Main(const int argc, const char **argv)
std::string entry = entrypoint.GetValue();
arg_list_t fileNames = files.GetValue();
PassManager passManager(vm, entry);
for (const auto &fileName : fileNames) {
LOG_ECMA(DEBUG) << "start to execute ark file" << fileName;
std::vector<BytecodeTranslationInfo> infoList;
const panda_file::File *file = nullptr;
auto res = vm->CollectInfoOfPandaFile(fileName, entry, infoList, file);
if (!res) {
std::cerr << "Cannot execute panda file '" << fileName << "' with entry '" << entry << "'" << std::endl;
LOG_ECMA(DEBUG) << "start to execute ark file: " << fileName;
if (passManager.Compile(fileName) == false) {
ret = false;
break;
}
for (auto &info : infoList) {
BytecodeCircuitBuilder builder;
builder.BytecodeToCircuit(info.pcArray, *info.file, info.method);
}
}
if (!Runtime::Destroy()) {

View File

@ -120,14 +120,9 @@ public:
void PUBLIC_API BytecodeToCircuit(const std::vector<uint8_t *> &pcArray, const panda_file::File &pf,
const JSMethod *method);
[[nodiscard]] kungfu::Circuit& GetCircuit()
[[nodiscard]] kungfu::Circuit* GetCircuit()
{
return circuit_;
}
[[nodiscard]] const kungfu::Circuit& GetCircuit() const
{
return circuit_;
return &circuit_;
}
[[nodiscard]] const std::map<kungfu::GateRef, std::pair<size_t, uint8_t *>>& GetGateToBytecode() const

102
ecmascript/compiler/pass.h Normal file
View File

@ -0,0 +1,102 @@
/*
* 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_PASS_H
#define ECMASCRIPT_COMPILER_PASS_H
#include "verifier.h"
#include "scheduler.h"
#include "fast_stub.h"
#include "llvm_codegen.h"
namespace panda::ecmascript::kungfu {
class PassData {
public:
explicit PassData(Circuit* circuit) : circuit_(circuit) {}
~PassData() = default;
const ControlFlowGraph &GetScheduleResult() const
{
return cfg_;
}
void SetScheduleResult(const ControlFlowGraph &result)
{
cfg_ = result;
}
virtual Circuit* GetCircuit() const
{
return circuit_;
}
private:
Circuit* circuit_;
ControlFlowGraph cfg_;
};
template<typename T1>
class PassRunner {
public:
explicit PassRunner(T1* data) : data_(data) {}
~PassRunner() = default;
template<typename T2, typename... Args>
bool RunPass(Args... args)
{
T2 pass;
return pass.Run(data_, std::forward<Args>(args)...);
}
private:
T1* data_;
};
class GenericLoweringPass {
public:
bool Run(PassData* data)
{
return true;
}
};
class VerifierPass {
public:
bool Run(PassData* data)
{
Verifier::Run(data->GetCircuit());
return true;
}
};
class SchedulingPass {
public:
bool Run(PassData* data)
{
data->SetScheduleResult(Scheduler::Run(data->GetCircuit()));
return true;
}
};
class LLVMIRGenPass {
public:
bool Run(PassData* data)
{
return true;
}
private:
std::unique_ptr<CodeGeneratorImpl> llvmImpl_ {nullptr};
};
}
#endif

View File

@ -0,0 +1,42 @@
/*
* 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.
*/
#include "pass_manager.h"
#include "pass.h"
namespace panda::ecmascript::kungfu {
bool PassManager::Compile(std::string fileName)
{
std::vector<BytecodeTranslationInfo> infoList;
const panda_file::File *file = nullptr;
auto res = vm_->CollectInfoOfPandaFile(fileName, entry_, infoList, file);
if (!res) {
std::cerr << "Cannot execute panda file '" << fileName << "' with entry '" << entry_ << "'" << std::endl;
return false;
}
for (auto &info : infoList) {
BytecodeCircuitBuilder builder;
builder.BytecodeToCircuit(info.pcArray, *info.file, info.method);
PassData data(builder.GetCircuit());
PassRunner<PassData> pipeline(&data);
pipeline.RunPass<GenericLoweringPass>();
pipeline.RunPass<VerifierPass>();
pipeline.RunPass<SchedulingPass>();
pipeline.RunPass<LLVMIRGenPass>();
}
return true;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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_PASS_MANAGER_H
#define ECMASCRIPT_COMPILER_PASS_MANAGER_H
#include "ecmascript/ecma_vm.h"
#include "bytecode_circuit_builder.h"
namespace panda::ecmascript::kungfu {
class PassManager {
public:
PassManager(EcmaVM* vm, std::string entry) : vm_(vm), entry_(entry) {}
PassManager() = default;
bool Compile(std::string fileName);
private:
EcmaVM* vm_;
std::string entry_;
};
}
#endif

View File

@ -28,21 +28,13 @@
#include "scheduler.h"
#include "stub-inl.h"
#include "verifier.h"
#include "pass.h"
namespace panda::ecmascript::kungfu {
class PassPayLoad {
class StubPassData : public PassData {
public:
explicit PassPayLoad(Stub *stub, LLVMStubModule *module) : module_(module), stub_(stub) {}
~PassPayLoad() = default;
const ControlFlowGraph &GetScheduleResult() const
{
return cfg_;
}
void SetScheduleResult(const ControlFlowGraph &result)
{
cfg_ = result;
}
explicit StubPassData(Stub *stub, LLVMStubModule *module) : PassData(nullptr), module_(module), stub_(stub) {}
~StubPassData() = default;
const CompilationConfig *GetCompilationConfig() const
{
@ -67,27 +59,11 @@ public:
private:
LLVMStubModule *module_;
Stub *stub_;
ControlFlowGraph cfg_;
};
class PassRunner {
class StubBuildCircuitPass {
public:
explicit PassRunner(PassPayLoad *data) : data_(data) {}
~PassRunner() = default;
template<typename T, typename... Args>
bool RunPass(Args... args)
{
T pass;
return pass.Run(data_, std::forward<Args>(args)...);
}
private:
PassPayLoad *data_;
};
class BuildCircuitPass {
public:
bool Run(PassPayLoad *data)
bool Run(StubPassData *data)
{
auto stub = data->GetStub();
std::cout << "Stub Name: " << stub->GetMethodName() << std::endl;
@ -96,31 +72,13 @@ public:
}
};
class VerifierPass {
public:
bool Run(PassPayLoad *data)
{
Verifier::Run(data->GetCircuit());
return true;
}
};
class SchedulerPass {
public:
bool Run(PassPayLoad *data)
{
data->SetScheduleResult(Scheduler::Run(data->GetCircuit()));
return true;
}
};
class LLVMIRGenPass {
class StubLLVMIRGenPass {
public:
void CreateCodeGen(LLVMStubModule *module)
{
llvmImpl_ = std::make_unique<LLVMIRGeneratorImpl>(module);
}
bool Run(PassPayLoad *data, int index)
bool Run(StubPassData *data, int index)
{
auto stubModule = data->GetStubModule();
CreateCodeGen(stubModule);
@ -141,12 +99,12 @@ void StubAotCompiler::BuildStubModuleAndSave(const std::string &triple, panda::e
for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) {
auto stub = stubs_[i];
if (stub != nullptr) {
PassPayLoad data(stub, &stubModule);
PassRunner pipeline(&data);
pipeline.RunPass<BuildCircuitPass>();
StubPassData data(stub, &stubModule);
PassRunner<StubPassData> pipeline(&data);
pipeline.RunPass<StubBuildCircuitPass>();
pipeline.RunPass<VerifierPass>();
pipeline.RunPass<SchedulerPass>();
pipeline.RunPass<LLVMIRGenPass>(i);
pipeline.RunPass<SchedulingPass>();
pipeline.RunPass<StubLLVMIRGenPass>(i);
}
}