1 /*
2 * Copyright (c) 2023 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 "emitFiles.h"
17
18 #include <assembly-emitter.h>
19 #include <es2panda.h>
20 #include <mem/arena_allocator.h>
21 #include <protobufSnapshotGenerator.h>
22
23 namespace panda::es2panda::aot {
Schedule()24 void EmitFileQueue::Schedule()
25 {
26 ASSERT(jobsCount_ == 0);
27 std::unique_lock<std::mutex> lock(m_);
28
29 if (mergeAbc_) {
30 // generate merged abc
31 auto emitMergedAbcJob = new EmitMergedAbcJob(options_->CompilerOutput(), progsInfo_);
32 for (const auto &info: progsInfo_) {
33 // generate cache protoBins and set dependencies
34 if (!info.second->needUpdateCache) {
35 continue;
36 }
37 auto outputCacheIter = options_->CompilerOptions().cacheFiles.find(info.first);
38 if (outputCacheIter != options_->CompilerOptions().cacheFiles.end()) {
39 auto emitProtoJob = new EmitCacheJob(outputCacheIter->second, info.second);
40 emitProtoJob->DependsOn(emitMergedAbcJob);
41 jobs_.push_back(emitProtoJob);
42 jobsCount_++;
43 }
44 }
45 // One job should be placed after those jobs which depend on it to prevent blocking
46 jobs_.push_back(emitMergedAbcJob);
47 jobsCount_++;
48 } else {
49 for (const auto &info: progsInfo_) {
50 try {
51 // generate multi abcs
52 auto outputFileName = options_->OutputFiles().empty() ? options_->CompilerOutput() :
53 options_->OutputFiles().at(info.first);
54 auto emitSingleAbcJob = new EmitSingleAbcJob(outputFileName, &(info.second->program), statp_);
55 jobs_.push_back(emitSingleAbcJob);
56 jobsCount_++;
57 } catch (std::exception &error) {
58 throw Error(ErrorType::GENERIC, error.what());
59 }
60 }
61 }
62
63 lock.unlock();
64 jobsAvailable_.notify_all();
65 }
66
Run()67 void EmitSingleAbcJob::Run()
68 {
69 if (!panda::pandasm::AsmEmitter::Emit(panda::os::file::File::GetExtendedFilePath(outputFileName_), *prog_, statp_,
70 nullptr, true)) {
71 throw Error(ErrorType::GENERIC, "Failed to emit " + outputFileName_ + ", error: " +
72 panda::pandasm::AsmEmitter::GetLastError());
73 }
74 for (auto *dependant : dependants_) {
75 dependant->Signal();
76 }
77 }
78
Run()79 void EmitMergedAbcJob::Run()
80 {
81 std::vector<panda::pandasm::Program*> progs;
82 progs.reserve(progsInfo_.size());
83 for (const auto &info: progsInfo_) {
84 progs.push_back(&(info.second->program));
85 }
86 if (!panda::pandasm::AsmEmitter::EmitPrograms(panda::os::file::File::GetExtendedFilePath(outputFileName_), progs,
87 true)) {
88 throw Error(ErrorType::GENERIC, "Failed to emit " + outputFileName_ + ", error: " +
89 panda::pandasm::AsmEmitter::GetLastError());
90 }
91 for (auto *dependant : dependants_) {
92 dependant->Signal();
93 }
94 }
95
Run()96 void EmitCacheJob::Run()
97 {
98 std::unique_lock<std::mutex> lock(m_);
99 cond_.wait(lock, [this] { return dependencies_ == 0; });
100 panda::proto::ProtobufSnapshotGenerator::UpdateCacheFile(progCache_, outputProtoName_);
101 }
102
103 } // namespace panda::es2panda::util
104