1 /*
2 * Copyright (c) 2021-2025 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 "generateBin.h"
17 #include "bytecode_optimizer/bytecodeopt_options.h"
18 #include "bytecode_optimizer/optimize_bytecode.h"
19 #include "compiler/compiler_logger.h"
20 #include "compiler/compiler_options.h"
21 #include "util/options.h"
22
23 namespace ark::es2panda::util {
24
InitializeLogging(const util::Options & options)25 [[maybe_unused]] static void InitializeLogging(const util::Options &options)
26 {
27 ark::Logger::ComponentMask componentMask;
28 componentMask.set(ark::Logger::Component::ASSEMBLER);
29 componentMask.set(ark::Logger::Component::COMPILER);
30 componentMask.set(ark::Logger::Component::BYTECODE_OPTIMIZER);
31
32 if (!Logger::IsInitialized()) {
33 Logger::InitializeStdLogging(options.LogLevel(), componentMask);
34 } else {
35 Logger::EnableComponent(componentMask);
36 }
37 }
38
39 #ifdef PANDA_WITH_BYTECODE_OPTIMIZER
OptimizeBytecode(ark::pandasm::Program * prog,const util::Options & options,const ReporterFun & reporter,std::map<std::string,size_t> * statp,ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps * mapsp)40 static int OptimizeBytecode(ark::pandasm::Program *prog, const util::Options &options, const ReporterFun &reporter,
41 std::map<std::string, size_t> *statp,
42 ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp)
43 {
44 if (options.GetOptLevel() != 0) {
45 InitializeLogging(options);
46 if (!ark::pandasm::AsmEmitter::Emit(options.GetOutput(), *prog, statp, mapsp, true)) {
47 reporter(diagnostic::EMIT_FAILED, {ark::pandasm::AsmEmitter::GetLastError()});
48 return 1;
49 }
50
51 ark::bytecodeopt::g_options.SetOptLevel(options.GetOptLevel());
52 // Set default value instead of maximum set in ark::bytecodeopt::SetCompilerOptions()
53 ark::compiler::CompilerLogger::Init({"all"});
54 ark::compiler::g_options.SetCompilerMaxBytecodeSize(ark::compiler::g_options.GetCompilerMaxBytecodeSize());
55 ark::bytecodeopt::OptimizeBytecode(prog, mapsp, options.GetOutput(), options.IsDynamic(), true);
56 }
57
58 return 0;
59 }
60 #endif
61
GenerateProgramImpl(ark::pandasm::Program * prog,const util::Options & options,const ReporterFun & reporter,std::map<std::string,size_t> * statp,ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps * mapsp)62 static int GenerateProgramImpl(ark::pandasm::Program *prog, const util::Options &options, const ReporterFun &reporter,
63 std::map<std::string, size_t> *statp,
64 ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp)
65 {
66 if (options.IsDumpAssembly()) {
67 es2panda::Compiler::DumpAsm(prog);
68 }
69
70 if (!ark::pandasm::AsmEmitter::AssignProfileInfo(prog)) {
71 reporter(diagnostic::ASSIGN_PROFILE_INFO_FAILED, {});
72 return 1;
73 }
74
75 if (!ark::pandasm::AsmEmitter::Emit(options.GetOutput(), *prog, statp, mapsp, true)) {
76 reporter(diagnostic::EMIT_FAILED, {ark::pandasm::AsmEmitter::GetLastError()});
77 return 1;
78 }
79
80 if (options.IsDumpSizeStat()) {
81 size_t totalSize = 0;
82 std::cout << "Panda file size statistic:" << std::endl;
83 constexpr std::array<std::string_view, 2> INFO_STATS = {"instructions_number", "codesize"};
84
85 ES2PANDA_ASSERT(statp != nullptr);
86 auto &stat = *statp;
87 for (const auto &[name, size] : stat) {
88 if (find(INFO_STATS.begin(), INFO_STATS.end(), name) != INFO_STATS.end()) {
89 continue;
90 }
91 std::cout << name << " section: " << size << std::endl;
92 totalSize += size;
93 }
94
95 for (const auto &name : INFO_STATS) {
96 std::cout << name << ": " << stat.at(std::string(name)) << std::endl;
97 }
98
99 std::cout << "total: " << totalSize << std::endl;
100 }
101
102 return 0;
103 }
104
GenerateProgram(ark::pandasm::Program * prog,const util::Options & options,const ReporterFun & reporter)105 int GenerateProgram(ark::pandasm::Program *prog, const util::Options &options, const ReporterFun &reporter)
106 {
107 std::map<std::string, size_t> stat;
108 std::map<std::string, size_t> *statp = options.GetOptLevel() != 0 ? &stat : nullptr;
109 ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
110 ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = options.GetOptLevel() != 0 ? &maps : nullptr;
111
112 #ifdef PANDA_WITH_BYTECODE_OPTIMIZER
113 if (OptimizeBytecode(prog, options, reporter, statp, mapsp) != 0) {
114 return 1;
115 }
116 #endif
117 if (GenerateProgramImpl(prog, options, reporter, statp, mapsp) != 0) {
118 return 1;
119 }
120
121 return 0;
122 }
123
124 } // namespace ark::es2panda::util
125