xref: /llvm-project/llvm/lib/ObjCopy/wasm/WasmWriter.cpp (revision 54dad9e269f365d0eff2f63c5ee843564eecca7e)
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