125d7b4fbSAlexey Lapshin //===- WasmWriter.cpp -----------------------------------------------------===// 225d7b4fbSAlexey Lapshin // 325d7b4fbSAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 425d7b4fbSAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information. 525d7b4fbSAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 625d7b4fbSAlexey Lapshin // 725d7b4fbSAlexey Lapshin //===----------------------------------------------------------------------===// 825d7b4fbSAlexey Lapshin 925d7b4fbSAlexey Lapshin #include "WasmWriter.h" 1025d7b4fbSAlexey Lapshin #include "llvm/BinaryFormat/Wasm.h" 1125d7b4fbSAlexey Lapshin #include "llvm/Support/Endian.h" 1225d7b4fbSAlexey Lapshin #include "llvm/Support/LEB128.h" 1325d7b4fbSAlexey Lapshin #include "llvm/Support/raw_ostream.h" 1425d7b4fbSAlexey Lapshin 1525d7b4fbSAlexey Lapshin namespace llvm { 1625d7b4fbSAlexey Lapshin namespace objcopy { 1725d7b4fbSAlexey Lapshin namespace wasm { 1825d7b4fbSAlexey Lapshin 1925d7b4fbSAlexey Lapshin using namespace object; 2025d7b4fbSAlexey Lapshin using namespace llvm::wasm; 2125d7b4fbSAlexey Lapshin 2225d7b4fbSAlexey Lapshin Writer::SectionHeader Writer::createSectionHeader(const Section &S, 2325d7b4fbSAlexey Lapshin size_t &SectionSize) { 2425d7b4fbSAlexey Lapshin SectionHeader Header; 2525d7b4fbSAlexey Lapshin raw_svector_ostream OS(Header); 2625d7b4fbSAlexey Lapshin OS << S.SectionType; 2725d7b4fbSAlexey Lapshin bool HasName = S.SectionType == WASM_SEC_CUSTOM; 2825d7b4fbSAlexey Lapshin SectionSize = S.Contents.size(); 2925d7b4fbSAlexey Lapshin if (HasName) 3025d7b4fbSAlexey Lapshin SectionSize += getULEB128Size(S.Name.size()) + S.Name.size(); 311b21067cSDerek Schuff // If we read this section from an object file, use its original size for the 321b21067cSDerek Schuff // padding of the LEB value to avoid changing the file size. Otherwise, pad 331b21067cSDerek Schuff // out to 5 bytes to make it predictable, and match the behavior of clang. 34*e4e3ff5aSKazu Hirata unsigned HeaderSecSizeEncodingLen = S.HeaderSecSizeEncodingLen.value_or(5); 351b21067cSDerek Schuff encodeULEB128(SectionSize, OS, HeaderSecSizeEncodingLen); 3625d7b4fbSAlexey Lapshin if (HasName) { 3725d7b4fbSAlexey Lapshin encodeULEB128(S.Name.size(), OS); 3825d7b4fbSAlexey Lapshin OS << S.Name; 3925d7b4fbSAlexey Lapshin } 4025d7b4fbSAlexey Lapshin // Total section size is the content size plus 1 for the section type and 411b21067cSDerek Schuff // the LEB-encoded size. 421b21067cSDerek Schuff SectionSize = SectionSize + 1 + HeaderSecSizeEncodingLen; 4325d7b4fbSAlexey Lapshin return Header; 4425d7b4fbSAlexey Lapshin } 4525d7b4fbSAlexey Lapshin 4625d7b4fbSAlexey Lapshin size_t Writer::finalize() { 4725d7b4fbSAlexey Lapshin size_t ObjectSize = sizeof(WasmMagic) + sizeof(WasmVersion); 4825d7b4fbSAlexey Lapshin SectionHeaders.reserve(Obj.Sections.size()); 4925d7b4fbSAlexey Lapshin // Finalize the headers of each section so we know the total size. 5025d7b4fbSAlexey Lapshin for (const Section &S : Obj.Sections) { 5125d7b4fbSAlexey Lapshin size_t SectionSize; 5225d7b4fbSAlexey Lapshin SectionHeaders.push_back(createSectionHeader(S, SectionSize)); 5325d7b4fbSAlexey Lapshin ObjectSize += SectionSize; 5425d7b4fbSAlexey Lapshin } 5525d7b4fbSAlexey Lapshin return ObjectSize; 5625d7b4fbSAlexey Lapshin } 5725d7b4fbSAlexey Lapshin 5825d7b4fbSAlexey Lapshin Error Writer::write() { 5925d7b4fbSAlexey Lapshin size_t TotalSize = finalize(); 6025d7b4fbSAlexey Lapshin Out.reserveExtraSpace(TotalSize); 6125d7b4fbSAlexey Lapshin 6225d7b4fbSAlexey Lapshin // Write the header. 6325d7b4fbSAlexey Lapshin Out.write(Obj.Header.Magic.data(), Obj.Header.Magic.size()); 6425d7b4fbSAlexey Lapshin uint32_t Version; 6525d7b4fbSAlexey Lapshin support::endian::write32le(&Version, Obj.Header.Version); 6625d7b4fbSAlexey Lapshin Out.write(reinterpret_cast<const char *>(&Version), sizeof(Version)); 6725d7b4fbSAlexey Lapshin 6825d7b4fbSAlexey Lapshin // Write each section. 6925d7b4fbSAlexey Lapshin for (size_t I = 0, S = SectionHeaders.size(); I < S; ++I) { 7025d7b4fbSAlexey Lapshin Out.write(SectionHeaders[I].data(), SectionHeaders[I].size()); 7125d7b4fbSAlexey Lapshin Out.write(reinterpret_cast<const char *>(Obj.Sections[I].Contents.data()), 7225d7b4fbSAlexey Lapshin Obj.Sections[I].Contents.size()); 7325d7b4fbSAlexey Lapshin } 7425d7b4fbSAlexey Lapshin 7525d7b4fbSAlexey Lapshin return Error::success(); 7625d7b4fbSAlexey Lapshin } 7725d7b4fbSAlexey Lapshin 7825d7b4fbSAlexey Lapshin } // end namespace wasm 7925d7b4fbSAlexey Lapshin } // end namespace objcopy 8025d7b4fbSAlexey Lapshin } // end namespace llvm 81