xref: /freebsd-src/contrib/llvm-project/llvm/lib/ObjCopy/wasm/WasmWriter.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===- WasmWriter.cpp -----------------------------------------------------===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric 
9*81ad6265SDimitry Andric #include "WasmWriter.h"
10*81ad6265SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
11*81ad6265SDimitry Andric #include "llvm/Support/Endian.h"
12*81ad6265SDimitry Andric #include "llvm/Support/Errc.h"
13*81ad6265SDimitry Andric #include "llvm/Support/LEB128.h"
14*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
15*81ad6265SDimitry Andric 
16*81ad6265SDimitry Andric namespace llvm {
17*81ad6265SDimitry Andric namespace objcopy {
18*81ad6265SDimitry Andric namespace wasm {
19*81ad6265SDimitry Andric 
20*81ad6265SDimitry Andric using namespace object;
21*81ad6265SDimitry Andric using namespace llvm::wasm;
22*81ad6265SDimitry Andric 
23*81ad6265SDimitry Andric Writer::SectionHeader Writer::createSectionHeader(const Section &S,
24*81ad6265SDimitry Andric                                                   size_t &SectionSize) {
25*81ad6265SDimitry Andric   SectionHeader Header;
26*81ad6265SDimitry Andric   raw_svector_ostream OS(Header);
27*81ad6265SDimitry Andric   OS << S.SectionType;
28*81ad6265SDimitry Andric   bool HasName = S.SectionType == WASM_SEC_CUSTOM;
29*81ad6265SDimitry Andric   SectionSize = S.Contents.size();
30*81ad6265SDimitry Andric   if (HasName)
31*81ad6265SDimitry Andric     SectionSize += getULEB128Size(S.Name.size()) + S.Name.size();
32*81ad6265SDimitry Andric   // Pad the LEB value out to 5 bytes to make it a predictable size, and
33*81ad6265SDimitry Andric   // match the behavior of clang.
34*81ad6265SDimitry Andric   encodeULEB128(SectionSize, OS, 5);
35*81ad6265SDimitry Andric   if (HasName) {
36*81ad6265SDimitry Andric     encodeULEB128(S.Name.size(), OS);
37*81ad6265SDimitry Andric     OS << S.Name;
38*81ad6265SDimitry Andric   }
39*81ad6265SDimitry Andric   // Total section size is the content size plus 1 for the section type and
40*81ad6265SDimitry Andric   // 5 for the LEB-encoded size.
41*81ad6265SDimitry Andric   SectionSize = SectionSize + 1 + 5;
42*81ad6265SDimitry Andric   return Header;
43*81ad6265SDimitry Andric }
44*81ad6265SDimitry Andric 
45*81ad6265SDimitry Andric size_t Writer::finalize() {
46*81ad6265SDimitry Andric   size_t ObjectSize = sizeof(WasmMagic) + sizeof(WasmVersion);
47*81ad6265SDimitry Andric   SectionHeaders.reserve(Obj.Sections.size());
48*81ad6265SDimitry Andric   // Finalize the headers of each section so we know the total size.
49*81ad6265SDimitry Andric   for (const Section &S : Obj.Sections) {
50*81ad6265SDimitry Andric     size_t SectionSize;
51*81ad6265SDimitry Andric     SectionHeaders.push_back(createSectionHeader(S, SectionSize));
52*81ad6265SDimitry Andric     ObjectSize += SectionSize;
53*81ad6265SDimitry Andric   }
54*81ad6265SDimitry Andric   return ObjectSize;
55*81ad6265SDimitry Andric }
56*81ad6265SDimitry Andric 
57*81ad6265SDimitry Andric Error Writer::write() {
58*81ad6265SDimitry Andric   size_t TotalSize = finalize();
59*81ad6265SDimitry Andric   Out.reserveExtraSpace(TotalSize);
60*81ad6265SDimitry Andric 
61*81ad6265SDimitry Andric   // Write the header.
62*81ad6265SDimitry Andric   Out.write(Obj.Header.Magic.data(), Obj.Header.Magic.size());
63*81ad6265SDimitry Andric   uint32_t Version;
64*81ad6265SDimitry Andric   support::endian::write32le(&Version, Obj.Header.Version);
65*81ad6265SDimitry Andric   Out.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
66*81ad6265SDimitry Andric 
67*81ad6265SDimitry Andric   // Write each section.
68*81ad6265SDimitry Andric   for (size_t I = 0, S = SectionHeaders.size(); I < S; ++I) {
69*81ad6265SDimitry Andric     Out.write(SectionHeaders[I].data(), SectionHeaders[I].size());
70*81ad6265SDimitry Andric     Out.write(reinterpret_cast<const char *>(Obj.Sections[I].Contents.data()),
71*81ad6265SDimitry Andric               Obj.Sections[I].Contents.size());
72*81ad6265SDimitry Andric   }
73*81ad6265SDimitry Andric 
74*81ad6265SDimitry Andric   return Error::success();
75*81ad6265SDimitry Andric }
76*81ad6265SDimitry Andric 
77*81ad6265SDimitry Andric } // end namespace wasm
78*81ad6265SDimitry Andric } // end namespace objcopy
79*81ad6265SDimitry Andric } // end namespace llvm
80