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