xref: /openbsd-src/gnu/llvm/lld/wasm/SyntheticSections.h (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
1ece8a530Spatrick //===- SyntheticSection.h ---------------------------------------*- C++ -*-===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick //
9ece8a530Spatrick // Synthetic sections represent chunks of linker-created data. If you
10ece8a530Spatrick // need to create a chunk of data that to be included in some section
11ece8a530Spatrick // in the result, you probably want to create that as a synthetic section.
12ece8a530Spatrick //
13ece8a530Spatrick //===----------------------------------------------------------------------===//
14ece8a530Spatrick 
15ece8a530Spatrick #ifndef LLD_WASM_SYNTHETIC_SECTIONS_H
16ece8a530Spatrick #define LLD_WASM_SYNTHETIC_SECTIONS_H
17ece8a530Spatrick 
18ece8a530Spatrick #include "OutputSections.h"
19ece8a530Spatrick 
20ece8a530Spatrick #include "llvm/ADT/SmallSet.h"
21ece8a530Spatrick #include "llvm/ADT/StringMap.h"
221cf9926bSpatrick #include "llvm/BinaryFormat/WasmTraits.h"
23*dfe94b16Srobert #include <optional>
24ece8a530Spatrick 
25ece8a530Spatrick #define DEBUG_TYPE "lld"
26ece8a530Spatrick 
27ece8a530Spatrick namespace lld {
28ece8a530Spatrick namespace wasm {
29ece8a530Spatrick 
30ece8a530Spatrick // An init entry to be written to either the synthetic init func or the
31ece8a530Spatrick // linking metadata.
32ece8a530Spatrick struct WasmInitEntry {
33ece8a530Spatrick   const FunctionSymbol *sym;
34ece8a530Spatrick   uint32_t priority;
35ece8a530Spatrick };
36ece8a530Spatrick 
37ece8a530Spatrick class SyntheticSection : public OutputSection {
38ece8a530Spatrick public:
39ece8a530Spatrick   SyntheticSection(uint32_t type, std::string name = "")
OutputSection(type,name)40ece8a530Spatrick       : OutputSection(type, name), bodyOutputStream(body) {
41ece8a530Spatrick     if (!name.empty())
42ece8a530Spatrick       writeStr(bodyOutputStream, name, "section name");
43ece8a530Spatrick   }
44ece8a530Spatrick 
writeTo(uint8_t * buf)45ece8a530Spatrick   void writeTo(uint8_t *buf) override {
46ece8a530Spatrick     assert(offset);
47ece8a530Spatrick     log("writing " + toString(*this));
48ece8a530Spatrick     memcpy(buf + offset, header.data(), header.size());
49ece8a530Spatrick     memcpy(buf + offset + header.size(), body.data(), body.size());
50ece8a530Spatrick   }
51ece8a530Spatrick 
getSize()52ece8a530Spatrick   size_t getSize() const override { return header.size() + body.size(); }
53ece8a530Spatrick 
writeBody()54ece8a530Spatrick   virtual void writeBody() {}
55ece8a530Spatrick 
assignIndexes()56ece8a530Spatrick   virtual void assignIndexes() {}
57ece8a530Spatrick 
finalizeContents()58ece8a530Spatrick   void finalizeContents() override {
59ece8a530Spatrick     writeBody();
60ece8a530Spatrick     bodyOutputStream.flush();
61ece8a530Spatrick     createHeader(body.size());
62ece8a530Spatrick   }
63ece8a530Spatrick 
getStream()64ece8a530Spatrick   raw_ostream &getStream() { return bodyOutputStream; }
65ece8a530Spatrick 
66ece8a530Spatrick   std::string body;
67ece8a530Spatrick 
68ece8a530Spatrick protected:
69ece8a530Spatrick   llvm::raw_string_ostream bodyOutputStream;
70ece8a530Spatrick };
71ece8a530Spatrick 
72ece8a530Spatrick // Create the custom "dylink" section containing information for the dynamic
73ece8a530Spatrick // linker.
74ece8a530Spatrick // See
75*dfe94b16Srobert // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
76ece8a530Spatrick class DylinkSection : public SyntheticSection {
77ece8a530Spatrick public:
DylinkSection()78*dfe94b16Srobert   DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink.0") {}
79*dfe94b16Srobert   bool isNeeded() const override;
80ece8a530Spatrick   void writeBody() override;
81ece8a530Spatrick 
82ece8a530Spatrick   uint32_t memAlign = 0;
83ece8a530Spatrick   uint32_t memSize = 0;
84ece8a530Spatrick };
85ece8a530Spatrick 
86ece8a530Spatrick class TypeSection : public SyntheticSection {
87ece8a530Spatrick public:
TypeSection()88ece8a530Spatrick   TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {}
89ece8a530Spatrick 
isNeeded()90ece8a530Spatrick   bool isNeeded() const override { return types.size() > 0; };
91ece8a530Spatrick   void writeBody() override;
92ece8a530Spatrick   uint32_t registerType(const WasmSignature &sig);
93ece8a530Spatrick   uint32_t lookupType(const WasmSignature &sig);
94ece8a530Spatrick 
95ece8a530Spatrick protected:
96ece8a530Spatrick   std::vector<const WasmSignature *> types;
97ece8a530Spatrick   llvm::DenseMap<WasmSignature, int32_t> typeIndices;
98ece8a530Spatrick };
99ece8a530Spatrick 
1001cf9926bSpatrick /**
1011cf9926bSpatrick  * A key for some kind of imported entity of type `T`.
1021cf9926bSpatrick  *
1031cf9926bSpatrick  * Used when de-duplicating imports.
1041cf9926bSpatrick  */
1051cf9926bSpatrick template <typename T> struct ImportKey {
1061cf9926bSpatrick public:
1071cf9926bSpatrick   enum class State { Plain, Empty, Tombstone };
1081cf9926bSpatrick 
1091cf9926bSpatrick public:
1101cf9926bSpatrick   T type;
111*dfe94b16Srobert   std::optional<StringRef> importModule;
112*dfe94b16Srobert   std::optional<StringRef> importName;
1131cf9926bSpatrick   State state;
1141cf9926bSpatrick 
1151cf9926bSpatrick public:
ImportKeyImportKey1161cf9926bSpatrick   ImportKey(T type) : type(type), state(State::Plain) {}
ImportKeyImportKey1171cf9926bSpatrick   ImportKey(T type, State state) : type(type), state(state) {}
ImportKeyImportKey118*dfe94b16Srobert   ImportKey(T type, std::optional<StringRef> importModule,
119*dfe94b16Srobert             std::optional<StringRef> importName)
1201cf9926bSpatrick       : type(type), importModule(importModule), importName(importName),
1211cf9926bSpatrick         state(State::Plain) {}
1221cf9926bSpatrick };
1231cf9926bSpatrick 
1241cf9926bSpatrick template <typename T>
1251cf9926bSpatrick inline bool operator==(const ImportKey<T> &lhs, const ImportKey<T> &rhs) {
1261cf9926bSpatrick   return lhs.state == rhs.state && lhs.importModule == rhs.importModule &&
1271cf9926bSpatrick          lhs.importName == rhs.importName && lhs.type == rhs.type;
1281cf9926bSpatrick }
1291cf9926bSpatrick 
1301cf9926bSpatrick } // namespace wasm
1311cf9926bSpatrick } // namespace lld
1321cf9926bSpatrick 
1331cf9926bSpatrick // `ImportKey<T>` can be used as a key in a `DenseMap` if `T` can be used as a
1341cf9926bSpatrick // key in a `DenseMap`.
1351cf9926bSpatrick namespace llvm {
1361cf9926bSpatrick template <typename T> struct DenseMapInfo<lld::wasm::ImportKey<T>> {
1371cf9926bSpatrick   static lld::wasm::ImportKey<T> getEmptyKey() {
1381cf9926bSpatrick     typename lld::wasm::ImportKey<T> key(llvm::DenseMapInfo<T>::getEmptyKey());
1391cf9926bSpatrick     key.state = lld::wasm::ImportKey<T>::State::Empty;
1401cf9926bSpatrick     return key;
1411cf9926bSpatrick   }
1421cf9926bSpatrick   static lld::wasm::ImportKey<T> getTombstoneKey() {
1431cf9926bSpatrick     typename lld::wasm::ImportKey<T> key(llvm::DenseMapInfo<T>::getEmptyKey());
1441cf9926bSpatrick     key.state = lld::wasm::ImportKey<T>::State::Tombstone;
1451cf9926bSpatrick     return key;
1461cf9926bSpatrick   }
1471cf9926bSpatrick   static unsigned getHashValue(const lld::wasm::ImportKey<T> &key) {
1481cf9926bSpatrick     uintptr_t hash = hash_value(key.importModule);
1491cf9926bSpatrick     hash = hash_combine(hash, key.importName);
1501cf9926bSpatrick     hash = hash_combine(hash, llvm::DenseMapInfo<T>::getHashValue(key.type));
1511cf9926bSpatrick     hash = hash_combine(hash, key.state);
1521cf9926bSpatrick     return hash;
1531cf9926bSpatrick   }
1541cf9926bSpatrick   static bool isEqual(const lld::wasm::ImportKey<T> &lhs,
1551cf9926bSpatrick                       const lld::wasm::ImportKey<T> &rhs) {
1561cf9926bSpatrick     return lhs == rhs;
1571cf9926bSpatrick   }
1581cf9926bSpatrick };
1591cf9926bSpatrick } // end namespace llvm
1601cf9926bSpatrick 
1611cf9926bSpatrick namespace lld {
1621cf9926bSpatrick namespace wasm {
1631cf9926bSpatrick 
164ece8a530Spatrick class ImportSection : public SyntheticSection {
165ece8a530Spatrick public:
166ece8a530Spatrick   ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {}
167ece8a530Spatrick   bool isNeeded() const override { return getNumImports() > 0; }
168ece8a530Spatrick   void writeBody() override;
169ece8a530Spatrick   void addImport(Symbol *sym);
170ece8a530Spatrick   void addGOTEntry(Symbol *sym);
171ece8a530Spatrick   void seal() { isSealed = true; }
172ece8a530Spatrick   uint32_t getNumImports() const;
173ece8a530Spatrick   uint32_t getNumImportedGlobals() const {
174ece8a530Spatrick     assert(isSealed);
175ece8a530Spatrick     return numImportedGlobals;
176ece8a530Spatrick   }
177ece8a530Spatrick   uint32_t getNumImportedFunctions() const {
178ece8a530Spatrick     assert(isSealed);
179ece8a530Spatrick     return numImportedFunctions;
180ece8a530Spatrick   }
1811cf9926bSpatrick   uint32_t getNumImportedTags() const {
182ece8a530Spatrick     assert(isSealed);
1831cf9926bSpatrick     return numImportedTags;
1841cf9926bSpatrick   }
1851cf9926bSpatrick   uint32_t getNumImportedTables() const {
1861cf9926bSpatrick     assert(isSealed);
1871cf9926bSpatrick     return numImportedTables;
188ece8a530Spatrick   }
189ece8a530Spatrick 
190ece8a530Spatrick   std::vector<const Symbol *> importedSymbols;
1911cf9926bSpatrick   std::vector<const Symbol *> gotSymbols;
192ece8a530Spatrick 
193ece8a530Spatrick protected:
194ece8a530Spatrick   bool isSealed = false;
195ece8a530Spatrick   unsigned numImportedGlobals = 0;
196ece8a530Spatrick   unsigned numImportedFunctions = 0;
1971cf9926bSpatrick   unsigned numImportedTags = 0;
1981cf9926bSpatrick   unsigned numImportedTables = 0;
1991cf9926bSpatrick   llvm::DenseMap<ImportKey<WasmGlobalType>, uint32_t> importedGlobals;
2001cf9926bSpatrick   llvm::DenseMap<ImportKey<WasmSignature>, uint32_t> importedFunctions;
2011cf9926bSpatrick   llvm::DenseMap<ImportKey<WasmTableType>, uint32_t> importedTables;
202*dfe94b16Srobert   llvm::DenseMap<ImportKey<WasmSignature>, uint32_t> importedTags;
203ece8a530Spatrick };
204ece8a530Spatrick 
205ece8a530Spatrick class FunctionSection : public SyntheticSection {
206ece8a530Spatrick public:
207ece8a530Spatrick   FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {}
208ece8a530Spatrick 
209ece8a530Spatrick   bool isNeeded() const override { return inputFunctions.size() > 0; };
210ece8a530Spatrick   void writeBody() override;
211ece8a530Spatrick   void addFunction(InputFunction *func);
212ece8a530Spatrick 
213ece8a530Spatrick   std::vector<InputFunction *> inputFunctions;
214ece8a530Spatrick 
215ece8a530Spatrick protected:
216ece8a530Spatrick };
217ece8a530Spatrick 
218ece8a530Spatrick class TableSection : public SyntheticSection {
219ece8a530Spatrick public:
220ece8a530Spatrick   TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
221ece8a530Spatrick 
2221cf9926bSpatrick   bool isNeeded() const override { return inputTables.size() > 0; };
2231cf9926bSpatrick   void assignIndexes() override;
224ece8a530Spatrick   void writeBody() override;
2251cf9926bSpatrick   void addTable(InputTable *table);
2261cf9926bSpatrick 
2271cf9926bSpatrick   std::vector<InputTable *> inputTables;
228ece8a530Spatrick };
229ece8a530Spatrick 
230bb684c34Spatrick class MemorySection : public SyntheticSection {
231bb684c34Spatrick public:
232bb684c34Spatrick   MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {}
233bb684c34Spatrick 
234*dfe94b16Srobert   bool isNeeded() const override { return !config->memoryImport.has_value(); }
235bb684c34Spatrick   void writeBody() override;
236bb684c34Spatrick 
237bb684c34Spatrick   uint64_t numMemoryPages = 0;
238bb684c34Spatrick   uint64_t maxMemoryPages = 0;
239bb684c34Spatrick };
240bb684c34Spatrick 
2411cf9926bSpatrick // The tag section contains a list of declared wasm tags associated with the
2421cf9926bSpatrick // module. Currently the only supported tag kind is exceptions. All C++
2431cf9926bSpatrick // exceptions are represented by a single tag. A tag entry in this section
2441cf9926bSpatrick // contains information on what kind of tag it is (e.g. exception) and the type
2451cf9926bSpatrick // of values associated with the tag. (In Wasm, a tag can contain multiple
2461cf9926bSpatrick // values of primitive types. But for C++ exceptions, we just throw a pointer
2471cf9926bSpatrick // which is an i32 value (for wasm32 architecture), so the signature of C++
2481cf9926bSpatrick // exception is (i32)->(void), because all exception tag types are assumed to
2491cf9926bSpatrick // have void return type to share WasmSignature with functions.)
2501cf9926bSpatrick class TagSection : public SyntheticSection {
251bb684c34Spatrick public:
2521cf9926bSpatrick   TagSection() : SyntheticSection(llvm::wasm::WASM_SEC_TAG) {}
253bb684c34Spatrick   void writeBody() override;
2541cf9926bSpatrick   bool isNeeded() const override { return inputTags.size() > 0; }
2551cf9926bSpatrick   void addTag(InputTag *tag);
256bb684c34Spatrick 
2571cf9926bSpatrick   std::vector<InputTag *> inputTags;
258bb684c34Spatrick };
259bb684c34Spatrick 
260ece8a530Spatrick class GlobalSection : public SyntheticSection {
261ece8a530Spatrick public:
262ece8a530Spatrick   GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {}
2631cf9926bSpatrick 
2641cf9926bSpatrick   static bool classof(const OutputSection *sec) {
2651cf9926bSpatrick     return sec->type == llvm::wasm::WASM_SEC_GLOBAL;
2661cf9926bSpatrick   }
2671cf9926bSpatrick 
268ece8a530Spatrick   uint32_t numGlobals() const {
269ece8a530Spatrick     assert(isSealed);
270ece8a530Spatrick     return inputGlobals.size() + dataAddressGlobals.size() +
2711cf9926bSpatrick            internalGotSymbols.size();
272ece8a530Spatrick   }
273ece8a530Spatrick   bool isNeeded() const override { return numGlobals() > 0; }
274ece8a530Spatrick   void assignIndexes() override;
275ece8a530Spatrick   void writeBody() override;
276ece8a530Spatrick   void addGlobal(InputGlobal *global);
2771cf9926bSpatrick 
2781cf9926bSpatrick   // Add an internal GOT entry global that corresponds to the given symbol.
2791cf9926bSpatrick   // Normally GOT entries are imported and assigned by the external dynamic
2801cf9926bSpatrick   // linker.  However, when linking PIC code statically or when linking with
2811cf9926bSpatrick   // -Bsymbolic we can internalize GOT entries by declaring globals the hold
2821cf9926bSpatrick   // symbol addresses.
2831cf9926bSpatrick   //
2841cf9926bSpatrick   // For the static linking case these internal globals can be completely
2851cf9926bSpatrick   // eliminated by a post-link optimizer such as wasm-opt.
2861cf9926bSpatrick   //
2871cf9926bSpatrick   // TODO(sbc): Another approach to optimizing these away could be to use
2881cf9926bSpatrick   // specific relocation types combined with linker relaxation which could
2891cf9926bSpatrick   // transform a `global.get` to an `i32.const`.
2901cf9926bSpatrick   void addInternalGOTEntry(Symbol *sym);
291*dfe94b16Srobert   bool needsRelocations() {
292*dfe94b16Srobert     if (config->extendedConst)
293*dfe94b16Srobert       return false;
294*dfe94b16Srobert     return llvm::any_of(internalGotSymbols,
295*dfe94b16Srobert                         [=](Symbol *sym) { return !sym->isTLS(); });
296*dfe94b16Srobert   }
297*dfe94b16Srobert   bool needsTLSRelocations() {
298*dfe94b16Srobert     return llvm::any_of(internalGotSymbols,
299*dfe94b16Srobert                         [=](Symbol *sym) { return sym->isTLS(); });
300*dfe94b16Srobert   }
301*dfe94b16Srobert   void generateRelocationCode(raw_ostream &os, bool TLS) const;
302ece8a530Spatrick 
303*dfe94b16Srobert   std::vector<DefinedData *> dataAddressGlobals;
3041cf9926bSpatrick   std::vector<InputGlobal *> inputGlobals;
3051cf9926bSpatrick   std::vector<Symbol *> internalGotSymbols;
306ece8a530Spatrick 
307ece8a530Spatrick protected:
308ece8a530Spatrick   bool isSealed = false;
309ece8a530Spatrick };
310ece8a530Spatrick 
311ece8a530Spatrick class ExportSection : public SyntheticSection {
312ece8a530Spatrick public:
313ece8a530Spatrick   ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {}
314ece8a530Spatrick   bool isNeeded() const override { return exports.size() > 0; }
315ece8a530Spatrick   void writeBody() override;
316ece8a530Spatrick 
317ece8a530Spatrick   std::vector<llvm::wasm::WasmExport> exports;
3181cf9926bSpatrick   std::vector<const Symbol *> exportedSymbols;
319ece8a530Spatrick };
320ece8a530Spatrick 
321ece8a530Spatrick class StartSection : public SyntheticSection {
322ece8a530Spatrick public:
3231cf9926bSpatrick   StartSection() : SyntheticSection(llvm::wasm::WASM_SEC_START) {}
324ece8a530Spatrick   bool isNeeded() const override;
325ece8a530Spatrick   void writeBody() override;
326ece8a530Spatrick };
327ece8a530Spatrick 
328ece8a530Spatrick class ElemSection : public SyntheticSection {
329ece8a530Spatrick public:
330ece8a530Spatrick   ElemSection()
331ece8a530Spatrick       : SyntheticSection(llvm::wasm::WASM_SEC_ELEM) {}
332ece8a530Spatrick   bool isNeeded() const override { return indirectFunctions.size() > 0; };
333ece8a530Spatrick   void writeBody() override;
334ece8a530Spatrick   void addEntry(FunctionSymbol *sym);
335ece8a530Spatrick   uint32_t numEntries() const { return indirectFunctions.size(); }
336ece8a530Spatrick 
337ece8a530Spatrick protected:
338ece8a530Spatrick   std::vector<const FunctionSymbol *> indirectFunctions;
339ece8a530Spatrick };
340ece8a530Spatrick 
341ece8a530Spatrick class DataCountSection : public SyntheticSection {
342ece8a530Spatrick public:
343ece8a530Spatrick   DataCountSection(ArrayRef<OutputSegment *> segments);
344ece8a530Spatrick   bool isNeeded() const override;
345ece8a530Spatrick   void writeBody() override;
346ece8a530Spatrick 
347ece8a530Spatrick protected:
348ece8a530Spatrick   uint32_t numSegments;
349ece8a530Spatrick };
350ece8a530Spatrick 
351ece8a530Spatrick // Create the custom "linking" section containing linker metadata.
352ece8a530Spatrick // This is only created when relocatable output is requested.
353ece8a530Spatrick class LinkingSection : public SyntheticSection {
354ece8a530Spatrick public:
355ece8a530Spatrick   LinkingSection(const std::vector<WasmInitEntry> &initFunctions,
356ece8a530Spatrick                  const std::vector<OutputSegment *> &dataSegments)
357ece8a530Spatrick       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"),
358ece8a530Spatrick         initFunctions(initFunctions), dataSegments(dataSegments) {}
359ece8a530Spatrick   bool isNeeded() const override {
360ece8a530Spatrick     return config->relocatable || config->emitRelocs;
361ece8a530Spatrick   }
362ece8a530Spatrick   void writeBody() override;
363ece8a530Spatrick   void addToSymtab(Symbol *sym);
364ece8a530Spatrick 
365ece8a530Spatrick protected:
366ece8a530Spatrick   std::vector<const Symbol *> symtabEntries;
367ece8a530Spatrick   llvm::StringMap<uint32_t> sectionSymbolIndices;
368ece8a530Spatrick   const std::vector<WasmInitEntry> &initFunctions;
369ece8a530Spatrick   const std::vector<OutputSegment *> &dataSegments;
370ece8a530Spatrick };
371ece8a530Spatrick 
372ece8a530Spatrick // Create the custom "name" section containing debug symbol names.
373ece8a530Spatrick class NameSection : public SyntheticSection {
374ece8a530Spatrick public:
3751cf9926bSpatrick   NameSection(ArrayRef<OutputSegment *> segments)
3761cf9926bSpatrick       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name"),
3771cf9926bSpatrick         segments(segments) {}
3781cf9926bSpatrick   bool isNeeded() const override { return !config->stripAll && numNames() > 0; }
379ece8a530Spatrick   void writeBody() override;
3801cf9926bSpatrick   unsigned numNames() const { return numNamedGlobals() + numNamedFunctions(); }
3811cf9926bSpatrick   unsigned numNamedGlobals() const;
3821cf9926bSpatrick   unsigned numNamedFunctions() const;
3831cf9926bSpatrick   unsigned numNamedDataSegments() const;
3841cf9926bSpatrick 
3851cf9926bSpatrick protected:
3861cf9926bSpatrick   ArrayRef<OutputSegment *> segments;
387ece8a530Spatrick };
388ece8a530Spatrick 
389ece8a530Spatrick class ProducersSection : public SyntheticSection {
390ece8a530Spatrick public:
391ece8a530Spatrick   ProducersSection()
392ece8a530Spatrick       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {}
393ece8a530Spatrick   bool isNeeded() const override {
394ece8a530Spatrick     return !config->stripAll && fieldCount() > 0;
395ece8a530Spatrick   }
396ece8a530Spatrick   void writeBody() override;
397ece8a530Spatrick   void addInfo(const llvm::wasm::WasmProducerInfo &info);
398ece8a530Spatrick 
399ece8a530Spatrick protected:
400ece8a530Spatrick   int fieldCount() const {
401ece8a530Spatrick     return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty());
402ece8a530Spatrick   }
403ece8a530Spatrick   SmallVector<std::pair<std::string, std::string>, 8> languages;
404ece8a530Spatrick   SmallVector<std::pair<std::string, std::string>, 8> tools;
405ece8a530Spatrick   SmallVector<std::pair<std::string, std::string>, 8> sDKs;
406ece8a530Spatrick };
407ece8a530Spatrick 
408ece8a530Spatrick class TargetFeaturesSection : public SyntheticSection {
409ece8a530Spatrick public:
410ece8a530Spatrick   TargetFeaturesSection()
411ece8a530Spatrick       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {}
412ece8a530Spatrick   bool isNeeded() const override {
413ece8a530Spatrick     return !config->stripAll && features.size() > 0;
414ece8a530Spatrick   }
415ece8a530Spatrick   void writeBody() override;
416ece8a530Spatrick 
417ece8a530Spatrick   llvm::SmallSet<std::string, 8> features;
418ece8a530Spatrick };
419ece8a530Spatrick 
420ece8a530Spatrick class RelocSection : public SyntheticSection {
421ece8a530Spatrick public:
422ece8a530Spatrick   RelocSection(StringRef name, OutputSection *sec)
423bb684c34Spatrick       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, std::string(name)),
424bb684c34Spatrick         sec(sec) {}
425ece8a530Spatrick   void writeBody() override;
426ece8a530Spatrick   bool isNeeded() const override { return sec->getNumRelocations() > 0; };
427ece8a530Spatrick 
428ece8a530Spatrick protected:
429ece8a530Spatrick   OutputSection *sec;
430ece8a530Spatrick };
431ece8a530Spatrick 
432ece8a530Spatrick // Linker generated output sections
433ece8a530Spatrick struct OutStruct {
434ece8a530Spatrick   DylinkSection *dylinkSec;
435ece8a530Spatrick   TypeSection *typeSec;
436ece8a530Spatrick   FunctionSection *functionSec;
437ece8a530Spatrick   ImportSection *importSec;
438ece8a530Spatrick   TableSection *tableSec;
439ece8a530Spatrick   MemorySection *memorySec;
440ece8a530Spatrick   GlobalSection *globalSec;
4411cf9926bSpatrick   TagSection *tagSec;
442ece8a530Spatrick   ExportSection *exportSec;
443ece8a530Spatrick   StartSection *startSec;
444ece8a530Spatrick   ElemSection *elemSec;
445ece8a530Spatrick   DataCountSection *dataCountSec;
446ece8a530Spatrick   LinkingSection *linkingSec;
447ece8a530Spatrick   NameSection *nameSec;
448ece8a530Spatrick   ProducersSection *producersSec;
449ece8a530Spatrick   TargetFeaturesSection *targetFeaturesSec;
450ece8a530Spatrick };
451ece8a530Spatrick 
452ece8a530Spatrick extern OutStruct out;
453ece8a530Spatrick 
454ece8a530Spatrick } // namespace wasm
455ece8a530Spatrick } // namespace lld
456ece8a530Spatrick 
457ece8a530Spatrick #endif
458