• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "ecmascript/compiler/stub_compiler.h"
17 
18 #include "ecmascript/base/config.h"
19 #include "ecmascript/base/string_helper.h"
20 #include "ecmascript/compiler/codegen/llvm/llvm_codegen.h"
21 #include "ecmascript/compiler/file_generators.h"
22 #include "ecmascript/compiler/interpreter_stub-inl.h"
23 #include "ecmascript/compiler/pass.h"
24 #include "ecmascript/compiler/scheduler.h"
25 #include "ecmascript/compiler/stub.h"
26 #include "ecmascript/compiler/stub_builder-inl.h"
27 #include "ecmascript/compiler/verifier.h"
28 #include "ecmascript/js_runtime_options.h"
29 #include "ecmascript/log.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 #include "ecmascript/compiler/baseline/baseline_stub_csigns.h"
32 
33 namespace panda::ecmascript::kungfu {
34 class StubPassData : public PassData {
35 public:
StubPassData(Stub * stub,LLVMModule * module,CompilerLog * log)36     StubPassData(Stub *stub, LLVMModule *module, CompilerLog *log)
37         : PassData(nullptr, nullptr, nullptr, log, "stubs"),
38           cfg_(module->GetTripleStr()),
39           module_(module),
40           stub_(stub) {}
41     ~StubPassData() = default;
42 
GetCompilationConfig() const43     const CompilationConfig *GetCompilationConfig() const
44     {
45         return &cfg_;
46     }
47 
GetCircuit() const48     Circuit *GetCircuit() const
49     {
50         return stub_->GetCircuit();
51     }
52 
GetStubModule() const53     LLVMModule *GetStubModule() const
54     {
55         return module_;
56     }
57 
GetStub() const58     Stub *GetStub() const
59     {
60         return stub_;
61     }
62 
63 private:
64     CompilationConfig cfg_;
65     LLVMModule *module_;
66     Stub *stub_;
67 };
68 
69 class StubBuildCircuitPass {
70 public:
Run(StubPassData * data)71     bool Run(StubPassData *data)
72     {
73         auto stub = data->GetStub();
74         LOG_COMPILER(INFO) << "Stub Name: " << stub->GetMethodName();
75         stub->GenerateCircuit(data->GetCompilationConfig());
76         return true;
77     }
78 };
79 
80 class StubLLVMIRGenPass {
81 public:
CreateCodeGen(LLVMModule * module,bool enableLog)82     void CreateCodeGen(LLVMModule *module, bool enableLog)
83     {
84         llvmImpl_ = std::make_unique<LLVMIRGeneratorImpl>(module, enableLog);
85     }
86 
Run(StubPassData * data,size_t index)87     bool Run(StubPassData *data, size_t index)
88     {
89         bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->OutputASM();
90         auto stubModule = data->GetStubModule();
91         CreateCodeGen(stubModule, enableLog);
92         CodeGenerator codegen(llvmImpl_, "stubs");
93         codegen.RunForStub(data->GetCircuit(), data->GetConstScheduleResult(), index, data->GetCompilationConfig());
94         return true;
95     }
96 private:
97     std::unique_ptr<CodeGeneratorImpl> llvmImpl_ {nullptr};
98 };
99 
RunPipeline(LLVMModule * module,NativeAreaAllocator * allocator) const100 void StubCompiler::RunPipeline(LLVMModule *module, NativeAreaAllocator *allocator) const
101 {
102     auto callSigns = module->GetCSigns();
103     CompilerLog *log = GetLog();
104     for (size_t i = 0; i < callSigns.size(); i++) {
105         auto &cs = callSigns[i];
106         Circuit circuit(allocator, module->GetDebugInfo(), cs->GetName().c_str(), module->Is64Bit());
107         Stub stub(cs, &circuit);
108         log->SetStubLog(stub.GetMethodName(), GetLogList());
109 
110         StubPassData data(&stub, module, log);
111         PassRunner<StubPassData> pipeline(&data);
112         pipeline.RunPass<StubBuildCircuitPass>();
113         pipeline.RunPass<VerifierPass>();
114         pipeline.RunPass<SchedulingPass>();
115         pipeline.RunPass<StubLLVMIRGenPass>(i);
116     }
117 }
118 
InitializeCS() const119 void StubCompiler::InitializeCS() const
120 {
121     BytecodeStubCSigns::Initialize();
122     CommonStubCSigns::Initialize();
123     BaselineStubCSigns::Initialize();
124     BuiltinsStubCSigns::Initialize();
125     RuntimeStubCSigns::Initialize();
126 }
127 
BuildStubModuleAndSave() const128 bool StubCompiler::BuildStubModuleAndSave() const
129 {
130     if (filePath_.empty()) {
131         return false;
132     }
133 
134     InitializeCS();
135     CompilerLog *log = GetLog();
136     MethodLogList *logList = GetLogList();
137 
138     NativeAreaAllocator allocator;
139     StubFileGenerator generator(log, logList, triple_, concurrentCompile_);
140 
141     LOG_COMPILER(INFO) << "=============== compiling bytecode handler stubs ===============";
142     LOptions stubOp(optLevel_, FPFlag::ELIM_FP, relocMode_);
143     Module* stubM = generator.AddModule(&allocator, "bc_stub", triple_, stubOp, log->OutputASM(), StubFileKind::BC);
144     if (!stubM->IsLLVM()) {
145         LOG_COMPILER(FATAL) << " Stub compiler is not supported for litecg ===============";
146         return false;
147     }
148     RunPipeline(static_cast<LLVMModule*>(stubM->GetModule()), &allocator);
149 
150     LOG_COMPILER(INFO) << "=============== compiling common stubs ===============";
151     LOptions comOp(optLevel_, FPFlag::RESERVE_FP, relocMode_);
152     Module* comM = generator.AddModule(&allocator, "com_stub", triple_, comOp, log->OutputASM(), StubFileKind::COM);
153     if (!comM->IsLLVM()) {
154         LOG_COMPILER(FATAL) << " Stub compiler is not supported for litecg ===============";
155         return false;
156     }
157     RunPipeline(static_cast<LLVMModule*>(comM->GetModule()), &allocator);
158 
159     LOG_COMPILER(INFO) << "=============== compiling builtins stubs ===============";
160     LOptions builtinOp(optLevel_, FPFlag::RESERVE_FP, relocMode_);
161     Module* builtinM = generator.AddModule(&allocator, "builtin_stub", triple_, builtinOp, log->OutputASM(),
162                                            StubFileKind::BUILTIN);
163     if (!builtinM->IsLLVM()) {
164         LOG_COMPILER(FATAL) << " Stub compiler is not supported for litecg ===============";
165         return false;
166     }
167     RunPipeline(static_cast<LLVMModule*>(builtinM->GetModule()), &allocator);
168 
169     LOG_COMPILER(INFO) << "=============== compiling baseline stubs ===============";
170     LOptions baselineOp(optLevel_, FPFlag::RESERVE_FP, relocMode_);
171     Module* baselineM = generator.AddModule(&allocator, "baseline_stub", triple_, baselineOp, log->OutputASM(),
172                                             StubFileKind::BASELINE);
173     if (!baselineM->IsLLVM()) {
174         LOG_COMPILER(FATAL) << " Stub compiler is not supported for litecg ===============";
175         return false;
176     }
177     RunPipeline(static_cast<LLVMModule*>(baselineM->GetModule()), &allocator);
178 
179     generator.SaveStubFile(filePath_);
180     return true;
181 }
182 
GetHelper()183 std::string GetHelper()
184 {
185     std::string str;
186     str.append(STUB_HELP_HEAD_MSG);
187     str.append(HELP_OPTION_MSG);
188     return str;
189 }
190 }  // namespace panda::ecmascript::kungfu
191 
main(const int argc,const char ** argv)192 int main(const int argc, const char **argv)
193 {
194     panda::ecmascript::JSRuntimeOptions runtimeOptions;
195     bool ret = runtimeOptions.ParseCommand(argc, argv);
196     if (!ret) {
197         std::cerr << panda::ecmascript::kungfu::GetHelper();
198         return 1;
199     }
200 
201     panda::ecmascript::Log::Initialize(runtimeOptions);
202     std::string triple = runtimeOptions.GetTargetTriple();
203     std::string stubFile = runtimeOptions.GetStubFile();
204     size_t optLevel = runtimeOptions.GetOptLevel();
205     size_t relocMode = runtimeOptions.GetRelocMode();
206     std::string logOption = runtimeOptions.GetCompilerLogOption();
207     std::string methodsList = runtimeOptions.GetMethodsListForLog();
208     bool concurrentCompile = runtimeOptions.IsConcurrentCompile();
209 
210     panda::ecmascript::kungfu::CompilerLog logOpt(logOption);
211     panda::ecmascript::kungfu::MethodLogList logList(methodsList);
212     panda::ecmascript::kungfu::StubCompiler compiler(triple, stubFile, optLevel, relocMode, &logOpt, &logList,
213                                                      concurrentCompile);
214 
215     bool res = compiler.BuildStubModuleAndSave();
216     LOG_COMPILER(INFO) << "stub compiler run finish, result condition(T/F):" << std::boolalpha << res;
217     return res ? 0 : -1;
218 }
219