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 auto targetApi = options_->CompilerOptions().targetApiVersion;
29
30 if (mergeAbc_) {
31 // generate merged abc
32 auto emitMergedAbcJob = new EmitMergedAbcJob(options_->CompilerOutput(), progsInfo_, targetApi);
33 for (const auto &info: progsInfo_) {
34 // generate cache protoBins and set dependencies
35 if (!info.second->needUpdateCache) {
36 continue;
37 }
38 auto outputCacheIter = options_->CompilerOptions().cacheFiles.find(info.first);
39 if (outputCacheIter != options_->CompilerOptions().cacheFiles.end()) {
40 auto emitProtoJob = new EmitCacheJob(outputCacheIter->second, info.second);
41 emitProtoJob->DependsOn(emitMergedAbcJob);
42 jobs_.push_back(emitProtoJob);
43 jobsCount_++;
44 }
45 }
46 // One job should be placed after those jobs which depend on it to prevent blocking
47 jobs_.push_back(emitMergedAbcJob);
48 jobsCount_++;
49 } else {
50 for (const auto &info: progsInfo_) {
51 try {
52 // generate multi abcs
53 auto outputFileName = options_->OutputFiles().empty() ? options_->CompilerOutput() :
54 options_->OutputFiles().at(info.first);
55 auto emitSingleAbcJob = new EmitSingleAbcJob(outputFileName, &(info.second->program), statp_,
56 targetApi);
57 jobs_.push_back(emitSingleAbcJob);
58 jobsCount_++;
59 } catch (std::exception &error) {
60 throw Error(ErrorType::GENERIC, error.what());
61 }
62 }
63 }
64
65 lock.unlock();
66 jobsAvailable_.notify_all();
67 }
68
Run()69 void EmitSingleAbcJob::Run()
70 {
71 if (!panda::pandasm::AsmEmitter::Emit(panda::os::file::File::GetExtendedFilePath(outputFileName_), *prog_, statp_,
72 nullptr, true, nullptr, targetApiVersion_)) {
73 throw Error(ErrorType::GENERIC, "Failed to emit " + outputFileName_ + ", error: " +
74 panda::pandasm::AsmEmitter::GetLastError());
75 }
76 for (auto *dependant : dependants_) {
77 dependant->Signal();
78 }
79 }
80
Run()81 void EmitMergedAbcJob::Run()
82 {
83 std::vector<panda::pandasm::Program*> progs;
84 progs.reserve(progsInfo_.size());
85 for (const auto &info: progsInfo_) {
86 progs.push_back(&(info.second->program));
87 }
88
89 bool success = panda::pandasm::AsmEmitter::EmitPrograms(
90 panda::os::file::File::GetExtendedFilePath(outputFileName_), progs, true, targetApiVersion_);
91
92 for (auto *dependant : dependants_) {
93 dependant->Signal();
94 }
95
96 if (!success) {
97 throw Error(ErrorType::GENERIC, "Failed to emit " + outputFileName_ + ", error: " +
98 panda::pandasm::AsmEmitter::GetLastError() +
99 "\nIf you're using any cache file generated by older version of SDK, " +
100 "please try cleaning the cache files and rebuild");
101 }
102 }
103
Run()104 void EmitCacheJob::Run()
105 {
106 std::unique_lock<std::mutex> lock(m_);
107 cond_.wait(lock, [this] { return dependencies_ == 0; });
108 panda::proto::ProtobufSnapshotGenerator::UpdateCacheFile(progCache_, outputProtoName_);
109 }
110
111 } // namespace panda::es2panda::util
112