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