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 #include "stub_aot_compiler.h"
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <iostream>
21 #include <unistd.h>
22
23 #include "ecmascript/base/config.h"
24 #include "fast_stub.h"
25 #include "interpreter_stub-inl.h"
26 #include "generated/stub_aot_options_gen.h"
27 #include "libpandabase/utils/pandargs.h"
28 #include "libpandabase/utils/span.h"
29 #include "llvm_codegen.h"
30 #include "scheduler.h"
31 #include "stub-inl.h"
32 #include "verifier.h"
33 #include "pass.h"
34
35 namespace panda::ecmascript::kungfu {
36 class StubPassData : public PassData {
37 public:
StubPassData(Stub * stub,LLVMStubModule * module)38 explicit StubPassData(Stub *stub, LLVMStubModule *module) : PassData(nullptr), module_(module), stub_(stub) {}
39 ~StubPassData() = default;
40
GetCompilationConfig() const41 const CompilationConfig *GetCompilationConfig() const
42 {
43 return module_->GetCompilationConfig();
44 }
45
GetCircuit() const46 Circuit *GetCircuit() const
47 {
48 return stub_->GetEnvironment()->GetCircuit();
49 }
50
GetStubModule() const51 LLVMStubModule *GetStubModule() const
52 {
53 return module_;
54 }
55
GetStub() const56 Stub *GetStub() const
57 {
58 return stub_;
59 }
60
61 private:
62 LLVMStubModule *module_;
63 Stub *stub_;
64 };
65
66 class StubBuildCircuitPass {
67 public:
Run(StubPassData * data)68 bool Run(StubPassData *data)
69 {
70 auto stub = data->GetStub();
71 std::cout << "Stub Name: " << stub->GetMethodName() << std::endl;
72 stub->GenerateCircuit(data->GetCompilationConfig());
73 return true;
74 }
75 };
76
77 class StubLLVMIRGenPass {
78 public:
CreateCodeGen(LLVMStubModule * module)79 void CreateCodeGen(LLVMStubModule *module)
80 {
81 llvmImpl_ = std::make_unique<LLVMIRGeneratorImpl>(module);
82 }
Run(StubPassData * data,int index)83 bool Run(StubPassData *data, int index)
84 {
85 auto stubModule = data->GetStubModule();
86 CreateCodeGen(stubModule);
87 CodeGenerator codegen(llvmImpl_);
88 codegen.Run(data->GetCircuit(), data->GetScheduleResult(), index, data->GetCompilationConfig());
89 return true;
90 }
91 private:
92 std::unique_ptr<CodeGeneratorImpl> llvmImpl_{nullptr};
93 };
94
BuildStubModuleAndSave(const std::string & triple,panda::ecmascript::StubModule * module,const std::string & filename)95 void StubAotCompiler::BuildStubModuleAndSave(const std::string &triple, panda::ecmascript::StubModule *module,
96 const std::string &filename)
97 {
98 LLVMStubModule stubModule("fast_stubs", triple);
99 std::vector<int> stubSet = GetStubIndices();
100 stubModule.Initialize(stubSet);
101 for (int i = 0; i < ALL_STUB_MAXCOUNT; i++) {
102 auto stub = stubs_[i];
103 if (stub != nullptr) {
104 StubPassData data(stub, &stubModule);
105 PassRunner<StubPassData> pipeline(&data);
106 pipeline.RunPass<StubBuildCircuitPass>();
107 pipeline.RunPass<VerifierPass>();
108 pipeline.RunPass<SchedulingPass>();
109 pipeline.RunPass<StubLLVMIRGenPass>(i);
110 }
111 }
112
113 LLVMModuleAssembler assembler(&stubModule);
114 assembler.AssembleModule();
115 assembler.AssembleStubModule(module);
116
117 auto codeSize = assembler.GetCodeSize();
118 panda::ecmascript::MachineCode *code = reinterpret_cast<panda::ecmascript::MachineCode *>(
119 new uint64_t[(panda::ecmascript::MachineCode::SIZE + codeSize) / sizeof(uint64_t) + 1]);
120 code->SetInstructionSizeInBytes(codeSize);
121
122 assembler.CopyAssemblerToCode(code);
123
124 module->SetCode(code);
125 module->Save(filename);
126
127 delete[] code;
128 }
129 } // namespace panda::ecmascript::kungfu
130
131
main(const int argc,const char ** argv)132 int main(const int argc, const char **argv)
133 {
134 panda::Span<const char *> sp(argv, argc);
135 panda::Stub_Aot_Options stubOptions(sp[0]);
136 panda::PandArg<bool> help("help", false, "Print this message and exit");
137 panda::PandArg<bool> options("options", false, "Print compiler options");
138 panda::PandArgParser paParser;
139
140 stubOptions.AddOptions(&paParser);
141 paParser.Add(&help);
142 paParser.Add(&options);
143
144 if (!paParser.Parse(argc, argv) || help.GetValue()) {
145 std::cerr << paParser.GetErrorString() << std::endl;
146 std::cerr << "Usage: " << "ark_stub_opt" << " [OPTIONS]" << std::endl;
147 std::cerr << std::endl;
148 std::cerr << "optional arguments:" << std::endl;
149
150 std::cerr << paParser.GetHelpString() << std::endl;
151 return 1;
152 }
153
154 std::string tripleString = stubOptions.GetTargetTriple();
155 std::string moduleFilename = stubOptions.GetStubOutputFile();
156 std::string compiledStubList = stubOptions.GetCompiledStubs();
157 panda::ecmascript::kungfu::StubAotCompiler moduleBuilder;
158 #define SET_STUB_TO_MODULE(name, counter) \
159 panda::ecmascript::kungfu::Circuit name##Circuit; \
160 panda::ecmascript::kungfu::name##Stub name##Stub(& name##Circuit); \
161 if (compiledStubList.compare("All") == 0 || compiledStubList.find(#name) != std::string::npos) { \
162 moduleBuilder.SetStub(STUB_ID(name), &name##Stub); \
163 }
164 FAST_RUNTIME_STUB_LIST(SET_STUB_TO_MODULE)
165 #if ECMASCRIPT_COMPILE_INTERPRETER_ASM
166 INTERPRETER_STUB_LIST(SET_STUB_TO_MODULE)
167 #endif
168 panda::ecmascript::StubModule stubModule;
169 moduleBuilder.BuildStubModuleAndSave(tripleString, &stubModule, moduleFilename);
170 std::cout << "BuildStubModuleAndSave success" << std::endl;
171 return 0;
172 }
173