• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/file_generators.h"
17 
18 #include "ecmascript/compiler/llvm_ir_builder.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/snapshot/mem/snapshot.h"
21 #include "ecmascript/stackmap/ark_stackmap_builder.h"
22 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
23 
24 namespace panda::ecmascript::kungfu {
CollectStackMapDes(ModuleSectionDes & des) const25 void Module::CollectStackMapDes(ModuleSectionDes& des) const
26 {
27     uint32_t stackmapSize = des.GetSecSize(ElfSecName::LLVM_STACKMAP);
28     std::unique_ptr<uint8_t[]> stackmapPtr(std::make_unique<uint8_t[]>(stackmapSize));
29     uint64_t addr = des.GetSecAddr(ElfSecName::LLVM_STACKMAP);
30     if (addr == 0) { // assembler stub don't existed llvm stackmap
31         return;
32     }
33     uint64_t textAddr = des.GetSecAddr(ElfSecName::TEXT);
34     if (memcpy_s(stackmapPtr.get(), stackmapSize, reinterpret_cast<void *>(addr), stackmapSize) != EOK) {
35         LOG_FULL(FATAL) << "memcpy_s failed";
36         UNREACHABLE();
37     }
38     std::shared_ptr<uint8_t> ptr = nullptr;
39     uint32_t size = 0;
40     ArkStackMapBuilder builder;
41     std::tie(ptr, size) = builder.Run(std::move(stackmapPtr), textAddr);
42     des.EraseSec(ElfSecName::LLVM_STACKMAP);
43     des.SetArkStackMapPtr(ptr);
44     des.SetArkStackMapSize(size);
45 }
46 
CollectAsmStubCodeInfo(std::map<uintptr_t,std::string> & addr2name,uint32_t bridgeModuleIdx)47 void StubFileGenerator::CollectAsmStubCodeInfo(std::map<uintptr_t, std::string> &addr2name,
48                                                uint32_t bridgeModuleIdx)
49 {
50     uint32_t funSize = 0;
51     for (size_t i = 0; i < asmModule_.GetFunctionCount(); i++) {
52         auto cs = asmModule_.GetCSign(i);
53         auto entryOffset = asmModule_.GetFunction(cs->GetID());
54         if (i < asmModule_.GetFunctionCount() - 1) {
55             auto nextcs = asmModule_.GetCSign(i + 1);
56             funSize = asmModule_.GetFunction(nextcs->GetID()) - entryOffset;
57         } else {
58             funSize = asmModule_.GetBufferSize() - entryOffset;
59         }
60         stubInfo_.AddEntry(cs->GetTargetKind(), false, cs->GetID(), entryOffset, bridgeModuleIdx, 0, funSize);
61         ASSERT(!cs->GetName().empty());
62         auto curSecBegin = asmModule_.GetBuffer();
63         uintptr_t entry = reinterpret_cast<uintptr_t>(curSecBegin) + entryOffset;
64         addr2name[entry] = cs->GetName();
65     }
66 }
67 
CollectCodeInfo()68 void StubFileGenerator::CollectCodeInfo()
69 {
70     std::map<uintptr_t, std::string> addr2name;
71     for (size_t i = 0; i < modulePackage_.size(); i++) {
72         modulePackage_[i].CollectFuncEntryInfo(addr2name, stubInfo_, i, GetLog());
73         ModuleSectionDes des;
74         modulePackage_[i].CollectModuleSectionDes(des, true);
75         stubInfo_.AddModuleDes(des);
76     }
77     // idx for bridge module is the one after last module in modulePackage
78     CollectAsmStubCodeInfo(addr2name, modulePackage_.size());
79     DisassembleEachFunc(addr2name);
80 }
81 
CollectCodeInfo()82 void AOTFileGenerator::CollectCodeInfo()
83 {
84     std::map<uintptr_t, std::string> addr2name;
85     for (size_t i = 0; i < modulePackage_.size(); i++) {
86         modulePackage_[i].CollectFuncEntryInfo(addr2name, aotInfo_, i, GetLog());
87         ModuleSectionDes des;
88         modulePackage_[i].CollectModuleSectionDes(des);
89         aotInfo_.AddModuleDes(des);
90     }
91     DisassembleEachFunc(addr2name);
92 }
93 
RunAsmAssembler()94 void StubFileGenerator::RunAsmAssembler()
95 {
96     NativeAreaAllocator allocator;
97     Chunk chunk(&allocator);
98     asmModule_.Run(&cfg_, &chunk);
99 
100     auto buffer = asmModule_.GetBuffer();
101     auto bufferSize = asmModule_.GetBufferSize();
102     if (bufferSize == 0U) {
103         return;
104     }
105     stubInfo_.FillAsmStubTempHolder(buffer, bufferSize);
106     stubInfo_.accumulateTotalSize(bufferSize);
107 }
108 
SaveStubFile(const std::string & filename)109 void StubFileGenerator::SaveStubFile(const std::string &filename)
110 {
111     RunLLVMAssembler();
112     RunAsmAssembler();
113     CollectCodeInfo();
114     stubInfo_.Save(filename);
115 }
116 
SaveAOTFile(const std::string & filename)117 void AOTFileGenerator::SaveAOTFile(const std::string &filename)
118 {
119     TimeScope timescope("LLVMCodeGenPass-AN", const_cast<CompilerLog *>(log_));
120     RunLLVMAssembler();
121     CollectCodeInfo();
122     GenerateMethodToEntryIndexMap();
123     aotInfo_.Save(filename, cfg_.GetTriple());
124     DestoryModule();
125 }
126 
SaveSnapshotFile()127 void AOTFileGenerator::SaveSnapshotFile()
128 {
129     TimeScope timescope("LLVMCodeGenPass-AI", const_cast<CompilerLog *>(log_));
130     Snapshot snapshot(vm_);
131     const CString snapshotPath(vm_->GetJSOptions().GetAOTOutputFile().c_str());
132     vm_->GetTSManager()->ResolveSnapshotConstantPool(methodToEntryIndexMap_);
133     snapshot.Serialize(snapshotPath + AOTFileManager::FILE_EXTENSION_AI);
134 }
135 }  // namespace panda::ecmascript::kungfu
136