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