1 //===- WasmWriter.cpp -----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "WasmWriter.h"
10 #include "llvm/BinaryFormat/Wasm.h"
11 #include "llvm/Support/Endian.h"
12 #include "llvm/Support/LEB128.h"
13 #include "llvm/Support/raw_ostream.h"
19 using namespace object
;
20 using namespace llvm::wasm
;
22 Writer::SectionHeader
Writer::createSectionHeader(const Section
&S
,
23 size_t &SectionSize
) {
25 raw_svector_ostream
OS(Header
);
27 bool HasName
= S
.SectionType
== WASM_SEC_CUSTOM
;
28 SectionSize
= S
.Contents
.size();
30 SectionSize
+= getULEB128Size(S
.Name
.size()) + S
.Name
.size();
31 // If we read this section from an object file, use its original size for the
32 // padding of the LEB value to avoid changing the file size. Otherwise, pad
33 // out to 5 bytes to make it predictable, and match the behavior of clang.
34 unsigned HeaderSecSizeEncodingLen
= S
.HeaderSecSizeEncodingLen
.value_or(5);
35 encodeULEB128(SectionSize
, OS
, HeaderSecSizeEncodingLen
);
37 encodeULEB128(S
.Name
.size(), OS
);
40 // Total section size is the content size plus 1 for the section type and
41 // the LEB-encoded size.
42 SectionSize
= SectionSize
+ 1 + HeaderSecSizeEncodingLen
;
46 size_t Writer::finalize() {
47 size_t ObjectSize
= sizeof(WasmMagic
) + sizeof(WasmVersion
);
48 SectionHeaders
.reserve(Obj
.Sections
.size());
49 // Finalize the headers of each section so we know the total size.
50 for (const Section
&S
: Obj
.Sections
) {
52 SectionHeaders
.push_back(createSectionHeader(S
, SectionSize
));
53 ObjectSize
+= SectionSize
;
58 Error
Writer::write() {
59 size_t TotalSize
= finalize();
60 Out
.reserveExtraSpace(TotalSize
);
63 Out
.write(Obj
.Header
.Magic
.data(), Obj
.Header
.Magic
.size());
65 support::endian::write32le(&Version
, Obj
.Header
.Version
);
66 Out
.write(reinterpret_cast<const char *>(&Version
), sizeof(Version
));
68 // Write each section.
69 for (size_t I
= 0, S
= SectionHeaders
.size(); I
< S
; ++I
) {
70 Out
.write(SectionHeaders
[I
].data(), SectionHeaders
[I
].size());
71 Out
.write(reinterpret_cast<const char *>(Obj
.Sections
[I
].Contents
.data()),
72 Obj
.Sections
[I
].Contents
.size());
75 return Error::success();
78 } // end namespace wasm
79 } // end namespace objcopy
80 } // end namespace llvm