• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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