Mercurial > hg > CbC > CbC_llvm
view lld/wasm/SyntheticSections.h @ 223:5f17cb93ff66 llvm-original
LLVM13 (2021/7/18)
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 18 Jul 2021 22:43:00 +0900 |
parents | 79ff65ed7e25 |
children | c4bab56944e8 |
line wrap: on
line source
//===- SyntheticSection.h ---------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Synthetic sections represent chunks of linker-created data. If you // need to create a chunk of data that to be included in some section // in the result, you probably want to create that as a synthetic section. // //===----------------------------------------------------------------------===// #ifndef LLD_WASM_SYNTHETIC_SECTIONS_H #define LLD_WASM_SYNTHETIC_SECTIONS_H #include "OutputSections.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/BinaryFormat/WasmTraits.h" #define DEBUG_TYPE "lld" namespace lld { namespace wasm { // An init entry to be written to either the synthetic init func or the // linking metadata. struct WasmInitEntry { const FunctionSymbol *sym; uint32_t priority; }; class SyntheticSection : public OutputSection { public: SyntheticSection(uint32_t type, std::string name = "") : OutputSection(type, name), bodyOutputStream(body) { if (!name.empty()) writeStr(bodyOutputStream, name, "section name"); } void writeTo(uint8_t *buf) override { assert(offset); log("writing " + toString(*this)); memcpy(buf + offset, header.data(), header.size()); memcpy(buf + offset + header.size(), body.data(), body.size()); } size_t getSize() const override { return header.size() + body.size(); } virtual void writeBody() {} virtual void assignIndexes() {} void finalizeContents() override { writeBody(); bodyOutputStream.flush(); createHeader(body.size()); } raw_ostream &getStream() { return bodyOutputStream; } std::string body; protected: llvm::raw_string_ostream bodyOutputStream; }; // Create the custom "dylink" section containing information for the dynamic // linker. // See // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md class DylinkSection : public SyntheticSection { public: DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {} bool isNeeded() const override { return config->isPic; } void writeBody() override; uint32_t memAlign = 0; uint32_t memSize = 0; }; class TypeSection : public SyntheticSection { public: TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {} bool isNeeded() const override { return types.size() > 0; }; void writeBody() override; uint32_t registerType(const WasmSignature &sig); uint32_t lookupType(const WasmSignature &sig); protected: std::vector<const WasmSignature *> types; llvm::DenseMap<WasmSignature, int32_t> typeIndices; }; class ImportSection : public SyntheticSection { public: ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {} bool isNeeded() const override { return getNumImports() > 0; } void writeBody() override; void addImport(Symbol *sym); void addGOTEntry(Symbol *sym); void seal() { isSealed = true; } uint32_t getNumImports() const; uint32_t getNumImportedGlobals() const { assert(isSealed); return numImportedGlobals; } uint32_t getNumImportedFunctions() const { assert(isSealed); return numImportedFunctions; } uint32_t getNumImportedTags() const { assert(isSealed); return numImportedTags; } uint32_t getNumImportedTables() const { assert(isSealed); return numImportedTables; } std::vector<const Symbol *> importedSymbols; std::vector<const Symbol *> gotSymbols; protected: bool isSealed = false; unsigned numImportedGlobals = 0; unsigned numImportedFunctions = 0; unsigned numImportedTags = 0; unsigned numImportedTables = 0; }; class FunctionSection : public SyntheticSection { public: FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {} bool isNeeded() const override { return inputFunctions.size() > 0; }; void writeBody() override; void addFunction(InputFunction *func); std::vector<InputFunction *> inputFunctions; protected: }; class TableSection : public SyntheticSection { public: TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {} bool isNeeded() const override { return inputTables.size() > 0; }; void assignIndexes() override; void writeBody() override; void addTable(InputTable *table); std::vector<InputTable *> inputTables; }; class MemorySection : public SyntheticSection { public: MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {} bool isNeeded() const override { return !config->importMemory; } void writeBody() override; uint64_t numMemoryPages = 0; uint64_t maxMemoryPages = 0; }; // The tag section contains a list of declared wasm tags associated with the // module. Currently the only supported tag kind is exceptions. All C++ // exceptions are represented by a single tag. A tag entry in this section // contains information on what kind of tag it is (e.g. exception) and the type // of values associated with the tag. (In Wasm, a tag can contain multiple // values of primitive types. But for C++ exceptions, we just throw a pointer // which is an i32 value (for wasm32 architecture), so the signature of C++ // exception is (i32)->(void), because all exception tag types are assumed to // have void return type to share WasmSignature with functions.) class TagSection : public SyntheticSection { public: TagSection() : SyntheticSection(llvm::wasm::WASM_SEC_TAG) {} void writeBody() override; bool isNeeded() const override { return inputTags.size() > 0; } void addTag(InputTag *tag); std::vector<InputTag *> inputTags; }; class GlobalSection : public SyntheticSection { public: GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {} static bool classof(const OutputSection *sec) { return sec->type == llvm::wasm::WASM_SEC_GLOBAL; } uint32_t numGlobals() const { assert(isSealed); return inputGlobals.size() + dataAddressGlobals.size() + internalGotSymbols.size(); } bool isNeeded() const override { return numGlobals() > 0; } void assignIndexes() override; void writeBody() override; void addGlobal(InputGlobal *global); // Add an internal GOT entry global that corresponds to the given symbol. // Normally GOT entries are imported and assigned by the external dynamic // linker. However, when linking PIC code statically or when linking with // -Bsymbolic we can internalize GOT entries by declaring globals the hold // symbol addresses. // // For the static linking case these internal globals can be completely // eliminated by a post-link optimizer such as wasm-opt. // // TODO(sbc): Another approach to optimizing these away could be to use // specific relocation types combined with linker relaxation which could // transform a `global.get` to an `i32.const`. void addInternalGOTEntry(Symbol *sym); bool needsRelocations() { return internalGotSymbols.size(); } void generateRelocationCode(raw_ostream &os) const; std::vector<const DefinedData *> dataAddressGlobals; std::vector<InputGlobal *> inputGlobals; std::vector<Symbol *> internalGotSymbols; protected: bool isSealed = false; }; class ExportSection : public SyntheticSection { public: ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {} bool isNeeded() const override { return exports.size() > 0; } void writeBody() override; std::vector<llvm::wasm::WasmExport> exports; std::vector<const Symbol *> exportedSymbols; }; class StartSection : public SyntheticSection { public: StartSection() : SyntheticSection(llvm::wasm::WASM_SEC_START) {} bool isNeeded() const override; void writeBody() override; }; class ElemSection : public SyntheticSection { public: ElemSection() : SyntheticSection(llvm::wasm::WASM_SEC_ELEM) {} bool isNeeded() const override { return indirectFunctions.size() > 0; }; void writeBody() override; void addEntry(FunctionSymbol *sym); uint32_t numEntries() const { return indirectFunctions.size(); } protected: std::vector<const FunctionSymbol *> indirectFunctions; }; class DataCountSection : public SyntheticSection { public: DataCountSection(ArrayRef<OutputSegment *> segments); bool isNeeded() const override; void writeBody() override; protected: uint32_t numSegments; }; // Create the custom "linking" section containing linker metadata. // This is only created when relocatable output is requested. class LinkingSection : public SyntheticSection { public: LinkingSection(const std::vector<WasmInitEntry> &initFunctions, const std::vector<OutputSegment *> &dataSegments) : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"), initFunctions(initFunctions), dataSegments(dataSegments) {} bool isNeeded() const override { return config->relocatable || config->emitRelocs; } void writeBody() override; void addToSymtab(Symbol *sym); protected: std::vector<const Symbol *> symtabEntries; llvm::StringMap<uint32_t> sectionSymbolIndices; const std::vector<WasmInitEntry> &initFunctions; const std::vector<OutputSegment *> &dataSegments; }; // Create the custom "name" section containing debug symbol names. class NameSection : public SyntheticSection { public: NameSection(ArrayRef<OutputSegment *> segments) : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name"), segments(segments) {} bool isNeeded() const override { return !config->stripDebug && !config->stripAll && numNames() > 0; } void writeBody() override; unsigned numNames() const { return numNamedGlobals() + numNamedFunctions(); } unsigned numNamedGlobals() const; unsigned numNamedFunctions() const; unsigned numNamedDataSegments() const; protected: ArrayRef<OutputSegment *> segments; }; class ProducersSection : public SyntheticSection { public: ProducersSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {} bool isNeeded() const override { return !config->stripAll && fieldCount() > 0; } void writeBody() override; void addInfo(const llvm::wasm::WasmProducerInfo &info); protected: int fieldCount() const { return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty()); } SmallVector<std::pair<std::string, std::string>, 8> languages; SmallVector<std::pair<std::string, std::string>, 8> tools; SmallVector<std::pair<std::string, std::string>, 8> sDKs; }; class TargetFeaturesSection : public SyntheticSection { public: TargetFeaturesSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {} bool isNeeded() const override { return !config->stripAll && features.size() > 0; } void writeBody() override; llvm::SmallSet<std::string, 8> features; }; class RelocSection : public SyntheticSection { public: RelocSection(StringRef name, OutputSection *sec) : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, std::string(name)), sec(sec) {} void writeBody() override; bool isNeeded() const override { return sec->getNumRelocations() > 0; }; protected: OutputSection *sec; }; // Linker generated output sections struct OutStruct { DylinkSection *dylinkSec; TypeSection *typeSec; FunctionSection *functionSec; ImportSection *importSec; TableSection *tableSec; MemorySection *memorySec; GlobalSection *globalSec; TagSection *tagSec; ExportSection *exportSec; StartSection *startSec; ElemSection *elemSec; DataCountSection *dataCountSec; LinkingSection *linkingSec; NameSection *nameSec; ProducersSection *producersSec; TargetFeaturesSection *targetFeaturesSec; }; extern OutStruct out; } // namespace wasm } // namespace lld #endif