• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 <assembly-program.h>
17 #include <assembly-emitter.h>
18 #include <emitFiles.h>
19 #include <es2panda.h>
20 #include <mem/arena_allocator.h>
21 #include <mem/pool_manager.h>
22 #include <options.h>
23 #include <protobufSnapshotGenerator.h>
24 #include <util/dumper.h>
25 #include <util/moduleHelpers.h>
26 #include <util/programCache.h>
27 #include <util/workerQueue.h>
28 
29 #include <iostream>
30 
31 namespace panda::es2panda::aot {
32 using mem::MemConfig;
33 class MemManager {
34 public:
MemManager()35     explicit MemManager()
36     {
37         constexpr auto COMPILER_SIZE = 8192_MB;
38 
39         MemConfig::Initialize(0, 0, COMPILER_SIZE, 0);
40         PoolManager::Initialize(PoolType::MMAP);
41     }
42 
43     NO_COPY_SEMANTIC(MemManager);
44     NO_MOVE_SEMANTIC(MemManager);
45 
~MemManager()46     ~MemManager()
47     {
48         PoolManager::Finalize();
49         MemConfig::Finalize();
50     }
51 };
52 
GenerateBase64Output(panda::pandasm::Program * prog)53 static void GenerateBase64Output(panda::pandasm::Program *prog)
54 {
55     auto pandaFile = panda::pandasm::AsmEmitter::Emit(*prog);
56     const uint8_t *buffer = pandaFile->GetBase();
57     size_t size = pandaFile->GetPtr().GetSize();
58     std::string content(reinterpret_cast<const char*>(buffer), size);
59     std::string base64Output = util::Base64Encode(content);
60     std::cout << base64Output << std::endl;
61 }
62 
DumpPandaFileSizeStatistic(std::map<std::string,size_t> & stat)63 static void DumpPandaFileSizeStatistic(std::map<std::string, size_t> &stat)
64 {
65     size_t totalSize = 0;
66     std::cout << "Panda file size statistic:" << std::endl;
67     constexpr std::array<std::string_view, 2> INFO_STATS = {"instructions_number", "codesize"};
68 
69     for (const auto &[name, size] : stat) {
70         if (find(INFO_STATS.begin(), INFO_STATS.end(), name) != INFO_STATS.end()) {
71             continue;
72         }
73         std::cout << name << " section: " << size << std::endl;
74         totalSize += size;
75     }
76 
77     for (const auto &name : INFO_STATS) {
78         std::cout << name << ": " << stat.at(std::string(name)) << std::endl;
79     }
80 
81     std::cout << "total: " << totalSize << std::endl;
82 }
83 
GenerateProgramsByWorkers(const std::map<std::string,panda::es2panda::util::ProgramCache * > & programsInfo,const std::unique_ptr<panda::es2panda::aot::Options> & options,std::map<std::string,size_t> * statp)84 static bool GenerateProgramsByWorkers(const std::map<std::string, panda::es2panda::util::ProgramCache*> &programsInfo,
85     const std::unique_ptr<panda::es2panda::aot::Options> &options, std::map<std::string, size_t> *statp)
86 {
87     auto queue = new panda::es2panda::aot::EmitFileQueue(options, statp, programsInfo);
88 
89     bool emitResult = true;
90     try {
91         queue->Schedule();
92         queue->Consume();
93         queue->Wait();
94     } catch (const class Error &e) {
95         emitResult = false;
96         std::cerr << e.Message() << std::endl;
97     }
98 
99     delete queue;
100     queue = nullptr;
101 
102     return emitResult;
103 }
104 
DumpProgramInfos(const std::map<std::string,panda::es2panda::util::ProgramCache * > & programsInfo,const std::unique_ptr<panda::es2panda::aot::Options> & options)105 static void DumpProgramInfos(const std::map<std::string, panda::es2panda::util::ProgramCache*> &programsInfo,
106     const std::unique_ptr<panda::es2panda::aot::Options> &options)
107 {
108     const es2panda::CompilerOptions &compilerOptions = options->CompilerOptions();
109     if (compilerOptions.dumpAsm || compilerOptions.dumpLiteralBuffer) {
110         for (const auto &progInfo : programsInfo) {
111             if (compilerOptions.dumpAsm) {
112                 es2panda::Compiler::DumpAsm(&(progInfo.second->program));
113             }
114 
115             if (compilerOptions.dumpLiteralBuffer) {
116                 panda::es2panda::util::Dumper::DumpLiterals(progInfo.second->program.literalarray_table);
117             }
118         }
119     }
120 }
121 
GenerateProgram(const std::map<std::string,panda::es2panda::util::ProgramCache * > & programsInfo,const std::unique_ptr<panda::es2panda::aot::Options> & options)122 static bool GenerateProgram(const std::map<std::string, panda::es2panda::util::ProgramCache*> &programsInfo,
123     const std::unique_ptr<panda::es2panda::aot::Options> &options)
124 {
125     DumpProgramInfos(programsInfo, options);
126 
127     if (programsInfo.size() == 1) {
128         auto *prog = &(programsInfo.begin()->second->program);
129         if (options->OutputFiles().empty() && options->CompilerOutput().empty()) {
130             GenerateBase64Output(prog);
131             return true;
132         }
133 
134         if (options->compilerProtoOutput().size() > 0) {
135             panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(*prog, options->compilerProtoOutput());
136             return true;
137         }
138     }
139 
140     bool dumpSize = options->SizeStat();
141     std::map<std::string, size_t> stat;
142     std::map<std::string, size_t> *statp = dumpSize ? &stat : nullptr;
143 
144     if (!GenerateProgramsByWorkers(programsInfo, options, statp)) {
145         return false;
146     }
147 
148     if (dumpSize) {
149         DumpPandaFileSizeStatistic(stat);
150     }
151 
152     return true;
153 }
154 
GenerateAbcFiles(const std::map<std::string,panda::es2panda::util::ProgramCache * > & programsInfo,const std::unique_ptr<panda::es2panda::aot::Options> & options,size_t expectedProgsCount)155 static bool GenerateAbcFiles(const std::map<std::string, panda::es2panda::util::ProgramCache*> &programsInfo,
156     const std::unique_ptr<panda::es2panda::aot::Options> &options, size_t expectedProgsCount)
157 {
158     if (programsInfo.size() != expectedProgsCount) {
159         std::cerr << "the size of programs is expected to be " << expectedProgsCount
160                   << ", but is " << programsInfo.size() << std::endl;
161         return false;
162     }
163 
164     if (!GenerateProgram(programsInfo, options)) {
165         std::cerr << "GenerateProgram Failed!" << std::endl;
166         return false;
167     }
168 
169     return true;
170 }
171 
Run(int argc,const char ** argv)172 int Run(int argc, const char **argv)
173 {
174     auto options = std::make_unique<Options>();
175     if (!options->Parse(argc, argv)) {
176         std::cerr << options->ErrorMsg() << std::endl;
177         return 1;
178     }
179 
180     if (options->CompilerOptions().bcVersion || options->CompilerOptions().bcMinVersion) {
181         std::string version = options->CompilerOptions().bcVersion ?
182             panda::panda_file::GetVersion(panda::panda_file::version) :
183             panda::panda_file::GetVersion(panda::panda_file::minVersion);
184         std::cout << version << std::endl;
185         return 0;
186     }
187 
188     std::map<std::string, panda::es2panda::util::ProgramCache*> programsInfo;
189     size_t expectedProgsCount = options->CompilerOptions().sourceFiles.size();
190     panda::ArenaAllocator allocator(panda::SpaceType::SPACE_TYPE_COMPILER, nullptr, true);
191 
192     int ret = Compiler::CompileFiles(options->CompilerOptions(), programsInfo, &allocator);
193     if (options->ParseOnly()) {
194         return ret;
195     }
196 
197     if (!options->NpmModuleEntryList().empty()) {
198         es2panda::util::ModuleHelpers::CompileNpmModuleEntryList(options->NpmModuleEntryList(),
199             options->CompilerOptions(), programsInfo, &allocator);
200         expectedProgsCount++;
201     }
202 
203     if (!GenerateAbcFiles(programsInfo, options, expectedProgsCount)) {
204         return 1;
205     }
206 
207     return 0;
208 }
209 }  // namespace panda::es2panda::aot
210 
main(int argc,const char ** argv)211 int main(int argc, const char **argv)
212 {
213     panda::es2panda::aot::MemManager mm;
214     return panda::es2panda::aot::Run(argc, argv);
215 }
216