Index: lld/trunk/COFF/Chunks.h =================================================================== --- lld/trunk/COFF/Chunks.h +++ lld/trunk/COFF/Chunks.h @@ -40,10 +40,10 @@ class Symbol; // Mask for permissions (discardable, writable, readable, executable, etc). -const uint32_t PermMask = 0xFE000000; +const uint32_t permMask = 0xFE000000; // Mask for section types (code, data, bss). -const uint32_t TypeMask = 0x000000E0; +const uint32_t typeMask = 0x000000E0; // The log base 2 of the largest section alignment, which is log2(8192), or 13. enum : unsigned { Log2MaxSectionAlignment = 13 }; @@ -55,23 +55,23 @@ class Chunk { public: enum Kind : uint8_t { SectionKind, OtherKind, ImportThunkKind }; - Kind kind() const { return ChunkKind; } + Kind kind() const { return chunkKind; } // Returns the size of this chunk (even if this is a common or BSS.) size_t getSize() const; // Returns chunk alignment in power of two form. Value values are powers of // two from 1 to 8192. - uint32_t getAlignment() const { return 1U << P2Align; } + uint32_t getAlignment() const { return 1U << p2Align; } // Update the chunk section alignment measured in bytes. Internally alignment // is stored in log2. - void setAlignment(uint32_t Align) { + void setAlignment(uint32_t align) { // Treat zero byte alignment as 1 byte alignment. - Align = Align ? Align : 1; - assert(llvm::isPowerOf2_32(Align) && "alignment is not a power of 2"); - P2Align = llvm::Log2_32(Align); - assert(P2Align <= Log2MaxSectionAlignment && + align = align ? align : 1; + assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2"); + p2Align = llvm::Log2_32(align); + assert(p2Align <= Log2MaxSectionAlignment && "impossible requested alignment"); } @@ -79,15 +79,15 @@ // beginning of the file. Because this function may use RVA values // of other chunks for relocations, you need to set them properly // before calling this function. - void writeTo(uint8_t *Buf) const; + void writeTo(uint8_t *buf) const; // The writer sets and uses the addresses. In practice, PE images cannot be // larger than 2GB. Chunks are always laid as part of the image, so Chunk RVAs // can be stored with 32 bits. - uint32_t getRVA() const { return RVA; } - void setRVA(uint64_t V) { - RVA = (uint32_t)V; - assert(RVA == V && "RVA truncated"); + uint32_t getRVA() const { return rva; } + void setRVA(uint64_t v) { + rva = (uint32_t)v; + assert(rva == v && "RVA truncated"); } // Returns readable/writable/executable bits. @@ -99,13 +99,13 @@ // An output section has pointers to chunks in the section, and each // chunk has a back pointer to an output section. - void setOutputSectionIdx(uint16_t O) { OSIdx = O; } - uint16_t getOutputSectionIdx() const { return OSIdx; } + void setOutputSectionIdx(uint16_t o) { osidx = o; } + uint16_t getOutputSectionIdx() const { return osidx; } OutputSection *getOutputSection() const; // Windows-specific. // Collect all locations that contain absolute addresses for base relocations. - void getBaserels(std::vector *Res); + void getBaserels(std::vector *res); // Returns a human-readable name of this chunk. Chunks are unnamed chunks of // bytes, so this is used only for logging or debugging. @@ -117,28 +117,28 @@ bool isHotPatchable() const; protected: - Chunk(Kind K = OtherKind) : ChunkKind(K), HasData(true), P2Align(0) {} + Chunk(Kind k = OtherKind) : chunkKind(k), hasData(true), p2Align(0) {} - const Kind ChunkKind; + const Kind chunkKind; public: // Returns true if this has non-zero data. BSS chunks return // false. If false is returned, the space occupied by this chunk // will be filled with zeros. Corresponds to the // IMAGE_SCN_CNT_UNINITIALIZED_DATA section characteristic bit. - uint8_t HasData : 1; + uint8_t hasData : 1; public: // The alignment of this chunk, stored in log2 form. The writer uses the // value. - uint8_t P2Align : 7; + uint8_t p2Align : 7; // The output section index for this chunk. The first valid section number is // one. - uint16_t OSIdx = 0; + uint16_t osidx = 0; // The RVA of this chunk in the output. The writer sets a value. - uint32_t RVA = 0; + uint32_t rva = 0; }; class NonSectionChunk : public Chunk { @@ -154,7 +154,7 @@ // beginning of the file. Because this function may use RVA values // of other chunks for relocations, you need to set them properly // before calling this function. - virtual void writeTo(uint8_t *Buf) const {} + virtual void writeTo(uint8_t *buf) const {} // Returns the section name if this is a section chunk. // It is illegal to call this function on non-section chunks. @@ -164,16 +164,16 @@ // Windows-specific. // Collect all locations that contain absolute addresses for base relocations. - virtual void getBaserels(std::vector *Res) {} + virtual void getBaserels(std::vector *res) {} // Returns a human-readable name of this chunk. Chunks are unnamed chunks of // bytes, so this is used only for logging or debugging. virtual StringRef getDebugName() const { return ""; } - static bool classof(const Chunk *C) { return C->kind() != SectionKind; } + static bool classof(const Chunk *c) { return c->kind() != SectionKind; } protected: - NonSectionChunk(Kind K = OtherKind) : Chunk(K) {} + NonSectionChunk(Kind k = OtherKind) : Chunk(k) {} }; // A chunk corresponding a section of an input file. @@ -187,41 +187,41 @@ std::random_access_iterator_tag, Symbol *> { friend SectionChunk; - ObjFile *File; + ObjFile *file; - symbol_iterator(ObjFile *File, const coff_relocation *I) - : symbol_iterator::iterator_adaptor_base(I), File(File) {} + symbol_iterator(ObjFile *file, const coff_relocation *i) + : symbol_iterator::iterator_adaptor_base(i), file(file) {} public: symbol_iterator() = default; - Symbol *operator*() const { return File->getSymbol(I->SymbolTableIndex); } + Symbol *operator*() const { return file->getSymbol(I->SymbolTableIndex); } }; - SectionChunk(ObjFile *File, const coff_section *Header); - static bool classof(const Chunk *C) { return C->kind() == SectionKind; } - size_t getSize() const { return Header->SizeOfRawData; } + SectionChunk(ObjFile *file, const coff_section *header); + static bool classof(const Chunk *c) { return c->kind() == SectionKind; } + size_t getSize() const { return header->SizeOfRawData; } ArrayRef getContents() const; - void writeTo(uint8_t *Buf) const; + void writeTo(uint8_t *buf) const; uint32_t getOutputCharacteristics() const { - return Header->Characteristics & (PermMask | TypeMask); + return header->Characteristics & (permMask | typeMask); } StringRef getSectionName() const { - return StringRef(SectionNameData, SectionNameSize); + return StringRef(sectionNameData, sectionNameSize); } - void getBaserels(std::vector *Res); + void getBaserels(std::vector *res); bool isCOMDAT() const; - void applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, - uint64_t P) const; - void applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, - uint64_t P) const; - void applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, - uint64_t P) const; - void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, - uint64_t P) const; + void applyRelX64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, + uint64_t p) const; + void applyRelX86(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, + uint64_t p) const; + void applyRelARM(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, + uint64_t p) const; + void applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s, + uint64_t p) const; - void getRuntimePseudoRelocs(std::vector &Res); + void getRuntimePseudoRelocs(std::vector &res); // Called if the garbage collector decides to not include this chunk // in a final output. It's supposed to print out a log message to stdout. @@ -229,7 +229,7 @@ // Adds COMDAT associative sections to this COMDAT section. A chunk // and its children are treated as a group by the garbage collector. - void addAssociative(SectionChunk *Child); + void addAssociative(SectionChunk *child); StringRef getDebugName() const; @@ -246,19 +246,19 @@ // Allow iteration over the bodies of this chunk's relocated symbols. llvm::iterator_range symbols() const { - return llvm::make_range(symbol_iterator(File, RelocsData), - symbol_iterator(File, RelocsData + RelocsSize)); + return llvm::make_range(symbol_iterator(file, relocsData), + symbol_iterator(file, relocsData + relocsSize)); } ArrayRef getRelocs() const { - return llvm::makeArrayRef(RelocsData, RelocsSize); + return llvm::makeArrayRef(relocsData, relocsSize); } // Reloc setter used by ARM range extension thunk insertion. - void setRelocs(ArrayRef NewRelocs) { - RelocsData = NewRelocs.data(); - RelocsSize = NewRelocs.size(); - assert(RelocsSize == NewRelocs.size() && "reloc size truncation"); + void setRelocs(ArrayRef newRelocs) { + relocsData = newRelocs.data(); + relocsSize = newRelocs.size(); + assert(relocsSize == newRelocs.size() && "reloc size truncation"); } // Single linked list iterator for associated comdat children. @@ -267,26 +267,26 @@ AssociatedIterator, std::forward_iterator_tag, SectionChunk> { public: AssociatedIterator() = default; - AssociatedIterator(SectionChunk *Head) : Cur(Head) {} - AssociatedIterator &operator=(const AssociatedIterator &R) { - Cur = R.Cur; + AssociatedIterator(SectionChunk *head) : cur(head) {} + AssociatedIterator &operator=(const AssociatedIterator &r) { + cur = r.cur; return *this; } - bool operator==(const AssociatedIterator &R) const { return Cur == R.Cur; } - const SectionChunk &operator*() const { return *Cur; } - SectionChunk &operator*() { return *Cur; } + bool operator==(const AssociatedIterator &r) const { return cur == r.cur; } + const SectionChunk &operator*() const { return *cur; } + SectionChunk &operator*() { return *cur; } AssociatedIterator &operator++() { - Cur = Cur->AssocChildren; + cur = cur->assocChildren; return *this; } private: - SectionChunk *Cur = nullptr; + SectionChunk *cur = nullptr; }; // Allow iteration over the associated child chunks for this section. llvm::iterator_range children() const { - return llvm::make_range(AssociatedIterator(AssocChildren), + return llvm::make_range(AssociatedIterator(assocChildren), AssociatedIterator(nullptr)); } @@ -295,56 +295,56 @@ ArrayRef consumeDebugMagic(); - static ArrayRef consumeDebugMagic(ArrayRef Data, - StringRef SectionName); + static ArrayRef consumeDebugMagic(ArrayRef data, + StringRef sectionName); - static SectionChunk *findByName(ArrayRef Sections, - StringRef Name); + static SectionChunk *findByName(ArrayRef sections, + StringRef name); // The file that this chunk was created from. - ObjFile *File; + ObjFile *file; // Pointer to the COFF section header in the input file. - const coff_section *Header; + const coff_section *header; // The COMDAT leader symbol if this is a COMDAT chunk. - DefinedRegular *Sym = nullptr; + DefinedRegular *sym = nullptr; // The CRC of the contents as described in the COFF spec 4.5.5. // Auxiliary Format 5: Section Definitions. Used for ICF. - uint32_t Checksum = 0; + uint32_t checksum = 0; // Used by the garbage collector. - bool Live; + bool live; // Whether this section needs to be kept distinct from other sections during // ICF. This is set by the driver using address-significance tables. - bool KeepUnique = false; + bool keepUnique = false; // The COMDAT selection if this is a COMDAT chunk. - llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0; + llvm::COFF::COMDATType selection = (llvm::COFF::COMDATType)0; // A pointer pointing to a replacement for this chunk. // Initially it points to "this" object. If this chunk is merged // with other chunk by ICF, it points to another chunk, // and this chunk is considered as dead. - SectionChunk *Repl; + SectionChunk *repl; private: - SectionChunk *AssocChildren = nullptr; + SectionChunk *assocChildren = nullptr; // Used for ICF (Identical COMDAT Folding) - void replace(SectionChunk *Other); - uint32_t Class[2] = {0, 0}; + void replace(SectionChunk *other); + uint32_t eqClass[2] = {0, 0}; // Relocations for this section. Size is stored below. - const coff_relocation *RelocsData; + const coff_relocation *relocsData; // Section name string. Size is stored below. - const char *SectionNameData; + const char *sectionNameData; - uint32_t RelocsSize = 0; - uint32_t SectionNameSize = 0; + uint32_t relocsSize = 0; + uint32_t sectionNameSize = 0; }; // Inline methods to implement faux-virtual dispatch for SectionChunk. @@ -364,11 +364,11 @@ ->getOutputCharacteristics(); } -inline void Chunk::writeTo(uint8_t *Buf) const { +inline void Chunk::writeTo(uint8_t *buf) const { if (isa(this)) - static_cast(this)->writeTo(Buf); + static_cast(this)->writeTo(buf); else - static_cast(this)->writeTo(Buf); + static_cast(this)->writeTo(buf); } inline StringRef Chunk::getSectionName() const { @@ -378,11 +378,11 @@ return static_cast(this)->getSectionName(); } -inline void Chunk::getBaserels(std::vector *Res) { +inline void Chunk::getBaserels(std::vector *res) { if (isa(this)) - static_cast(this)->getBaserels(Res); + static_cast(this)->getBaserels(res); else - static_cast(this)->getBaserels(Res); + static_cast(this)->getBaserels(res); } inline StringRef Chunk::getDebugName() const { @@ -403,58 +403,58 @@ // on the offsets assigned by the StringTableBuilder. class MergeChunk : public NonSectionChunk { public: - MergeChunk(uint32_t Alignment); - static void addSection(SectionChunk *C); + MergeChunk(uint32_t alignment); + static void addSection(SectionChunk *c); void finalizeContents(); void assignSubsectionRVAs(); uint32_t getOutputCharacteristics() const override; StringRef getSectionName() const override { return ".rdata"; } size_t getSize() const override; - void writeTo(uint8_t *Buf) const override; + void writeTo(uint8_t *buf) const override; - static MergeChunk *Instances[Log2MaxSectionAlignment + 1]; - std::vector Sections; + static MergeChunk *instances[Log2MaxSectionAlignment + 1]; + std::vector sections; private: - llvm::StringTableBuilder Builder; - bool Finalized = false; + llvm::StringTableBuilder builder; + bool finalized = false; }; // A chunk for common symbols. Common chunks don't have actual data. class CommonChunk : public NonSectionChunk { public: - CommonChunk(const COFFSymbolRef Sym); - size_t getSize() const override { return Sym.getValue(); } + CommonChunk(const COFFSymbolRef sym); + size_t getSize() const override { return sym.getValue(); } uint32_t getOutputCharacteristics() const override; StringRef getSectionName() const override { return ".bss"; } private: - const COFFSymbolRef Sym; + const COFFSymbolRef sym; }; // A chunk for linker-created strings. class StringChunk : public NonSectionChunk { public: - explicit StringChunk(StringRef S) : Str(S) {} - size_t getSize() const override { return Str.size() + 1; } - void writeTo(uint8_t *Buf) const override; + explicit StringChunk(StringRef s) : str(s) {} + size_t getSize() const override { return str.size() + 1; } + void writeTo(uint8_t *buf) const override; private: - StringRef Str; + StringRef str; }; -static const uint8_t ImportThunkX86[] = { +static const uint8_t importThunkX86[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0 }; -static const uint8_t ImportThunkARM[] = { +static const uint8_t importThunkARM[] = { 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip] }; -static const uint8_t ImportThunkARM64[] = { +static const uint8_t importThunkARM64[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, #0 0x10, 0x02, 0x40, 0xf9, // ldr x16, [x16] 0x00, 0x02, 0x1f, 0xd6, // br x16 @@ -465,83 +465,83 @@ // contents will be a JMP instruction to some __imp_ symbol. class ImportThunkChunk : public NonSectionChunk { public: - ImportThunkChunk(Defined *S) - : NonSectionChunk(ImportThunkKind), ImpSymbol(S) {} - static bool classof(const Chunk *C) { return C->kind() == ImportThunkKind; } + ImportThunkChunk(Defined *s) + : NonSectionChunk(ImportThunkKind), impSymbol(s) {} + static bool classof(const Chunk *c) { return c->kind() == ImportThunkKind; } protected: - Defined *ImpSymbol; + Defined *impSymbol; }; class ImportThunkChunkX64 : public ImportThunkChunk { public: - explicit ImportThunkChunkX64(Defined *S); - size_t getSize() const override { return sizeof(ImportThunkX86); } - void writeTo(uint8_t *Buf) const override; + explicit ImportThunkChunkX64(Defined *s); + size_t getSize() const override { return sizeof(importThunkX86); } + void writeTo(uint8_t *buf) const override; }; class ImportThunkChunkX86 : public ImportThunkChunk { public: - explicit ImportThunkChunkX86(Defined *S) : ImportThunkChunk(S) {} - size_t getSize() const override { return sizeof(ImportThunkX86); } - void getBaserels(std::vector *Res) override; - void writeTo(uint8_t *Buf) const override; + explicit ImportThunkChunkX86(Defined *s) : ImportThunkChunk(s) {} + size_t getSize() const override { return sizeof(importThunkX86); } + void getBaserels(std::vector *res) override; + void writeTo(uint8_t *buf) const override; }; class ImportThunkChunkARM : public ImportThunkChunk { public: - explicit ImportThunkChunkARM(Defined *S) : ImportThunkChunk(S) {} - size_t getSize() const override { return sizeof(ImportThunkARM); } - void getBaserels(std::vector *Res) override; - void writeTo(uint8_t *Buf) const override; + explicit ImportThunkChunkARM(Defined *s) : ImportThunkChunk(s) {} + size_t getSize() const override { return sizeof(importThunkARM); } + void getBaserels(std::vector *res) override; + void writeTo(uint8_t *buf) const override; }; class ImportThunkChunkARM64 : public ImportThunkChunk { public: - explicit ImportThunkChunkARM64(Defined *S) : ImportThunkChunk(S) {} - size_t getSize() const override { return sizeof(ImportThunkARM64); } - void writeTo(uint8_t *Buf) const override; + explicit ImportThunkChunkARM64(Defined *s) : ImportThunkChunk(s) {} + size_t getSize() const override { return sizeof(importThunkARM64); } + void writeTo(uint8_t *buf) const override; }; class RangeExtensionThunkARM : public NonSectionChunk { public: - explicit RangeExtensionThunkARM(Defined *T) : Target(T) {} + explicit RangeExtensionThunkARM(Defined *t) : target(t) {} size_t getSize() const override; - void writeTo(uint8_t *Buf) const override; + void writeTo(uint8_t *buf) const override; - Defined *Target; + Defined *target; }; class RangeExtensionThunkARM64 : public NonSectionChunk { public: - explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {} + explicit RangeExtensionThunkARM64(Defined *t) : target(t) {} size_t getSize() const override; - void writeTo(uint8_t *Buf) const override; + void writeTo(uint8_t *buf) const override; - Defined *Target; + Defined *target; }; // Windows-specific. // See comments for DefinedLocalImport class. class LocalImportChunk : public NonSectionChunk { public: - explicit LocalImportChunk(Defined *S) : Sym(S) { - setAlignment(Config->Wordsize); + explicit LocalImportChunk(Defined *s) : sym(s) { + setAlignment(config->wordsize); } size_t getSize() const override; - void getBaserels(std::vector *Res) override; - void writeTo(uint8_t *Buf) const override; + void getBaserels(std::vector *res) override; + void writeTo(uint8_t *buf) const override; private: - Defined *Sym; + Defined *sym; }; // Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and // offset into the chunk. Order does not matter as the RVA table will be sorted // later. struct ChunkAndOffset { - Chunk *InputChunk; - uint32_t Offset; + Chunk *inputChunk; + uint32_t offset; struct DenseMapInfo { static ChunkAndOffset getEmptyKey() { @@ -550,12 +550,12 @@ static ChunkAndOffset getTombstoneKey() { return {llvm::DenseMapInfo::getTombstoneKey(), 0}; } - static unsigned getHashValue(const ChunkAndOffset &CO) { + static unsigned getHashValue(const ChunkAndOffset &co) { return llvm::DenseMapInfo>::getHashValue( - {CO.InputChunk, CO.Offset}); + {co.inputChunk, co.offset}); } - static bool isEqual(const ChunkAndOffset &LHS, const ChunkAndOffset &RHS) { - return LHS.InputChunk == RHS.InputChunk && LHS.Offset == RHS.Offset; + static bool isEqual(const ChunkAndOffset &lhs, const ChunkAndOffset &rhs) { + return lhs.inputChunk == rhs.inputChunk && lhs.offset == rhs.offset; } }; }; @@ -565,12 +565,12 @@ // Table which contains symbol RVAs. Used for /safeseh and /guard:cf. class RVATableChunk : public NonSectionChunk { public: - explicit RVATableChunk(SymbolRVASet S) : Syms(std::move(S)) {} - size_t getSize() const override { return Syms.size() * 4; } - void writeTo(uint8_t *Buf) const override; + explicit RVATableChunk(SymbolRVASet s) : syms(std::move(s)) {} + size_t getSize() const override { return syms.size() * 4; } + void writeTo(uint8_t *buf) const override; private: - SymbolRVASet Syms; + SymbolRVASet syms; }; // Windows-specific. @@ -578,22 +578,22 @@ // See the PE/COFF spec 5.6 for details. class BaserelChunk : public NonSectionChunk { public: - BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End); - size_t getSize() const override { return Data.size(); } - void writeTo(uint8_t *Buf) const override; + BaserelChunk(uint32_t page, Baserel *begin, Baserel *end); + size_t getSize() const override { return data.size(); } + void writeTo(uint8_t *buf) const override; private: - std::vector Data; + std::vector data; }; class Baserel { public: - Baserel(uint32_t V, uint8_t Ty) : RVA(V), Type(Ty) {} - explicit Baserel(uint32_t V) : Baserel(V, getDefaultType()) {} + Baserel(uint32_t v, uint8_t ty) : rva(v), type(ty) {} + explicit Baserel(uint32_t v) : Baserel(v, getDefaultType()) {} uint8_t getDefaultType(); - uint32_t RVA; - uint8_t Type; + uint32_t rva; + uint8_t type; }; // This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a @@ -604,7 +604,7 @@ public: EmptyChunk() {} size_t getSize() const override { return 0; } - void writeTo(uint8_t *Buf) const override {} + void writeTo(uint8_t *buf) const override {} }; // MinGW specific, for the "automatic import of variables from DLLs" feature. @@ -615,15 +615,15 @@ // code. class PseudoRelocTableChunk : public NonSectionChunk { public: - PseudoRelocTableChunk(std::vector &Relocs) - : Relocs(std::move(Relocs)) { + PseudoRelocTableChunk(std::vector &relocs) + : relocs(std::move(relocs)) { setAlignment(4); } size_t getSize() const override; - void writeTo(uint8_t *Buf) const override; + void writeTo(uint8_t *buf) const override; private: - std::vector Relocs; + std::vector relocs; }; // MinGW specific; information about one individual location in the image @@ -631,48 +631,48 @@ // one individual element in the PseudoRelocTableChunk table. class RuntimePseudoReloc { public: - RuntimePseudoReloc(Defined *Sym, SectionChunk *Target, uint32_t TargetOffset, - int Flags) - : Sym(Sym), Target(Target), TargetOffset(TargetOffset), Flags(Flags) {} - - Defined *Sym; - SectionChunk *Target; - uint32_t TargetOffset; + RuntimePseudoReloc(Defined *sym, SectionChunk *target, uint32_t targetOffset, + int flags) + : sym(sym), target(target), targetOffset(targetOffset), flags(flags) {} + + Defined *sym; + SectionChunk *target; + uint32_t targetOffset; // The Flags field contains the size of the relocation, in bits. No other // flags are currently defined. - int Flags; + int flags; }; // MinGW specific. A Chunk that contains one pointer-sized absolute value. class AbsolutePointerChunk : public NonSectionChunk { public: - AbsolutePointerChunk(uint64_t Value) : Value(Value) { + AbsolutePointerChunk(uint64_t value) : value(value) { setAlignment(getSize()); } size_t getSize() const override; - void writeTo(uint8_t *Buf) const override; + void writeTo(uint8_t *buf) const override; private: - uint64_t Value; + uint64_t value; }; // Return true if this file has the hotpatch flag set to true in the S_COMPILE3 // record in codeview debug info. Also returns true for some thunks synthesized // by the linker. inline bool Chunk::isHotPatchable() const { - if (auto *SC = dyn_cast(this)) - return SC->File->HotPatchable; + if (auto *sc = dyn_cast(this)) + return sc->file->hotPatchable; else if (isa(this)) return true; return false; } -void applyMOV32T(uint8_t *Off, uint32_t V); -void applyBranch24T(uint8_t *Off, int32_t V); +void applyMOV32T(uint8_t *off, uint32_t v); +void applyBranch24T(uint8_t *off, int32_t v); -void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift); -void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit); -void applyArm64Branch26(uint8_t *Off, int64_t V); +void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift); +void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit); +void applyArm64Branch26(uint8_t *off, int64_t v); } // namespace coff } // namespace lld Index: lld/trunk/COFF/Chunks.cpp =================================================================== --- lld/trunk/COFF/Chunks.cpp +++ lld/trunk/COFF/Chunks.cpp @@ -29,27 +29,27 @@ namespace lld { namespace coff { -SectionChunk::SectionChunk(ObjFile *F, const coff_section *H) - : Chunk(SectionKind), File(F), Header(H), Repl(this) { +SectionChunk::SectionChunk(ObjFile *f, const coff_section *h) + : Chunk(SectionKind), file(f), header(h), repl(this) { // Initialize Relocs. - setRelocs(File->getCOFFObj()->getRelocations(Header)); + setRelocs(file->getCOFFObj()->getRelocations(header)); // Initialize SectionName. - StringRef SectionName; - if (Expected E = File->getCOFFObj()->getSectionName(Header)) - SectionName = *E; - SectionNameData = SectionName.data(); - SectionNameSize = SectionName.size(); + StringRef sectionName; + if (Expected e = file->getCOFFObj()->getSectionName(header)) + sectionName = *e; + sectionNameData = sectionName.data(); + sectionNameSize = sectionName.size(); - setAlignment(Header->getAlignment()); + setAlignment(header->getAlignment()); - HasData = !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA); + hasData = !(header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA); // If linker GC is disabled, every chunk starts out alive. If linker GC is // enabled, treat non-comdat sections as roots. Generally optimized object // files will be built with -ffunction-sections or /Gy, so most things worth // stripping will be in a comdat. - Live = !Config->DoGC || !isCOMDAT(); + live = !config->doGC || !isCOMDAT(); } // SectionChunk is one of the most frequently allocated classes, so it is @@ -57,173 +57,173 @@ // below is the size of this class on x64 platforms. static_assert(sizeof(SectionChunk) <= 88, "SectionChunk grew unexpectedly"); -static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); } -static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } -static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } -static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); } -static void or32(uint8_t *P, uint32_t V) { write32le(P, read32le(P) | V); } +static void add16(uint8_t *p, int16_t v) { write16le(p, read16le(p) + v); } +static void add32(uint8_t *p, int32_t v) { write32le(p, read32le(p) + v); } +static void add64(uint8_t *p, int64_t v) { write64le(p, read64le(p) + v); } +static void or16(uint8_t *p, uint16_t v) { write16le(p, read16le(p) | v); } +static void or32(uint8_t *p, uint32_t v) { write32le(p, read32le(p) | v); } // Verify that given sections are appropriate targets for SECREL // relocations. This check is relaxed because unfortunately debug // sections have section-relative relocations against absolute symbols. -static bool checkSecRel(const SectionChunk *Sec, OutputSection *OS) { - if (OS) +static bool checkSecRel(const SectionChunk *sec, OutputSection *os) { + if (os) return true; - if (Sec->isCodeView()) + if (sec->isCodeView()) return false; error("SECREL relocation cannot be applied to absolute symbols"); return false; } -static void applySecRel(const SectionChunk *Sec, uint8_t *Off, - OutputSection *OS, uint64_t S) { - if (!checkSecRel(Sec, OS)) +static void applySecRel(const SectionChunk *sec, uint8_t *off, + OutputSection *os, uint64_t s) { + if (!checkSecRel(sec, os)) return; - uint64_t SecRel = S - OS->getRVA(); - if (SecRel > UINT32_MAX) { - error("overflow in SECREL relocation in section: " + Sec->getSectionName()); + uint64_t secRel = s - os->getRVA(); + if (secRel > UINT32_MAX) { + error("overflow in SECREL relocation in section: " + sec->getSectionName()); return; } - add32(Off, SecRel); + add32(off, secRel); } -static void applySecIdx(uint8_t *Off, OutputSection *OS) { +static void applySecIdx(uint8_t *off, OutputSection *os) { // Absolute symbol doesn't have section index, but section index relocation // against absolute symbol should be resolved to one plus the last output // section index. This is required for compatibility with MSVC. - if (OS) - add16(Off, OS->SectionIndex); + if (os) + add16(off, os->sectionIndex); else - add16(Off, DefinedAbsolute::NumOutputSections + 1); + add16(off, DefinedAbsolute::numOutputSections + 1); } -void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS, - uint64_t S, uint64_t P) const { - switch (Type) { - case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break; - case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break; - case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break; - case IMAGE_REL_AMD64_REL32: add32(Off, S - P - 4); break; - case IMAGE_REL_AMD64_REL32_1: add32(Off, S - P - 5); break; - case IMAGE_REL_AMD64_REL32_2: add32(Off, S - P - 6); break; - case IMAGE_REL_AMD64_REL32_3: add32(Off, S - P - 7); break; - case IMAGE_REL_AMD64_REL32_4: add32(Off, S - P - 8); break; - case IMAGE_REL_AMD64_REL32_5: add32(Off, S - P - 9); break; - case IMAGE_REL_AMD64_SECTION: applySecIdx(Off, OS); break; - case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, OS, S); break; +void SectionChunk::applyRelX64(uint8_t *off, uint16_t type, OutputSection *os, + uint64_t s, uint64_t p) const { + switch (type) { + case IMAGE_REL_AMD64_ADDR32: add32(off, s + config->imageBase); break; + case IMAGE_REL_AMD64_ADDR64: add64(off, s + config->imageBase); break; + case IMAGE_REL_AMD64_ADDR32NB: add32(off, s); break; + case IMAGE_REL_AMD64_REL32: add32(off, s - p - 4); break; + case IMAGE_REL_AMD64_REL32_1: add32(off, s - p - 5); break; + case IMAGE_REL_AMD64_REL32_2: add32(off, s - p - 6); break; + case IMAGE_REL_AMD64_REL32_3: add32(off, s - p - 7); break; + case IMAGE_REL_AMD64_REL32_4: add32(off, s - p - 8); break; + case IMAGE_REL_AMD64_REL32_5: add32(off, s - p - 9); break; + case IMAGE_REL_AMD64_SECTION: applySecIdx(off, os); break; + case IMAGE_REL_AMD64_SECREL: applySecRel(this, off, os, s); break; default: - error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + - toString(File)); + error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " + + toString(file)); } } -void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS, - uint64_t S, uint64_t P) const { - switch (Type) { +void SectionChunk::applyRelX86(uint8_t *off, uint16_t type, OutputSection *os, + uint64_t s, uint64_t p) const { + switch (type) { case IMAGE_REL_I386_ABSOLUTE: break; - case IMAGE_REL_I386_DIR32: add32(Off, S + Config->ImageBase); break; - case IMAGE_REL_I386_DIR32NB: add32(Off, S); break; - case IMAGE_REL_I386_REL32: add32(Off, S - P - 4); break; - case IMAGE_REL_I386_SECTION: applySecIdx(Off, OS); break; - case IMAGE_REL_I386_SECREL: applySecRel(this, Off, OS, S); break; + case IMAGE_REL_I386_DIR32: add32(off, s + config->imageBase); break; + case IMAGE_REL_I386_DIR32NB: add32(off, s); break; + case IMAGE_REL_I386_REL32: add32(off, s - p - 4); break; + case IMAGE_REL_I386_SECTION: applySecIdx(off, os); break; + case IMAGE_REL_I386_SECREL: applySecRel(this, off, os, s); break; default: - error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + - toString(File)); + error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " + + toString(file)); } } -static void applyMOV(uint8_t *Off, uint16_t V) { - write16le(Off, (read16le(Off) & 0xfbf0) | ((V & 0x800) >> 1) | ((V >> 12) & 0xf)); - write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff)); +static void applyMOV(uint8_t *off, uint16_t v) { + write16le(off, (read16le(off) & 0xfbf0) | ((v & 0x800) >> 1) | ((v >> 12) & 0xf)); + write16le(off + 2, (read16le(off + 2) & 0x8f00) | ((v & 0x700) << 4) | (v & 0xff)); } -static uint16_t readMOV(uint8_t *Off, bool MOVT) { - uint16_t Op1 = read16le(Off); - if ((Op1 & 0xfbf0) != (MOVT ? 0xf2c0 : 0xf240)) - error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") + +static uint16_t readMOV(uint8_t *off, bool movt) { + uint16_t op1 = read16le(off); + if ((op1 & 0xfbf0) != (movt ? 0xf2c0 : 0xf240)) + error("unexpected instruction in " + Twine(movt ? "MOVT" : "MOVW") + " instruction in MOV32T relocation"); - uint16_t Op2 = read16le(Off + 2); - if ((Op2 & 0x8000) != 0) - error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") + + uint16_t op2 = read16le(off + 2); + if ((op2 & 0x8000) != 0) + error("unexpected instruction in " + Twine(movt ? "MOVT" : "MOVW") + " instruction in MOV32T relocation"); - return (Op2 & 0x00ff) | ((Op2 >> 4) & 0x0700) | ((Op1 << 1) & 0x0800) | - ((Op1 & 0x000f) << 12); + return (op2 & 0x00ff) | ((op2 >> 4) & 0x0700) | ((op1 << 1) & 0x0800) | + ((op1 & 0x000f) << 12); } -void applyMOV32T(uint8_t *Off, uint32_t V) { - uint16_t ImmW = readMOV(Off, false); // read MOVW operand - uint16_t ImmT = readMOV(Off + 4, true); // read MOVT operand - uint32_t Imm = ImmW | (ImmT << 16); - V += Imm; // add the immediate offset - applyMOV(Off, V); // set MOVW operand - applyMOV(Off + 4, V >> 16); // set MOVT operand +void applyMOV32T(uint8_t *off, uint32_t v) { + uint16_t immW = readMOV(off, false); // read MOVW operand + uint16_t immT = readMOV(off + 4, true); // read MOVT operand + uint32_t imm = immW | (immT << 16); + v += imm; // add the immediate offset + applyMOV(off, v); // set MOVW operand + applyMOV(off + 4, v >> 16); // set MOVT operand } -static void applyBranch20T(uint8_t *Off, int32_t V) { - if (!isInt<21>(V)) +static void applyBranch20T(uint8_t *off, int32_t v) { + if (!isInt<21>(v)) error("relocation out of range"); - uint32_t S = V < 0 ? 1 : 0; - uint32_t J1 = (V >> 19) & 1; - uint32_t J2 = (V >> 18) & 1; - or16(Off, (S << 10) | ((V >> 12) & 0x3f)); - or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); + uint32_t s = v < 0 ? 1 : 0; + uint32_t j1 = (v >> 19) & 1; + uint32_t j2 = (v >> 18) & 1; + or16(off, (s << 10) | ((v >> 12) & 0x3f)); + or16(off + 2, (j1 << 13) | (j2 << 11) | ((v >> 1) & 0x7ff)); } -void applyBranch24T(uint8_t *Off, int32_t V) { - if (!isInt<25>(V)) +void applyBranch24T(uint8_t *off, int32_t v) { + if (!isInt<25>(v)) error("relocation out of range"); - uint32_t S = V < 0 ? 1 : 0; - uint32_t J1 = ((~V >> 23) & 1) ^ S; - uint32_t J2 = ((~V >> 22) & 1) ^ S; - or16(Off, (S << 10) | ((V >> 12) & 0x3ff)); + uint32_t s = v < 0 ? 1 : 0; + uint32_t j1 = ((~v >> 23) & 1) ^ s; + uint32_t j2 = ((~v >> 22) & 1) ^ s; + or16(off, (s << 10) | ((v >> 12) & 0x3ff)); // Clear out the J1 and J2 bits which may be set. - write16le(Off + 2, (read16le(Off + 2) & 0xd000) | (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff)); + write16le(off + 2, (read16le(off + 2) & 0xd000) | (j1 << 13) | (j2 << 11) | ((v >> 1) & 0x7ff)); } -void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, - uint64_t S, uint64_t P) const { +void SectionChunk::applyRelARM(uint8_t *off, uint16_t type, OutputSection *os, + uint64_t s, uint64_t p) const { // Pointer to thumb code must have the LSB set. - uint64_t SX = S; - if (OS && (OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)) - SX |= 1; - switch (Type) { - case IMAGE_REL_ARM_ADDR32: add32(Off, SX + Config->ImageBase); break; - case IMAGE_REL_ARM_ADDR32NB: add32(Off, SX); break; - case IMAGE_REL_ARM_MOV32T: applyMOV32T(Off, SX + Config->ImageBase); break; - case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, SX - P - 4); break; - case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, SX - P - 4); break; - case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, SX - P - 4); break; - case IMAGE_REL_ARM_SECTION: applySecIdx(Off, OS); break; - case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, OS, S); break; - case IMAGE_REL_ARM_REL32: add32(Off, SX - P - 4); break; + uint64_t sx = s; + if (os && (os->header.Characteristics & IMAGE_SCN_MEM_EXECUTE)) + sx |= 1; + switch (type) { + case IMAGE_REL_ARM_ADDR32: add32(off, sx + config->imageBase); break; + case IMAGE_REL_ARM_ADDR32NB: add32(off, sx); break; + case IMAGE_REL_ARM_MOV32T: applyMOV32T(off, sx + config->imageBase); break; + case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(off, sx - p - 4); break; + case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(off, sx - p - 4); break; + case IMAGE_REL_ARM_BLX23T: applyBranch24T(off, sx - p - 4); break; + case IMAGE_REL_ARM_SECTION: applySecIdx(off, os); break; + case IMAGE_REL_ARM_SECREL: applySecRel(this, off, os, s); break; + case IMAGE_REL_ARM_REL32: add32(off, sx - p - 4); break; default: - error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + - toString(File)); + error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " + + toString(file)); } } // Interpret the existing immediate value as a byte offset to the // target symbol, then update the instruction with the immediate as // the page offset from the current instruction to the target. -void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) { - uint32_t Orig = read32le(Off); - uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC); - S += Imm; - Imm = (S >> Shift) - (P >> Shift); - uint32_t ImmLo = (Imm & 0x3) << 29; - uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; - uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); - write32le(Off, (Orig & ~Mask) | ImmLo | ImmHi); +void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift) { + uint32_t orig = read32le(off); + uint64_t imm = ((orig >> 29) & 0x3) | ((orig >> 3) & 0x1FFFFC); + s += imm; + imm = (s >> shift) - (p >> shift); + uint32_t immLo = (imm & 0x3) << 29; + uint32_t immHi = (imm & 0x1FFFFC) << 3; + uint64_t mask = (0x3 << 29) | (0x1FFFFC << 3); + write32le(off, (orig & ~mask) | immLo | immHi); } // Update the immediate field in a AARCH64 ldr, str, and add instruction. // Optionally limit the range of the written immediate by one or more bits // (RangeLimit). -void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) { - uint32_t Orig = read32le(Off); - Imm += (Orig >> 10) & 0xFFF; - Orig &= ~(0xFFF << 10); - write32le(Off, Orig | ((Imm & (0xFFF >> RangeLimit)) << 10)); +void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit) { + uint32_t orig = read32le(off); + imm += (orig >> 10) & 0xFFF; + orig &= ~(0xFFF << 10); + write32le(off, orig | ((imm & (0xFFF >> rangeLimit)) << 10)); } // Add the 12 bit page offset to the existing immediate. @@ -234,178 +234,178 @@ // Even if larger loads/stores have a larger range, limit the // effective offset to 12 bit, since it is intended to be a // page offset. -static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) { - uint32_t Orig = read32le(Off); - uint32_t Size = Orig >> 30; +static void applyArm64Ldr(uint8_t *off, uint64_t imm) { + uint32_t orig = read32le(off); + uint32_t size = orig >> 30; // 0x04000000 indicates SIMD/FP registers // 0x00800000 indicates 128 bit - if ((Orig & 0x4800000) == 0x4800000) - Size += 4; - if ((Imm & ((1 << Size) - 1)) != 0) + if ((orig & 0x4800000) == 0x4800000) + size += 4; + if ((imm & ((1 << size) - 1)) != 0) error("misaligned ldr/str offset"); - applyArm64Imm(Off, Imm >> Size, Size); + applyArm64Imm(off, imm >> size, size); } -static void applySecRelLow12A(const SectionChunk *Sec, uint8_t *Off, - OutputSection *OS, uint64_t S) { - if (checkSecRel(Sec, OS)) - applyArm64Imm(Off, (S - OS->getRVA()) & 0xfff, 0); +static void applySecRelLow12A(const SectionChunk *sec, uint8_t *off, + OutputSection *os, uint64_t s) { + if (checkSecRel(sec, os)) + applyArm64Imm(off, (s - os->getRVA()) & 0xfff, 0); } -static void applySecRelHigh12A(const SectionChunk *Sec, uint8_t *Off, - OutputSection *OS, uint64_t S) { - if (!checkSecRel(Sec, OS)) +static void applySecRelHigh12A(const SectionChunk *sec, uint8_t *off, + OutputSection *os, uint64_t s) { + if (!checkSecRel(sec, os)) return; - uint64_t SecRel = (S - OS->getRVA()) >> 12; - if (0xfff < SecRel) { + uint64_t secRel = (s - os->getRVA()) >> 12; + if (0xfff < secRel) { error("overflow in SECREL_HIGH12A relocation in section: " + - Sec->getSectionName()); + sec->getSectionName()); return; } - applyArm64Imm(Off, SecRel & 0xfff, 0); + applyArm64Imm(off, secRel & 0xfff, 0); } -static void applySecRelLdr(const SectionChunk *Sec, uint8_t *Off, - OutputSection *OS, uint64_t S) { - if (checkSecRel(Sec, OS)) - applyArm64Ldr(Off, (S - OS->getRVA()) & 0xfff); +static void applySecRelLdr(const SectionChunk *sec, uint8_t *off, + OutputSection *os, uint64_t s) { + if (checkSecRel(sec, os)) + applyArm64Ldr(off, (s - os->getRVA()) & 0xfff); } -void applyArm64Branch26(uint8_t *Off, int64_t V) { - if (!isInt<28>(V)) +void applyArm64Branch26(uint8_t *off, int64_t v) { + if (!isInt<28>(v)) error("relocation out of range"); - or32(Off, (V & 0x0FFFFFFC) >> 2); + or32(off, (v & 0x0FFFFFFC) >> 2); } -static void applyArm64Branch19(uint8_t *Off, int64_t V) { - if (!isInt<21>(V)) +static void applyArm64Branch19(uint8_t *off, int64_t v) { + if (!isInt<21>(v)) error("relocation out of range"); - or32(Off, (V & 0x001FFFFC) << 3); + or32(off, (v & 0x001FFFFC) << 3); } -static void applyArm64Branch14(uint8_t *Off, int64_t V) { - if (!isInt<16>(V)) +static void applyArm64Branch14(uint8_t *off, int64_t v) { + if (!isInt<16>(v)) error("relocation out of range"); - or32(Off, (V & 0x0000FFFC) << 3); + or32(off, (v & 0x0000FFFC) << 3); } -void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, - uint64_t S, uint64_t P) const { - switch (Type) { - case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P, 12); break; - case IMAGE_REL_ARM64_REL21: applyArm64Addr(Off, S, P, 0); break; - case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break; - case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break; - case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(Off, S - P); break; - case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(Off, S - P); break; - case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(Off, S - P); break; - case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break; - case IMAGE_REL_ARM64_ADDR32NB: add32(Off, S); break; - case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break; - case IMAGE_REL_ARM64_SECREL: applySecRel(this, Off, OS, S); break; - case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, Off, OS, S); break; - case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, Off, OS, S); break; - case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, Off, OS, S); break; - case IMAGE_REL_ARM64_SECTION: applySecIdx(Off, OS); break; - case IMAGE_REL_ARM64_REL32: add32(Off, S - P - 4); break; +void SectionChunk::applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os, + uint64_t s, uint64_t p) const { + switch (type) { + case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(off, s, p, 12); break; + case IMAGE_REL_ARM64_REL21: applyArm64Addr(off, s, p, 0); break; + case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(off, s & 0xfff, 0); break; + case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(off, s & 0xfff); break; + case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(off, s - p); break; + case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(off, s - p); break; + case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(off, s - p); break; + case IMAGE_REL_ARM64_ADDR32: add32(off, s + config->imageBase); break; + case IMAGE_REL_ARM64_ADDR32NB: add32(off, s); break; + case IMAGE_REL_ARM64_ADDR64: add64(off, s + config->imageBase); break; + case IMAGE_REL_ARM64_SECREL: applySecRel(this, off, os, s); break; + case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, off, os, s); break; + case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, off, os, s); break; + case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, off, os, s); break; + case IMAGE_REL_ARM64_SECTION: applySecIdx(off, os); break; + case IMAGE_REL_ARM64_REL32: add32(off, s - p - 4); break; default: - error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + - toString(File)); + error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " + + toString(file)); } } -static void maybeReportRelocationToDiscarded(const SectionChunk *FromChunk, - Defined *Sym, - const coff_relocation &Rel) { +static void maybeReportRelocationToDiscarded(const SectionChunk *fromChunk, + Defined *sym, + const coff_relocation &rel) { // Don't report these errors when the relocation comes from a debug info // section or in mingw mode. MinGW mode object files (built by GCC) can // have leftover sections with relocations against discarded comdat // sections. Such sections are left as is, with relocations untouched. - if (FromChunk->isCodeView() || FromChunk->isDWARF() || Config->MinGW) + if (fromChunk->isCodeView() || fromChunk->isDWARF() || config->mingw) return; // Get the name of the symbol. If it's null, it was discarded early, so we // have to go back to the object file. - ObjFile *File = FromChunk->File; - StringRef Name; - if (Sym) { - Name = Sym->getName(); + ObjFile *file = fromChunk->file; + StringRef name; + if (sym) { + name = sym->getName(); } else { - COFFSymbolRef COFFSym = - check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex)); - File->getCOFFObj()->getSymbolName(COFFSym, Name); + COFFSymbolRef coffSym = + check(file->getCOFFObj()->getSymbol(rel.SymbolTableIndex)); + file->getCOFFObj()->getSymbolName(coffSym, name); } - std::vector SymbolLocations = - getSymbolLocations(File, Rel.SymbolTableIndex); + std::vector symbolLocations = + getSymbolLocations(file, rel.SymbolTableIndex); - std::string Out; - llvm::raw_string_ostream OS(Out); - OS << "relocation against symbol in discarded section: " + Name; - for (const std::string &S : SymbolLocations) - OS << S; - error(OS.str()); + std::string out; + llvm::raw_string_ostream os(out); + os << "relocation against symbol in discarded section: " + name; + for (const std::string &s : symbolLocations) + os << s; + error(os.str()); } -void SectionChunk::writeTo(uint8_t *Buf) const { - if (!HasData) +void SectionChunk::writeTo(uint8_t *buf) const { + if (!hasData) return; // Copy section contents from source object file to output file. - ArrayRef A = getContents(); - if (!A.empty()) - memcpy(Buf, A.data(), A.size()); + ArrayRef a = getContents(); + if (!a.empty()) + memcpy(buf, a.data(), a.size()); // Apply relocations. - size_t InputSize = getSize(); - for (size_t I = 0, E = RelocsSize; I < E; I++) { - const coff_relocation &Rel = RelocsData[I]; + size_t inputSize = getSize(); + for (size_t i = 0, e = relocsSize; i < e; i++) { + const coff_relocation &rel = relocsData[i]; // Check for an invalid relocation offset. This check isn't perfect, because // we don't have the relocation size, which is only known after checking the // machine and relocation type. As a result, a relocation may overwrite the // beginning of the following input section. - if (Rel.VirtualAddress >= InputSize) { + if (rel.VirtualAddress >= inputSize) { error("relocation points beyond the end of its parent section"); continue; } - uint8_t *Off = Buf + Rel.VirtualAddress; + uint8_t *off = buf + rel.VirtualAddress; - auto *Sym = - dyn_cast_or_null(File->getSymbol(Rel.SymbolTableIndex)); + auto *sym = + dyn_cast_or_null(file->getSymbol(rel.SymbolTableIndex)); // Get the output section of the symbol for this relocation. The output // section is needed to compute SECREL and SECTION relocations used in debug // info. - Chunk *C = Sym ? Sym->getChunk() : nullptr; - OutputSection *OS = C ? C->getOutputSection() : nullptr; + Chunk *c = sym ? sym->getChunk() : nullptr; + OutputSection *os = c ? c->getOutputSection() : nullptr; // Skip the relocation if it refers to a discarded section, and diagnose it // as an error if appropriate. If a symbol was discarded early, it may be // null. If it was discarded late, the output section will be null, unless // it was an absolute or synthetic symbol. - if (!Sym || - (!OS && !isa(Sym) && !isa(Sym))) { - maybeReportRelocationToDiscarded(this, Sym, Rel); + if (!sym || + (!os && !isa(sym) && !isa(sym))) { + maybeReportRelocationToDiscarded(this, sym, rel); continue; } - uint64_t S = Sym->getRVA(); + uint64_t s = sym->getRVA(); // Compute the RVA of the relocation for relative relocations. - uint64_t P = RVA + Rel.VirtualAddress; - switch (Config->Machine) { + uint64_t p = rva + rel.VirtualAddress; + switch (config->machine) { case AMD64: - applyRelX64(Off, Rel.Type, OS, S, P); + applyRelX64(off, rel.Type, os, s, p); break; case I386: - applyRelX86(Off, Rel.Type, OS, S, P); + applyRelX86(off, rel.Type, os, s, p); break; case ARMNT: - applyRelARM(Off, Rel.Type, OS, S, P); + applyRelARM(off, rel.Type, os, s, p); break; case ARM64: - applyRelARM64(Off, Rel.Type, OS, S, P); + applyRelARM64(off, rel.Type, os, s, p); break; default: llvm_unreachable("unknown machine type"); @@ -413,32 +413,32 @@ } } -void SectionChunk::addAssociative(SectionChunk *Child) { +void SectionChunk::addAssociative(SectionChunk *child) { // Insert this child at the head of the list. - assert(Child->AssocChildren == nullptr && + assert(child->assocChildren == nullptr && "associated sections cannot have their own associated children"); - Child->AssocChildren = AssocChildren; - AssocChildren = Child; + child->assocChildren = assocChildren; + assocChildren = child; } -static uint8_t getBaserelType(const coff_relocation &Rel) { - switch (Config->Machine) { +static uint8_t getBaserelType(const coff_relocation &rel) { + switch (config->machine) { case AMD64: - if (Rel.Type == IMAGE_REL_AMD64_ADDR64) + if (rel.Type == IMAGE_REL_AMD64_ADDR64) return IMAGE_REL_BASED_DIR64; return IMAGE_REL_BASED_ABSOLUTE; case I386: - if (Rel.Type == IMAGE_REL_I386_DIR32) + if (rel.Type == IMAGE_REL_I386_DIR32) return IMAGE_REL_BASED_HIGHLOW; return IMAGE_REL_BASED_ABSOLUTE; case ARMNT: - if (Rel.Type == IMAGE_REL_ARM_ADDR32) + if (rel.Type == IMAGE_REL_ARM_ADDR32) return IMAGE_REL_BASED_HIGHLOW; - if (Rel.Type == IMAGE_REL_ARM_MOV32T) + if (rel.Type == IMAGE_REL_ARM_MOV32T) return IMAGE_REL_BASED_ARM_MOV32T; return IMAGE_REL_BASED_ABSOLUTE; case ARM64: - if (Rel.Type == IMAGE_REL_ARM64_ADDR64) + if (rel.Type == IMAGE_REL_ARM64_ADDR64) return IMAGE_REL_BASED_DIR64; return IMAGE_REL_BASED_ABSOLUTE; default: @@ -450,16 +450,16 @@ // Collect all locations that contain absolute addresses, which need to be // fixed by the loader if load-time relocation is needed. // Only called when base relocation is enabled. -void SectionChunk::getBaserels(std::vector *Res) { - for (size_t I = 0, E = RelocsSize; I < E; I++) { - const coff_relocation &Rel = RelocsData[I]; - uint8_t Ty = getBaserelType(Rel); - if (Ty == IMAGE_REL_BASED_ABSOLUTE) +void SectionChunk::getBaserels(std::vector *res) { + for (size_t i = 0, e = relocsSize; i < e; i++) { + const coff_relocation &rel = relocsData[i]; + uint8_t ty = getBaserelType(rel); + if (ty == IMAGE_REL_BASED_ABSOLUTE) continue; - Symbol *Target = File->getSymbol(Rel.SymbolTableIndex); - if (!Target || isa(Target)) + Symbol *target = file->getSymbol(rel.SymbolTableIndex); + if (!target || isa(target)) continue; - Res->emplace_back(RVA + Rel.VirtualAddress, Ty); + res->emplace_back(rva + rel.VirtualAddress, ty); } } @@ -470,7 +470,7 @@ // another DLL) This returns the size the relocation is supposed to update, // in bits, or 0 if the relocation cannot be handled as a runtime pseudo // relocation. -static int getRuntimePseudoRelocSize(uint16_t Type) { +static int getRuntimePseudoRelocSize(uint16_t type) { // Relocations that either contain an absolute address, or a plain // relative offset, since the runtime pseudo reloc implementation // adds 8/16/32/64 bit values to a memory address. @@ -496,9 +496,9 @@ // the image, or temporarily changed at runtime with VirtualProtect. // Since this only operates on direct address values, it doesn't work for // ARM/ARM64 relocations, other than the plain ADDR32/ADDR64 relocations. - switch (Config->Machine) { + switch (config->machine) { case AMD64: - switch (Type) { + switch (type) { case IMAGE_REL_AMD64_ADDR64: return 64; case IMAGE_REL_AMD64_ADDR32: @@ -513,7 +513,7 @@ return 0; } case I386: - switch (Type) { + switch (type) { case IMAGE_REL_I386_DIR32: case IMAGE_REL_I386_REL32: return 32; @@ -521,14 +521,14 @@ return 0; } case ARMNT: - switch (Type) { + switch (type) { case IMAGE_REL_ARM_ADDR32: return 32; default: return 0; } case ARM64: - switch (Type) { + switch (type) { case IMAGE_REL_ARM64_ADDR64: return 64; case IMAGE_REL_ARM64_ADDR32: @@ -547,48 +547,48 @@ // to a module local variable, which turned out to actually need to be // imported from another DLL). void SectionChunk::getRuntimePseudoRelocs( - std::vector &Res) { - for (const coff_relocation &Rel : getRelocs()) { - auto *Target = - dyn_cast_or_null(File->getSymbol(Rel.SymbolTableIndex)); - if (!Target || !Target->IsRuntimePseudoReloc) + std::vector &res) { + for (const coff_relocation &rel : getRelocs()) { + auto *target = + dyn_cast_or_null(file->getSymbol(rel.SymbolTableIndex)); + if (!target || !target->isRuntimePseudoReloc) continue; - int SizeInBits = getRuntimePseudoRelocSize(Rel.Type); - if (SizeInBits == 0) { - error("unable to automatically import from " + Target->getName() + + int sizeInBits = getRuntimePseudoRelocSize(rel.Type); + if (sizeInBits == 0) { + error("unable to automatically import from " + target->getName() + " with relocation type " + - File->getCOFFObj()->getRelocationTypeName(Rel.Type) + " in " + - toString(File)); + file->getCOFFObj()->getRelocationTypeName(rel.Type) + " in " + + toString(file)); continue; } // SizeInBits is used to initialize the Flags field; currently no // other flags are defined. - Res.emplace_back( - RuntimePseudoReloc(Target, this, Rel.VirtualAddress, SizeInBits)); + res.emplace_back( + RuntimePseudoReloc(target, this, rel.VirtualAddress, sizeInBits)); } } bool SectionChunk::isCOMDAT() const { - return Header->Characteristics & IMAGE_SCN_LNK_COMDAT; + return header->Characteristics & IMAGE_SCN_LNK_COMDAT; } void SectionChunk::printDiscardedMessage() const { // Removed by dead-stripping. If it's removed by ICF, ICF already // printed out the name, so don't repeat that here. - if (Sym && this == Repl) - message("Discarded " + Sym->getName()); + if (sym && this == repl) + message("Discarded " + sym->getName()); } StringRef SectionChunk::getDebugName() const { - if (Sym) - return Sym->getName(); + if (sym) + return sym->getName(); return ""; } ArrayRef SectionChunk::getContents() const { - ArrayRef A; - cantFail(File->getCOFFObj()->getSectionContents(Header, A)); - return A; + ArrayRef a; + cantFail(file->getCOFFObj()->getSectionContents(header, a)); + return a; } ArrayRef SectionChunk::consumeDebugMagic() { @@ -596,57 +596,57 @@ return consumeDebugMagic(getContents(), getSectionName()); } -ArrayRef SectionChunk::consumeDebugMagic(ArrayRef Data, - StringRef SectionName) { - if (Data.empty()) +ArrayRef SectionChunk::consumeDebugMagic(ArrayRef data, + StringRef sectionName) { + if (data.empty()) return {}; // First 4 bytes are section magic. - if (Data.size() < 4) - fatal("the section is too short: " + SectionName); + if (data.size() < 4) + fatal("the section is too short: " + sectionName); - if (!SectionName.startswith(".debug$")) - fatal("invalid section: " + SectionName); + if (!sectionName.startswith(".debug$")) + fatal("invalid section: " + sectionName); - uint32_t Magic = support::endian::read32le(Data.data()); - uint32_t ExpectedMagic = SectionName == ".debug$H" + uint32_t magic = support::endian::read32le(data.data()); + uint32_t expectedMagic = sectionName == ".debug$H" ? DEBUG_HASHES_SECTION_MAGIC : DEBUG_SECTION_MAGIC; - if (Magic != ExpectedMagic) { - warn("ignoring section " + SectionName + " with unrecognized magic 0x" + - utohexstr(Magic)); + if (magic != expectedMagic) { + warn("ignoring section " + sectionName + " with unrecognized magic 0x" + + utohexstr(magic)); return {}; } - return Data.slice(4); + return data.slice(4); } -SectionChunk *SectionChunk::findByName(ArrayRef Sections, - StringRef Name) { - for (SectionChunk *C : Sections) - if (C->getSectionName() == Name) - return C; +SectionChunk *SectionChunk::findByName(ArrayRef sections, + StringRef name) { + for (SectionChunk *c : sections) + if (c->getSectionName() == name) + return c; return nullptr; } -void SectionChunk::replace(SectionChunk *Other) { - P2Align = std::max(P2Align, Other->P2Align); - Other->Repl = Repl; - Other->Live = false; +void SectionChunk::replace(SectionChunk *other) { + p2Align = std::max(p2Align, other->p2Align); + other->repl = repl; + other->live = false; } uint32_t SectionChunk::getSectionNumber() const { - DataRefImpl R; - R.p = reinterpret_cast(Header); - SectionRef S(R, File->getCOFFObj()); - return S.getIndex() + 1; + DataRefImpl r; + r.p = reinterpret_cast(header); + SectionRef s(r, file->getCOFFObj()); + return s.getIndex() + 1; } -CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) { +CommonChunk::CommonChunk(const COFFSymbolRef s) : sym(s) { // The value of a common symbol is its size. Align all common symbols smaller // than 32 bytes naturally, i.e. round the size up to the next power of two. // This is what MSVC link.exe does. - setAlignment(std::min(32U, uint32_t(PowerOf2Ceil(Sym.getValue())))); - HasData = false; + setAlignment(std::min(32U, uint32_t(PowerOf2Ceil(sym.getValue())))); + hasData = false; } uint32_t CommonChunk::getOutputCharacteristics() const { @@ -654,139 +654,139 @@ IMAGE_SCN_MEM_WRITE; } -void StringChunk::writeTo(uint8_t *Buf) const { - memcpy(Buf, Str.data(), Str.size()); - Buf[Str.size()] = '\0'; +void StringChunk::writeTo(uint8_t *buf) const { + memcpy(buf, str.data(), str.size()); + buf[str.size()] = '\0'; } -ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImportThunkChunk(S) { +ImportThunkChunkX64::ImportThunkChunkX64(Defined *s) : ImportThunkChunk(s) { // Intel Optimization Manual says that all branch targets // should be 16-byte aligned. MSVC linker does this too. setAlignment(16); } -void ImportThunkChunkX64::writeTo(uint8_t *Buf) const { - memcpy(Buf, ImportThunkX86, sizeof(ImportThunkX86)); +void ImportThunkChunkX64::writeTo(uint8_t *buf) const { + memcpy(buf, importThunkX86, sizeof(importThunkX86)); // The first two bytes is a JMP instruction. Fill its operand. - write32le(Buf + 2, ImpSymbol->getRVA() - RVA - getSize()); + write32le(buf + 2, impSymbol->getRVA() - rva - getSize()); } -void ImportThunkChunkX86::getBaserels(std::vector *Res) { - Res->emplace_back(getRVA() + 2); +void ImportThunkChunkX86::getBaserels(std::vector *res) { + res->emplace_back(getRVA() + 2); } -void ImportThunkChunkX86::writeTo(uint8_t *Buf) const { - memcpy(Buf, ImportThunkX86, sizeof(ImportThunkX86)); +void ImportThunkChunkX86::writeTo(uint8_t *buf) const { + memcpy(buf, importThunkX86, sizeof(importThunkX86)); // The first two bytes is a JMP instruction. Fill its operand. - write32le(Buf + 2, - ImpSymbol->getRVA() + Config->ImageBase); + write32le(buf + 2, + impSymbol->getRVA() + config->imageBase); } -void ImportThunkChunkARM::getBaserels(std::vector *Res) { - Res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T); +void ImportThunkChunkARM::getBaserels(std::vector *res) { + res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T); } -void ImportThunkChunkARM::writeTo(uint8_t *Buf) const { - memcpy(Buf, ImportThunkARM, sizeof(ImportThunkARM)); +void ImportThunkChunkARM::writeTo(uint8_t *buf) const { + memcpy(buf, importThunkARM, sizeof(importThunkARM)); // Fix mov.w and mov.t operands. - applyMOV32T(Buf, ImpSymbol->getRVA() + Config->ImageBase); + applyMOV32T(buf, impSymbol->getRVA() + config->imageBase); } -void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { - int64_t Off = ImpSymbol->getRVA() & 0xfff; - memcpy(Buf, ImportThunkARM64, sizeof(ImportThunkARM64)); - applyArm64Addr(Buf, ImpSymbol->getRVA(), RVA, 12); - applyArm64Ldr(Buf + 4, Off); +void ImportThunkChunkARM64::writeTo(uint8_t *buf) const { + int64_t off = impSymbol->getRVA() & 0xfff; + memcpy(buf, importThunkARM64, sizeof(importThunkARM64)); + applyArm64Addr(buf, impSymbol->getRVA(), rva, 12); + applyArm64Ldr(buf + 4, off); } // A Thumb2, PIC, non-interworking range extension thunk. -const uint8_t ArmThunk[] = { +const uint8_t armThunk[] = { 0x40, 0xf2, 0x00, 0x0c, // P: movw ip,:lower16:S - (P + (L1-P) + 4) 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4) 0xe7, 0x44, // L1: add pc, ip }; size_t RangeExtensionThunkARM::getSize() const { - assert(Config->Machine == ARMNT); - return sizeof(ArmThunk); + assert(config->machine == ARMNT); + return sizeof(armThunk); } -void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const { - assert(Config->Machine == ARMNT); - uint64_t Offset = Target->getRVA() - RVA - 12; - memcpy(Buf, ArmThunk, sizeof(ArmThunk)); - applyMOV32T(Buf, uint32_t(Offset)); +void RangeExtensionThunkARM::writeTo(uint8_t *buf) const { + assert(config->machine == ARMNT); + uint64_t offset = target->getRVA() - rva - 12; + memcpy(buf, armThunk, sizeof(armThunk)); + applyMOV32T(buf, uint32_t(offset)); } // A position independent ARM64 adrp+add thunk, with a maximum range of // +/- 4 GB, which is enough for any PE-COFF. -const uint8_t Arm64Thunk[] = { +const uint8_t arm64Thunk[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest 0x10, 0x02, 0x00, 0x91, // add x16, x16, :lo12:Dest 0x00, 0x02, 0x1f, 0xd6, // br x16 }; size_t RangeExtensionThunkARM64::getSize() const { - assert(Config->Machine == ARM64); - return sizeof(Arm64Thunk); + assert(config->machine == ARM64); + return sizeof(arm64Thunk); } -void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const { - assert(Config->Machine == ARM64); - memcpy(Buf, Arm64Thunk, sizeof(Arm64Thunk)); - applyArm64Addr(Buf + 0, Target->getRVA(), RVA, 12); - applyArm64Imm(Buf + 4, Target->getRVA() & 0xfff, 0); +void RangeExtensionThunkARM64::writeTo(uint8_t *buf) const { + assert(config->machine == ARM64); + memcpy(buf, arm64Thunk, sizeof(arm64Thunk)); + applyArm64Addr(buf + 0, target->getRVA(), rva, 12); + applyArm64Imm(buf + 4, target->getRVA() & 0xfff, 0); } -void LocalImportChunk::getBaserels(std::vector *Res) { - Res->emplace_back(getRVA()); +void LocalImportChunk::getBaserels(std::vector *res) { + res->emplace_back(getRVA()); } -size_t LocalImportChunk::getSize() const { return Config->Wordsize; } +size_t LocalImportChunk::getSize() const { return config->wordsize; } -void LocalImportChunk::writeTo(uint8_t *Buf) const { - if (Config->is64()) { - write64le(Buf, Sym->getRVA() + Config->ImageBase); +void LocalImportChunk::writeTo(uint8_t *buf) const { + if (config->is64()) { + write64le(buf, sym->getRVA() + config->imageBase); } else { - write32le(Buf, Sym->getRVA() + Config->ImageBase); + write32le(buf, sym->getRVA() + config->imageBase); } } -void RVATableChunk::writeTo(uint8_t *Buf) const { - ulittle32_t *Begin = reinterpret_cast(Buf); - size_t Cnt = 0; - for (const ChunkAndOffset &CO : Syms) - Begin[Cnt++] = CO.InputChunk->getRVA() + CO.Offset; - std::sort(Begin, Begin + Cnt); - assert(std::unique(Begin, Begin + Cnt) == Begin + Cnt && +void RVATableChunk::writeTo(uint8_t *buf) const { + ulittle32_t *begin = reinterpret_cast(buf); + size_t cnt = 0; + for (const ChunkAndOffset &co : syms) + begin[cnt++] = co.inputChunk->getRVA() + co.offset; + std::sort(begin, begin + cnt); + assert(std::unique(begin, begin + cnt) == begin + cnt && "RVA tables should be de-duplicated"); } // MinGW specific, for the "automatic import of variables from DLLs" feature. size_t PseudoRelocTableChunk::getSize() const { - if (Relocs.empty()) + if (relocs.empty()) return 0; - return 12 + 12 * Relocs.size(); + return 12 + 12 * relocs.size(); } // MinGW specific. -void PseudoRelocTableChunk::writeTo(uint8_t *Buf) const { - if (Relocs.empty()) +void PseudoRelocTableChunk::writeTo(uint8_t *buf) const { + if (relocs.empty()) return; - ulittle32_t *Table = reinterpret_cast(Buf); + ulittle32_t *table = reinterpret_cast(buf); // This is the list header, to signal the runtime pseudo relocation v2 // format. - Table[0] = 0; - Table[1] = 0; - Table[2] = 1; - - size_t Idx = 3; - for (const RuntimePseudoReloc &RPR : Relocs) { - Table[Idx + 0] = RPR.Sym->getRVA(); - Table[Idx + 1] = RPR.Target->getRVA() + RPR.TargetOffset; - Table[Idx + 2] = RPR.Flags; - Idx += 3; + table[0] = 0; + table[1] = 0; + table[2] = 1; + + size_t idx = 3; + for (const RuntimePseudoReloc &rpr : relocs) { + table[idx + 0] = rpr.sym->getRVA(); + table[idx + 1] = rpr.target->getRVA() + rpr.targetOffset; + table[idx + 2] = rpr.flags; + idx += 3; } } @@ -829,26 +829,26 @@ // // Usually we have a lot of relocations for each page, so the number of // bytes for one .reloc entry is close to 2 bytes on average. -BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) { +BaserelChunk::BaserelChunk(uint32_t page, Baserel *begin, Baserel *end) { // Block header consists of 4 byte page RVA and 4 byte block size. // Each entry is 2 byte. Last entry may be padding. - Data.resize(alignTo((End - Begin) * 2 + 8, 4)); - uint8_t *P = Data.data(); - write32le(P, Page); - write32le(P + 4, Data.size()); - P += 8; - for (Baserel *I = Begin; I != End; ++I) { - write16le(P, (I->Type << 12) | (I->RVA - Page)); - P += 2; + data.resize(alignTo((end - begin) * 2 + 8, 4)); + uint8_t *p = data.data(); + write32le(p, page); + write32le(p + 4, data.size()); + p += 8; + for (Baserel *i = begin; i != end; ++i) { + write16le(p, (i->type << 12) | (i->rva - page)); + p += 2; } } -void BaserelChunk::writeTo(uint8_t *Buf) const { - memcpy(Buf, Data.data(), Data.size()); +void BaserelChunk::writeTo(uint8_t *buf) const { + memcpy(buf, data.data(), data.size()); } uint8_t Baserel::getDefaultType() { - switch (Config->Machine) { + switch (config->machine) { case AMD64: case ARM64: return IMAGE_REL_BASED_DIR64; @@ -860,38 +860,38 @@ } } -MergeChunk *MergeChunk::Instances[Log2MaxSectionAlignment + 1] = {}; +MergeChunk *MergeChunk::instances[Log2MaxSectionAlignment + 1] = {}; -MergeChunk::MergeChunk(uint32_t Alignment) - : Builder(StringTableBuilder::RAW, Alignment) { - setAlignment(Alignment); +MergeChunk::MergeChunk(uint32_t alignment) + : builder(StringTableBuilder::RAW, alignment) { + setAlignment(alignment); } -void MergeChunk::addSection(SectionChunk *C) { - assert(isPowerOf2_32(C->getAlignment())); - uint8_t P2Align = llvm::Log2_32(C->getAlignment()); - assert(P2Align < array_lengthof(Instances)); - auto *&MC = Instances[P2Align]; - if (!MC) - MC = make(C->getAlignment()); - MC->Sections.push_back(C); +void MergeChunk::addSection(SectionChunk *c) { + assert(isPowerOf2_32(c->getAlignment())); + uint8_t p2Align = llvm::Log2_32(c->getAlignment()); + assert(p2Align < array_lengthof(instances)); + auto *&mc = instances[p2Align]; + if (!mc) + mc = make(c->getAlignment()); + mc->sections.push_back(c); } void MergeChunk::finalizeContents() { - assert(!Finalized && "should only finalize once"); - for (SectionChunk *C : Sections) - if (C->Live) - Builder.add(toStringRef(C->getContents())); - Builder.finalize(); - Finalized = true; + assert(!finalized && "should only finalize once"); + for (SectionChunk *c : sections) + if (c->live) + builder.add(toStringRef(c->getContents())); + builder.finalize(); + finalized = true; } void MergeChunk::assignSubsectionRVAs() { - for (SectionChunk *C : Sections) { - if (!C->Live) + for (SectionChunk *c : sections) { + if (!c->live) continue; - size_t Off = Builder.getOffset(toStringRef(C->getContents())); - C->setRVA(RVA + Off); + size_t off = builder.getOffset(toStringRef(c->getContents())); + c->setRVA(rva + off); } } @@ -900,21 +900,21 @@ } size_t MergeChunk::getSize() const { - return Builder.getSize(); + return builder.getSize(); } -void MergeChunk::writeTo(uint8_t *Buf) const { - Builder.write(Buf); +void MergeChunk::writeTo(uint8_t *buf) const { + builder.write(buf); } // MinGW specific. -size_t AbsolutePointerChunk::getSize() const { return Config->Wordsize; } +size_t AbsolutePointerChunk::getSize() const { return config->wordsize; } -void AbsolutePointerChunk::writeTo(uint8_t *Buf) const { - if (Config->is64()) { - write64le(Buf, Value); +void AbsolutePointerChunk::writeTo(uint8_t *buf) const { + if (config->is64()) { + write64le(buf, value); } else { - write32le(Buf, Value); + write32le(buf, value); } } Index: lld/trunk/COFF/Config.h =================================================================== --- lld/trunk/COFF/Config.h +++ lld/trunk/COFF/Config.h @@ -38,30 +38,30 @@ // Represents an /export option. struct Export { - StringRef Name; // N in /export:N or /export:E=N - StringRef ExtName; // E in /export:E=N - Symbol *Sym = nullptr; - uint16_t Ordinal = 0; - bool Noname = false; - bool Data = false; - bool Private = false; - bool Constant = false; + StringRef name; // N in /export:N or /export:E=N + StringRef extName; // E in /export:E=N + Symbol *sym = nullptr; + uint16_t ordinal = 0; + bool noname = false; + bool data = false; + bool isPrivate = false; + bool constant = false; // If an export is a form of /export:foo=dllname.bar, that means // that foo should be exported as an alias to bar in the DLL. // ForwardTo is set to "dllname.bar" part. Usually empty. - StringRef ForwardTo; - StringChunk *ForwardChunk = nullptr; + StringRef forwardTo; + StringChunk *forwardChunk = nullptr; // True if this /export option was in .drectves section. - bool Directives = false; - StringRef SymbolName; - StringRef ExportName; // Name in DLL - - bool operator==(const Export &E) { - return (Name == E.Name && ExtName == E.ExtName && - Ordinal == E.Ordinal && Noname == E.Noname && - Data == E.Data && Private == E.Private); + bool directives = false; + StringRef symbolName; + StringRef exportName; // Name in DLL + + bool operator==(const Export &e) { + return (name == e.name && extName == e.extName && + ordinal == e.ordinal && noname == e.noname && + data == e.data && isPrivate == e.isPrivate); } }; @@ -81,137 +81,137 @@ // Global configuration. struct Configuration { enum ManifestKind { SideBySide, Embed, No }; - bool is64() { return Machine == AMD64 || Machine == ARM64; } + bool is64() { return machine == AMD64 || machine == ARM64; } - llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; - size_t Wordsize; - bool Verbose = false; - WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; - Symbol *Entry = nullptr; - bool NoEntry = false; - std::string OutputFile; - std::string ImportName; - bool Demangle = true; - bool DoGC = true; - bool DoICF = true; - bool TailMerge; - bool Relocatable = true; - bool ForceMultiple = false; - bool ForceMultipleRes = false; - bool ForceUnresolved = false; - bool Debug = false; - bool DebugDwarf = false; - bool DebugGHashes = false; - bool DebugSymtab = false; - bool ShowTiming = false; - bool ShowSummary = false; - unsigned DebugTypes = static_cast(DebugType::None); - std::vector NatvisFiles; - llvm::SmallString<128> PDBAltPath; - llvm::SmallString<128> PDBPath; - llvm::SmallString<128> PDBSourcePath; - std::vector Argv; + llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN; + size_t wordsize; + bool verbose = false; + WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; + Symbol *entry = nullptr; + bool noEntry = false; + std::string outputFile; + std::string importName; + bool demangle = true; + bool doGC = true; + bool doICF = true; + bool tailMerge; + bool relocatable = true; + bool forceMultiple = false; + bool forceMultipleRes = false; + bool forceUnresolved = false; + bool debug = false; + bool debugDwarf = false; + bool debugGHashes = false; + bool debugSymtab = false; + bool showTiming = false; + bool showSummary = false; + unsigned debugTypes = static_cast(DebugType::None); + std::vector natvisFiles; + llvm::SmallString<128> pdbAltPath; + llvm::SmallString<128> pdbPath; + llvm::SmallString<128> pdbSourcePath; + std::vector argv; // Symbols in this set are considered as live by the garbage collector. - std::vector GCRoot; + std::vector gCRoot; - std::set NoDefaultLibs; - bool NoDefaultLibAll = false; + std::set noDefaultLibs; + bool noDefaultLibAll = false; // True if we are creating a DLL. - bool DLL = false; - StringRef Implib; - std::vector Exports; - std::set DelayLoads; - std::map DLLOrder; - Symbol *DelayLoadHelper = nullptr; + bool dll = false; + StringRef implib; + std::vector exports; + std::set delayLoads; + std::map dllOrder; + Symbol *delayLoadHelper = nullptr; - bool SaveTemps = false; + bool saveTemps = false; // /guard:cf - GuardCFLevel GuardCF = GuardCFLevel::Off; + GuardCFLevel guardCF = GuardCFLevel::Off; // Used for SafeSEH. - Symbol *SEHTable = nullptr; - Symbol *SEHCount = nullptr; + Symbol *sehTable = nullptr; + Symbol *sehCount = nullptr; // Used for /opt:lldlto=N - unsigned LTOO = 2; + unsigned ltoo = 2; // Used for /opt:lldltojobs=N - unsigned ThinLTOJobs = 0; + unsigned thinLTOJobs = 0; // Used for /opt:lldltopartitions=N - unsigned LTOPartitions = 1; + unsigned ltoPartitions = 1; // Used for /opt:lldltocache=path - StringRef LTOCache; + StringRef ltoCache; // Used for /opt:lldltocachepolicy=policy - llvm::CachePruningPolicy LTOCachePolicy; + llvm::CachePruningPolicy ltoCachePolicy; // Used for /merge:from=to (e.g. /merge:.rdata=.text) - std::map Merge; + std::map merge; // Used for /section=.name,{DEKPRSW} to set section attributes. - std::map Section; + std::map section; // Options for manifest files. - ManifestKind Manifest = No; - int ManifestID = 1; - StringRef ManifestDependency; - bool ManifestUAC = true; - std::vector ManifestInput; - StringRef ManifestLevel = "'asInvoker'"; - StringRef ManifestUIAccess = "'false'"; - StringRef ManifestFile; + ManifestKind manifest = No; + int manifestID = 1; + StringRef manifestDependency; + bool manifestUAC = true; + std::vector manifestInput; + StringRef manifestLevel = "'asInvoker'"; + StringRef manifestUIAccess = "'false'"; + StringRef manifestFile; // Used for /aligncomm. - std::map AlignComm; + std::map alignComm; // Used for /failifmismatch. - std::map> MustMatch; + std::map> mustMatch; // Used for /alternatename. - std::map AlternateNames; + std::map alternateNames; // Used for /order. - llvm::StringMap Order; + llvm::StringMap order; // Used for /lldmap. - std::string MapFile; + std::string mapFile; - uint64_t ImageBase = -1; - uint64_t FileAlign = 512; - uint64_t StackReserve = 1024 * 1024; - uint64_t StackCommit = 4096; - uint64_t HeapReserve = 1024 * 1024; - uint64_t HeapCommit = 4096; - uint32_t MajorImageVersion = 0; - uint32_t MinorImageVersion = 0; - uint32_t MajorOSVersion = 6; - uint32_t MinorOSVersion = 0; - uint32_t Timestamp = 0; - uint32_t FunctionPadMin = 0; - bool DynamicBase = true; - bool AllowBind = true; - bool NxCompat = true; - bool AllowIsolation = true; - bool TerminalServerAware = true; - bool LargeAddressAware = false; - bool HighEntropyVA = false; - bool AppContainer = false; - bool MinGW = false; - bool WarnMissingOrderSymbol = true; - bool WarnLocallyDefinedImported = true; - bool WarnDebugInfoUnusable = true; - bool Incremental = true; - bool IntegrityCheck = false; - bool KillAt = false; - bool Repro = false; - bool SwaprunCD = false; - bool SwaprunNet = false; + uint64_t imageBase = -1; + uint64_t fileAlign = 512; + uint64_t stackReserve = 1024 * 1024; + uint64_t stackCommit = 4096; + uint64_t heapReserve = 1024 * 1024; + uint64_t heapCommit = 4096; + uint32_t majorImageVersion = 0; + uint32_t minorImageVersion = 0; + uint32_t majorOSVersion = 6; + uint32_t minorOSVersion = 0; + uint32_t timestamp = 0; + uint32_t functionPadMin = 0; + bool dynamicBase = true; + bool allowBind = true; + bool nxCompat = true; + bool allowIsolation = true; + bool terminalServerAware = true; + bool largeAddressAware = false; + bool highEntropyVA = false; + bool appContainer = false; + bool mingw = false; + bool warnMissingOrderSymbol = true; + bool warnLocallyDefinedImported = true; + bool warnDebugInfoUnusable = true; + bool incremental = true; + bool integrityCheck = false; + bool killAt = false; + bool repro = false; + bool swaprunCD = false; + bool swaprunNet = false; }; -extern Configuration *Config; +extern Configuration *config; } // namespace coff } // namespace lld Index: lld/trunk/COFF/DLL.h =================================================================== --- lld/trunk/COFF/DLL.h +++ lld/trunk/COFF/DLL.h @@ -21,45 +21,45 @@ // call create() to populate the chunk vectors. class IdataContents { public: - void add(DefinedImportData *Sym) { Imports.push_back(Sym); } - bool empty() { return Imports.empty(); } + void add(DefinedImportData *sym) { imports.push_back(sym); } + bool empty() { return imports.empty(); } void create(); - std::vector Imports; - std::vector Dirs; - std::vector Lookups; - std::vector Addresses; - std::vector Hints; - std::vector DLLNames; + std::vector imports; + std::vector dirs; + std::vector lookups; + std::vector addresses; + std::vector hints; + std::vector dllNames; }; // Windows-specific. // DelayLoadContents creates all chunks for the delay-load DLL import table. class DelayLoadContents { public: - void add(DefinedImportData *Sym) { Imports.push_back(Sym); } - bool empty() { return Imports.empty(); } - void create(Defined *Helper); + void add(DefinedImportData *sym) { imports.push_back(sym); } + bool empty() { return imports.empty(); } + void create(Defined *helper); std::vector getChunks(); std::vector getDataChunks(); - ArrayRef getCodeChunks() { return Thunks; } + ArrayRef getCodeChunks() { return thunks; } - uint64_t getDirRVA() { return Dirs[0]->getRVA(); } + uint64_t getDirRVA() { return dirs[0]->getRVA(); } uint64_t getDirSize(); private: - Chunk *newThunkChunk(DefinedImportData *S, Chunk *Dir); + Chunk *newThunkChunk(DefinedImportData *s, Chunk *dir); - Defined *Helper; - std::vector Imports; - std::vector Dirs; - std::vector ModuleHandles; - std::vector Addresses; - std::vector Names; - std::vector HintNames; - std::vector Thunks; - std::vector DLLNames; + Defined *helper; + std::vector imports; + std::vector dirs; + std::vector moduleHandles; + std::vector addresses; + std::vector names; + std::vector hintNames; + std::vector thunks; + std::vector dllNames; }; // Windows-specific. @@ -67,11 +67,11 @@ class EdataContents { public: EdataContents(); - std::vector Chunks; + std::vector chunks; - uint64_t getRVA() { return Chunks[0]->getRVA(); } + uint64_t getRVA() { return chunks[0]->getRVA(); } uint64_t getSize() { - return Chunks.back()->getRVA() + Chunks.back()->getSize() - getRVA(); + return chunks.back()->getRVA() + chunks.back()->getSize() - getRVA(); } }; Index: lld/trunk/COFF/DLL.cpp =================================================================== --- lld/trunk/COFF/DLL.cpp +++ lld/trunk/COFF/DLL.cpp @@ -37,41 +37,41 @@ // A chunk for the import descriptor table. class HintNameChunk : public NonSectionChunk { public: - HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {} + HintNameChunk(StringRef n, uint16_t h) : name(n), hint(h) {} size_t getSize() const override { // Starts with 2 byte Hint field, followed by a null-terminated string, // ends with 0 or 1 byte padding. - return alignTo(Name.size() + 3, 2); + return alignTo(name.size() + 3, 2); } - void writeTo(uint8_t *Buf) const override { - memset(Buf, 0, getSize()); - write16le(Buf, Hint); - memcpy(Buf + 2, Name.data(), Name.size()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); + write16le(buf, hint); + memcpy(buf + 2, name.data(), name.size()); } private: - StringRef Name; - uint16_t Hint; + StringRef name; + uint16_t hint; }; // A chunk for the import descriptor table. class LookupChunk : public NonSectionChunk { public: - explicit LookupChunk(Chunk *C) : HintName(C) { - setAlignment(Config->Wordsize); + explicit LookupChunk(Chunk *c) : hintName(c) { + setAlignment(config->wordsize); } - size_t getSize() const override { return Config->Wordsize; } + size_t getSize() const override { return config->wordsize; } - void writeTo(uint8_t *Buf) const override { - if (Config->is64()) - write64le(Buf, HintName->getRVA()); + void writeTo(uint8_t *buf) const override { + if (config->is64()) + write64le(buf, hintName->getRVA()); else - write32le(Buf, HintName->getRVA()); + write32le(buf, hintName->getRVA()); } - Chunk *HintName; + Chunk *hintName; }; // A chunk for the import descriptor table. @@ -79,82 +79,82 @@ // See Microsoft PE/COFF spec 7.1. Import Header for details. class OrdinalOnlyChunk : public NonSectionChunk { public: - explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { - setAlignment(Config->Wordsize); + explicit OrdinalOnlyChunk(uint16_t v) : ordinal(v) { + setAlignment(config->wordsize); } - size_t getSize() const override { return Config->Wordsize; } + size_t getSize() const override { return config->wordsize; } - void writeTo(uint8_t *Buf) const override { + void writeTo(uint8_t *buf) const override { // An import-by-ordinal slot has MSB 1 to indicate that // this is import-by-ordinal (and not import-by-name). - if (Config->is64()) { - write64le(Buf, (1ULL << 63) | Ordinal); + if (config->is64()) { + write64le(buf, (1ULL << 63) | ordinal); } else { - write32le(Buf, (1ULL << 31) | Ordinal); + write32le(buf, (1ULL << 31) | ordinal); } } - uint16_t Ordinal; + uint16_t ordinal; }; // A chunk for the import descriptor table. class ImportDirectoryChunk : public NonSectionChunk { public: - explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {} + explicit ImportDirectoryChunk(Chunk *n) : dllName(n) {} size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } - void writeTo(uint8_t *Buf) const override { - memset(Buf, 0, getSize()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); - auto *E = (coff_import_directory_table_entry *)(Buf); - E->ImportLookupTableRVA = LookupTab->getRVA(); - E->NameRVA = DLLName->getRVA(); - E->ImportAddressTableRVA = AddressTab->getRVA(); + auto *e = (coff_import_directory_table_entry *)(buf); + e->ImportLookupTableRVA = lookupTab->getRVA(); + e->NameRVA = dllName->getRVA(); + e->ImportAddressTableRVA = addressTab->getRVA(); } - Chunk *DLLName; - Chunk *LookupTab; - Chunk *AddressTab; + Chunk *dllName; + Chunk *lookupTab; + Chunk *addressTab; }; // A chunk representing null terminator in the import table. // Contents of this chunk is always null bytes. class NullChunk : public NonSectionChunk { public: - explicit NullChunk(size_t N) : Size(N) { HasData = false; } - size_t getSize() const override { return Size; } + explicit NullChunk(size_t n) : size(n) { hasData = false; } + size_t getSize() const override { return size; } - void writeTo(uint8_t *Buf) const override { - memset(Buf, 0, Size); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, size); } private: - size_t Size; + size_t size; }; static std::vector> -binImports(const std::vector &Imports) { +binImports(const std::vector &imports) { // Group DLL-imported symbols by DLL name because that's how // symbols are layed out in the import descriptor table. - auto Less = [](const std::string &A, const std::string &B) { - return Config->DLLOrder[A] < Config->DLLOrder[B]; + auto less = [](const std::string &a, const std::string &b) { + return config->dllOrder[a] < config->dllOrder[b]; }; std::map, - bool(*)(const std::string &, const std::string &)> M(Less); - for (DefinedImportData *Sym : Imports) - M[Sym->getDLLName().lower()].push_back(Sym); + bool(*)(const std::string &, const std::string &)> m(less); + for (DefinedImportData *sym : imports) + m[sym->getDLLName().lower()].push_back(sym); - std::vector> V; - for (auto &KV : M) { + std::vector> v; + for (auto &kv : m) { // Sort symbols by name for each group. - std::vector &Syms = KV.second; - std::sort(Syms.begin(), Syms.end(), - [](DefinedImportData *A, DefinedImportData *B) { - return A->getName() < B->getName(); + std::vector &syms = kv.second; + std::sort(syms.begin(), syms.end(), + [](DefinedImportData *a, DefinedImportData *b) { + return a->getName() < b->getName(); }); - V.push_back(std::move(Syms)); + v.push_back(std::move(syms)); } - return V; + return v; } // Export table @@ -163,34 +163,34 @@ // A chunk for the delay import descriptor table etnry. class DelayDirectoryChunk : public NonSectionChunk { public: - explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {} + explicit DelayDirectoryChunk(Chunk *n) : dllName(n) {} size_t getSize() const override { return sizeof(delay_import_directory_table_entry); } - void writeTo(uint8_t *Buf) const override { - memset(Buf, 0, getSize()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); - auto *E = (delay_import_directory_table_entry *)(Buf); - E->Attributes = 1; - E->Name = DLLName->getRVA(); - E->ModuleHandle = ModuleHandle->getRVA(); - E->DelayImportAddressTable = AddressTab->getRVA(); - E->DelayImportNameTable = NameTab->getRVA(); + auto *e = (delay_import_directory_table_entry *)(buf); + e->Attributes = 1; + e->Name = dllName->getRVA(); + e->ModuleHandle = moduleHandle->getRVA(); + e->DelayImportAddressTable = addressTab->getRVA(); + e->DelayImportNameTable = nameTab->getRVA(); } - Chunk *DLLName; - Chunk *ModuleHandle; - Chunk *AddressTab; - Chunk *NameTab; + Chunk *dllName; + Chunk *moduleHandle; + Chunk *addressTab; + Chunk *nameTab; }; // Initial contents for delay-loaded functions. // This code calls __delayLoadHelper2 function to resolve a symbol // and then overwrites its jump table slot with the result // for subsequent function calls. -static const uint8_t ThunkX64[] = { +static const uint8_t thunkX64[] = { 0x51, // push rcx 0x52, // push rdx 0x41, 0x50, // push r8 @@ -215,7 +215,7 @@ 0xFF, 0xE0, // jmp rax }; -static const uint8_t ThunkX86[] = { +static const uint8_t thunkX86[] = { 0x51, // push ecx 0x52, // push edx 0x68, 0, 0, 0, 0, // push offset ___imp__ @@ -226,7 +226,7 @@ 0xFF, 0xE0, // jmp eax }; -static const uint8_t ThunkARM[] = { +static const uint8_t thunkARM[] = { 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_ 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_ 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr} @@ -242,7 +242,7 @@ 0x60, 0x47, // bx ip }; -static const uint8_t ThunkARM64[] = { +static const uint8_t thunkARM64[] = { 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_ 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_ 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]! @@ -275,117 +275,117 @@ // A chunk for the delay import thunk. class ThunkChunkX64 : public NonSectionChunk { public: - ThunkChunkX64(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + ThunkChunkX64(Defined *i, Chunk *d, Defined *h) + : imp(i), desc(d), helper(h) {} - size_t getSize() const override { return sizeof(ThunkX64); } + size_t getSize() const override { return sizeof(thunkX64); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf, ThunkX64, sizeof(ThunkX64)); - write32le(Buf + 36, Imp->getRVA() - RVA - 40); - write32le(Buf + 43, Desc->getRVA() - RVA - 47); - write32le(Buf + 48, Helper->getRVA() - RVA - 52); + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkX64, sizeof(thunkX64)); + write32le(buf + 36, imp->getRVA() - rva - 40); + write32le(buf + 43, desc->getRVA() - rva - 47); + write32le(buf + 48, helper->getRVA() - rva - 52); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + Defined *imp = nullptr; + Chunk *desc = nullptr; + Defined *helper = nullptr; }; class ThunkChunkX86 : public NonSectionChunk { public: - ThunkChunkX86(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + ThunkChunkX86(Defined *i, Chunk *d, Defined *h) + : imp(i), desc(d), helper(h) {} - size_t getSize() const override { return sizeof(ThunkX86); } + size_t getSize() const override { return sizeof(thunkX86); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf, ThunkX86, sizeof(ThunkX86)); - write32le(Buf + 3, Imp->getRVA() + Config->ImageBase); - write32le(Buf + 8, Desc->getRVA() + Config->ImageBase); - write32le(Buf + 13, Helper->getRVA() - RVA - 17); + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkX86, sizeof(thunkX86)); + write32le(buf + 3, imp->getRVA() + config->imageBase); + write32le(buf + 8, desc->getRVA() + config->imageBase); + write32le(buf + 13, helper->getRVA() - rva - 17); } - void getBaserels(std::vector *Res) override { - Res->emplace_back(RVA + 3); - Res->emplace_back(RVA + 8); + void getBaserels(std::vector *res) override { + res->emplace_back(rva + 3); + res->emplace_back(rva + 8); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + Defined *imp = nullptr; + Chunk *desc = nullptr; + Defined *helper = nullptr; }; class ThunkChunkARM : public NonSectionChunk { public: - ThunkChunkARM(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + ThunkChunkARM(Defined *i, Chunk *d, Defined *h) + : imp(i), desc(d), helper(h) {} - size_t getSize() const override { return sizeof(ThunkARM); } + size_t getSize() const override { return sizeof(thunkARM); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf, ThunkARM, sizeof(ThunkARM)); - applyMOV32T(Buf + 0, Imp->getRVA() + Config->ImageBase); - applyMOV32T(Buf + 22, Desc->getRVA() + Config->ImageBase); - applyBranch24T(Buf + 30, Helper->getRVA() - RVA - 34); + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkARM, sizeof(thunkARM)); + applyMOV32T(buf + 0, imp->getRVA() + config->imageBase); + applyMOV32T(buf + 22, desc->getRVA() + config->imageBase); + applyBranch24T(buf + 30, helper->getRVA() - rva - 34); } - void getBaserels(std::vector *Res) override { - Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T); - Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T); + void getBaserels(std::vector *res) override { + res->emplace_back(rva + 0, IMAGE_REL_BASED_ARM_MOV32T); + res->emplace_back(rva + 22, IMAGE_REL_BASED_ARM_MOV32T); } - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + Defined *imp = nullptr; + Chunk *desc = nullptr; + Defined *helper = nullptr; }; class ThunkChunkARM64 : public NonSectionChunk { public: - ThunkChunkARM64(Defined *I, Chunk *D, Defined *H) - : Imp(I), Desc(D), Helper(H) {} + ThunkChunkARM64(Defined *i, Chunk *d, Defined *h) + : imp(i), desc(d), helper(h) {} - size_t getSize() const override { return sizeof(ThunkARM64); } + size_t getSize() const override { return sizeof(thunkARM64); } - void writeTo(uint8_t *Buf) const override { - memcpy(Buf, ThunkARM64, sizeof(ThunkARM64)); - applyArm64Addr(Buf + 0, Imp->getRVA(), RVA + 0, 12); - applyArm64Imm(Buf + 4, Imp->getRVA() & 0xfff, 0); - applyArm64Addr(Buf + 52, Desc->getRVA(), RVA + 52, 12); - applyArm64Imm(Buf + 56, Desc->getRVA() & 0xfff, 0); - applyArm64Branch26(Buf + 60, Helper->getRVA() - RVA - 60); - } - - Defined *Imp = nullptr; - Chunk *Desc = nullptr; - Defined *Helper = nullptr; + void writeTo(uint8_t *buf) const override { + memcpy(buf, thunkARM64, sizeof(thunkARM64)); + applyArm64Addr(buf + 0, imp->getRVA(), rva + 0, 12); + applyArm64Imm(buf + 4, imp->getRVA() & 0xfff, 0); + applyArm64Addr(buf + 52, desc->getRVA(), rva + 52, 12); + applyArm64Imm(buf + 56, desc->getRVA() & 0xfff, 0); + applyArm64Branch26(buf + 60, helper->getRVA() - rva - 60); + } + + Defined *imp = nullptr; + Chunk *desc = nullptr; + Defined *helper = nullptr; }; // A chunk for the import descriptor table. class DelayAddressChunk : public NonSectionChunk { public: - explicit DelayAddressChunk(Chunk *C) : Thunk(C) { - setAlignment(Config->Wordsize); + explicit DelayAddressChunk(Chunk *c) : thunk(c) { + setAlignment(config->wordsize); } - size_t getSize() const override { return Config->Wordsize; } + size_t getSize() const override { return config->wordsize; } - void writeTo(uint8_t *Buf) const override { - if (Config->is64()) { - write64le(Buf, Thunk->getRVA() + Config->ImageBase); + void writeTo(uint8_t *buf) const override { + if (config->is64()) { + write64le(buf, thunk->getRVA() + config->imageBase); } else { - uint32_t Bit = 0; + uint32_t bit = 0; // Pointer to thumb code must have the LSB set, so adjust it. - if (Config->Machine == ARMNT) - Bit = 1; - write32le(Buf, (Thunk->getRVA() + Config->ImageBase) | Bit); + if (config->machine == ARMNT) + bit = 1; + write32le(buf, (thunk->getRVA() + config->imageBase) | bit); } } - void getBaserels(std::vector *Res) override { - Res->emplace_back(RVA); + void getBaserels(std::vector *res) override { + res->emplace_back(rva); } - Chunk *Thunk; + Chunk *thunk; }; // Export table @@ -394,248 +394,248 @@ // A chunk for the export descriptor table. class ExportDirectoryChunk : public NonSectionChunk { public: - ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O) - : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N), - OrdinalTab(O) {} + ExportDirectoryChunk(int i, int j, Chunk *d, Chunk *a, Chunk *n, Chunk *o) + : maxOrdinal(i), nameTabSize(j), dllName(d), addressTab(a), nameTab(n), + ordinalTab(o) {} size_t getSize() const override { return sizeof(export_directory_table_entry); } - void writeTo(uint8_t *Buf) const override { - memset(Buf, 0, getSize()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); - auto *E = (export_directory_table_entry *)(Buf); - E->NameRVA = DLLName->getRVA(); - E->OrdinalBase = 0; - E->AddressTableEntries = MaxOrdinal + 1; - E->NumberOfNamePointers = NameTabSize; - E->ExportAddressTableRVA = AddressTab->getRVA(); - E->NamePointerRVA = NameTab->getRVA(); - E->OrdinalTableRVA = OrdinalTab->getRVA(); - } - - uint16_t MaxOrdinal; - uint16_t NameTabSize; - Chunk *DLLName; - Chunk *AddressTab; - Chunk *NameTab; - Chunk *OrdinalTab; + auto *e = (export_directory_table_entry *)(buf); + e->NameRVA = dllName->getRVA(); + e->OrdinalBase = 0; + e->AddressTableEntries = maxOrdinal + 1; + e->NumberOfNamePointers = nameTabSize; + e->ExportAddressTableRVA = addressTab->getRVA(); + e->NamePointerRVA = nameTab->getRVA(); + e->OrdinalTableRVA = ordinalTab->getRVA(); + } + + uint16_t maxOrdinal; + uint16_t nameTabSize; + Chunk *dllName; + Chunk *addressTab; + Chunk *nameTab; + Chunk *ordinalTab; }; class AddressTableChunk : public NonSectionChunk { public: - explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {} - size_t getSize() const override { return Size * 4; } + explicit AddressTableChunk(size_t maxOrdinal) : size(maxOrdinal + 1) {} + size_t getSize() const override { return size * 4; } - void writeTo(uint8_t *Buf) const override { - memset(Buf, 0, getSize()); + void writeTo(uint8_t *buf) const override { + memset(buf, 0, getSize()); - for (const Export &E : Config->Exports) { - uint8_t *P = Buf + E.Ordinal * 4; - uint32_t Bit = 0; + for (const Export &e : config->exports) { + uint8_t *p = buf + e.ordinal * 4; + uint32_t bit = 0; // Pointer to thumb code must have the LSB set, so adjust it. - if (Config->Machine == ARMNT && !E.Data) - Bit = 1; - if (E.ForwardChunk) { - write32le(P, E.ForwardChunk->getRVA() | Bit); + if (config->machine == ARMNT && !e.data) + bit = 1; + if (e.forwardChunk) { + write32le(p, e.forwardChunk->getRVA() | bit); } else { - write32le(P, cast(E.Sym)->getRVA() | Bit); + write32le(p, cast(e.sym)->getRVA() | bit); } } } private: - size_t Size; + size_t size; }; class NamePointersChunk : public NonSectionChunk { public: - explicit NamePointersChunk(std::vector &V) : Chunks(V) {} - size_t getSize() const override { return Chunks.size() * 4; } + explicit NamePointersChunk(std::vector &v) : chunks(v) {} + size_t getSize() const override { return chunks.size() * 4; } - void writeTo(uint8_t *Buf) const override { - for (Chunk *C : Chunks) { - write32le(Buf, C->getRVA()); - Buf += 4; + void writeTo(uint8_t *buf) const override { + for (Chunk *c : chunks) { + write32le(buf, c->getRVA()); + buf += 4; } } private: - std::vector Chunks; + std::vector chunks; }; class ExportOrdinalChunk : public NonSectionChunk { public: - explicit ExportOrdinalChunk(size_t I) : Size(I) {} - size_t getSize() const override { return Size * 2; } + explicit ExportOrdinalChunk(size_t i) : size(i) {} + size_t getSize() const override { return size * 2; } - void writeTo(uint8_t *Buf) const override { - for (Export &E : Config->Exports) { - if (E.Noname) + void writeTo(uint8_t *buf) const override { + for (Export &e : config->exports) { + if (e.noname) continue; - write16le(Buf, E.Ordinal); - Buf += 2; + write16le(buf, e.ordinal); + buf += 2; } } private: - size_t Size; + size_t size; }; } // anonymous namespace void IdataContents::create() { - std::vector> V = binImports(Imports); + std::vector> v = binImports(imports); // Create .idata contents for each DLL. - for (std::vector &Syms : V) { + for (std::vector &syms : v) { // Create lookup and address tables. If they have external names, // we need to create HintName chunks to store the names. // If they don't (if they are import-by-ordinals), we store only // ordinal values to the table. - size_t Base = Lookups.size(); - for (DefinedImportData *S : Syms) { - uint16_t Ord = S->getOrdinal(); - if (S->getExternalName().empty()) { - Lookups.push_back(make(Ord)); - Addresses.push_back(make(Ord)); + size_t base = lookups.size(); + for (DefinedImportData *s : syms) { + uint16_t ord = s->getOrdinal(); + if (s->getExternalName().empty()) { + lookups.push_back(make(ord)); + addresses.push_back(make(ord)); continue; } - auto *C = make(S->getExternalName(), Ord); - Lookups.push_back(make(C)); - Addresses.push_back(make(C)); - Hints.push_back(C); + auto *c = make(s->getExternalName(), ord); + lookups.push_back(make(c)); + addresses.push_back(make(c)); + hints.push_back(c); } // Terminate with null values. - Lookups.push_back(make(Config->Wordsize)); - Addresses.push_back(make(Config->Wordsize)); + lookups.push_back(make(config->wordsize)); + addresses.push_back(make(config->wordsize)); - for (int I = 0, E = Syms.size(); I < E; ++I) - Syms[I]->setLocation(Addresses[Base + I]); + for (int i = 0, e = syms.size(); i < e; ++i) + syms[i]->setLocation(addresses[base + i]); // Create the import table header. - DLLNames.push_back(make(Syms[0]->getDLLName())); - auto *Dir = make(DLLNames.back()); - Dir->LookupTab = Lookups[Base]; - Dir->AddressTab = Addresses[Base]; - Dirs.push_back(Dir); + dllNames.push_back(make(syms[0]->getDLLName())); + auto *dir = make(dllNames.back()); + dir->lookupTab = lookups[base]; + dir->addressTab = addresses[base]; + dirs.push_back(dir); } // Add null terminator. - Dirs.push_back(make(sizeof(ImportDirectoryTableEntry))); + dirs.push_back(make(sizeof(ImportDirectoryTableEntry))); } std::vector DelayLoadContents::getChunks() { - std::vector V; - V.insert(V.end(), Dirs.begin(), Dirs.end()); - V.insert(V.end(), Names.begin(), Names.end()); - V.insert(V.end(), HintNames.begin(), HintNames.end()); - V.insert(V.end(), DLLNames.begin(), DLLNames.end()); - return V; + std::vector v; + v.insert(v.end(), dirs.begin(), dirs.end()); + v.insert(v.end(), names.begin(), names.end()); + v.insert(v.end(), hintNames.begin(), hintNames.end()); + v.insert(v.end(), dllNames.begin(), dllNames.end()); + return v; } std::vector DelayLoadContents::getDataChunks() { - std::vector V; - V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end()); - V.insert(V.end(), Addresses.begin(), Addresses.end()); - return V; + std::vector v; + v.insert(v.end(), moduleHandles.begin(), moduleHandles.end()); + v.insert(v.end(), addresses.begin(), addresses.end()); + return v; } uint64_t DelayLoadContents::getDirSize() { - return Dirs.size() * sizeof(delay_import_directory_table_entry); + return dirs.size() * sizeof(delay_import_directory_table_entry); } -void DelayLoadContents::create(Defined *H) { - Helper = H; - std::vector> V = binImports(Imports); +void DelayLoadContents::create(Defined *h) { + helper = h; + std::vector> v = binImports(imports); // Create .didat contents for each DLL. - for (std::vector &Syms : V) { + for (std::vector &syms : v) { // Create the delay import table header. - DLLNames.push_back(make(Syms[0]->getDLLName())); - auto *Dir = make(DLLNames.back()); + dllNames.push_back(make(syms[0]->getDLLName())); + auto *dir = make(dllNames.back()); - size_t Base = Addresses.size(); - for (DefinedImportData *S : Syms) { - Chunk *T = newThunkChunk(S, Dir); - auto *A = make(T); - Addresses.push_back(A); - Thunks.push_back(T); - StringRef ExtName = S->getExternalName(); - if (ExtName.empty()) { - Names.push_back(make(S->getOrdinal())); + size_t base = addresses.size(); + for (DefinedImportData *s : syms) { + Chunk *t = newThunkChunk(s, dir); + auto *a = make(t); + addresses.push_back(a); + thunks.push_back(t); + StringRef extName = s->getExternalName(); + if (extName.empty()) { + names.push_back(make(s->getOrdinal())); } else { - auto *C = make(ExtName, 0); - Names.push_back(make(C)); - HintNames.push_back(C); + auto *c = make(extName, 0); + names.push_back(make(c)); + hintNames.push_back(c); } } // Terminate with null values. - Addresses.push_back(make(8)); - Names.push_back(make(8)); + addresses.push_back(make(8)); + names.push_back(make(8)); - for (int I = 0, E = Syms.size(); I < E; ++I) - Syms[I]->setLocation(Addresses[Base + I]); - auto *MH = make(8); - MH->setAlignment(8); - ModuleHandles.push_back(MH); + for (int i = 0, e = syms.size(); i < e; ++i) + syms[i]->setLocation(addresses[base + i]); + auto *mh = make(8); + mh->setAlignment(8); + moduleHandles.push_back(mh); // Fill the delay import table header fields. - Dir->ModuleHandle = MH; - Dir->AddressTab = Addresses[Base]; - Dir->NameTab = Names[Base]; - Dirs.push_back(Dir); + dir->moduleHandle = mh; + dir->addressTab = addresses[base]; + dir->nameTab = names[base]; + dirs.push_back(dir); } // Add null terminator. - Dirs.push_back(make(sizeof(delay_import_directory_table_entry))); + dirs.push_back(make(sizeof(delay_import_directory_table_entry))); } -Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { - switch (Config->Machine) { +Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *s, Chunk *dir) { + switch (config->machine) { case AMD64: - return make(S, Dir, Helper); + return make(s, dir, helper); case I386: - return make(S, Dir, Helper); + return make(s, dir, helper); case ARMNT: - return make(S, Dir, Helper); + return make(s, dir, helper); case ARM64: - return make(S, Dir, Helper); + return make(s, dir, helper); default: llvm_unreachable("unsupported machine type"); } } EdataContents::EdataContents() { - uint16_t MaxOrdinal = 0; - for (Export &E : Config->Exports) - MaxOrdinal = std::max(MaxOrdinal, E.Ordinal); - - auto *DLLName = make(sys::path::filename(Config->OutputFile)); - auto *AddressTab = make(MaxOrdinal); - std::vector Names; - for (Export &E : Config->Exports) - if (!E.Noname) - Names.push_back(make(E.ExportName)); - - std::vector Forwards; - for (Export &E : Config->Exports) { - if (E.ForwardTo.empty()) + uint16_t maxOrdinal = 0; + for (Export &e : config->exports) + maxOrdinal = std::max(maxOrdinal, e.ordinal); + + auto *dllName = make(sys::path::filename(config->outputFile)); + auto *addressTab = make(maxOrdinal); + std::vector names; + for (Export &e : config->exports) + if (!e.noname) + names.push_back(make(e.exportName)); + + std::vector forwards; + for (Export &e : config->exports) { + if (e.forwardTo.empty()) continue; - E.ForwardChunk = make(E.ForwardTo); - Forwards.push_back(E.ForwardChunk); + e.forwardChunk = make(e.forwardTo); + forwards.push_back(e.forwardChunk); } - auto *NameTab = make(Names); - auto *OrdinalTab = make(Names.size()); - auto *Dir = make(MaxOrdinal, Names.size(), DLLName, - AddressTab, NameTab, OrdinalTab); - Chunks.push_back(Dir); - Chunks.push_back(DLLName); - Chunks.push_back(AddressTab); - Chunks.push_back(NameTab); - Chunks.push_back(OrdinalTab); - Chunks.insert(Chunks.end(), Names.begin(), Names.end()); - Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end()); + auto *nameTab = make(names); + auto *ordinalTab = make(names.size()); + auto *dir = make(maxOrdinal, names.size(), dllName, + addressTab, nameTab, ordinalTab); + chunks.push_back(dir); + chunks.push_back(dllName); + chunks.push_back(addressTab); + chunks.push_back(nameTab); + chunks.push_back(ordinalTab); + chunks.insert(chunks.end(), names.begin(), names.end()); + chunks.insert(chunks.end(), forwards.begin(), forwards.end()); } } // namespace coff Index: lld/trunk/COFF/DebugTypes.h =================================================================== --- lld/trunk/COFF/DebugTypes.h +++ lld/trunk/COFF/DebugTypes.h @@ -31,30 +31,30 @@ public: enum TpiKind { Regular, PCH, UsingPCH, PDB, UsingPDB }; - TpiSource(TpiKind K, const ObjFile *F); + TpiSource(TpiKind k, const ObjFile *f); virtual ~TpiSource() {} - const TpiKind Kind; - const ObjFile *File; + const TpiKind kind; + const ObjFile *file; }; -TpiSource *makeTpiSource(const ObjFile *F); -TpiSource *makeUseTypeServerSource(const ObjFile *F, - const llvm::codeview::TypeServer2Record *TS); -TpiSource *makePrecompSource(const ObjFile *F); -TpiSource *makeUsePrecompSource(const ObjFile *F, - const llvm::codeview::PrecompRecord *Precomp); +TpiSource *makeTpiSource(const ObjFile *f); +TpiSource *makeUseTypeServerSource(const ObjFile *f, + const llvm::codeview::TypeServer2Record *ts); +TpiSource *makePrecompSource(const ObjFile *f); +TpiSource *makeUsePrecompSource(const ObjFile *f, + const llvm::codeview::PrecompRecord *precomp); -void loadTypeServerSource(llvm::MemoryBufferRef M); +void loadTypeServerSource(llvm::MemoryBufferRef m); // Temporary interface to get the dependency -template const T &retrieveDependencyInfo(const TpiSource *Source); +template const T &retrieveDependencyInfo(const TpiSource *source); // Temporary interface until we move PDBLinker::maybeMergeTypeServerPDB here llvm::Expected -findTypeServerSource(const ObjFile *F); +findTypeServerSource(const ObjFile *f); } // namespace coff } // namespace lld #endif \ No newline at end of file Index: lld/trunk/COFF/DebugTypes.cpp =================================================================== --- lld/trunk/COFF/DebugTypes.cpp +++ lld/trunk/COFF/DebugTypes.cpp @@ -32,40 +32,40 @@ // before any dependent OBJ. class TypeServerSource : public TpiSource { public: - explicit TypeServerSource(MemoryBufferRef M, llvm::pdb::NativeSession *S) - : TpiSource(PDB, nullptr), Session(S), MB(M) {} + explicit TypeServerSource(MemoryBufferRef m, llvm::pdb::NativeSession *s) + : TpiSource(PDB, nullptr), session(s), mb(m) {} // Queue a PDB type server for loading in the COFF Driver - static void enqueue(const ObjFile *DependentFile, - const TypeServer2Record &TS); + static void enqueue(const ObjFile *dependentFile, + const TypeServer2Record &ts); // Create an instance - static Expected getInstance(MemoryBufferRef M); + static Expected getInstance(MemoryBufferRef m); // Fetch the PDB instance loaded for a corresponding dependent OBJ. static Expected - findFromFile(const ObjFile *DependentFile); + findFromFile(const ObjFile *dependentFile); static std::map> - Instances; + instances; // The interface to the PDB (if it was opened successfully) - std::unique_ptr Session; + std::unique_ptr session; private: - MemoryBufferRef MB; + MemoryBufferRef mb; }; // This class represents the debug type stream of an OBJ file that depends on a // PDB type server (see TypeServerSource). class UseTypeServerSource : public TpiSource { public: - UseTypeServerSource(const ObjFile *F, const TypeServer2Record *TS) - : TpiSource(UsingPDB, F), TypeServerDependency(*TS) {} + UseTypeServerSource(const ObjFile *f, const TypeServer2Record *ts) + : TpiSource(UsingPDB, f), typeServerDependency(*ts) {} // Information about the PDB type server dependency, that needs to be loaded // in before merging this OBJ. - TypeServer2Record TypeServerDependency; + TypeServer2Record typeServerDependency; }; // This class represents the debug type stream of a Microsoft precompiled @@ -74,76 +74,76 @@ // such files, clang does not. class PrecompSource : public TpiSource { public: - PrecompSource(const ObjFile *F) : TpiSource(PCH, F) {} + PrecompSource(const ObjFile *f) : TpiSource(PCH, f) {} }; // This class represents the debug type stream of an OBJ file that depends on a // Microsoft precompiled headers OBJ (see PrecompSource). class UsePrecompSource : public TpiSource { public: - UsePrecompSource(const ObjFile *F, const PrecompRecord *Precomp) - : TpiSource(UsingPCH, F), PrecompDependency(*Precomp) {} + UsePrecompSource(const ObjFile *f, const PrecompRecord *precomp) + : TpiSource(UsingPCH, f), precompDependency(*precomp) {} // Information about the Precomp OBJ dependency, that needs to be loaded in // before merging this OBJ. - PrecompRecord PrecompDependency; + PrecompRecord precompDependency; }; } // namespace static std::vector> GC; -TpiSource::TpiSource(TpiKind K, const ObjFile *F) : Kind(K), File(F) { +TpiSource::TpiSource(TpiKind k, const ObjFile *f) : kind(k), file(f) { GC.push_back(std::unique_ptr(this)); } -TpiSource *lld::coff::makeTpiSource(const ObjFile *F) { - return new TpiSource(TpiSource::Regular, F); +TpiSource *lld::coff::makeTpiSource(const ObjFile *f) { + return new TpiSource(TpiSource::Regular, f); } -TpiSource *lld::coff::makeUseTypeServerSource(const ObjFile *F, - const TypeServer2Record *TS) { - TypeServerSource::enqueue(F, *TS); - return new UseTypeServerSource(F, TS); +TpiSource *lld::coff::makeUseTypeServerSource(const ObjFile *f, + const TypeServer2Record *ts) { + TypeServerSource::enqueue(f, *ts); + return new UseTypeServerSource(f, ts); } -TpiSource *lld::coff::makePrecompSource(const ObjFile *F) { - return new PrecompSource(F); +TpiSource *lld::coff::makePrecompSource(const ObjFile *f) { + return new PrecompSource(f); } -TpiSource *lld::coff::makeUsePrecompSource(const ObjFile *F, - const PrecompRecord *Precomp) { - return new UsePrecompSource(F, Precomp); +TpiSource *lld::coff::makeUsePrecompSource(const ObjFile *f, + const PrecompRecord *precomp) { + return new UsePrecompSource(f, precomp); } namespace lld { namespace coff { template <> -const PrecompRecord &retrieveDependencyInfo(const TpiSource *Source) { - assert(Source->Kind == TpiSource::UsingPCH); - return ((const UsePrecompSource *)Source)->PrecompDependency; +const PrecompRecord &retrieveDependencyInfo(const TpiSource *source) { + assert(source->kind == TpiSource::UsingPCH); + return ((const UsePrecompSource *)source)->precompDependency; } template <> -const TypeServer2Record &retrieveDependencyInfo(const TpiSource *Source) { - assert(Source->Kind == TpiSource::UsingPDB); - return ((const UseTypeServerSource *)Source)->TypeServerDependency; +const TypeServer2Record &retrieveDependencyInfo(const TpiSource *source) { + assert(source->kind == TpiSource::UsingPDB); + return ((const UseTypeServerSource *)source)->typeServerDependency; } } // namespace coff } // namespace lld std::map> - TypeServerSource::Instances; + TypeServerSource::instances; // Make a PDB path assuming the PDB is in the same folder as the OBJ -static std::string getPdbBaseName(const ObjFile *File, StringRef TSPath) { - StringRef LocalPath = - !File->ParentName.empty() ? File->ParentName : File->getName(); - SmallString<128> Path = sys::path::parent_path(LocalPath); +static std::string getPdbBaseName(const ObjFile *file, StringRef tSPath) { + StringRef localPath = + !file->parentName.empty() ? file->parentName : file->getName(); + SmallString<128> path = sys::path::parent_path(localPath); // Currently, type server PDBs are only created by MSVC cl, which only runs // on Windows, so we can assume type server paths are Windows style. - sys::path::append(Path, sys::path::filename(TSPath, sys::path::Style::windows)); - return Path.str(); + sys::path::append(path, sys::path::filename(tSPath, sys::path::Style::windows)); + return path.str(); } // The casing of the PDB path stamped in the OBJ can differ from the actual path @@ -158,80 +158,80 @@ } // If existing, return the actual PDB path on disk. -static Optional findPdbPath(StringRef PDBPath, - const ObjFile *DependentFile) { +static Optional findPdbPath(StringRef pdbPath, + const ObjFile *dependentFile) { // Ensure the file exists before anything else. In some cases, if the path // points to a removable device, Driver::enqueuePath() would fail with an // error (EAGAIN, "resource unavailable try again") which we want to skip // silently. - if (llvm::sys::fs::exists(PDBPath)) - return normalizePdbPath(PDBPath); - std::string Ret = getPdbBaseName(DependentFile, PDBPath); - if (llvm::sys::fs::exists(Ret)) - return normalizePdbPath(Ret); + if (llvm::sys::fs::exists(pdbPath)) + return normalizePdbPath(pdbPath); + std::string ret = getPdbBaseName(dependentFile, pdbPath); + if (llvm::sys::fs::exists(ret)) + return normalizePdbPath(ret); return None; } // Fetch the PDB instance that was already loaded by the COFF Driver. Expected -TypeServerSource::findFromFile(const ObjFile *DependentFile) { - const TypeServer2Record &TS = - retrieveDependencyInfo(DependentFile->DebugTypesObj); - - Optional P = findPdbPath(TS.Name, DependentFile); - if (!P) - return createFileError(TS.Name, errorCodeToError(std::error_code( +TypeServerSource::findFromFile(const ObjFile *dependentFile) { + const TypeServer2Record &ts = + retrieveDependencyInfo(dependentFile->debugTypesObj); + + Optional p = findPdbPath(ts.Name, dependentFile); + if (!p) + return createFileError(ts.Name, errorCodeToError(std::error_code( ENOENT, std::generic_category()))); - auto It = TypeServerSource::Instances.find(*P); + auto it = TypeServerSource::instances.find(*p); // The PDB file exists on disk, at this point we expect it to have been // inserted in the map by TypeServerSource::loadPDB() - assert(It != TypeServerSource::Instances.end()); + assert(it != TypeServerSource::instances.end()); - std::pair &PDB = It->second; + std::pair &pdb = it->second; - if (!PDB.second) + if (!pdb.second) return createFileError( - *P, createStringError(inconvertibleErrorCode(), PDB.first.c_str())); + *p, createStringError(inconvertibleErrorCode(), pdb.first.c_str())); - pdb::PDBFile &PDBFile = (PDB.second)->Session->getPDBFile(); - pdb::InfoStream &Info = cantFail(PDBFile.getPDBInfoStream()); + pdb::PDBFile &pdbFile = (pdb.second)->session->getPDBFile(); + pdb::InfoStream &info = cantFail(pdbFile.getPDBInfoStream()); // Just because a file with a matching name was found doesn't mean it can be // used. The GUID must match between the PDB header and the OBJ // TypeServer2 record. The 'Age' is used by MSVC incremental compilation. - if (Info.getGuid() != TS.getGuid()) + if (info.getGuid() != ts.getGuid()) return createFileError( - TS.Name, + ts.Name, make_error(pdb::pdb_error_code::signature_out_of_date)); - return PDB.second; + return pdb.second; } // FIXME: Temporary interface until PDBLinker::maybeMergeTypeServerPDB() is // moved here. Expected -lld::coff::findTypeServerSource(const ObjFile *F) { - Expected TS = TypeServerSource::findFromFile(F); - if (!TS) - return TS.takeError(); - return TS.get()->Session.get(); +lld::coff::findTypeServerSource(const ObjFile *f) { + Expected ts = TypeServerSource::findFromFile(f); + if (!ts) + return ts.takeError(); + return ts.get()->session.get(); } // Queue a PDB type server for loading in the COFF Driver -void TypeServerSource::enqueue(const ObjFile *DependentFile, - const TypeServer2Record &TS) { +void TypeServerSource::enqueue(const ObjFile *dependentFile, + const TypeServer2Record &ts) { // Start by finding where the PDB is located (either the record path or next // to the OBJ file) - Optional P = findPdbPath(TS.Name, DependentFile); - if (!P) + Optional p = findPdbPath(ts.Name, dependentFile); + if (!p) return; - auto It = TypeServerSource::Instances.emplace( - *P, std::pair{}); - if (!It.second) + auto it = TypeServerSource::instances.emplace( + *p, std::pair{}); + if (!it.second) return; // another OBJ already scheduled this PDB for load - Driver->enqueuePath(*P, false); + driver->enqueuePath(*p, false); } // Create an instance of TypeServerSource or an error string if the PDB couldn't @@ -239,30 +239,30 @@ // will be merged in. NOTE - a PDB load failure is not a link error: some // debug info will simply be missing from the final PDB - that is the default // accepted behavior. -void lld::coff::loadTypeServerSource(llvm::MemoryBufferRef M) { - std::string Path = normalizePdbPath(M.getBufferIdentifier()); +void lld::coff::loadTypeServerSource(llvm::MemoryBufferRef m) { + std::string path = normalizePdbPath(m.getBufferIdentifier()); - Expected TS = TypeServerSource::getInstance(M); - if (!TS) - TypeServerSource::Instances[Path] = {toString(TS.takeError()), nullptr}; + Expected ts = TypeServerSource::getInstance(m); + if (!ts) + TypeServerSource::instances[path] = {toString(ts.takeError()), nullptr}; else - TypeServerSource::Instances[Path] = {{}, *TS}; + TypeServerSource::instances[path] = {{}, *ts}; } -Expected TypeServerSource::getInstance(MemoryBufferRef M) { - std::unique_ptr ISession; - Error Err = pdb::NativeSession::createFromPdb( - MemoryBuffer::getMemBuffer(M, false), ISession); - if (Err) - return std::move(Err); +Expected TypeServerSource::getInstance(MemoryBufferRef m) { + std::unique_ptr iSession; + Error err = pdb::NativeSession::createFromPdb( + MemoryBuffer::getMemBuffer(m, false), iSession); + if (err) + return std::move(err); - std::unique_ptr Session( - static_cast(ISession.release())); + std::unique_ptr session( + static_cast(iSession.release())); - pdb::PDBFile &PDBFile = Session->getPDBFile(); - Expected Info = PDBFile.getPDBInfoStream(); + pdb::PDBFile &pdbFile = session->getPDBFile(); + Expected info = pdbFile.getPDBInfoStream(); // All PDB Files should have an Info stream. - if (!Info) - return Info.takeError(); - return new TypeServerSource(M, Session.release()); + if (!info) + return info.takeError(); + return new TypeServerSource(m, session.release()); } Index: lld/trunk/COFF/Driver.h =================================================================== --- lld/trunk/COFF/Driver.h +++ lld/trunk/COFF/Driver.h @@ -30,7 +30,7 @@ namespace coff { class LinkerDriver; -extern LinkerDriver *Driver; +extern LinkerDriver *driver; using llvm::COFF::MachineTypes; using llvm::COFF::WindowsSubsystem; @@ -44,71 +44,71 @@ class ArgParser { public: // Concatenate LINK environment variable and given arguments and parse them. - llvm::opt::InputArgList parseLINK(std::vector Args); + llvm::opt::InputArgList parseLINK(std::vector args); // Tokenizes a given string and then parses as command line options. - llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } + llvm::opt::InputArgList parse(StringRef s) { return parse(tokenize(s)); } // Tokenizes a given string and then parses as command line options in // .drectve section. /EXPORT options are returned in second element // to be processed in fastpath. std::pair> - parseDirectives(StringRef S); + parseDirectives(StringRef s); private: // Parses command line options. - llvm::opt::InputArgList parse(llvm::ArrayRef Args); + llvm::opt::InputArgList parse(llvm::ArrayRef args); - std::vector tokenize(StringRef S); + std::vector tokenize(StringRef s); - COFFOptTable Table; + COFFOptTable table; }; class LinkerDriver { public: - void link(llvm::ArrayRef Args); + void link(llvm::ArrayRef args); // Used by the resolver to parse .drectve section contents. - void parseDirectives(InputFile *File); + void parseDirectives(InputFile *file); // Used by ArchiveFile to enqueue members. - void enqueueArchiveMember(const Archive::Child &C, StringRef SymName, - StringRef ParentName); + void enqueueArchiveMember(const Archive::Child &c, StringRef symName, + StringRef parentName); - MemoryBufferRef takeBuffer(std::unique_ptr MB); + MemoryBufferRef takeBuffer(std::unique_ptr mb); - void enqueuePath(StringRef Path, bool WholeArchive); + void enqueuePath(StringRef path, bool wholeArchive); private: - std::unique_ptr Tar; // for /linkrepro + std::unique_ptr tar; // for /linkrepro // Opens a file. Path has to be resolved already. - MemoryBufferRef openFile(StringRef Path); + MemoryBufferRef openFile(StringRef path); // Searches a file from search paths. - Optional findFile(StringRef Filename); - Optional findLib(StringRef Filename); - StringRef doFindFile(StringRef Filename); - StringRef doFindLib(StringRef Filename); - StringRef doFindLibMinGW(StringRef Filename); + Optional findFile(StringRef filename); + Optional findLib(StringRef filename); + StringRef doFindFile(StringRef filename); + StringRef doFindLib(StringRef filename); + StringRef doFindLibMinGW(StringRef filename); // Parses LIB environment which contains a list of search paths. void addLibSearchPaths(); // Library search path. The first element is always "" (current directory). - std::vector SearchPaths; + std::vector searchPaths; - void maybeExportMinGWSymbols(const llvm::opt::InputArgList &Args); + void maybeExportMinGWSymbols(const llvm::opt::InputArgList &args); // We don't want to add the same file more than once. // Files are uniquified by their filesystem and file number. - std::set VisitedFiles; + std::set visitedFiles; - std::set VisitedLibs; + std::set visitedLibs; - Symbol *addUndefined(StringRef Sym); + Symbol *addUndefined(StringRef sym); - StringRef mangleMaybe(Symbol *S); + StringRef mangleMaybe(Symbol *s); // Windows specific -- "main" is not the only main function in Windows. // You can choose one from these four -- {w,}{WinMain,main}. @@ -120,36 +120,36 @@ StringRef findDefaultEntry(); WindowsSubsystem inferSubsystem(); - void addBuffer(std::unique_ptr MB, bool WholeArchive); - void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName, - StringRef ParentName, uint64_t OffsetInArchive); + void addBuffer(std::unique_ptr mb, bool wholeArchive); + void addArchiveBuffer(MemoryBufferRef mbref, StringRef symName, + StringRef parentName, uint64_t offsetInArchive); - void enqueueTask(std::function Task); + void enqueueTask(std::function task); bool run(); - std::list> TaskQueue; - std::vector FilePaths; - std::vector Resources; + std::list> taskQueue; + std::vector filePaths; + std::vector resources; - llvm::StringSet<> DirectivesExports; + llvm::StringSet<> directivesExports; }; // Functions below this line are defined in DriverUtils.cpp. -void printHelp(const char *Argv0); +void printHelp(const char *argv0); // Parses a string in the form of "[,]". -void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr); +void parseNumbers(StringRef arg, uint64_t *addr, uint64_t *size = nullptr); -void parseGuard(StringRef Arg); +void parseGuard(StringRef arg); // Parses a string in the form of "[.]". // Minor's default value is 0. -void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor); +void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor); // Parses a string in the form of "[,[.]]". -void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, - uint32_t *Minor); +void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major, + uint32_t *minor); void parseAlternateName(StringRef); void parseMerge(StringRef); @@ -157,23 +157,23 @@ void parseAligncomm(StringRef); // Parses a string in the form of "[:]" -void parseFunctionPadMin(llvm::opt::Arg *A, llvm::COFF::MachineTypes Machine); +void parseFunctionPadMin(llvm::opt::Arg *a, llvm::COFF::MachineTypes machine); // Parses a string in the form of "EMBED[,=]|NO". -void parseManifest(StringRef Arg); +void parseManifest(StringRef arg); // Parses a string in the form of "level=|uiAccess=" -void parseManifestUAC(StringRef Arg); +void parseManifestUAC(StringRef arg); // Parses a string in the form of "cd|net[,(cd|net)]*" -void parseSwaprun(StringRef Arg); +void parseSwaprun(StringRef arg); // Create a resource file containing a manifest XML. std::unique_ptr createManifestRes(); void createSideBySideManifest(); // Used for dllexported symbols. -Export parseExport(StringRef Arg); +Export parseExport(StringRef arg); void fixupExports(); void assignExportOrdinals(); @@ -181,12 +181,12 @@ // if value matches previous values for the key. // This feature used in the directive section to reject // incompatible objects. -void checkFailIfMismatch(StringRef Arg, InputFile *Source); +void checkFailIfMismatch(StringRef arg, InputFile *source); // Convert Windows resource files (.res files) to a .obj file. -MemoryBufferRef convertResToCOFF(ArrayRef MBs); +MemoryBufferRef convertResToCOFF(ArrayRef mbs); -void runMSVCLinker(std::string Rsp, ArrayRef Objects); +void runMSVCLinker(std::string rsp, ArrayRef objects); // Create enum with OPT_xxx values for each option in Options.td enum { Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -54,54 +54,54 @@ namespace lld { namespace coff { -static Timer InputFileTimer("Input File Reading", Timer::root()); +static Timer inputFileTimer("Input File Reading", Timer::root()); -Configuration *Config; -LinkerDriver *Driver; +Configuration *config; +LinkerDriver *driver; -bool link(ArrayRef Args, bool CanExitEarly, raw_ostream &Diag) { - errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); - errorHandler().ErrorOS = &Diag; - errorHandler().ColorDiagnostics = Diag.has_colors(); - errorHandler().ErrorLimitExceededMsg = +bool link(ArrayRef args, bool canExitEarly, raw_ostream &diag) { + errorHandler().logName = args::getFilenameWithoutExe(args[0]); + errorHandler().errorOS = &diag; + errorHandler().colorDiagnostics = diag.has_colors(); + errorHandler().errorLimitExceededMsg = "too many errors emitted, stopping now" " (use /errorlimit:0 to see all errors)"; - errorHandler().ExitEarly = CanExitEarly; - Config = make(); + errorHandler().exitEarly = canExitEarly; + config = make(); - Symtab = make(); + symtab = make(); - Driver = make(); - Driver->link(Args); + driver = make(); + driver->link(args); // Call exit() if we can to avoid calling destructors. - if (CanExitEarly) + if (canExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); - ObjFile::Instances.clear(); - ImportFile::Instances.clear(); - BitcodeFile::Instances.clear(); - memset(MergeChunk::Instances, 0, sizeof(MergeChunk::Instances)); + ObjFile::instances.clear(); + ImportFile::instances.clear(); + BitcodeFile::instances.clear(); + memset(MergeChunk::instances, 0, sizeof(MergeChunk::instances)); return !errorCount(); } // Drop directory components and replace extension with ".exe" or ".dll". -static std::string getOutputPath(StringRef Path) { - auto P = Path.find_last_of("\\/"); - StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1); - const char* E = Config->DLL ? ".dll" : ".exe"; - return (S.substr(0, S.rfind('.')) + E).str(); +static std::string getOutputPath(StringRef path) { + auto p = path.find_last_of("\\/"); + StringRef s = (p == StringRef::npos) ? path : path.substr(p + 1); + const char* e = config->dll ? ".dll" : ".exe"; + return (s.substr(0, s.rfind('.')) + e).str(); } // Returns true if S matches /crtend.?\.o$/. -static bool isCrtend(StringRef S) { - if (!S.endswith(".o")) +static bool isCrtend(StringRef s) { + if (!s.endswith(".o")) return false; - S = S.drop_back(2); - if (S.endswith("crtend")) + s = s.drop_back(2); + if (s.endswith("crtend")) return true; - return !S.empty() && S.drop_back().endswith("crtend"); + return !s.empty() && s.drop_back().endswith("crtend"); } // ErrorOr is not default constructible, so it cannot be used as the type @@ -113,257 +113,257 @@ // Create a std::future that opens and maps a file using the best strategy for // the host platform. -static std::future createFutureForFile(std::string Path) { +static std::future createFutureForFile(std::string path) { #if _WIN32 // On Windows, file I/O is relatively slow so it is best to do this // asynchronously. auto Strategy = std::launch::async; #else - auto Strategy = std::launch::deferred; + auto strategy = std::launch::deferred; #endif - return std::async(Strategy, [=]() { - auto MBOrErr = MemoryBuffer::getFile(Path, + return std::async(strategy, [=]() { + auto mbOrErr = MemoryBuffer::getFile(path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false); - if (!MBOrErr) - return MBErrPair{nullptr, MBOrErr.getError()}; - return MBErrPair{std::move(*MBOrErr), std::error_code()}; + if (!mbOrErr) + return MBErrPair{nullptr, mbOrErr.getError()}; + return MBErrPair{std::move(*mbOrErr), std::error_code()}; }); } // Symbol names are mangled by prepending "_" on x86. -static StringRef mangle(StringRef Sym) { - assert(Config->Machine != IMAGE_FILE_MACHINE_UNKNOWN); - if (Config->Machine == I386) - return Saver.save("_" + Sym); - return Sym; +static StringRef mangle(StringRef sym) { + assert(config->machine != IMAGE_FILE_MACHINE_UNKNOWN); + if (config->machine == I386) + return saver.save("_" + sym); + return sym; } -static bool findUnderscoreMangle(StringRef Sym) { - Symbol *S = Symtab->findMangle(mangle(Sym)); - return S && !isa(S); +static bool findUnderscoreMangle(StringRef sym) { + Symbol *s = symtab->findMangle(mangle(sym)); + return s && !isa(s); } -MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr MB) { - MemoryBufferRef MBRef = *MB; - make>(std::move(MB)); // take ownership +MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr mb) { + MemoryBufferRef mbref = *mb; + make>(std::move(mb)); // take ownership - if (Driver->Tar) - Driver->Tar->append(relativeToRoot(MBRef.getBufferIdentifier()), - MBRef.getBuffer()); - return MBRef; + if (driver->tar) + driver->tar->append(relativeToRoot(mbref.getBufferIdentifier()), + mbref.getBuffer()); + return mbref; } -void LinkerDriver::addBuffer(std::unique_ptr MB, - bool WholeArchive) { - StringRef Filename = MB->getBufferIdentifier(); +void LinkerDriver::addBuffer(std::unique_ptr mb, + bool wholeArchive) { + StringRef filename = mb->getBufferIdentifier(); - MemoryBufferRef MBRef = takeBuffer(std::move(MB)); - FilePaths.push_back(Filename); + MemoryBufferRef mbref = takeBuffer(std::move(mb)); + filePaths.push_back(filename); // File type is detected by contents, not by file extension. - switch (identify_magic(MBRef.getBuffer())) { + switch (identify_magic(mbref.getBuffer())) { case file_magic::windows_resource: - Resources.push_back(MBRef); + resources.push_back(mbref); break; case file_magic::archive: - if (WholeArchive) { - std::unique_ptr File = - CHECK(Archive::create(MBRef), Filename + ": failed to parse archive"); + if (wholeArchive) { + std::unique_ptr file = + CHECK(Archive::create(mbref), filename + ": failed to parse archive"); - for (MemoryBufferRef M : getArchiveMembers(File.get())) - addArchiveBuffer(M, "", Filename, 0); + for (MemoryBufferRef m : getArchiveMembers(file.get())) + addArchiveBuffer(m, "", filename, 0); return; } - Symtab->addFile(make(MBRef)); + symtab->addFile(make(mbref)); break; case file_magic::bitcode: - Symtab->addFile(make(MBRef, "", 0)); + symtab->addFile(make(mbref, "", 0)); break; case file_magic::coff_object: case file_magic::coff_import_library: - Symtab->addFile(make(MBRef)); + symtab->addFile(make(mbref)); break; case file_magic::pdb: - loadTypeServerSource(MBRef); + loadTypeServerSource(mbref); break; case file_magic::coff_cl_gl_object: - error(Filename + ": is not a native COFF file. Recompile without /GL"); + error(filename + ": is not a native COFF file. Recompile without /GL"); break; case file_magic::pecoff_executable: - if (Filename.endswith_lower(".dll")) { - error(Filename + ": bad file type. Did you specify a DLL instead of an " + if (filename.endswith_lower(".dll")) { + error(filename + ": bad file type. Did you specify a DLL instead of an " "import library?"); break; } LLVM_FALLTHROUGH; default: - error(MBRef.getBufferIdentifier() + ": unknown file type"); + error(mbref.getBufferIdentifier() + ": unknown file type"); break; } } -void LinkerDriver::enqueuePath(StringRef Path, bool WholeArchive) { - auto Future = - std::make_shared>(createFutureForFile(Path)); - std::string PathStr = Path; +void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive) { + auto future = + std::make_shared>(createFutureForFile(path)); + std::string pathStr = path; enqueueTask([=]() { - auto MBOrErr = Future->get(); - if (MBOrErr.second) { - std::string Msg = - "could not open '" + PathStr + "': " + MBOrErr.second.message(); + auto mbOrErr = future->get(); + if (mbOrErr.second) { + std::string msg = + "could not open '" + pathStr + "': " + mbOrErr.second.message(); // Check if the filename is a typo for an option flag. OptTable thinks // that all args that are not known options and that start with / are // filenames, but e.g. `/nodefaultlibs` is more likely a typo for // the option `/nodefaultlib` than a reference to a file in the root // directory. - std::string Nearest; - if (COFFOptTable().findNearest(PathStr, Nearest) > 1) - error(Msg); + std::string nearest; + if (COFFOptTable().findNearest(pathStr, nearest) > 1) + error(msg); else - error(Msg + "; did you mean '" + Nearest + "'"); + error(msg + "; did you mean '" + nearest + "'"); } else - Driver->addBuffer(std::move(MBOrErr.first), WholeArchive); + driver->addBuffer(std::move(mbOrErr.first), wholeArchive); }); } -void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, - StringRef ParentName, - uint64_t OffsetInArchive) { - file_magic Magic = identify_magic(MB.getBuffer()); - if (Magic == file_magic::coff_import_library) { - InputFile *Imp = make(MB); - Imp->ParentName = ParentName; - Symtab->addFile(Imp); +void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, + StringRef parentName, + uint64_t offsetInArchive) { + file_magic magic = identify_magic(mb.getBuffer()); + if (magic == file_magic::coff_import_library) { + InputFile *imp = make(mb); + imp->parentName = parentName; + symtab->addFile(imp); return; } - InputFile *Obj; - if (Magic == file_magic::coff_object) { - Obj = make(MB); - } else if (Magic == file_magic::bitcode) { - Obj = make(MB, ParentName, OffsetInArchive); + InputFile *obj; + if (magic == file_magic::coff_object) { + obj = make(mb); + } else if (magic == file_magic::bitcode) { + obj = make(mb, parentName, offsetInArchive); } else { - error("unknown file type: " + MB.getBufferIdentifier()); + error("unknown file type: " + mb.getBufferIdentifier()); return; } - Obj->ParentName = ParentName; - Symtab->addFile(Obj); - log("Loaded " + toString(Obj) + " for " + SymName); + obj->parentName = parentName; + symtab->addFile(obj); + log("Loaded " + toString(obj) + " for " + symName); } -void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, - StringRef SymName, - StringRef ParentName) { +void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, + StringRef symName, + StringRef parentName) { - auto ReportBufferError = [=](Error &&E, - StringRef ChildName) { + auto reportBufferError = [=](Error &&e, + StringRef childName) { fatal("could not get the buffer for the member defining symbol " + - SymName + ": " + ParentName + "(" + ChildName + "): " + - toString(std::move(E))); + symName + ": " + parentName + "(" + childName + "): " + + toString(std::move(e))); }; - if (!C.getParent()->isThin()) { - uint64_t OffsetInArchive = C.getChildOffset(); - Expected MBOrErr = C.getMemoryBufferRef(); - if (!MBOrErr) - ReportBufferError(MBOrErr.takeError(), check(C.getFullName())); - MemoryBufferRef MB = MBOrErr.get(); + if (!c.getParent()->isThin()) { + uint64_t offsetInArchive = c.getChildOffset(); + Expected mbOrErr = c.getMemoryBufferRef(); + if (!mbOrErr) + reportBufferError(mbOrErr.takeError(), check(c.getFullName())); + MemoryBufferRef mb = mbOrErr.get(); enqueueTask([=]() { - Driver->addArchiveBuffer(MB, SymName, ParentName, OffsetInArchive); + driver->addArchiveBuffer(mb, symName, parentName, offsetInArchive); }); return; } - std::string ChildName = CHECK( - C.getFullName(), + std::string childName = CHECK( + c.getFullName(), "could not get the filename for the member defining symbol " + - SymName); - auto Future = std::make_shared>( - createFutureForFile(ChildName)); + symName); + auto future = std::make_shared>( + createFutureForFile(childName)); enqueueTask([=]() { - auto MBOrErr = Future->get(); - if (MBOrErr.second) - ReportBufferError(errorCodeToError(MBOrErr.second), ChildName); - Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName, - ParentName, /* OffsetInArchive */ 0); + auto mbOrErr = future->get(); + if (mbOrErr.second) + reportBufferError(errorCodeToError(mbOrErr.second), childName); + driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), symName, + parentName, /* OffsetInArchive */ 0); }); } -static bool isDecorated(StringRef Sym) { - return Sym.startswith("@") || Sym.contains("@@") || Sym.startswith("?") || - (!Config->MinGW && Sym.contains('@')); +static bool isDecorated(StringRef sym) { + return sym.startswith("@") || sym.contains("@@") || sym.startswith("?") || + (!config->mingw && sym.contains('@')); } // Parses .drectve section contents and returns a list of files // specified by /defaultlib. -void LinkerDriver::parseDirectives(InputFile *File) { - StringRef S = File->getDirectives(); - if (S.empty()) +void LinkerDriver::parseDirectives(InputFile *file) { + StringRef s = file->getDirectives(); + if (s.empty()) return; - log("Directives: " + toString(File) + ": " + S); + log("Directives: " + toString(file) + ": " + s); - ArgParser Parser; + ArgParser parser; // .drectve is always tokenized using Windows shell rules. // /EXPORT: option can appear too many times, processing in fastpath. - opt::InputArgList Args; - std::vector Exports; - std::tie(Args, Exports) = Parser.parseDirectives(S); + opt::InputArgList args; + std::vector exports; + std::tie(args, exports) = parser.parseDirectives(s); - for (StringRef E : Exports) { + for (StringRef e : exports) { // If a common header file contains dllexported function // declarations, many object files may end up with having the // same /EXPORT options. In order to save cost of parsing them, // we dedup them first. - if (!DirectivesExports.insert(E).second) + if (!directivesExports.insert(e).second) continue; - Export Exp = parseExport(E); - if (Config->Machine == I386 && Config->MinGW) { - if (!isDecorated(Exp.Name)) - Exp.Name = Saver.save("_" + Exp.Name); - if (!Exp.ExtName.empty() && !isDecorated(Exp.ExtName)) - Exp.ExtName = Saver.save("_" + Exp.ExtName); + Export exp = parseExport(e); + if (config->machine == I386 && config->mingw) { + if (!isDecorated(exp.name)) + exp.name = saver.save("_" + exp.name); + if (!exp.extName.empty() && !isDecorated(exp.extName)) + exp.extName = saver.save("_" + exp.extName); } - Exp.Directives = true; - Config->Exports.push_back(Exp); + exp.directives = true; + config->exports.push_back(exp); } - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_aligncomm: - parseAligncomm(Arg->getValue()); + parseAligncomm(arg->getValue()); break; case OPT_alternatename: - parseAlternateName(Arg->getValue()); + parseAlternateName(arg->getValue()); break; case OPT_defaultlib: - if (Optional Path = findLib(Arg->getValue())) - enqueuePath(*Path, false); + if (Optional path = findLib(arg->getValue())) + enqueuePath(*path, false); break; case OPT_entry: - Config->Entry = addUndefined(mangle(Arg->getValue())); + config->entry = addUndefined(mangle(arg->getValue())); break; case OPT_failifmismatch: - checkFailIfMismatch(Arg->getValue(), File); + checkFailIfMismatch(arg->getValue(), file); break; case OPT_incl: - addUndefined(Arg->getValue()); + addUndefined(arg->getValue()); break; case OPT_merge: - parseMerge(Arg->getValue()); + parseMerge(arg->getValue()); break; case OPT_nodefaultlib: - Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()).lower()); + config->noDefaultLibs.insert(doFindLib(arg->getValue()).lower()); break; case OPT_section: - parseSection(Arg->getValue()); + parseSection(arg->getValue()); break; case OPT_subsystem: - parseSubsystem(Arg->getValue(), &Config->Subsystem, - &Config->MajorOSVersion, &Config->MinorOSVersion); + parseSubsystem(arg->getValue(), &config->subsystem, + &config->majorOSVersion, &config->minorOSVersion); break; // Only add flags here that link.exe accepts in // `#pragma comment(linker, "/flag")`-generated sections. @@ -372,138 +372,138 @@ case OPT_throwingnew: break; default: - error(Arg->getSpelling() + " is not allowed in .drectve"); + error(arg->getSpelling() + " is not allowed in .drectve"); } } } // Find file from search paths. You can omit ".obj", this function takes // care of that. Note that the returned path is not guaranteed to exist. -StringRef LinkerDriver::doFindFile(StringRef Filename) { - bool HasPathSep = (Filename.find_first_of("/\\") != StringRef::npos); - if (HasPathSep) - return Filename; - bool HasExt = Filename.contains('.'); - for (StringRef Dir : SearchPaths) { - SmallString<128> Path = Dir; - sys::path::append(Path, Filename); - if (sys::fs::exists(Path.str())) - return Saver.save(Path.str()); - if (!HasExt) { - Path.append(".obj"); - if (sys::fs::exists(Path.str())) - return Saver.save(Path.str()); - } - } - return Filename; -} - -static Optional getUniqueID(StringRef Path) { - sys::fs::UniqueID Ret; - if (sys::fs::getUniqueID(Path, Ret)) +StringRef LinkerDriver::doFindFile(StringRef filename) { + bool hasPathSep = (filename.find_first_of("/\\") != StringRef::npos); + if (hasPathSep) + return filename; + bool hasExt = filename.contains('.'); + for (StringRef dir : searchPaths) { + SmallString<128> path = dir; + sys::path::append(path, filename); + if (sys::fs::exists(path.str())) + return saver.save(path.str()); + if (!hasExt) { + path.append(".obj"); + if (sys::fs::exists(path.str())) + return saver.save(path.str()); + } + } + return filename; +} + +static Optional getUniqueID(StringRef path) { + sys::fs::UniqueID ret; + if (sys::fs::getUniqueID(path, ret)) return None; - return Ret; + return ret; } // Resolves a file path. This never returns the same path // (in that case, it returns None). -Optional LinkerDriver::findFile(StringRef Filename) { - StringRef Path = doFindFile(Filename); +Optional LinkerDriver::findFile(StringRef filename) { + StringRef path = doFindFile(filename); - if (Optional ID = getUniqueID(Path)) { - bool Seen = !VisitedFiles.insert(*ID).second; - if (Seen) + if (Optional id = getUniqueID(path)) { + bool seen = !visitedFiles.insert(*id).second; + if (seen) return None; } - if (Path.endswith_lower(".lib")) - VisitedLibs.insert(sys::path::filename(Path)); - return Path; + if (path.endswith_lower(".lib")) + visitedLibs.insert(sys::path::filename(path)); + return path; } // MinGW specific. If an embedded directive specified to link to // foo.lib, but it isn't found, try libfoo.a instead. -StringRef LinkerDriver::doFindLibMinGW(StringRef Filename) { - if (Filename.contains('/') || Filename.contains('\\')) - return Filename; - - SmallString<128> S = Filename; - sys::path::replace_extension(S, ".a"); - StringRef LibName = Saver.save("lib" + S.str()); - return doFindFile(LibName); +StringRef LinkerDriver::doFindLibMinGW(StringRef filename) { + if (filename.contains('/') || filename.contains('\\')) + return filename; + + SmallString<128> s = filename; + sys::path::replace_extension(s, ".a"); + StringRef libName = saver.save("lib" + s.str()); + return doFindFile(libName); } // Find library file from search path. -StringRef LinkerDriver::doFindLib(StringRef Filename) { +StringRef LinkerDriver::doFindLib(StringRef filename) { // Add ".lib" to Filename if that has no file extension. - bool HasExt = Filename.contains('.'); - if (!HasExt) - Filename = Saver.save(Filename + ".lib"); - StringRef Ret = doFindFile(Filename); + bool hasExt = filename.contains('.'); + if (!hasExt) + filename = saver.save(filename + ".lib"); + StringRef ret = doFindFile(filename); // For MinGW, if the find above didn't turn up anything, try // looking for a MinGW formatted library name. - if (Config->MinGW && Ret == Filename) - return doFindLibMinGW(Filename); - return Ret; + if (config->mingw && ret == filename) + return doFindLibMinGW(filename); + return ret; } // Resolves a library path. /nodefaultlib options are taken into // consideration. This never returns the same path (in that case, // it returns None). -Optional LinkerDriver::findLib(StringRef Filename) { - if (Config->NoDefaultLibAll) +Optional LinkerDriver::findLib(StringRef filename) { + if (config->noDefaultLibAll) return None; - if (!VisitedLibs.insert(Filename.lower()).second) + if (!visitedLibs.insert(filename.lower()).second) return None; - StringRef Path = doFindLib(Filename); - if (Config->NoDefaultLibs.count(Path.lower())) + StringRef path = doFindLib(filename); + if (config->noDefaultLibs.count(path.lower())) return None; - if (Optional ID = getUniqueID(Path)) - if (!VisitedFiles.insert(*ID).second) + if (Optional id = getUniqueID(path)) + if (!visitedFiles.insert(*id).second) return None; - return Path; + return path; } // Parses LIB environment which contains a list of search paths. void LinkerDriver::addLibSearchPaths() { - Optional EnvOpt = Process::GetEnv("LIB"); - if (!EnvOpt.hasValue()) + Optional envOpt = Process::GetEnv("LIB"); + if (!envOpt.hasValue()) return; - StringRef Env = Saver.save(*EnvOpt); - while (!Env.empty()) { - StringRef Path; - std::tie(Path, Env) = Env.split(';'); - SearchPaths.push_back(Path); + StringRef env = saver.save(*envOpt); + while (!env.empty()) { + StringRef path; + std::tie(path, env) = env.split(';'); + searchPaths.push_back(path); } } -Symbol *LinkerDriver::addUndefined(StringRef Name) { - Symbol *B = Symtab->addUndefined(Name); - if (!B->IsGCRoot) { - B->IsGCRoot = true; - Config->GCRoot.push_back(B); +Symbol *LinkerDriver::addUndefined(StringRef name) { + Symbol *b = symtab->addUndefined(name); + if (!b->isGCRoot) { + b->isGCRoot = true; + config->gCRoot.push_back(b); } - return B; + return b; } -StringRef LinkerDriver::mangleMaybe(Symbol *S) { +StringRef LinkerDriver::mangleMaybe(Symbol *s) { // If the plain symbol name has already been resolved, do nothing. - Undefined *Unmangled = dyn_cast(S); - if (!Unmangled) + Undefined *unmangled = dyn_cast(s); + if (!unmangled) return ""; // Otherwise, see if a similar, mangled symbol exists in the symbol table. - Symbol *Mangled = Symtab->findMangle(Unmangled->getName()); - if (!Mangled) + Symbol *mangled = symtab->findMangle(unmangled->getName()); + if (!mangled) return ""; // If we find a similar mangled symbol, make this an alias to it and return // its name. - log(Unmangled->getName() + " aliased to " + Mangled->getName()); - Unmangled->WeakAlias = Symtab->addUndefined(Mangled->getName()); - return Mangled->getName(); + log(unmangled->getName() + " aliased to " + mangled->getName()); + unmangled->weakAlias = symtab->addUndefined(mangled->getName()); + return mangled->getName(); } // Windows specific -- find default entry point name. @@ -512,15 +512,15 @@ // each of which corresponds to a user-defined "main" function. This function // infers an entry point from a user-defined "main" function. StringRef LinkerDriver::findDefaultEntry() { - assert(Config->Subsystem != IMAGE_SUBSYSTEM_UNKNOWN && + assert(config->subsystem != IMAGE_SUBSYSTEM_UNKNOWN && "must handle /subsystem before calling this"); - if (Config->MinGW) - return mangle(Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI + if (config->mingw) + return mangle(config->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI ? "WinMainCRTStartup" : "mainCRTStartup"); - if (Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { + if (config->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { if (findUnderscoreMangle("wWinMain")) { if (!findUnderscoreMangle("WinMain")) return mangle("wWinMainCRTStartup"); @@ -537,44 +537,44 @@ } WindowsSubsystem LinkerDriver::inferSubsystem() { - if (Config->DLL) + if (config->dll) return IMAGE_SUBSYSTEM_WINDOWS_GUI; - if (Config->MinGW) + if (config->mingw) return IMAGE_SUBSYSTEM_WINDOWS_CUI; // Note that link.exe infers the subsystem from the presence of these // functions even if /entry: or /nodefaultlib are passed which causes them // to not be called. - bool HaveMain = findUnderscoreMangle("main"); - bool HaveWMain = findUnderscoreMangle("wmain"); - bool HaveWinMain = findUnderscoreMangle("WinMain"); - bool HaveWWinMain = findUnderscoreMangle("wWinMain"); - if (HaveMain || HaveWMain) { - if (HaveWinMain || HaveWWinMain) { - warn(std::string("found ") + (HaveMain ? "main" : "wmain") + " and " + - (HaveWinMain ? "WinMain" : "wWinMain") + + bool haveMain = findUnderscoreMangle("main"); + bool haveWMain = findUnderscoreMangle("wmain"); + bool haveWinMain = findUnderscoreMangle("WinMain"); + bool haveWWinMain = findUnderscoreMangle("wWinMain"); + if (haveMain || haveWMain) { + if (haveWinMain || haveWWinMain) { + warn(std::string("found ") + (haveMain ? "main" : "wmain") + " and " + + (haveWinMain ? "WinMain" : "wWinMain") + "; defaulting to /subsystem:console"); } return IMAGE_SUBSYSTEM_WINDOWS_CUI; } - if (HaveWinMain || HaveWWinMain) + if (haveWinMain || haveWWinMain) return IMAGE_SUBSYSTEM_WINDOWS_GUI; return IMAGE_SUBSYSTEM_UNKNOWN; } static uint64_t getDefaultImageBase() { - if (Config->is64()) - return Config->DLL ? 0x180000000 : 0x140000000; - return Config->DLL ? 0x10000000 : 0x400000; + if (config->is64()) + return config->dll ? 0x180000000 : 0x140000000; + return config->dll ? 0x10000000 : 0x400000; } -static std::string createResponseFile(const opt::InputArgList &Args, - ArrayRef FilePaths, - ArrayRef SearchPaths) { - SmallString<0> Data; - raw_svector_ostream OS(Data); +static std::string createResponseFile(const opt::InputArgList &args, + ArrayRef filePaths, + ArrayRef searchPaths) { + SmallString<0> data; + raw_svector_ostream os(data); - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_linkrepro: case OPT_INPUT: case OPT_defaultlib: @@ -589,34 +589,34 @@ case OPT_implib: case OPT_pdb: case OPT_out: - OS << Arg->getSpelling() << sys::path::filename(Arg->getValue()) << "\n"; + os << arg->getSpelling() << sys::path::filename(arg->getValue()) << "\n"; break; default: - OS << toString(*Arg) << "\n"; + os << toString(*arg) << "\n"; } } - for (StringRef Path : SearchPaths) { - std::string RelPath = relativeToRoot(Path); - OS << "/libpath:" << quote(RelPath) << "\n"; + for (StringRef path : searchPaths) { + std::string relPath = relativeToRoot(path); + os << "/libpath:" << quote(relPath) << "\n"; } - for (StringRef Path : FilePaths) - OS << quote(relativeToRoot(Path)) << "\n"; + for (StringRef path : filePaths) + os << quote(relativeToRoot(path)) << "\n"; - return Data.str(); + return data.str(); } enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab }; -static DebugKind parseDebugKind(const opt::InputArgList &Args) { - auto *A = Args.getLastArg(OPT_debug, OPT_debug_opt); - if (!A) +static DebugKind parseDebugKind(const opt::InputArgList &args) { + auto *a = args.getLastArg(OPT_debug, OPT_debug_opt); + if (!a) return DebugKind::None; - if (A->getNumValues() == 0) + if (a->getNumValues() == 0) return DebugKind::Full; - DebugKind Debug = StringSwitch(A->getValue()) + DebugKind debug = StringSwitch(a->getValue()) .CaseLower("none", DebugKind::None) .CaseLower("full", DebugKind::Full) .CaseLower("fastlink", DebugKind::FastLink) @@ -626,68 +626,68 @@ .CaseLower("symtab", DebugKind::Symtab) .Default(DebugKind::Unknown); - if (Debug == DebugKind::FastLink) { + if (debug == DebugKind::FastLink) { warn("/debug:fastlink unsupported; using /debug:full"); return DebugKind::Full; } - if (Debug == DebugKind::Unknown) { - error("/debug: unknown option: " + Twine(A->getValue())); + if (debug == DebugKind::Unknown) { + error("/debug: unknown option: " + Twine(a->getValue())); return DebugKind::None; } - return Debug; + return debug; } -static unsigned parseDebugTypes(const opt::InputArgList &Args) { - unsigned DebugTypes = static_cast(DebugType::None); +static unsigned parseDebugTypes(const opt::InputArgList &args) { + unsigned debugTypes = static_cast(DebugType::None); - if (auto *A = Args.getLastArg(OPT_debugtype)) { - SmallVector Types; - StringRef(A->getValue()) - .split(Types, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false); + if (auto *a = args.getLastArg(OPT_debugtype)) { + SmallVector types; + StringRef(a->getValue()) + .split(types, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false); - for (StringRef Type : Types) { - unsigned V = StringSwitch(Type.lower()) + for (StringRef type : types) { + unsigned v = StringSwitch(type.lower()) .Case("cv", static_cast(DebugType::CV)) .Case("pdata", static_cast(DebugType::PData)) .Case("fixup", static_cast(DebugType::Fixup)) .Default(0); - if (V == 0) { - warn("/debugtype: unknown option '" + Type + "'"); + if (v == 0) { + warn("/debugtype: unknown option '" + type + "'"); continue; } - DebugTypes |= V; + debugTypes |= v; } - return DebugTypes; + return debugTypes; } // Default debug types - DebugTypes = static_cast(DebugType::CV); - if (Args.hasArg(OPT_driver)) - DebugTypes |= static_cast(DebugType::PData); - if (Args.hasArg(OPT_profile)) - DebugTypes |= static_cast(DebugType::Fixup); - - return DebugTypes; + debugTypes = static_cast(DebugType::CV); + if (args.hasArg(OPT_driver)) + debugTypes |= static_cast(DebugType::PData); + if (args.hasArg(OPT_profile)) + debugTypes |= static_cast(DebugType::Fixup); + + return debugTypes; } -static std::string getMapFile(const opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_lldmap, OPT_lldmap_file); - if (!Arg) +static std::string getMapFile(const opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_lldmap, OPT_lldmap_file); + if (!arg) return ""; - if (Arg->getOption().getID() == OPT_lldmap_file) - return Arg->getValue(); + if (arg->getOption().getID() == OPT_lldmap_file) + return arg->getValue(); - assert(Arg->getOption().getID() == OPT_lldmap); - StringRef OutFile = Config->OutputFile; - return (OutFile.substr(0, OutFile.rfind('.')) + ".map").str(); + assert(arg->getOption().getID() == OPT_lldmap); + StringRef outFile = config->outputFile; + return (outFile.substr(0, outFile.rfind('.')) + ".map").str(); } static std::string getImplibPath() { - if (!Config->Implib.empty()) - return Config->Implib; - SmallString<128> Out = StringRef(Config->OutputFile); - sys::path::replace_extension(Out, ".lib"); - return Out.str(); + if (!config->implib.empty()) + return config->implib; + SmallString<128> out = StringRef(config->outputFile); + sys::path::replace_extension(out, ".lib"); + return out.str(); } // @@ -698,226 +698,226 @@ // LINK | {value} | {value}.{.dll/.exe} | {output name} // LIB | {value} | {value}.dll | {output name}.dll // -static std::string getImportName(bool AsLib) { - SmallString<128> Out; +static std::string getImportName(bool asLib) { + SmallString<128> out; - if (Config->ImportName.empty()) { - Out.assign(sys::path::filename(Config->OutputFile)); - if (AsLib) - sys::path::replace_extension(Out, ".dll"); + if (config->importName.empty()) { + out.assign(sys::path::filename(config->outputFile)); + if (asLib) + sys::path::replace_extension(out, ".dll"); } else { - Out.assign(Config->ImportName); - if (!sys::path::has_extension(Out)) - sys::path::replace_extension(Out, - (Config->DLL || AsLib) ? ".dll" : ".exe"); - } - - return Out.str(); -} - -static void createImportLibrary(bool AsLib) { - std::vector Exports; - for (Export &E1 : Config->Exports) { - COFFShortExport E2; - E2.Name = E1.Name; - E2.SymbolName = E1.SymbolName; - E2.ExtName = E1.ExtName; - E2.Ordinal = E1.Ordinal; - E2.Noname = E1.Noname; - E2.Data = E1.Data; - E2.Private = E1.Private; - E2.Constant = E1.Constant; - Exports.push_back(E2); - } - - auto HandleError = [](Error &&E) { - handleAllErrors(std::move(E), - [](ErrorInfoBase &EIB) { error(EIB.message()); }); + out.assign(config->importName); + if (!sys::path::has_extension(out)) + sys::path::replace_extension(out, + (config->dll || asLib) ? ".dll" : ".exe"); + } + + return out.str(); +} + +static void createImportLibrary(bool asLib) { + std::vector exports; + for (Export &e1 : config->exports) { + COFFShortExport e2; + e2.Name = e1.name; + e2.SymbolName = e1.symbolName; + e2.ExtName = e1.extName; + e2.Ordinal = e1.ordinal; + e2.Noname = e1.noname; + e2.Data = e1.data; + e2.Private = e1.isPrivate; + e2.Constant = e1.constant; + exports.push_back(e2); + } + + auto handleError = [](Error &&e) { + handleAllErrors(std::move(e), + [](ErrorInfoBase &eib) { error(eib.message()); }); }; - std::string LibName = getImportName(AsLib); - std::string Path = getImplibPath(); + std::string libName = getImportName(asLib); + std::string path = getImplibPath(); - if (!Config->Incremental) { - HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine, - Config->MinGW)); + if (!config->incremental) { + handleError(writeImportLibrary(libName, path, exports, config->machine, + config->mingw)); return; } // If the import library already exists, replace it only if the contents // have changed. - ErrorOr> OldBuf = MemoryBuffer::getFile( - Path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false); - if (!OldBuf) { - HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine, - Config->MinGW)); + ErrorOr> oldBuf = MemoryBuffer::getFile( + path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false); + if (!oldBuf) { + handleError(writeImportLibrary(libName, path, exports, config->machine, + config->mingw)); return; } - SmallString<128> TmpName; - if (std::error_code EC = - sys::fs::createUniqueFile(Path + ".tmp-%%%%%%%%.lib", TmpName)) - fatal("cannot create temporary file for import library " + Path + ": " + - EC.message()); - - if (Error E = writeImportLibrary(LibName, TmpName, Exports, Config->Machine, - Config->MinGW)) { - HandleError(std::move(E)); + SmallString<128> tmpName; + if (std::error_code ec = + sys::fs::createUniqueFile(path + ".tmp-%%%%%%%%.lib", tmpName)) + fatal("cannot create temporary file for import library " + path + ": " + + ec.message()); + + if (Error e = writeImportLibrary(libName, tmpName, exports, config->machine, + config->mingw)) { + handleError(std::move(e)); return; } - std::unique_ptr NewBuf = check(MemoryBuffer::getFile( - TmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false)); - if ((*OldBuf)->getBuffer() != NewBuf->getBuffer()) { - OldBuf->reset(); - HandleError(errorCodeToError(sys::fs::rename(TmpName, Path))); + std::unique_ptr newBuf = check(MemoryBuffer::getFile( + tmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false)); + if ((*oldBuf)->getBuffer() != newBuf->getBuffer()) { + oldBuf->reset(); + handleError(errorCodeToError(sys::fs::rename(tmpName, path))); } else { - sys::fs::remove(TmpName); + sys::fs::remove(tmpName); } } -static void parseModuleDefs(StringRef Path) { - std::unique_ptr MB = CHECK( - MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); - COFFModuleDefinition M = check(parseCOFFModuleDefinition( - MB->getMemBufferRef(), Config->Machine, Config->MinGW)); - - if (Config->OutputFile.empty()) - Config->OutputFile = Saver.save(M.OutputFile); - Config->ImportName = Saver.save(M.ImportName); - if (M.ImageBase) - Config->ImageBase = M.ImageBase; - if (M.StackReserve) - Config->StackReserve = M.StackReserve; - if (M.StackCommit) - Config->StackCommit = M.StackCommit; - if (M.HeapReserve) - Config->HeapReserve = M.HeapReserve; - if (M.HeapCommit) - Config->HeapCommit = M.HeapCommit; - if (M.MajorImageVersion) - Config->MajorImageVersion = M.MajorImageVersion; - if (M.MinorImageVersion) - Config->MinorImageVersion = M.MinorImageVersion; - if (M.MajorOSVersion) - Config->MajorOSVersion = M.MajorOSVersion; - if (M.MinorOSVersion) - Config->MinorOSVersion = M.MinorOSVersion; +static void parseModuleDefs(StringRef path) { + std::unique_ptr mb = CHECK( + MemoryBuffer::getFile(path, -1, false, true), "could not open " + path); + COFFModuleDefinition m = check(parseCOFFModuleDefinition( + mb->getMemBufferRef(), config->machine, config->mingw)); + + if (config->outputFile.empty()) + config->outputFile = saver.save(m.OutputFile); + config->importName = saver.save(m.ImportName); + if (m.ImageBase) + config->imageBase = m.ImageBase; + if (m.StackReserve) + config->stackReserve = m.StackReserve; + if (m.StackCommit) + config->stackCommit = m.StackCommit; + if (m.HeapReserve) + config->heapReserve = m.HeapReserve; + if (m.HeapCommit) + config->heapCommit = m.HeapCommit; + if (m.MajorImageVersion) + config->majorImageVersion = m.MajorImageVersion; + if (m.MinorImageVersion) + config->minorImageVersion = m.MinorImageVersion; + if (m.MajorOSVersion) + config->majorOSVersion = m.MajorOSVersion; + if (m.MinorOSVersion) + config->minorOSVersion = m.MinorOSVersion; - for (COFFShortExport E1 : M.Exports) { - Export E2; + for (COFFShortExport e1 : m.Exports) { + Export e2; // In simple cases, only Name is set. Renamed exports are parsed // and set as "ExtName = Name". If Name has the form "OtherDll.Func", // it shouldn't be a normal exported function but a forward to another // DLL instead. This is supported by both MS and GNU linkers. - if (E1.ExtName != E1.Name && StringRef(E1.Name).contains('.')) { - E2.Name = Saver.save(E1.ExtName); - E2.ForwardTo = Saver.save(E1.Name); - Config->Exports.push_back(E2); + if (e1.ExtName != e1.Name && StringRef(e1.Name).contains('.')) { + e2.name = saver.save(e1.ExtName); + e2.forwardTo = saver.save(e1.Name); + config->exports.push_back(e2); continue; } - E2.Name = Saver.save(E1.Name); - E2.ExtName = Saver.save(E1.ExtName); - E2.Ordinal = E1.Ordinal; - E2.Noname = E1.Noname; - E2.Data = E1.Data; - E2.Private = E1.Private; - E2.Constant = E1.Constant; - Config->Exports.push_back(E2); + e2.name = saver.save(e1.Name); + e2.extName = saver.save(e1.ExtName); + e2.ordinal = e1.Ordinal; + e2.noname = e1.Noname; + e2.data = e1.Data; + e2.isPrivate = e1.Private; + e2.constant = e1.Constant; + config->exports.push_back(e2); } } -void LinkerDriver::enqueueTask(std::function Task) { - TaskQueue.push_back(std::move(Task)); +void LinkerDriver::enqueueTask(std::function task) { + taskQueue.push_back(std::move(task)); } bool LinkerDriver::run() { - ScopedTimer T(InputFileTimer); + ScopedTimer t(inputFileTimer); - bool DidWork = !TaskQueue.empty(); - while (!TaskQueue.empty()) { - TaskQueue.front()(); - TaskQueue.pop_front(); + bool didWork = !taskQueue.empty(); + while (!taskQueue.empty()) { + taskQueue.front()(); + taskQueue.pop_front(); } - return DidWork; + return didWork; } // Parse an /order file. If an option is given, the linker places // COMDAT sections in the same order as their names appear in the // given file. -static void parseOrderFile(StringRef Arg) { +static void parseOrderFile(StringRef arg) { // For some reason, the MSVC linker requires a filename to be // preceded by "@". - if (!Arg.startswith("@")) { + if (!arg.startswith("@")) { error("malformed /order option: '@' missing"); return; } // Get a list of all comdat sections for error checking. - DenseSet Set; - for (Chunk *C : Symtab->getChunks()) - if (auto *Sec = dyn_cast(C)) - if (Sec->Sym) - Set.insert(Sec->Sym->getName()); + DenseSet set; + for (Chunk *c : symtab->getChunks()) + if (auto *sec = dyn_cast(c)) + if (sec->sym) + set.insert(sec->sym->getName()); // Open a file. - StringRef Path = Arg.substr(1); - std::unique_ptr MB = CHECK( - MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); + StringRef path = arg.substr(1); + std::unique_ptr mb = CHECK( + MemoryBuffer::getFile(path, -1, false, true), "could not open " + path); // Parse a file. An order file contains one symbol per line. // All symbols that were not present in a given order file are // considered to have the lowest priority 0 and are placed at // end of an output section. - for (std::string S : args::getLines(MB->getMemBufferRef())) { - if (Config->Machine == I386 && !isDecorated(S)) - S = "_" + S; - - if (Set.count(S) == 0) { - if (Config->WarnMissingOrderSymbol) - warn("/order:" + Arg + ": missing symbol: " + S + " [LNK4037]"); + for (std::string s : args::getLines(mb->getMemBufferRef())) { + if (config->machine == I386 && !isDecorated(s)) + s = "_" + s; + + if (set.count(s) == 0) { + if (config->warnMissingOrderSymbol) + warn("/order:" + arg + ": missing symbol: " + s + " [LNK4037]"); } else - Config->Order[S] = INT_MIN + Config->Order.size(); + config->order[s] = INT_MIN + config->order.size(); } } -static void markAddrsig(Symbol *S) { - if (auto *D = dyn_cast_or_null(S)) - if (SectionChunk *C = dyn_cast_or_null(D->getChunk())) - C->KeepUnique = true; +static void markAddrsig(Symbol *s) { + if (auto *d = dyn_cast_or_null(s)) + if (SectionChunk *c = dyn_cast_or_null(d->getChunk())) + c->keepUnique = true; } static void findKeepUniqueSections() { // Exported symbols could be address-significant in other executables or DSOs, // so we conservatively mark them as address-significant. - for (Export &R : Config->Exports) - markAddrsig(R.Sym); + for (Export &r : config->exports) + markAddrsig(r.sym); // Visit the address-significance table in each object file and mark each // referenced symbol as address-significant. - for (ObjFile *Obj : ObjFile::Instances) { - ArrayRef Syms = Obj->getSymbols(); - if (Obj->AddrsigSec) { - ArrayRef Contents; + for (ObjFile *obj : ObjFile::instances) { + ArrayRef syms = obj->getSymbols(); + if (obj->addrsigSec) { + ArrayRef contents; cantFail( - Obj->getCOFFObj()->getSectionContents(Obj->AddrsigSec, Contents)); - const uint8_t *Cur = Contents.begin(); - while (Cur != Contents.end()) { - unsigned Size; - const char *Err; - uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); - if (Err) - fatal(toString(Obj) + ": could not decode addrsig section: " + Err); - if (SymIndex >= Syms.size()) - fatal(toString(Obj) + ": invalid symbol index in addrsig section"); - markAddrsig(Syms[SymIndex]); - Cur += Size; + obj->getCOFFObj()->getSectionContents(obj->addrsigSec, contents)); + const uint8_t *cur = contents.begin(); + while (cur != contents.end()) { + unsigned size; + const char *err; + uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err); + if (err) + fatal(toString(obj) + ": could not decode addrsig section: " + err); + if (symIndex >= syms.size()) + fatal(toString(obj) + ": invalid symbol index in addrsig section"); + markAddrsig(syms[symIndex]); + cur += size; } } else { // If an object file does not have an address-significance table, // conservatively mark all of its symbols as address-significant. - for (Symbol *S : Syms) - markAddrsig(S); + for (Symbol *s : syms) + markAddrsig(s); } } } @@ -928,14 +928,14 @@ // binary). // lld only supports %_PDB% and %_EXT% and warns on references to all other env // vars. -static void parsePDBAltPath(StringRef AltPath) { - SmallString<128> Buf; - StringRef PDBBasename = - sys::path::filename(Config->PDBPath, sys::path::Style::windows); - StringRef BinaryExtension = - sys::path::extension(Config->OutputFile, sys::path::Style::windows); - if (!BinaryExtension.empty()) - BinaryExtension = BinaryExtension.substr(1); // %_EXT% does not include '.'. +static void parsePDBAltPath(StringRef altPath) { + SmallString<128> buf; + StringRef pdbBasename = + sys::path::filename(config->pdbPath, sys::path::Style::windows); + StringRef binaryExtension = + sys::path::extension(config->outputFile, sys::path::Style::windows); + if (!binaryExtension.empty()) + binaryExtension = binaryExtension.substr(1); // %_EXT% does not include '.'. // Invariant: // +--------- Cursor ('a...' might be the empty string). @@ -943,34 +943,34 @@ // | | +- SecondMark // v v v // a...%...%... - size_t Cursor = 0; - while (Cursor < AltPath.size()) { - size_t FirstMark, SecondMark; - if ((FirstMark = AltPath.find('%', Cursor)) == StringRef::npos || - (SecondMark = AltPath.find('%', FirstMark + 1)) == StringRef::npos) { + size_t cursor = 0; + while (cursor < altPath.size()) { + size_t firstMark, secondMark; + if ((firstMark = altPath.find('%', cursor)) == StringRef::npos || + (secondMark = altPath.find('%', firstMark + 1)) == StringRef::npos) { // Didn't find another full fragment, treat rest of string as literal. - Buf.append(AltPath.substr(Cursor)); + buf.append(altPath.substr(cursor)); break; } // Found a full fragment. Append text in front of first %, and interpret // text between first and second % as variable name. - Buf.append(AltPath.substr(Cursor, FirstMark - Cursor)); - StringRef Var = AltPath.substr(FirstMark, SecondMark - FirstMark + 1); - if (Var.equals_lower("%_pdb%")) - Buf.append(PDBBasename); - else if (Var.equals_lower("%_ext%")) - Buf.append(BinaryExtension); + buf.append(altPath.substr(cursor, firstMark - cursor)); + StringRef var = altPath.substr(firstMark, secondMark - firstMark + 1); + if (var.equals_lower("%_pdb%")) + buf.append(pdbBasename); + else if (var.equals_lower("%_ext%")) + buf.append(binaryExtension); else { warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " + - Var + " as literal"); - Buf.append(Var); + var + " as literal"); + buf.append(var); } - Cursor = SecondMark + 1; + cursor = secondMark + 1; } - Config->PDBAltPath = Buf; + config->pdbAltPath = buf; } /// Check that at most one resource obj file was used. @@ -983,19 +983,19 @@ // LNK4078, mirror that. The normal use of resource files is to give the // linker many .res files, which are then converted to a single resource obj // file internally, so this is not a big restriction in practice. - ObjFile *ResourceObjFile = nullptr; - for (ObjFile *F : ObjFile::Instances) { - if (!F->IsResourceObjFile) + ObjFile *resourceObjFile = nullptr; + for (ObjFile *f : ObjFile::instances) { + if (!f->isResourceObjFile) continue; - if (!ResourceObjFile) { - ResourceObjFile = F; + if (!resourceObjFile) { + resourceObjFile = f; continue; } - error(toString(F) + + error(toString(f) + ": more than one resource obj file not allowed, already got " + - toString(ResourceObjFile)); + toString(resourceObjFile)); } } @@ -1005,39 +1005,39 @@ // explicitly specified. The automatic behavior can be disabled using the // -exclude-all-symbols option, so that lld-link behaves like link.exe rather // than MinGW in the case that nothing is explicitly exported. -void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &Args) { - if (!Config->DLL) +void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) { + if (!config->dll) return; - if (!Args.hasArg(OPT_export_all_symbols)) { - if (!Config->Exports.empty()) + if (!args.hasArg(OPT_export_all_symbols)) { + if (!config->exports.empty()) return; - if (Args.hasArg(OPT_exclude_all_symbols)) + if (args.hasArg(OPT_exclude_all_symbols)) return; } - AutoExporter Exporter; + AutoExporter exporter; - for (auto *Arg : Args.filtered(OPT_wholearchive_file)) - if (Optional Path = doFindFile(Arg->getValue())) - Exporter.addWholeArchive(*Path); - - Symtab->forEachSymbol([&](Symbol *S) { - auto *Def = dyn_cast(S); - if (!Exporter.shouldExport(Def)) + for (auto *arg : args.filtered(OPT_wholearchive_file)) + if (Optional path = doFindFile(arg->getValue())) + exporter.addWholeArchive(*path); + + symtab->forEachSymbol([&](Symbol *s) { + auto *def = dyn_cast(s); + if (!exporter.shouldExport(def)) return; - Export E; - E.Name = Def->getName(); - E.Sym = Def; - if (Chunk *C = Def->getChunk()) - if (!(C->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)) - E.Data = true; - Config->Exports.push_back(E); + Export e; + e.name = def->getName(); + e.sym = def; + if (Chunk *c = def->getChunk()) + if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)) + e.data = true; + config->exports.push_back(e); }); } -void LinkerDriver::link(ArrayRef ArgsArr) { +void LinkerDriver::link(ArrayRef argsArr) { // Needed for LTO. InitializeAllTargetInfos(); InitializeAllTargets(); @@ -1047,306 +1047,306 @@ // If the first command line argument is "/lib", link.exe acts like lib.exe. // We call our own implementation of lib.exe that understands bitcode files. - if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) { - if (llvm::libDriverMain(ArgsArr.slice(1)) != 0) + if (argsArr.size() > 1 && StringRef(argsArr[1]).equals_lower("/lib")) { + if (llvm::libDriverMain(argsArr.slice(1)) != 0) fatal("lib failed"); return; } // Parse command line options. - ArgParser Parser; - opt::InputArgList Args = Parser.parseLINK(ArgsArr); + ArgParser parser; + opt::InputArgList args = parser.parseLINK(argsArr); // Parse and evaluate -mllvm options. - std::vector V; - V.push_back("lld-link (LLVM option parsing)"); - for (auto *Arg : Args.filtered(OPT_mllvm)) - V.push_back(Arg->getValue()); - cl::ParseCommandLineOptions(V.size(), V.data()); + std::vector v; + v.push_back("lld-link (LLVM option parsing)"); + for (auto *arg : args.filtered(OPT_mllvm)) + v.push_back(arg->getValue()); + cl::ParseCommandLineOptions(v.size(), v.data()); // Handle /errorlimit early, because error() depends on it. - if (auto *Arg = Args.getLastArg(OPT_errorlimit)) { - int N = 20; - StringRef S = Arg->getValue(); - if (S.getAsInteger(10, N)) - error(Arg->getSpelling() + " number expected, but got " + S); - errorHandler().ErrorLimit = N; + if (auto *arg = args.getLastArg(OPT_errorlimit)) { + int n = 20; + StringRef s = arg->getValue(); + if (s.getAsInteger(10, n)) + error(arg->getSpelling() + " number expected, but got " + s); + errorHandler().errorLimit = n; } // Handle /help - if (Args.hasArg(OPT_help)) { - printHelp(ArgsArr[0]); + if (args.hasArg(OPT_help)) { + printHelp(argsArr[0]); return; } - lld::ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_threads_no, true); + lld::threadsEnabled = args.hasFlag(OPT_threads, OPT_threads_no, true); - if (Args.hasArg(OPT_show_timing)) - Config->ShowTiming = true; + if (args.hasArg(OPT_show_timing)) + config->showTiming = true; - Config->ShowSummary = Args.hasArg(OPT_summary); + config->showSummary = args.hasArg(OPT_summary); - ScopedTimer T(Timer::root()); + ScopedTimer t(Timer::root()); // Handle --version, which is an lld extension. This option is a bit odd // because it doesn't start with "/", but we deliberately chose "--" to // avoid conflict with /version and for compatibility with clang-cl. - if (Args.hasArg(OPT_dash_dash_version)) { + if (args.hasArg(OPT_dash_dash_version)) { outs() << getLLDVersion() << "\n"; return; } // Handle /lldmingw early, since it can potentially affect how other // options are handled. - Config->MinGW = Args.hasArg(OPT_lldmingw); + config->mingw = args.hasArg(OPT_lldmingw); - if (auto *Arg = Args.getLastArg(OPT_linkrepro)) { - SmallString<64> Path = StringRef(Arg->getValue()); - sys::path::append(Path, "repro.tar"); + if (auto *arg = args.getLastArg(OPT_linkrepro)) { + SmallString<64> path = StringRef(arg->getValue()); + sys::path::append(path, "repro.tar"); - Expected> ErrOrWriter = - TarWriter::create(Path, "repro"); + Expected> errOrWriter = + TarWriter::create(path, "repro"); - if (ErrOrWriter) { - Tar = std::move(*ErrOrWriter); + if (errOrWriter) { + tar = std::move(*errOrWriter); } else { - error("/linkrepro: failed to open " + Path + ": " + - toString(ErrOrWriter.takeError())); + error("/linkrepro: failed to open " + path + ": " + + toString(errOrWriter.takeError())); } } - if (!Args.hasArg(OPT_INPUT)) { - if (Args.hasArg(OPT_deffile)) - Config->NoEntry = true; + if (!args.hasArg(OPT_INPUT)) { + if (args.hasArg(OPT_deffile)) + config->noEntry = true; else fatal("no input files"); } // Construct search path list. - SearchPaths.push_back(""); - for (auto *Arg : Args.filtered(OPT_libpath)) - SearchPaths.push_back(Arg->getValue()); + searchPaths.push_back(""); + for (auto *arg : args.filtered(OPT_libpath)) + searchPaths.push_back(arg->getValue()); addLibSearchPaths(); // Handle /ignore - for (auto *Arg : Args.filtered(OPT_ignore)) { - SmallVector Vec; - StringRef(Arg->getValue()).split(Vec, ','); - for (StringRef S : Vec) { - if (S == "4037") - Config->WarnMissingOrderSymbol = false; - else if (S == "4099") - Config->WarnDebugInfoUnusable = false; - else if (S == "4217") - Config->WarnLocallyDefinedImported = false; + for (auto *arg : args.filtered(OPT_ignore)) { + SmallVector vec; + StringRef(arg->getValue()).split(vec, ','); + for (StringRef s : vec) { + if (s == "4037") + config->warnMissingOrderSymbol = false; + else if (s == "4099") + config->warnDebugInfoUnusable = false; + else if (s == "4217") + config->warnLocallyDefinedImported = false; // Other warning numbers are ignored. } } // Handle /out - if (auto *Arg = Args.getLastArg(OPT_out)) - Config->OutputFile = Arg->getValue(); + if (auto *arg = args.getLastArg(OPT_out)) + config->outputFile = arg->getValue(); // Handle /verbose - if (Args.hasArg(OPT_verbose)) - Config->Verbose = true; - errorHandler().Verbose = Config->Verbose; + if (args.hasArg(OPT_verbose)) + config->verbose = true; + errorHandler().verbose = config->verbose; // Handle /force or /force:unresolved - if (Args.hasArg(OPT_force, OPT_force_unresolved)) - Config->ForceUnresolved = true; + if (args.hasArg(OPT_force, OPT_force_unresolved)) + config->forceUnresolved = true; // Handle /force or /force:multiple - if (Args.hasArg(OPT_force, OPT_force_multiple)) - Config->ForceMultiple = true; + if (args.hasArg(OPT_force, OPT_force_multiple)) + config->forceMultiple = true; // Handle /force or /force:multipleres - if (Args.hasArg(OPT_force, OPT_force_multipleres)) - Config->ForceMultipleRes = true; + if (args.hasArg(OPT_force, OPT_force_multipleres)) + config->forceMultipleRes = true; // Handle /debug - DebugKind Debug = parseDebugKind(Args); - if (Debug == DebugKind::Full || Debug == DebugKind::Dwarf || - Debug == DebugKind::GHash) { - Config->Debug = true; - Config->Incremental = true; + DebugKind debug = parseDebugKind(args); + if (debug == DebugKind::Full || debug == DebugKind::Dwarf || + debug == DebugKind::GHash) { + config->debug = true; + config->incremental = true; } // Handle /demangle - Config->Demangle = Args.hasFlag(OPT_demangle, OPT_demangle_no); + config->demangle = args.hasFlag(OPT_demangle, OPT_demangle_no); // Handle /debugtype - Config->DebugTypes = parseDebugTypes(Args); + config->debugTypes = parseDebugTypes(args); // Handle /pdb - bool ShouldCreatePDB = - (Debug == DebugKind::Full || Debug == DebugKind::GHash); - if (ShouldCreatePDB) { - if (auto *Arg = Args.getLastArg(OPT_pdb)) - Config->PDBPath = Arg->getValue(); - if (auto *Arg = Args.getLastArg(OPT_pdbaltpath)) - Config->PDBAltPath = Arg->getValue(); - if (Args.hasArg(OPT_natvis)) - Config->NatvisFiles = Args.getAllArgValues(OPT_natvis); + bool shouldCreatePDB = + (debug == DebugKind::Full || debug == DebugKind::GHash); + if (shouldCreatePDB) { + if (auto *arg = args.getLastArg(OPT_pdb)) + config->pdbPath = arg->getValue(); + if (auto *arg = args.getLastArg(OPT_pdbaltpath)) + config->pdbAltPath = arg->getValue(); + if (args.hasArg(OPT_natvis)) + config->natvisFiles = args.getAllArgValues(OPT_natvis); - if (auto *Arg = Args.getLastArg(OPT_pdb_source_path)) - Config->PDBSourcePath = Arg->getValue(); + if (auto *arg = args.getLastArg(OPT_pdb_source_path)) + config->pdbSourcePath = arg->getValue(); } // Handle /noentry - if (Args.hasArg(OPT_noentry)) { - if (Args.hasArg(OPT_dll)) - Config->NoEntry = true; + if (args.hasArg(OPT_noentry)) { + if (args.hasArg(OPT_dll)) + config->noEntry = true; else error("/noentry must be specified with /dll"); } // Handle /dll - if (Args.hasArg(OPT_dll)) { - Config->DLL = true; - Config->ManifestID = 2; + if (args.hasArg(OPT_dll)) { + config->dll = true; + config->manifestID = 2; } // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase // because we need to explicitly check whether that option or its inverse was // present in the argument list in order to handle /fixed. - auto *DynamicBaseArg = Args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no); - if (DynamicBaseArg && - DynamicBaseArg->getOption().getID() == OPT_dynamicbase_no) - Config->DynamicBase = false; + auto *dynamicBaseArg = args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no); + if (dynamicBaseArg && + dynamicBaseArg->getOption().getID() == OPT_dynamicbase_no) + config->dynamicBase = false; // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the // default setting for any other project type.", but link.exe defaults to // /FIXED:NO for exe outputs as well. Match behavior, not docs. - bool Fixed = Args.hasFlag(OPT_fixed, OPT_fixed_no, false); - if (Fixed) { - if (DynamicBaseArg && - DynamicBaseArg->getOption().getID() == OPT_dynamicbase) { + bool fixed = args.hasFlag(OPT_fixed, OPT_fixed_no, false); + if (fixed) { + if (dynamicBaseArg && + dynamicBaseArg->getOption().getID() == OPT_dynamicbase) { error("/fixed must not be specified with /dynamicbase"); } else { - Config->Relocatable = false; - Config->DynamicBase = false; + config->relocatable = false; + config->dynamicBase = false; } } // Handle /appcontainer - Config->AppContainer = - Args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false); + config->appContainer = + args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false); // Handle /machine - if (auto *Arg = Args.getLastArg(OPT_machine)) { - Config->Machine = getMachineType(Arg->getValue()); - if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) - fatal(Twine("unknown /machine argument: ") + Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_machine)) { + config->machine = getMachineType(arg->getValue()); + if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) + fatal(Twine("unknown /machine argument: ") + arg->getValue()); } // Handle /nodefaultlib: - for (auto *Arg : Args.filtered(OPT_nodefaultlib)) - Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()).lower()); + for (auto *arg : args.filtered(OPT_nodefaultlib)) + config->noDefaultLibs.insert(doFindLib(arg->getValue()).lower()); // Handle /nodefaultlib - if (Args.hasArg(OPT_nodefaultlib_all)) - Config->NoDefaultLibAll = true; + if (args.hasArg(OPT_nodefaultlib_all)) + config->noDefaultLibAll = true; // Handle /base - if (auto *Arg = Args.getLastArg(OPT_base)) - parseNumbers(Arg->getValue(), &Config->ImageBase); + if (auto *arg = args.getLastArg(OPT_base)) + parseNumbers(arg->getValue(), &config->imageBase); // Handle /filealign - if (auto *Arg = Args.getLastArg(OPT_filealign)) { - parseNumbers(Arg->getValue(), &Config->FileAlign); - if (!isPowerOf2_64(Config->FileAlign)) - error("/filealign: not a power of two: " + Twine(Config->FileAlign)); + if (auto *arg = args.getLastArg(OPT_filealign)) { + parseNumbers(arg->getValue(), &config->fileAlign); + if (!isPowerOf2_64(config->fileAlign)) + error("/filealign: not a power of two: " + Twine(config->fileAlign)); } // Handle /stack - if (auto *Arg = Args.getLastArg(OPT_stack)) - parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit); + if (auto *arg = args.getLastArg(OPT_stack)) + parseNumbers(arg->getValue(), &config->stackReserve, &config->stackCommit); // Handle /guard:cf - if (auto *Arg = Args.getLastArg(OPT_guard)) - parseGuard(Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_guard)) + parseGuard(arg->getValue()); // Handle /heap - if (auto *Arg = Args.getLastArg(OPT_heap)) - parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit); + if (auto *arg = args.getLastArg(OPT_heap)) + parseNumbers(arg->getValue(), &config->heapReserve, &config->heapCommit); // Handle /version - if (auto *Arg = Args.getLastArg(OPT_version)) - parseVersion(Arg->getValue(), &Config->MajorImageVersion, - &Config->MinorImageVersion); + if (auto *arg = args.getLastArg(OPT_version)) + parseVersion(arg->getValue(), &config->majorImageVersion, + &config->minorImageVersion); // Handle /subsystem - if (auto *Arg = Args.getLastArg(OPT_subsystem)) - parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion, - &Config->MinorOSVersion); + if (auto *arg = args.getLastArg(OPT_subsystem)) + parseSubsystem(arg->getValue(), &config->subsystem, &config->majorOSVersion, + &config->minorOSVersion); // Handle /timestamp - if (llvm::opt::Arg *Arg = Args.getLastArg(OPT_timestamp, OPT_repro)) { - if (Arg->getOption().getID() == OPT_repro) { - Config->Timestamp = 0; - Config->Repro = true; + if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) { + if (arg->getOption().getID() == OPT_repro) { + config->timestamp = 0; + config->repro = true; } else { - Config->Repro = false; - StringRef Value(Arg->getValue()); - if (Value.getAsInteger(0, Config->Timestamp)) - fatal(Twine("invalid timestamp: ") + Value + + config->repro = false; + StringRef value(arg->getValue()); + if (value.getAsInteger(0, config->timestamp)) + fatal(Twine("invalid timestamp: ") + value + ". Expected 32-bit integer"); } } else { - Config->Repro = false; - Config->Timestamp = time(nullptr); + config->repro = false; + config->timestamp = time(nullptr); } // Handle /alternatename - for (auto *Arg : Args.filtered(OPT_alternatename)) - parseAlternateName(Arg->getValue()); + for (auto *arg : args.filtered(OPT_alternatename)) + parseAlternateName(arg->getValue()); // Handle /include - for (auto *Arg : Args.filtered(OPT_incl)) - addUndefined(Arg->getValue()); + for (auto *arg : args.filtered(OPT_incl)) + addUndefined(arg->getValue()); // Handle /implib - if (auto *Arg = Args.getLastArg(OPT_implib)) - Config->Implib = Arg->getValue(); + if (auto *arg = args.getLastArg(OPT_implib)) + config->implib = arg->getValue(); // Handle /opt. - bool DoGC = Debug == DebugKind::None || Args.hasArg(OPT_profile); - unsigned ICFLevel = - Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on - unsigned TailMerge = 1; - for (auto *Arg : Args.filtered(OPT_opt)) { - std::string Str = StringRef(Arg->getValue()).lower(); - SmallVector Vec; - StringRef(Str).split(Vec, ','); - for (StringRef S : Vec) { - if (S == "ref") { - DoGC = true; - } else if (S == "noref") { - DoGC = false; - } else if (S == "icf" || S.startswith("icf=")) { - ICFLevel = 2; - } else if (S == "noicf") { - ICFLevel = 0; - } else if (S == "lldtailmerge") { - TailMerge = 2; - } else if (S == "nolldtailmerge") { - TailMerge = 0; - } else if (S.startswith("lldlto=")) { - StringRef OptLevel = S.substr(7); - if (OptLevel.getAsInteger(10, Config->LTOO) || Config->LTOO > 3) - error("/opt:lldlto: invalid optimization level: " + OptLevel); - } else if (S.startswith("lldltojobs=")) { - StringRef Jobs = S.substr(11); - if (Jobs.getAsInteger(10, Config->ThinLTOJobs) || - Config->ThinLTOJobs == 0) - error("/opt:lldltojobs: invalid job count: " + Jobs); - } else if (S.startswith("lldltopartitions=")) { - StringRef N = S.substr(17); - if (N.getAsInteger(10, Config->LTOPartitions) || - Config->LTOPartitions == 0) - error("/opt:lldltopartitions: invalid partition count: " + N); - } else if (S != "lbr" && S != "nolbr") - error("/opt: unknown option: " + S); + bool doGC = debug == DebugKind::None || args.hasArg(OPT_profile); + unsigned icfLevel = + args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on + unsigned tailMerge = 1; + for (auto *arg : args.filtered(OPT_opt)) { + std::string str = StringRef(arg->getValue()).lower(); + SmallVector vec; + StringRef(str).split(vec, ','); + for (StringRef s : vec) { + if (s == "ref") { + doGC = true; + } else if (s == "noref") { + doGC = false; + } else if (s == "icf" || s.startswith("icf=")) { + icfLevel = 2; + } else if (s == "noicf") { + icfLevel = 0; + } else if (s == "lldtailmerge") { + tailMerge = 2; + } else if (s == "nolldtailmerge") { + tailMerge = 0; + } else if (s.startswith("lldlto=")) { + StringRef optLevel = s.substr(7); + if (optLevel.getAsInteger(10, config->ltoo) || config->ltoo > 3) + error("/opt:lldlto: invalid optimization level: " + optLevel); + } else if (s.startswith("lldltojobs=")) { + StringRef jobs = s.substr(11); + if (jobs.getAsInteger(10, config->thinLTOJobs) || + config->thinLTOJobs == 0) + error("/opt:lldltojobs: invalid job count: " + jobs); + } else if (s.startswith("lldltopartitions=")) { + StringRef n = s.substr(17); + if (n.getAsInteger(10, config->ltoPartitions) || + config->ltoPartitions == 0) + error("/opt:lldltopartitions: invalid partition count: " + n); + } else if (s != "lbr" && s != "nolbr") + error("/opt: unknown option: " + s); } } @@ -1355,37 +1355,37 @@ // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical // code. If the user passes /OPT:ICF explicitly, LLD should merge identical // comdat readonly data. - if (ICFLevel == 1 && !DoGC) - ICFLevel = 0; - Config->DoGC = DoGC; - Config->DoICF = ICFLevel > 0; - Config->TailMerge = (TailMerge == 1 && Config->DoICF) || TailMerge == 2; + if (icfLevel == 1 && !doGC) + icfLevel = 0; + config->doGC = doGC; + config->doICF = icfLevel > 0; + config->tailMerge = (tailMerge == 1 && config->doICF) || tailMerge == 2; // Handle /lldsavetemps - if (Args.hasArg(OPT_lldsavetemps)) - Config->SaveTemps = true; + if (args.hasArg(OPT_lldsavetemps)) + config->saveTemps = true; // Handle /kill-at - if (Args.hasArg(OPT_kill_at)) - Config->KillAt = true; + if (args.hasArg(OPT_kill_at)) + config->killAt = true; // Handle /lldltocache - if (auto *Arg = Args.getLastArg(OPT_lldltocache)) - Config->LTOCache = Arg->getValue(); + if (auto *arg = args.getLastArg(OPT_lldltocache)) + config->ltoCache = arg->getValue(); // Handle /lldsavecachepolicy - if (auto *Arg = Args.getLastArg(OPT_lldltocachepolicy)) - Config->LTOCachePolicy = CHECK( - parseCachePruningPolicy(Arg->getValue()), - Twine("/lldltocachepolicy: invalid cache policy: ") + Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_lldltocachepolicy)) + config->ltoCachePolicy = CHECK( + parseCachePruningPolicy(arg->getValue()), + Twine("/lldltocachepolicy: invalid cache policy: ") + arg->getValue()); // Handle /failifmismatch - for (auto *Arg : Args.filtered(OPT_failifmismatch)) - checkFailIfMismatch(Arg->getValue(), nullptr); + for (auto *arg : args.filtered(OPT_failifmismatch)) + checkFailIfMismatch(arg->getValue(), nullptr); // Handle /merge - for (auto *Arg : Args.filtered(OPT_merge)) - parseMerge(Arg->getValue()); + for (auto *arg : args.filtered(OPT_merge)) + parseMerge(arg->getValue()); // Add default section merging rules after user rules. User rules take // precedence, but we will emit a warning if there is a conflict. @@ -1395,128 +1395,128 @@ parseMerge(".xdata=.rdata"); parseMerge(".bss=.data"); - if (Config->MinGW) { + if (config->mingw) { parseMerge(".ctors=.rdata"); parseMerge(".dtors=.rdata"); parseMerge(".CRT=.rdata"); } // Handle /section - for (auto *Arg : Args.filtered(OPT_section)) - parseSection(Arg->getValue()); + for (auto *arg : args.filtered(OPT_section)) + parseSection(arg->getValue()); // Handle /aligncomm - for (auto *Arg : Args.filtered(OPT_aligncomm)) - parseAligncomm(Arg->getValue()); + for (auto *arg : args.filtered(OPT_aligncomm)) + parseAligncomm(arg->getValue()); // Handle /manifestdependency. This enables /manifest unless /manifest:no is // also passed. - if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) { - Config->ManifestDependency = Arg->getValue(); - Config->Manifest = Configuration::SideBySide; + if (auto *arg = args.getLastArg(OPT_manifestdependency)) { + config->manifestDependency = arg->getValue(); + config->manifest = Configuration::SideBySide; } // Handle /manifest and /manifest: - if (auto *Arg = Args.getLastArg(OPT_manifest, OPT_manifest_colon)) { - if (Arg->getOption().getID() == OPT_manifest) - Config->Manifest = Configuration::SideBySide; + if (auto *arg = args.getLastArg(OPT_manifest, OPT_manifest_colon)) { + if (arg->getOption().getID() == OPT_manifest) + config->manifest = Configuration::SideBySide; else - parseManifest(Arg->getValue()); + parseManifest(arg->getValue()); } // Handle /manifestuac - if (auto *Arg = Args.getLastArg(OPT_manifestuac)) - parseManifestUAC(Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_manifestuac)) + parseManifestUAC(arg->getValue()); // Handle /manifestfile - if (auto *Arg = Args.getLastArg(OPT_manifestfile)) - Config->ManifestFile = Arg->getValue(); + if (auto *arg = args.getLastArg(OPT_manifestfile)) + config->manifestFile = arg->getValue(); // Handle /manifestinput - for (auto *Arg : Args.filtered(OPT_manifestinput)) - Config->ManifestInput.push_back(Arg->getValue()); + for (auto *arg : args.filtered(OPT_manifestinput)) + config->manifestInput.push_back(arg->getValue()); - if (!Config->ManifestInput.empty() && - Config->Manifest != Configuration::Embed) { + if (!config->manifestInput.empty() && + config->manifest != Configuration::Embed) { fatal("/manifestinput: requires /manifest:embed"); } // Handle miscellaneous boolean flags. - Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true); - Config->AllowIsolation = - Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true); - Config->Incremental = - Args.hasFlag(OPT_incremental, OPT_incremental_no, - !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order) && - !Args.hasArg(OPT_profile)); - Config->IntegrityCheck = - Args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false); - Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); - for (auto *Arg : Args.filtered(OPT_swaprun)) - parseSwaprun(Arg->getValue()); - Config->TerminalServerAware = - !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); - Config->DebugDwarf = Debug == DebugKind::Dwarf; - Config->DebugGHashes = Debug == DebugKind::GHash; - Config->DebugSymtab = Debug == DebugKind::Symtab; + config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true); + config->allowIsolation = + args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true); + config->incremental = + args.hasFlag(OPT_incremental, OPT_incremental_no, + !config->doGC && !config->doICF && !args.hasArg(OPT_order) && + !args.hasArg(OPT_profile)); + config->integrityCheck = + args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false); + config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); + for (auto *arg : args.filtered(OPT_swaprun)) + parseSwaprun(arg->getValue()); + config->terminalServerAware = + !config->dll && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); + config->debugDwarf = debug == DebugKind::Dwarf; + config->debugGHashes = debug == DebugKind::GHash; + config->debugSymtab = debug == DebugKind::Symtab; - Config->MapFile = getMapFile(Args); + config->mapFile = getMapFile(args); - if (Config->Incremental && Args.hasArg(OPT_profile)) { + if (config->incremental && args.hasArg(OPT_profile)) { warn("ignoring '/incremental' due to '/profile' specification"); - Config->Incremental = false; + config->incremental = false; } - if (Config->Incremental && Args.hasArg(OPT_order)) { + if (config->incremental && args.hasArg(OPT_order)) { warn("ignoring '/incremental' due to '/order' specification"); - Config->Incremental = false; + config->incremental = false; } - if (Config->Incremental && Config->DoGC) { + if (config->incremental && config->doGC) { warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to " "disable"); - Config->Incremental = false; + config->incremental = false; } - if (Config->Incremental && Config->DoICF) { + if (config->incremental && config->doICF) { warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to " "disable"); - Config->Incremental = false; + config->incremental = false; } if (errorCount()) return; - std::set WholeArchives; - for (auto *Arg : Args.filtered(OPT_wholearchive_file)) - if (Optional Path = doFindFile(Arg->getValue())) - if (Optional ID = getUniqueID(*Path)) - WholeArchives.insert(*ID); + std::set wholeArchives; + for (auto *arg : args.filtered(OPT_wholearchive_file)) + if (Optional path = doFindFile(arg->getValue())) + if (Optional id = getUniqueID(*path)) + wholeArchives.insert(*id); // A predicate returning true if a given path is an argument for // /wholearchive:, or /wholearchive is enabled globally. // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj" // needs to be handled as "/wholearchive:foo.obj foo.obj". - auto IsWholeArchive = [&](StringRef Path) -> bool { - if (Args.hasArg(OPT_wholearchive_flag)) + auto isWholeArchive = [&](StringRef path) -> bool { + if (args.hasArg(OPT_wholearchive_flag)) return true; - if (Optional ID = getUniqueID(Path)) - return WholeArchives.count(*ID); + if (Optional id = getUniqueID(path)) + return wholeArchives.count(*id); return false; }; // Create a list of input files. Files can be given as arguments // for /defaultlib option. - for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) - if (Optional Path = findFile(Arg->getValue())) - enqueuePath(*Path, IsWholeArchive(*Path)); - - for (auto *Arg : Args.filtered(OPT_defaultlib)) - if (Optional Path = findLib(Arg->getValue())) - enqueuePath(*Path, false); + for (auto *arg : args.filtered(OPT_INPUT, OPT_wholearchive_file)) + if (Optional path = findFile(arg->getValue())) + enqueuePath(*path, isWholeArchive(*path)); + + for (auto *arg : args.filtered(OPT_defaultlib)) + if (Optional path = findLib(arg->getValue())) + enqueuePath(*path, false); // Windows specific -- Create a resource file containing a manifest file. - if (Config->Manifest == Configuration::Embed) + if (config->manifest == Configuration::Embed) addBuffer(createManifestRes(), false); // Read all input files given via the command line. @@ -1527,61 +1527,61 @@ // We should have inferred a machine type by now from the input files, but if // not we assume x64. - if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) { + if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) { warn("/machine is not specified. x64 is assumed"); - Config->Machine = AMD64; + config->machine = AMD64; } - Config->Wordsize = Config->is64() ? 8 : 4; + config->wordsize = config->is64() ? 8 : 4; // Handle /functionpadmin - for (auto *Arg : Args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt)) - parseFunctionPadMin(Arg, Config->Machine); + for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt)) + parseFunctionPadMin(arg, config->machine); // Input files can be Windows resource files (.res files). We use // WindowsResource to convert resource files to a regular COFF file, // then link the resulting file normally. - if (!Resources.empty()) - Symtab->addFile(make(convertResToCOFF(Resources))); + if (!resources.empty()) + symtab->addFile(make(convertResToCOFF(resources))); - if (Tar) - Tar->append("response.txt", - createResponseFile(Args, FilePaths, - ArrayRef(SearchPaths).slice(1))); + if (tar) + tar->append("response.txt", + createResponseFile(args, filePaths, + ArrayRef(searchPaths).slice(1))); // Handle /largeaddressaware - Config->LargeAddressAware = Args.hasFlag( - OPT_largeaddressaware, OPT_largeaddressaware_no, Config->is64()); + config->largeAddressAware = args.hasFlag( + OPT_largeaddressaware, OPT_largeaddressaware_no, config->is64()); // Handle /highentropyva - Config->HighEntropyVA = - Config->is64() && - Args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true); + config->highEntropyVA = + config->is64() && + args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true); - if (!Config->DynamicBase && - (Config->Machine == ARMNT || Config->Machine == ARM64)) + if (!config->dynamicBase && + (config->machine == ARMNT || config->machine == ARM64)) error("/dynamicbase:no is not compatible with " + - machineToStr(Config->Machine)); + machineToStr(config->machine)); // Handle /export - for (auto *Arg : Args.filtered(OPT_export)) { - Export E = parseExport(Arg->getValue()); - if (Config->Machine == I386) { - if (!isDecorated(E.Name)) - E.Name = Saver.save("_" + E.Name); - if (!E.ExtName.empty() && !isDecorated(E.ExtName)) - E.ExtName = Saver.save("_" + E.ExtName); + for (auto *arg : args.filtered(OPT_export)) { + Export e = parseExport(arg->getValue()); + if (config->machine == I386) { + if (!isDecorated(e.name)) + e.name = saver.save("_" + e.name); + if (!e.extName.empty() && !isDecorated(e.extName)) + e.extName = saver.save("_" + e.extName); } - Config->Exports.push_back(E); + config->exports.push_back(e); } // Handle /def - if (auto *Arg = Args.getLastArg(OPT_deffile)) { + if (auto *arg = args.getLastArg(OPT_deffile)) { // parseModuleDefs mutates Config object. - parseModuleDefs(Arg->getValue()); + parseModuleDefs(arg->getValue()); } // Handle generation of import library from a def file. - if (!Args.hasArg(OPT_INPUT)) { + if (!args.hasArg(OPT_INPUT)) { fixupExports(); createImportLibrary(/*AsLib=*/true); return; @@ -1590,101 +1590,101 @@ // Windows specific -- if no /subsystem is given, we need to infer // that from entry point name. Must happen before /entry handling, // and after the early return when just writing an import library. - if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) { - Config->Subsystem = inferSubsystem(); - if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) + if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) { + config->subsystem = inferSubsystem(); + if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) fatal("subsystem must be defined"); } // Handle /entry and /dll - if (auto *Arg = Args.getLastArg(OPT_entry)) { - Config->Entry = addUndefined(mangle(Arg->getValue())); - } else if (!Config->Entry && !Config->NoEntry) { - if (Args.hasArg(OPT_dll)) { - StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12" + if (auto *arg = args.getLastArg(OPT_entry)) { + config->entry = addUndefined(mangle(arg->getValue())); + } else if (!config->entry && !config->noEntry) { + if (args.hasArg(OPT_dll)) { + StringRef s = (config->machine == I386) ? "__DllMainCRTStartup@12" : "_DllMainCRTStartup"; - Config->Entry = addUndefined(S); + config->entry = addUndefined(s); } else { // Windows specific -- If entry point name is not given, we need to // infer that from user-defined entry name. - StringRef S = findDefaultEntry(); - if (S.empty()) + StringRef s = findDefaultEntry(); + if (s.empty()) fatal("entry point must be defined"); - Config->Entry = addUndefined(S); - log("Entry name inferred: " + S); + config->entry = addUndefined(s); + log("Entry name inferred: " + s); } } // Handle /delayload - for (auto *Arg : Args.filtered(OPT_delayload)) { - Config->DelayLoads.insert(StringRef(Arg->getValue()).lower()); - if (Config->Machine == I386) { - Config->DelayLoadHelper = addUndefined("___delayLoadHelper2@8"); + for (auto *arg : args.filtered(OPT_delayload)) { + config->delayLoads.insert(StringRef(arg->getValue()).lower()); + if (config->machine == I386) { + config->delayLoadHelper = addUndefined("___delayLoadHelper2@8"); } else { - Config->DelayLoadHelper = addUndefined("__delayLoadHelper2"); + config->delayLoadHelper = addUndefined("__delayLoadHelper2"); } } // Set default image name if neither /out or /def set it. - if (Config->OutputFile.empty()) { - Config->OutputFile = - getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue()); + if (config->outputFile.empty()) { + config->outputFile = + getOutputPath((*args.filtered(OPT_INPUT).begin())->getValue()); } // Fail early if an output file is not writable. - if (auto E = tryCreateFile(Config->OutputFile)) { - error("cannot open output file " + Config->OutputFile + ": " + E.message()); + if (auto e = tryCreateFile(config->outputFile)) { + error("cannot open output file " + config->outputFile + ": " + e.message()); return; } - if (ShouldCreatePDB) { + if (shouldCreatePDB) { // Put the PDB next to the image if no /pdb flag was passed. - if (Config->PDBPath.empty()) { - Config->PDBPath = Config->OutputFile; - sys::path::replace_extension(Config->PDBPath, ".pdb"); + if (config->pdbPath.empty()) { + config->pdbPath = config->outputFile; + sys::path::replace_extension(config->pdbPath, ".pdb"); } // The embedded PDB path should be the absolute path to the PDB if no // /pdbaltpath flag was passed. - if (Config->PDBAltPath.empty()) { - Config->PDBAltPath = Config->PDBPath; + if (config->pdbAltPath.empty()) { + config->pdbAltPath = config->pdbPath; // It's important to make the path absolute and remove dots. This path // will eventually be written into the PE header, and certain Microsoft // tools won't work correctly if these assumptions are not held. - sys::fs::make_absolute(Config->PDBAltPath); - sys::path::remove_dots(Config->PDBAltPath); + sys::fs::make_absolute(config->pdbAltPath); + sys::path::remove_dots(config->pdbAltPath); } else { // Don't do this earlier, so that Config->OutputFile is ready. - parsePDBAltPath(Config->PDBAltPath); + parsePDBAltPath(config->pdbAltPath); } } // Set default image base if /base is not given. - if (Config->ImageBase == uint64_t(-1)) - Config->ImageBase = getDefaultImageBase(); + if (config->imageBase == uint64_t(-1)) + config->imageBase = getDefaultImageBase(); - Symtab->addSynthetic(mangle("__ImageBase"), nullptr); - if (Config->Machine == I386) { - Symtab->addAbsolute("___safe_se_handler_table", 0); - Symtab->addAbsolute("___safe_se_handler_count", 0); - } - - Symtab->addAbsolute(mangle("__guard_fids_count"), 0); - Symtab->addAbsolute(mangle("__guard_fids_table"), 0); - Symtab->addAbsolute(mangle("__guard_flags"), 0); - Symtab->addAbsolute(mangle("__guard_iat_count"), 0); - Symtab->addAbsolute(mangle("__guard_iat_table"), 0); - Symtab->addAbsolute(mangle("__guard_longjmp_count"), 0); - Symtab->addAbsolute(mangle("__guard_longjmp_table"), 0); + symtab->addSynthetic(mangle("__ImageBase"), nullptr); + if (config->machine == I386) { + symtab->addAbsolute("___safe_se_handler_table", 0); + symtab->addAbsolute("___safe_se_handler_count", 0); + } + + symtab->addAbsolute(mangle("__guard_fids_count"), 0); + symtab->addAbsolute(mangle("__guard_fids_table"), 0); + symtab->addAbsolute(mangle("__guard_flags"), 0); + symtab->addAbsolute(mangle("__guard_iat_count"), 0); + symtab->addAbsolute(mangle("__guard_iat_table"), 0); + symtab->addAbsolute(mangle("__guard_longjmp_count"), 0); + symtab->addAbsolute(mangle("__guard_longjmp_table"), 0); // Needed for MSVC 2017 15.5 CRT. - Symtab->addAbsolute(mangle("__enclave_config"), 0); + symtab->addAbsolute(mangle("__enclave_config"), 0); - if (Config->MinGW) { - Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0); - Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0); - Symtab->addAbsolute(mangle("__CTOR_LIST__"), 0); - Symtab->addAbsolute(mangle("__DTOR_LIST__"), 0); + if (config->mingw) { + symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0); + symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0); + symtab->addAbsolute(mangle("__CTOR_LIST__"), 0); + symtab->addAbsolute(mangle("__DTOR_LIST__"), 0); } // This code may add new undefined symbols to the link, which may enqueue more @@ -1693,33 +1693,33 @@ do { // Windows specific -- if entry point is not found, // search for its mangled names. - if (Config->Entry) - mangleMaybe(Config->Entry); + if (config->entry) + mangleMaybe(config->entry); // Windows specific -- Make sure we resolve all dllexported symbols. - for (Export &E : Config->Exports) { - if (!E.ForwardTo.empty()) + for (Export &e : config->exports) { + if (!e.forwardTo.empty()) continue; - E.Sym = addUndefined(E.Name); - if (!E.Directives) - E.SymbolName = mangleMaybe(E.Sym); + e.sym = addUndefined(e.name); + if (!e.directives) + e.symbolName = mangleMaybe(e.sym); } // Add weak aliases. Weak aliases is a mechanism to give remaining // undefined symbols final chance to be resolved successfully. - for (auto Pair : Config->AlternateNames) { - StringRef From = Pair.first; - StringRef To = Pair.second; - Symbol *Sym = Symtab->find(From); - if (!Sym) + for (auto pair : config->alternateNames) { + StringRef from = pair.first; + StringRef to = pair.second; + Symbol *sym = symtab->find(from); + if (!sym) continue; - if (auto *U = dyn_cast(Sym)) - if (!U->WeakAlias) - U->WeakAlias = Symtab->addUndefined(To); + if (auto *u = dyn_cast(sym)) + if (!u->weakAlias) + u->weakAlias = symtab->addUndefined(to); } // Windows specific -- if __load_config_used can be resolved, resolve it. - if (Symtab->findUnderscore("_load_config_used")) + if (symtab->findUnderscore("_load_config_used")) addUndefined(mangle("_load_config_used")); } while (run()); @@ -1728,18 +1728,18 @@ // Do LTO by compiling bitcode input files to a set of native COFF files then // link those files. - Symtab->addCombinedLTOObjects(); + symtab->addCombinedLTOObjects(); run(); - if (Args.hasArg(OPT_include_optional)) { + if (args.hasArg(OPT_include_optional)) { // Handle /includeoptional - for (auto *Arg : Args.filtered(OPT_include_optional)) - if (dyn_cast_or_null(Symtab->find(Arg->getValue()))) - addUndefined(Arg->getValue()); + for (auto *arg : args.filtered(OPT_include_optional)) + if (dyn_cast_or_null(symtab->find(arg->getValue()))) + addUndefined(arg->getValue()); while (run()); } - if (Config->MinGW) { + if (config->mingw) { // Load any further object files that might be needed for doing automatic // imports. // @@ -1753,28 +1753,28 @@ // normal object file as well (although that won't be used for the // actual autoimport later on). If this pass adds new undefined references, // we won't iterate further to resolve them. - Symtab->loadMinGWAutomaticImports(); + symtab->loadMinGWAutomaticImports(); run(); } // Make sure we have resolved all symbols. - Symtab->reportRemainingUndefines(); + symtab->reportRemainingUndefines(); if (errorCount()) return; // Handle /safeseh. - if (Args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) { - for (ObjFile *File : ObjFile::Instances) - if (!File->hasSafeSEH()) - error("/safeseh: " + File->getName() + " is not compatible with SEH"); + if (args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) { + for (ObjFile *file : ObjFile::instances) + if (!file->hasSafeSEH()) + error("/safeseh: " + file->getName() + " is not compatible with SEH"); if (errorCount()) return; } - if (Config->MinGW) { + if (config->mingw) { // In MinGW, all symbols are automatically exported if no symbols // are chosen to be exported. - maybeExportMinGWSymbols(Args); + maybeExportMinGWSymbols(args); // Make sure the crtend.o object is the last object file. This object // file can contain terminating section chunks that need to be placed @@ -1782,12 +1782,12 @@ // order provided on the command line, while lld will pull in needed // files from static libraries only after the last object file on the // command line. - for (auto I = ObjFile::Instances.begin(), E = ObjFile::Instances.end(); - I != E; I++) { - ObjFile *File = *I; - if (isCrtend(File->getName())) { - ObjFile::Instances.erase(I); - ObjFile::Instances.push_back(File); + for (auto i = ObjFile::instances.begin(), e = ObjFile::instances.end(); + i != e; i++) { + ObjFile *file = *i; + if (isCrtend(file->getName())) { + ObjFile::instances.erase(i); + ObjFile::instances.push_back(file); break; } } @@ -1795,58 +1795,58 @@ // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. - if (!Config->Exports.empty() || Config->DLL) { + if (!config->exports.empty() || config->dll) { fixupExports(); createImportLibrary(/*AsLib=*/false); assignExportOrdinals(); } // Handle /output-def (MinGW specific). - if (auto *Arg = Args.getLastArg(OPT_output_def)) - writeDefFile(Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_output_def)) + writeDefFile(arg->getValue()); // Set extra alignment for .comm symbols - for (auto Pair : Config->AlignComm) { - StringRef Name = Pair.first; - uint32_t Alignment = Pair.second; - - Symbol *Sym = Symtab->find(Name); - if (!Sym) { - warn("/aligncomm symbol " + Name + " not found"); + for (auto pair : config->alignComm) { + StringRef name = pair.first; + uint32_t alignment = pair.second; + + Symbol *sym = symtab->find(name); + if (!sym) { + warn("/aligncomm symbol " + name + " not found"); continue; } // If the symbol isn't common, it must have been replaced with a regular // symbol, which will carry its own alignment. - auto *DC = dyn_cast(Sym); - if (!DC) + auto *dc = dyn_cast(sym); + if (!dc) continue; - CommonChunk *C = DC->getChunk(); - C->setAlignment(std::max(C->getAlignment(), Alignment)); + CommonChunk *c = dc->getChunk(); + c->setAlignment(std::max(c->getAlignment(), alignment)); } // Windows specific -- Create a side-by-side manifest file. - if (Config->Manifest == Configuration::SideBySide) + if (config->manifest == Configuration::SideBySide) createSideBySideManifest(); // Handle /order. We want to do this at this moment because we // need a complete list of comdat sections to warn on nonexistent // functions. - if (auto *Arg = Args.getLastArg(OPT_order)) - parseOrderFile(Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_order)) + parseOrderFile(arg->getValue()); // Identify unreferenced COMDAT sections. - if (Config->DoGC) - markLive(Symtab->getChunks()); + if (config->doGC) + markLive(symtab->getChunks()); // Needs to happen after the last call to addFile(). diagnoseMultipleResourceObjFiles(); // Identify identical COMDAT sections to merge them. - if (Config->DoICF) { + if (config->doICF) { findKeepUniqueSections(); - doICF(Symtab->getChunks()); + doICF(symtab->getChunks()); } // Write the result. @@ -1854,7 +1854,7 @@ // Stop early so we can print the results. Timer::root().stop(); - if (Config->ShowTiming) + if (config->showTiming) Timer::root().print(); } Index: lld/trunk/COFF/DriverUtils.cpp =================================================================== --- lld/trunk/COFF/DriverUtils.cpp +++ lld/trunk/COFF/DriverUtils.cpp @@ -47,75 +47,75 @@ class Executor { public: - explicit Executor(StringRef S) : Prog(Saver.save(S)) {} - void add(StringRef S) { Args.push_back(Saver.save(S)); } - void add(std::string &S) { Args.push_back(Saver.save(S)); } - void add(Twine S) { Args.push_back(Saver.save(S)); } - void add(const char *S) { Args.push_back(Saver.save(S)); } + explicit Executor(StringRef s) : prog(saver.save(s)) {} + void add(StringRef s) { args.push_back(saver.save(s)); } + void add(std::string &s) { args.push_back(saver.save(s)); } + void add(Twine s) { args.push_back(saver.save(s)); } + void add(const char *s) { args.push_back(saver.save(s)); } void run() { - ErrorOr ExeOrErr = sys::findProgramByName(Prog); - if (auto EC = ExeOrErr.getError()) - fatal("unable to find " + Prog + " in PATH: " + EC.message()); - StringRef Exe = Saver.save(*ExeOrErr); - Args.insert(Args.begin(), Exe); + ErrorOr exeOrErr = sys::findProgramByName(prog); + if (auto ec = exeOrErr.getError()) + fatal("unable to find " + prog + " in PATH: " + ec.message()); + StringRef exe = saver.save(*exeOrErr); + args.insert(args.begin(), exe); - if (sys::ExecuteAndWait(Args[0], Args) != 0) + if (sys::ExecuteAndWait(args[0], args) != 0) fatal("ExecuteAndWait failed: " + - llvm::join(Args.begin(), Args.end(), " ")); + llvm::join(args.begin(), args.end(), " ")); } private: - StringRef Prog; - std::vector Args; + StringRef prog; + std::vector args; }; } // anonymous namespace // Parses a string in the form of "[,]". -void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) { - StringRef S1, S2; - std::tie(S1, S2) = Arg.split(','); - if (S1.getAsInteger(0, *Addr)) - fatal("invalid number: " + S1); - if (Size && !S2.empty() && S2.getAsInteger(0, *Size)) - fatal("invalid number: " + S2); +void parseNumbers(StringRef arg, uint64_t *addr, uint64_t *size) { + StringRef s1, s2; + std::tie(s1, s2) = arg.split(','); + if (s1.getAsInteger(0, *addr)) + fatal("invalid number: " + s1); + if (size && !s2.empty() && s2.getAsInteger(0, *size)) + fatal("invalid number: " + s2); } // Parses a string in the form of "[.]". // If second number is not present, Minor is set to 0. -void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) { - StringRef S1, S2; - std::tie(S1, S2) = Arg.split('.'); - if (S1.getAsInteger(0, *Major)) - fatal("invalid number: " + S1); - *Minor = 0; - if (!S2.empty() && S2.getAsInteger(0, *Minor)) - fatal("invalid number: " + S2); -} - -void parseGuard(StringRef FullArg) { - SmallVector SplitArgs; - FullArg.split(SplitArgs, ","); - for (StringRef Arg : SplitArgs) { - if (Arg.equals_lower("no")) - Config->GuardCF = GuardCFLevel::Off; - else if (Arg.equals_lower("nolongjmp")) - Config->GuardCF = GuardCFLevel::NoLongJmp; - else if (Arg.equals_lower("cf") || Arg.equals_lower("longjmp")) - Config->GuardCF = GuardCFLevel::Full; +void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor) { + StringRef s1, s2; + std::tie(s1, s2) = arg.split('.'); + if (s1.getAsInteger(0, *major)) + fatal("invalid number: " + s1); + *minor = 0; + if (!s2.empty() && s2.getAsInteger(0, *minor)) + fatal("invalid number: " + s2); +} + +void parseGuard(StringRef fullArg) { + SmallVector splitArgs; + fullArg.split(splitArgs, ","); + for (StringRef arg : splitArgs) { + if (arg.equals_lower("no")) + config->guardCF = GuardCFLevel::Off; + else if (arg.equals_lower("nolongjmp")) + config->guardCF = GuardCFLevel::NoLongJmp; + else if (arg.equals_lower("cf") || arg.equals_lower("longjmp")) + config->guardCF = GuardCFLevel::Full; else - fatal("invalid argument to /guard: " + Arg); + fatal("invalid argument to /guard: " + arg); } } // Parses a string in the form of "[,[.]]". -void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major, - uint32_t *Minor) { - StringRef SysStr, Ver; - std::tie(SysStr, Ver) = Arg.split(','); - std::string SysStrLower = SysStr.lower(); - *Sys = StringSwitch(SysStrLower) +void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major, + uint32_t *minor) { + StringRef sysStr, ver; + std::tie(sysStr, ver) = arg.split(','); + std::string sysStrLower = sysStr.lower(); + *sys = StringSwitch(sysStrLower) .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI) .Case("default", IMAGE_SUBSYSTEM_UNKNOWN) @@ -127,217 +127,217 @@ .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI) .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI) .Default(IMAGE_SUBSYSTEM_UNKNOWN); - if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN && SysStrLower != "default") - fatal("unknown subsystem: " + SysStr); - if (!Ver.empty()) - parseVersion(Ver, Major, Minor); + if (*sys == IMAGE_SUBSYSTEM_UNKNOWN && sysStrLower != "default") + fatal("unknown subsystem: " + sysStr); + if (!ver.empty()) + parseVersion(ver, major, minor); } // Parse a string of the form of "=". // Results are directly written to Config. -void parseAlternateName(StringRef S) { - StringRef From, To; - std::tie(From, To) = S.split('='); - if (From.empty() || To.empty()) - fatal("/alternatename: invalid argument: " + S); - auto It = Config->AlternateNames.find(From); - if (It != Config->AlternateNames.end() && It->second != To) - fatal("/alternatename: conflicts: " + S); - Config->AlternateNames.insert(It, std::make_pair(From, To)); +void parseAlternateName(StringRef s) { + StringRef from, to; + std::tie(from, to) = s.split('='); + if (from.empty() || to.empty()) + fatal("/alternatename: invalid argument: " + s); + auto it = config->alternateNames.find(from); + if (it != config->alternateNames.end() && it->second != to) + fatal("/alternatename: conflicts: " + s); + config->alternateNames.insert(it, std::make_pair(from, to)); } // Parse a string of the form of "=". // Results are directly written to Config. -void parseMerge(StringRef S) { - StringRef From, To; - std::tie(From, To) = S.split('='); - if (From.empty() || To.empty()) - fatal("/merge: invalid argument: " + S); - if (From == ".rsrc" || To == ".rsrc") +void parseMerge(StringRef s) { + StringRef from, to; + std::tie(from, to) = s.split('='); + if (from.empty() || to.empty()) + fatal("/merge: invalid argument: " + s); + if (from == ".rsrc" || to == ".rsrc") fatal("/merge: cannot merge '.rsrc' with any section"); - if (From == ".reloc" || To == ".reloc") + if (from == ".reloc" || to == ".reloc") fatal("/merge: cannot merge '.reloc' with any section"); - auto Pair = Config->Merge.insert(std::make_pair(From, To)); - bool Inserted = Pair.second; - if (!Inserted) { - StringRef Existing = Pair.first->second; - if (Existing != To) - warn(S + ": already merged into " + Existing); + auto pair = config->merge.insert(std::make_pair(from, to)); + bool inserted = pair.second; + if (!inserted) { + StringRef existing = pair.first->second; + if (existing != to) + warn(s + ": already merged into " + existing); } } -static uint32_t parseSectionAttributes(StringRef S) { - uint32_t Ret = 0; - for (char C : S.lower()) { - switch (C) { +static uint32_t parseSectionAttributes(StringRef s) { + uint32_t ret = 0; + for (char c : s.lower()) { + switch (c) { case 'd': - Ret |= IMAGE_SCN_MEM_DISCARDABLE; + ret |= IMAGE_SCN_MEM_DISCARDABLE; break; case 'e': - Ret |= IMAGE_SCN_MEM_EXECUTE; + ret |= IMAGE_SCN_MEM_EXECUTE; break; case 'k': - Ret |= IMAGE_SCN_MEM_NOT_CACHED; + ret |= IMAGE_SCN_MEM_NOT_CACHED; break; case 'p': - Ret |= IMAGE_SCN_MEM_NOT_PAGED; + ret |= IMAGE_SCN_MEM_NOT_PAGED; break; case 'r': - Ret |= IMAGE_SCN_MEM_READ; + ret |= IMAGE_SCN_MEM_READ; break; case 's': - Ret |= IMAGE_SCN_MEM_SHARED; + ret |= IMAGE_SCN_MEM_SHARED; break; case 'w': - Ret |= IMAGE_SCN_MEM_WRITE; + ret |= IMAGE_SCN_MEM_WRITE; break; default: - fatal("/section: invalid argument: " + S); + fatal("/section: invalid argument: " + s); } } - return Ret; + return ret; } // Parses /section option argument. -void parseSection(StringRef S) { - StringRef Name, Attrs; - std::tie(Name, Attrs) = S.split(','); - if (Name.empty() || Attrs.empty()) - fatal("/section: invalid argument: " + S); - Config->Section[Name] = parseSectionAttributes(Attrs); +void parseSection(StringRef s) { + StringRef name, attrs; + std::tie(name, attrs) = s.split(','); + if (name.empty() || attrs.empty()) + fatal("/section: invalid argument: " + s); + config->section[name] = parseSectionAttributes(attrs); } // Parses /aligncomm option argument. -void parseAligncomm(StringRef S) { - StringRef Name, Align; - std::tie(Name, Align) = S.split(','); - if (Name.empty() || Align.empty()) { - error("/aligncomm: invalid argument: " + S); +void parseAligncomm(StringRef s) { + StringRef name, align; + std::tie(name, align) = s.split(','); + if (name.empty() || align.empty()) { + error("/aligncomm: invalid argument: " + s); return; } - int V; - if (Align.getAsInteger(0, V)) { - error("/aligncomm: invalid argument: " + S); + int v; + if (align.getAsInteger(0, v)) { + error("/aligncomm: invalid argument: " + s); return; } - Config->AlignComm[Name] = std::max(Config->AlignComm[Name], 1 << V); + config->alignComm[name] = std::max(config->alignComm[name], 1 << v); } // Parses /functionpadmin option argument. -void parseFunctionPadMin(llvm::opt::Arg *A, llvm::COFF::MachineTypes Machine) { - StringRef Arg = A->getNumValues() ? A->getValue() : ""; - if (!Arg.empty()) { +void parseFunctionPadMin(llvm::opt::Arg *a, llvm::COFF::MachineTypes machine) { + StringRef arg = a->getNumValues() ? a->getValue() : ""; + if (!arg.empty()) { // Optional padding in bytes is given. - if (Arg.getAsInteger(0, Config->FunctionPadMin)) - error("/functionpadmin: invalid argument: " + Arg); + if (arg.getAsInteger(0, config->functionPadMin)) + error("/functionpadmin: invalid argument: " + arg); return; } // No optional argument given. // Set default padding based on machine, similar to link.exe. // There is no default padding for ARM platforms. - if (Machine == I386) { - Config->FunctionPadMin = 5; - } else if (Machine == AMD64) { - Config->FunctionPadMin = 6; + if (machine == I386) { + config->functionPadMin = 5; + } else if (machine == AMD64) { + config->functionPadMin = 6; } else { - error("/functionpadmin: invalid argument for this machine: " + Arg); + error("/functionpadmin: invalid argument for this machine: " + arg); } } // Parses a string in the form of "EMBED[,=]|NO". // Results are directly written to Config. -void parseManifest(StringRef Arg) { - if (Arg.equals_lower("no")) { - Config->Manifest = Configuration::No; +void parseManifest(StringRef arg) { + if (arg.equals_lower("no")) { + config->manifest = Configuration::No; return; } - if (!Arg.startswith_lower("embed")) - fatal("invalid option " + Arg); - Config->Manifest = Configuration::Embed; - Arg = Arg.substr(strlen("embed")); - if (Arg.empty()) + if (!arg.startswith_lower("embed")) + fatal("invalid option " + arg); + config->manifest = Configuration::Embed; + arg = arg.substr(strlen("embed")); + if (arg.empty()) return; - if (!Arg.startswith_lower(",id=")) - fatal("invalid option " + Arg); - Arg = Arg.substr(strlen(",id=")); - if (Arg.getAsInteger(0, Config->ManifestID)) - fatal("invalid option " + Arg); + if (!arg.startswith_lower(",id=")) + fatal("invalid option " + arg); + arg = arg.substr(strlen(",id=")); + if (arg.getAsInteger(0, config->manifestID)) + fatal("invalid option " + arg); } // Parses a string in the form of "level=|uiAccess=|NO". // Results are directly written to Config. -void parseManifestUAC(StringRef Arg) { - if (Arg.equals_lower("no")) { - Config->ManifestUAC = false; +void parseManifestUAC(StringRef arg) { + if (arg.equals_lower("no")) { + config->manifestUAC = false; return; } for (;;) { - Arg = Arg.ltrim(); - if (Arg.empty()) + arg = arg.ltrim(); + if (arg.empty()) return; - if (Arg.startswith_lower("level=")) { - Arg = Arg.substr(strlen("level=")); - std::tie(Config->ManifestLevel, Arg) = Arg.split(" "); + if (arg.startswith_lower("level=")) { + arg = arg.substr(strlen("level=")); + std::tie(config->manifestLevel, arg) = arg.split(" "); continue; } - if (Arg.startswith_lower("uiaccess=")) { - Arg = Arg.substr(strlen("uiaccess=")); - std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" "); + if (arg.startswith_lower("uiaccess=")) { + arg = arg.substr(strlen("uiaccess=")); + std::tie(config->manifestUIAccess, arg) = arg.split(" "); continue; } - fatal("invalid option " + Arg); + fatal("invalid option " + arg); } } // Parses a string in the form of "cd|net[,(cd|net)]*" // Results are directly written to Config. -void parseSwaprun(StringRef Arg) { +void parseSwaprun(StringRef arg) { do { - StringRef Swaprun, NewArg; - std::tie(Swaprun, NewArg) = Arg.split(','); - if (Swaprun.equals_lower("cd")) - Config->SwaprunCD = true; - else if (Swaprun.equals_lower("net")) - Config->SwaprunNet = true; - else if (Swaprun.empty()) + StringRef swaprun, newArg; + std::tie(swaprun, newArg) = arg.split(','); + if (swaprun.equals_lower("cd")) + config->swaprunCD = true; + else if (swaprun.equals_lower("net")) + config->swaprunNet = true; + else if (swaprun.empty()) error("/swaprun: missing argument"); else - error("/swaprun: invalid argument: " + Swaprun); + error("/swaprun: invalid argument: " + swaprun); // To catch trailing commas, e.g. `/spawrun:cd,` - if (NewArg.empty() && Arg.endswith(",")) + if (newArg.empty() && arg.endswith(",")) error("/swaprun: missing argument"); - Arg = NewArg; - } while (!Arg.empty()); + arg = newArg; + } while (!arg.empty()); } // An RAII temporary file class that automatically removes a temporary file. namespace { class TemporaryFile { public: - TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") { - SmallString<128> S; - if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S)) - fatal("cannot create a temporary file: " + EC.message()); - Path = S.str(); - - if (!Contents.empty()) { - std::error_code EC; - raw_fd_ostream OS(Path, EC, sys::fs::F_None); - if (EC) - fatal("failed to open " + Path + ": " + EC.message()); - OS << Contents; + TemporaryFile(StringRef prefix, StringRef extn, StringRef contents = "") { + SmallString<128> s; + if (auto ec = sys::fs::createTemporaryFile("lld-" + prefix, extn, s)) + fatal("cannot create a temporary file: " + ec.message()); + path = s.str(); + + if (!contents.empty()) { + std::error_code ec; + raw_fd_ostream os(path, ec, sys::fs::F_None); + if (ec) + fatal("failed to open " + path + ": " + ec.message()); + os << contents; } } - TemporaryFile(TemporaryFile &&Obj) { - std::swap(Path, Obj.Path); + TemporaryFile(TemporaryFile &&obj) { + std::swap(path, obj.path); } ~TemporaryFile() { - if (Path.empty()) + if (path.empty()) return; - if (sys::fs::remove(Path)) - fatal("failed to remove " + Path); + if (sys::fs::remove(path)) + fatal("failed to remove " + path); } // Returns a memory buffer of this temporary file. @@ -346,389 +346,389 @@ // is called (you cannot remove an opened file on Windows.) std::unique_ptr getMemoryBuffer() { // IsVolatileSize=true forces MemoryBuffer to not use mmap(). - return CHECK(MemoryBuffer::getFile(Path, /*FileSize=*/-1, + return CHECK(MemoryBuffer::getFile(path, /*FileSize=*/-1, /*RequiresNullTerminator=*/false, /*IsVolatileSize=*/true), - "could not open " + Path); + "could not open " + path); } - std::string Path; + std::string path; }; } static std::string createDefaultXml() { - std::string Ret; - raw_string_ostream OS(Ret); + std::string ret; + raw_string_ostream os(ret); // Emit the XML. Note that we do *not* verify that the XML attributes are // syntactically correct. This is intentional for link.exe compatibility. - OS << "\n" + os << "\n" << "\n"; - if (Config->ManifestUAC) { - OS << " \n" + if (config->manifestUAC) { + os << " \n" << " \n" << " \n" - << " \n" + << " \n" << " \n" << " \n" << " \n"; } - if (!Config->ManifestDependency.empty()) { - OS << " \n" + if (!config->manifestDependency.empty()) { + os << " \n" << " \n" - << " ManifestDependency << " />\n" + << " manifestDependency << " />\n" << " \n" << " \n"; } - OS << "\n"; - return OS.str(); + os << "\n"; + return os.str(); } -static std::string createManifestXmlWithInternalMt(StringRef DefaultXml) { - std::unique_ptr DefaultXmlCopy = - MemoryBuffer::getMemBufferCopy(DefaultXml); +static std::string createManifestXmlWithInternalMt(StringRef defaultXml) { + std::unique_ptr defaultXmlCopy = + MemoryBuffer::getMemBufferCopy(defaultXml); - windows_manifest::WindowsManifestMerger Merger; - if (auto E = Merger.merge(*DefaultXmlCopy.get())) + windows_manifest::WindowsManifestMerger merger; + if (auto e = merger.merge(*defaultXmlCopy.get())) fatal("internal manifest tool failed on default xml: " + - toString(std::move(E))); + toString(std::move(e))); - for (StringRef Filename : Config->ManifestInput) { - std::unique_ptr Manifest = - check(MemoryBuffer::getFile(Filename)); - if (auto E = Merger.merge(*Manifest.get())) - fatal("internal manifest tool failed on file " + Filename + ": " + - toString(std::move(E))); + for (StringRef filename : config->manifestInput) { + std::unique_ptr manifest = + check(MemoryBuffer::getFile(filename)); + if (auto e = merger.merge(*manifest.get())) + fatal("internal manifest tool failed on file " + filename + ": " + + toString(std::move(e))); } - return Merger.getMergedManifest().get()->getBuffer(); + return merger.getMergedManifest().get()->getBuffer(); } -static std::string createManifestXmlWithExternalMt(StringRef DefaultXml) { +static std::string createManifestXmlWithExternalMt(StringRef defaultXml) { // Create the default manifest file as a temporary file. TemporaryFile Default("defaultxml", "manifest"); - std::error_code EC; - raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text); - if (EC) - fatal("failed to open " + Default.Path + ": " + EC.message()); - OS << DefaultXml; - OS.close(); + std::error_code ec; + raw_fd_ostream os(Default.path, ec, sys::fs::F_Text); + if (ec) + fatal("failed to open " + Default.path + ": " + ec.message()); + os << defaultXml; + os.close(); // Merge user-supplied manifests if they are given. Since libxml2 is not // enabled, we must shell out to Microsoft's mt.exe tool. - TemporaryFile User("user", "manifest"); + TemporaryFile user("user", "manifest"); - Executor E("mt.exe"); - E.add("/manifest"); - E.add(Default.Path); - for (StringRef Filename : Config->ManifestInput) { - E.add("/manifest"); - E.add(Filename); - } - E.add("/nologo"); - E.add("/out:" + StringRef(User.Path)); - E.run(); + Executor e("mt.exe"); + e.add("/manifest"); + e.add(Default.path); + for (StringRef filename : config->manifestInput) { + e.add("/manifest"); + e.add(filename); + } + e.add("/nologo"); + e.add("/out:" + StringRef(user.path)); + e.run(); - return CHECK(MemoryBuffer::getFile(User.Path), "could not open " + User.Path) + return CHECK(MemoryBuffer::getFile(user.path), "could not open " + user.path) .get() ->getBuffer(); } static std::string createManifestXml() { - std::string DefaultXml = createDefaultXml(); - if (Config->ManifestInput.empty()) - return DefaultXml; + std::string defaultXml = createDefaultXml(); + if (config->manifestInput.empty()) + return defaultXml; if (windows_manifest::isAvailable()) - return createManifestXmlWithInternalMt(DefaultXml); + return createManifestXmlWithInternalMt(defaultXml); - return createManifestXmlWithExternalMt(DefaultXml); + return createManifestXmlWithExternalMt(defaultXml); } static std::unique_ptr -createMemoryBufferForManifestRes(size_t ManifestSize) { - size_t ResSize = alignTo( +createMemoryBufferForManifestRes(size_t manifestSize) { + size_t resSize = alignTo( object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE + sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) + - sizeof(object::WinResHeaderSuffix) + ManifestSize, + sizeof(object::WinResHeaderSuffix) + manifestSize, object::WIN_RES_DATA_ALIGNMENT); - return WritableMemoryBuffer::getNewMemBuffer(ResSize, Config->OutputFile + + return WritableMemoryBuffer::getNewMemBuffer(resSize, config->outputFile + ".manifest.res"); } -static void writeResFileHeader(char *&Buf) { - memcpy(Buf, COFF::WinResMagic, sizeof(COFF::WinResMagic)); - Buf += sizeof(COFF::WinResMagic); - memset(Buf, 0, object::WIN_RES_NULL_ENTRY_SIZE); - Buf += object::WIN_RES_NULL_ENTRY_SIZE; +static void writeResFileHeader(char *&buf) { + memcpy(buf, COFF::WinResMagic, sizeof(COFF::WinResMagic)); + buf += sizeof(COFF::WinResMagic); + memset(buf, 0, object::WIN_RES_NULL_ENTRY_SIZE); + buf += object::WIN_RES_NULL_ENTRY_SIZE; } -static void writeResEntryHeader(char *&Buf, size_t ManifestSize) { +static void writeResEntryHeader(char *&buf, size_t manifestSize) { // Write the prefix. - auto *Prefix = reinterpret_cast(Buf); - Prefix->DataSize = ManifestSize; - Prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) + + auto *prefix = reinterpret_cast(buf); + prefix->DataSize = manifestSize; + prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) + sizeof(object::WinResHeaderSuffix); - Buf += sizeof(object::WinResHeaderPrefix); + buf += sizeof(object::WinResHeaderPrefix); // Write the Type/Name IDs. - auto *IDs = reinterpret_cast(Buf); - IDs->setType(RT_MANIFEST); - IDs->setName(Config->ManifestID); - Buf += sizeof(object::WinResIDs); + auto *iDs = reinterpret_cast(buf); + iDs->setType(RT_MANIFEST); + iDs->setName(config->manifestID); + buf += sizeof(object::WinResIDs); // Write the suffix. - auto *Suffix = reinterpret_cast(Buf); - Suffix->DataVersion = 0; - Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE; - Suffix->Language = SUBLANG_ENGLISH_US; - Suffix->Version = 0; - Suffix->Characteristics = 0; - Buf += sizeof(object::WinResHeaderSuffix); + auto *suffix = reinterpret_cast(buf); + suffix->DataVersion = 0; + suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE; + suffix->Language = SUBLANG_ENGLISH_US; + suffix->Version = 0; + suffix->Characteristics = 0; + buf += sizeof(object::WinResHeaderSuffix); } // Create a resource file containing a manifest XML. std::unique_ptr createManifestRes() { - std::string Manifest = createManifestXml(); + std::string manifest = createManifestXml(); - std::unique_ptr Res = - createMemoryBufferForManifestRes(Manifest.size()); + std::unique_ptr res = + createMemoryBufferForManifestRes(manifest.size()); - char *Buf = Res->getBufferStart(); - writeResFileHeader(Buf); - writeResEntryHeader(Buf, Manifest.size()); + char *buf = res->getBufferStart(); + writeResFileHeader(buf); + writeResEntryHeader(buf, manifest.size()); // Copy the manifest data into the .res file. - std::copy(Manifest.begin(), Manifest.end(), Buf); - return std::move(Res); + std::copy(manifest.begin(), manifest.end(), buf); + return std::move(res); } void createSideBySideManifest() { - std::string Path = Config->ManifestFile; - if (Path == "") - Path = Config->OutputFile + ".manifest"; - std::error_code EC; - raw_fd_ostream Out(Path, EC, sys::fs::F_Text); - if (EC) - fatal("failed to create manifest: " + EC.message()); - Out << createManifestXml(); + std::string path = config->manifestFile; + if (path == "") + path = config->outputFile + ".manifest"; + std::error_code ec; + raw_fd_ostream out(path, ec, sys::fs::F_Text); + if (ec) + fatal("failed to create manifest: " + ec.message()); + out << createManifestXml(); } // Parse a string in the form of // "[=][,@ordinal[,NONAME]][,DATA][,PRIVATE]" // or "=.". // Used for parsing /export arguments. -Export parseExport(StringRef Arg) { - Export E; - StringRef Rest; - std::tie(E.Name, Rest) = Arg.split(","); - if (E.Name.empty()) +Export parseExport(StringRef arg) { + Export e; + StringRef rest; + std::tie(e.name, rest) = arg.split(","); + if (e.name.empty()) goto err; - if (E.Name.contains('=')) { - StringRef X, Y; - std::tie(X, Y) = E.Name.split("="); + if (e.name.contains('=')) { + StringRef x, y; + std::tie(x, y) = e.name.split("="); // If "=.". - if (Y.contains(".")) { - E.Name = X; - E.ForwardTo = Y; - return E; + if (y.contains(".")) { + e.name = x; + e.forwardTo = y; + return e; } - E.ExtName = X; - E.Name = Y; - if (E.Name.empty()) + e.extName = x; + e.name = y; + if (e.name.empty()) goto err; } // If "=[,@ordinal[,NONAME]][,DATA][,PRIVATE]" - while (!Rest.empty()) { - StringRef Tok; - std::tie(Tok, Rest) = Rest.split(","); - if (Tok.equals_lower("noname")) { - if (E.Ordinal == 0) + while (!rest.empty()) { + StringRef tok; + std::tie(tok, rest) = rest.split(","); + if (tok.equals_lower("noname")) { + if (e.ordinal == 0) goto err; - E.Noname = true; + e.noname = true; continue; } - if (Tok.equals_lower("data")) { - E.Data = true; + if (tok.equals_lower("data")) { + e.data = true; continue; } - if (Tok.equals_lower("constant")) { - E.Constant = true; + if (tok.equals_lower("constant")) { + e.constant = true; continue; } - if (Tok.equals_lower("private")) { - E.Private = true; + if (tok.equals_lower("private")) { + e.isPrivate = true; continue; } - if (Tok.startswith("@")) { - int32_t Ord; - if (Tok.substr(1).getAsInteger(0, Ord)) + if (tok.startswith("@")) { + int32_t ord; + if (tok.substr(1).getAsInteger(0, ord)) goto err; - if (Ord <= 0 || 65535 < Ord) + if (ord <= 0 || 65535 < ord) goto err; - E.Ordinal = Ord; + e.ordinal = ord; continue; } goto err; } - return E; + return e; err: - fatal("invalid /export: " + Arg); + fatal("invalid /export: " + arg); } -static StringRef undecorate(StringRef Sym) { - if (Config->Machine != I386) - return Sym; +static StringRef undecorate(StringRef sym) { + if (config->machine != I386) + return sym; // In MSVC mode, a fully decorated stdcall function is exported // as-is with the leading underscore (with type IMPORT_NAME). // In MinGW mode, a decorated stdcall function gets the underscore // removed, just like normal cdecl functions. - if (Sym.startswith("_") && Sym.contains('@') && !Config->MinGW) - return Sym; - return Sym.startswith("_") ? Sym.substr(1) : Sym; + if (sym.startswith("_") && sym.contains('@') && !config->mingw) + return sym; + return sym.startswith("_") ? sym.substr(1) : sym; } // Convert stdcall/fastcall style symbols into unsuffixed symbols, // with or without a leading underscore. (MinGW specific.) -static StringRef killAt(StringRef Sym, bool Prefix) { - if (Sym.empty()) - return Sym; +static StringRef killAt(StringRef sym, bool prefix) { + if (sym.empty()) + return sym; // Strip any trailing stdcall suffix - Sym = Sym.substr(0, Sym.find('@', 1)); - if (!Sym.startswith("@")) { - if (Prefix && !Sym.startswith("_")) - return Saver.save("_" + Sym); - return Sym; + sym = sym.substr(0, sym.find('@', 1)); + if (!sym.startswith("@")) { + if (prefix && !sym.startswith("_")) + return saver.save("_" + sym); + return sym; } // For fastcall, remove the leading @ and replace it with an // underscore, if prefixes are used. - Sym = Sym.substr(1); - if (Prefix) - Sym = Saver.save("_" + Sym); - return Sym; + sym = sym.substr(1); + if (prefix) + sym = saver.save("_" + sym); + return sym; } // Performs error checking on all /export arguments. // It also sets ordinals. void fixupExports() { // Symbol ordinals must be unique. - std::set Ords; - for (Export &E : Config->Exports) { - if (E.Ordinal == 0) + std::set ords; + for (Export &e : config->exports) { + if (e.ordinal == 0) continue; - if (!Ords.insert(E.Ordinal).second) - fatal("duplicate export ordinal: " + E.Name); + if (!ords.insert(e.ordinal).second) + fatal("duplicate export ordinal: " + e.name); } - for (Export &E : Config->Exports) { - if (!E.ForwardTo.empty()) { - E.ExportName = undecorate(E.Name); + for (Export &e : config->exports) { + if (!e.forwardTo.empty()) { + e.exportName = undecorate(e.name); } else { - E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName); + e.exportName = undecorate(e.extName.empty() ? e.name : e.extName); } } - if (Config->KillAt && Config->Machine == I386) { - for (Export &E : Config->Exports) { - E.Name = killAt(E.Name, true); - E.ExportName = killAt(E.ExportName, false); - E.ExtName = killAt(E.ExtName, true); - E.SymbolName = killAt(E.SymbolName, true); + if (config->killAt && config->machine == I386) { + for (Export &e : config->exports) { + e.name = killAt(e.name, true); + e.exportName = killAt(e.exportName, false); + e.extName = killAt(e.extName, true); + e.symbolName = killAt(e.symbolName, true); } } // Uniquefy by name. - DenseMap Map(Config->Exports.size()); - std::vector V; - for (Export &E : Config->Exports) { - auto Pair = Map.insert(std::make_pair(E.ExportName, &E)); - bool Inserted = Pair.second; - if (Inserted) { - V.push_back(E); + DenseMap map(config->exports.size()); + std::vector v; + for (Export &e : config->exports) { + auto pair = map.insert(std::make_pair(e.exportName, &e)); + bool inserted = pair.second; + if (inserted) { + v.push_back(e); continue; } - Export *Existing = Pair.first->second; - if (E == *Existing || E.Name != Existing->Name) + Export *existing = pair.first->second; + if (e == *existing || e.name != existing->name) continue; - warn("duplicate /export option: " + E.Name); + warn("duplicate /export option: " + e.name); } - Config->Exports = std::move(V); + config->exports = std::move(v); // Sort by name. - std::sort(Config->Exports.begin(), Config->Exports.end(), - [](const Export &A, const Export &B) { - return A.ExportName < B.ExportName; + std::sort(config->exports.begin(), config->exports.end(), + [](const Export &a, const Export &b) { + return a.exportName < b.exportName; }); } void assignExportOrdinals() { // Assign unique ordinals if default (= 0). - uint16_t Max = 0; - for (Export &E : Config->Exports) - Max = std::max(Max, E.Ordinal); - for (Export &E : Config->Exports) - if (E.Ordinal == 0) - E.Ordinal = ++Max; + uint16_t max = 0; + for (Export &e : config->exports) + max = std::max(max, e.ordinal); + for (Export &e : config->exports) + if (e.ordinal == 0) + e.ordinal = ++max; } // Parses a string in the form of "key=value" and check // if value matches previous values for the same key. -void checkFailIfMismatch(StringRef Arg, InputFile *Source) { - StringRef K, V; - std::tie(K, V) = Arg.split('='); - if (K.empty() || V.empty()) - fatal("/failifmismatch: invalid argument: " + Arg); - std::pair Existing = Config->MustMatch[K]; - if (!Existing.first.empty() && V != Existing.first) { - std::string SourceStr = Source ? toString(Source) : "cmd-line"; - std::string ExistingStr = - Existing.second ? toString(Existing.second) : "cmd-line"; - fatal("/failifmismatch: mismatch detected for '" + K + "':\n>>> " + - ExistingStr + " has value " + Existing.first + "\n>>> " + SourceStr + - " has value " + V); +void checkFailIfMismatch(StringRef arg, InputFile *source) { + StringRef k, v; + std::tie(k, v) = arg.split('='); + if (k.empty() || v.empty()) + fatal("/failifmismatch: invalid argument: " + arg); + std::pair existing = config->mustMatch[k]; + if (!existing.first.empty() && v != existing.first) { + std::string sourceStr = source ? toString(source) : "cmd-line"; + std::string existingStr = + existing.second ? toString(existing.second) : "cmd-line"; + fatal("/failifmismatch: mismatch detected for '" + k + "':\n>>> " + + existingStr + " has value " + existing.first + "\n>>> " + sourceStr + + " has value " + v); } - Config->MustMatch[K] = {V, Source}; + config->mustMatch[k] = {v, source}; } // Convert Windows resource files (.res files) to a .obj file. // Does what cvtres.exe does, but in-process and cross-platform. -MemoryBufferRef convertResToCOFF(ArrayRef MBs) { - object::WindowsResourceParser Parser; +MemoryBufferRef convertResToCOFF(ArrayRef mbs) { + object::WindowsResourceParser parser; - for (MemoryBufferRef MB : MBs) { - std::unique_ptr Bin = check(object::createBinary(MB)); - object::WindowsResource *RF = dyn_cast(Bin.get()); - if (!RF) + for (MemoryBufferRef mb : mbs) { + std::unique_ptr bin = check(object::createBinary(mb)); + object::WindowsResource *rf = dyn_cast(bin.get()); + if (!rf) fatal("cannot compile non-resource file as resource"); - std::vector Duplicates; - if (auto EC = Parser.parse(RF, Duplicates)) - fatal(toString(std::move(EC))); - - for (const auto &DupeDiag : Duplicates) - if (Config->ForceMultipleRes) - warn(DupeDiag); + std::vector duplicates; + if (auto ec = parser.parse(rf, duplicates)) + fatal(toString(std::move(ec))); + + for (const auto &dupeDiag : duplicates) + if (config->forceMultipleRes) + warn(dupeDiag); else - error(DupeDiag); + error(dupeDiag); } - Expected> E = - llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser, - Config->Timestamp); - if (!E) - fatal("failed to write .res to COFF: " + toString(E.takeError())); - - MemoryBufferRef MBRef = **E; - make>(std::move(*E)); // take ownership - return MBRef; + Expected> e = + llvm::object::writeWindowsResourceCOFF(config->machine, parser, + config->timestamp); + if (!e) + fatal("failed to write .res to COFF: " + toString(e.takeError())); + + MemoryBufferRef mbref = **e; + make>(std::move(*e)); // take ownership + return mbref; } // Create OptTable @@ -739,7 +739,7 @@ #undef PREFIX // Create table mapping all options defined in Options.td -static const llvm::opt::OptTable::Info InfoTable[] = { +static const llvm::opt::OptTable::Info infoTable[] = { #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \ X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, @@ -747,36 +747,36 @@ #undef OPTION }; -COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {} +COFFOptTable::COFFOptTable() : OptTable(infoTable, true) {} // Set color diagnostics according to --color-diagnostics={auto,always,never} // or --no-color-diagnostics flags. -static void handleColorDiagnostics(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, +static void handleColorDiagnostics(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, OPT_no_color_diagnostics); - if (!Arg) + if (!arg) return; - if (Arg->getOption().getID() == OPT_color_diagnostics) { - errorHandler().ColorDiagnostics = true; - } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) { - errorHandler().ColorDiagnostics = false; + if (arg->getOption().getID() == OPT_color_diagnostics) { + errorHandler().colorDiagnostics = true; + } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { + errorHandler().colorDiagnostics = false; } else { - StringRef S = Arg->getValue(); - if (S == "always") - errorHandler().ColorDiagnostics = true; - else if (S == "never") - errorHandler().ColorDiagnostics = false; - else if (S != "auto") - error("unknown option: --color-diagnostics=" + S); + StringRef s = arg->getValue(); + if (s == "always") + errorHandler().colorDiagnostics = true; + else if (s == "never") + errorHandler().colorDiagnostics = false; + else if (s != "auto") + error("unknown option: --color-diagnostics=" + s); } } -static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) { - if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) { - StringRef S = Arg->getValue(); - if (S != "windows" && S != "posix") - error("invalid response file quoting: " + S); - if (S == "windows") +static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { + if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { + StringRef s = arg->getValue(); + if (s != "windows" && s != "posix") + error("invalid response file quoting: " + s); + if (s == "windows") return cl::TokenizeWindowsCommandLine; return cl::TokenizeGNUCommandLine; } @@ -785,111 +785,111 @@ } // Parses a given list of options. -opt::InputArgList ArgParser::parse(ArrayRef Argv) { +opt::InputArgList ArgParser::parse(ArrayRef argv) { // Make InputArgList from string vectors. - unsigned MissingIndex; - unsigned MissingCount; + unsigned missingIndex; + unsigned missingCount; // We need to get the quoting style for response files before parsing all // options so we parse here before and ignore all the options but // --rsp-quoting. - opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount); + opt::InputArgList args = table.ParseArgs(argv, missingIndex, missingCount); // Expand response files (arguments in the form of @) // and then parse the argument again. - SmallVector ExpandedArgv(Argv.data(), - Argv.data() + Argv.size()); - cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), ExpandedArgv); - Args = Table.ParseArgs(makeArrayRef(ExpandedArgv).drop_front(), MissingIndex, - MissingCount); + SmallVector expandedArgv(argv.data(), + argv.data() + argv.size()); + cl::ExpandResponseFiles(saver, getQuotingStyle(args), expandedArgv); + args = table.ParseArgs(makeArrayRef(expandedArgv).drop_front(), missingIndex, + missingCount); // Print the real command line if response files are expanded. - if (Args.hasArg(OPT_verbose) && Argv.size() != ExpandedArgv.size()) { - std::string Msg = "Command line:"; - for (const char *S : ExpandedArgv) - Msg += " " + std::string(S); - message(Msg); + if (args.hasArg(OPT_verbose) && argv.size() != expandedArgv.size()) { + std::string msg = "Command line:"; + for (const char *s : expandedArgv) + msg += " " + std::string(s); + message(msg); } // Save the command line after response file expansion so we can write it to // the PDB if necessary. - Config->Argv = {ExpandedArgv.begin(), ExpandedArgv.end()}; + config->argv = {expandedArgv.begin(), expandedArgv.end()}; // Handle /WX early since it converts missing argument warnings to errors. - errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false); + errorHandler().fatalWarnings = args.hasFlag(OPT_WX, OPT_WX_no, false); - if (MissingCount) - fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); + if (missingCount) + fatal(Twine(args.getArgString(missingIndex)) + ": missing argument"); - handleColorDiagnostics(Args); + handleColorDiagnostics(args); - for (auto *Arg : Args.filtered(OPT_UNKNOWN)) { - std::string Nearest; - if (Table.findNearest(Arg->getAsString(Args), Nearest) > 1) - warn("ignoring unknown argument '" + Arg->getAsString(Args) + "'"); + for (auto *arg : args.filtered(OPT_UNKNOWN)) { + std::string nearest; + if (table.findNearest(arg->getAsString(args), nearest) > 1) + warn("ignoring unknown argument '" + arg->getAsString(args) + "'"); else - warn("ignoring unknown argument '" + Arg->getAsString(Args) + - "', did you mean '" + Nearest + "'"); + warn("ignoring unknown argument '" + arg->getAsString(args) + + "', did you mean '" + nearest + "'"); } - if (Args.hasArg(OPT_lib)) + if (args.hasArg(OPT_lib)) warn("ignoring /lib since it's not the first argument"); - return Args; + return args; } // Tokenizes and parses a given string as command line in .drective section. // /EXPORT options are processed in fastpath. std::pair> -ArgParser::parseDirectives(StringRef S) { - std::vector Exports; - SmallVector Rest; - - for (StringRef Tok : tokenize(S)) { - if (Tok.startswith_lower("/export:") || Tok.startswith_lower("-export:")) - Exports.push_back(Tok.substr(strlen("/export:"))); +ArgParser::parseDirectives(StringRef s) { + std::vector exports; + SmallVector rest; + + for (StringRef tok : tokenize(s)) { + if (tok.startswith_lower("/export:") || tok.startswith_lower("-export:")) + exports.push_back(tok.substr(strlen("/export:"))); else - Rest.push_back(Tok.data()); + rest.push_back(tok.data()); } // Make InputArgList from unparsed string vectors. - unsigned MissingIndex; - unsigned MissingCount; + unsigned missingIndex; + unsigned missingCount; - opt::InputArgList Args = Table.ParseArgs(Rest, MissingIndex, MissingCount); + opt::InputArgList args = table.ParseArgs(rest, missingIndex, missingCount); - if (MissingCount) - fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); - for (auto *Arg : Args.filtered(OPT_UNKNOWN)) - warn("ignoring unknown argument: " + Arg->getAsString(Args)); - return {std::move(Args), std::move(Exports)}; + if (missingCount) + fatal(Twine(args.getArgString(missingIndex)) + ": missing argument"); + for (auto *arg : args.filtered(OPT_UNKNOWN)) + warn("ignoring unknown argument: " + arg->getAsString(args)); + return {std::move(args), std::move(exports)}; } // link.exe has an interesting feature. If LINK or _LINK_ environment // variables exist, their contents are handled as command line strings. // So you can pass extra arguments using them. -opt::InputArgList ArgParser::parseLINK(std::vector Argv) { +opt::InputArgList ArgParser::parseLINK(std::vector argv) { // Concatenate LINK env and command line arguments, and then parse them. - if (Optional S = Process::GetEnv("LINK")) { - std::vector V = tokenize(*S); - Argv.insert(std::next(Argv.begin()), V.begin(), V.end()); + if (Optional s = Process::GetEnv("LINK")) { + std::vector v = tokenize(*s); + argv.insert(std::next(argv.begin()), v.begin(), v.end()); } - if (Optional S = Process::GetEnv("_LINK_")) { - std::vector V = tokenize(*S); - Argv.insert(std::next(Argv.begin()), V.begin(), V.end()); + if (Optional s = Process::GetEnv("_LINK_")) { + std::vector v = tokenize(*s); + argv.insert(std::next(argv.begin()), v.begin(), v.end()); } - return parse(Argv); + return parse(argv); } -std::vector ArgParser::tokenize(StringRef S) { - SmallVector Tokens; - cl::TokenizeWindowsCommandLine(S, Saver, Tokens); - return std::vector(Tokens.begin(), Tokens.end()); +std::vector ArgParser::tokenize(StringRef s) { + SmallVector tokens; + cl::TokenizeWindowsCommandLine(s, saver, tokens); + return std::vector(tokens.begin(), tokens.end()); } -void printHelp(const char *Argv0) { +void printHelp(const char *argv0) { COFFOptTable().PrintHelp(outs(), - (std::string(Argv0) + " [options] file...").c_str(), + (std::string(argv0) + " [options] file...").c_str(), "LLVM Linker", false); } Index: lld/trunk/COFF/ICF.h =================================================================== --- lld/trunk/COFF/ICF.h +++ lld/trunk/COFF/ICF.h @@ -17,7 +17,7 @@ class Chunk; -void doICF(ArrayRef Chunks); +void doICF(ArrayRef chunks); } // namespace coff } // namespace lld Index: lld/trunk/COFF/ICF.cpp =================================================================== --- lld/trunk/COFF/ICF.cpp +++ lld/trunk/COFF/ICF.cpp @@ -37,32 +37,32 @@ namespace lld { namespace coff { -static Timer ICFTimer("ICF", Timer::root()); +static Timer icfTimer("ICF", Timer::root()); class ICF { public: - void run(ArrayRef V); + void run(ArrayRef v); private: - void segregate(size_t Begin, size_t End, bool Constant); + void segregate(size_t begin, size_t end, bool constant); - bool assocEquals(const SectionChunk *A, const SectionChunk *B); + bool assocEquals(const SectionChunk *a, const SectionChunk *b); - bool equalsConstant(const SectionChunk *A, const SectionChunk *B); - bool equalsVariable(const SectionChunk *A, const SectionChunk *B); + bool equalsConstant(const SectionChunk *a, const SectionChunk *b); + bool equalsVariable(const SectionChunk *a, const SectionChunk *b); - bool isEligible(SectionChunk *C); + bool isEligible(SectionChunk *c); - size_t findBoundary(size_t Begin, size_t End); + size_t findBoundary(size_t begin, size_t end); - void forEachClassRange(size_t Begin, size_t End, - std::function Fn); + void forEachClassRange(size_t begin, size_t end, + std::function fn); - void forEachClass(std::function Fn); + void forEachClass(std::function fn); - std::vector Chunks; - int Cnt = 0; - std::atomic Repeat = {false}; + std::vector chunks; + int cnt = 0; + std::atomic repeat = {false}; }; // Returns true if section S is subject of ICF. @@ -76,144 +76,144 @@ // merge read-only sections in a couple of cases where the address of the // section is insignificant to the user program and the behaviour matches that // of the Visual C++ linker. -bool ICF::isEligible(SectionChunk *C) { +bool ICF::isEligible(SectionChunk *c) { // Non-comdat chunks, dead chunks, and writable chunks are not elegible. - bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE; - if (!C->isCOMDAT() || !C->Live || Writable) + bool writable = c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE; + if (!c->isCOMDAT() || !c->live || writable) return false; // Code sections are eligible. - if (C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) + if (c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) return true; // .pdata and .xdata unwind info sections are eligible. - StringRef OutSecName = C->getSectionName().split('$').first; - if (OutSecName == ".pdata" || OutSecName == ".xdata") + StringRef outSecName = c->getSectionName().split('$').first; + if (outSecName == ".pdata" || outSecName == ".xdata") return true; // So are vtables. - if (C->Sym && C->Sym->getName().startswith("??_7")) + if (c->sym && c->sym->getName().startswith("??_7")) return true; // Anything else not in an address-significance table is eligible. - return !C->KeepUnique; + return !c->keepUnique; } // Split an equivalence class into smaller classes. -void ICF::segregate(size_t Begin, size_t End, bool Constant) { - while (Begin < End) { +void ICF::segregate(size_t begin, size_t end, bool constant) { + while (begin < end) { // Divide [Begin, End) into two. Let Mid be the start index of the // second group. - auto Bound = std::stable_partition( - Chunks.begin() + Begin + 1, Chunks.begin() + End, [&](SectionChunk *S) { - if (Constant) - return equalsConstant(Chunks[Begin], S); - return equalsVariable(Chunks[Begin], S); + auto bound = std::stable_partition( + chunks.begin() + begin + 1, chunks.begin() + end, [&](SectionChunk *s) { + if (constant) + return equalsConstant(chunks[begin], s); + return equalsVariable(chunks[begin], s); }); - size_t Mid = Bound - Chunks.begin(); + size_t mid = bound - chunks.begin(); // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an // equivalence class ID because every group ends with a unique index. - for (size_t I = Begin; I < Mid; ++I) - Chunks[I]->Class[(Cnt + 1) % 2] = Mid; + for (size_t i = begin; i < mid; ++i) + chunks[i]->eqClass[(cnt + 1) % 2] = mid; // If we created a group, we need to iterate the main loop again. - if (Mid != End) - Repeat = true; + if (mid != end) + repeat = true; - Begin = Mid; + begin = mid; } } // Returns true if two sections' associative children are equal. -bool ICF::assocEquals(const SectionChunk *A, const SectionChunk *B) { - auto ChildClasses = [&](const SectionChunk *SC) { - std::vector Classes; - for (const SectionChunk &C : SC->children()) - if (!C.getSectionName().startswith(".debug") && - C.getSectionName() != ".gfids$y" && C.getSectionName() != ".gljmp$y") - Classes.push_back(C.Class[Cnt % 2]); - return Classes; +bool ICF::assocEquals(const SectionChunk *a, const SectionChunk *b) { + auto childClasses = [&](const SectionChunk *sc) { + std::vector classes; + for (const SectionChunk &c : sc->children()) + if (!c.getSectionName().startswith(".debug") && + c.getSectionName() != ".gfids$y" && c.getSectionName() != ".gljmp$y") + classes.push_back(c.eqClass[cnt % 2]); + return classes; }; - return ChildClasses(A) == ChildClasses(B); + return childClasses(a) == childClasses(b); } // Compare "non-moving" part of two sections, namely everything // except relocation targets. -bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) { - if (A->RelocsSize != B->RelocsSize) +bool ICF::equalsConstant(const SectionChunk *a, const SectionChunk *b) { + if (a->relocsSize != b->relocsSize) return false; // Compare relocations. - auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { - if (R1.Type != R2.Type || - R1.VirtualAddress != R2.VirtualAddress) { + auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) { + if (r1.Type != r2.Type || + r1.VirtualAddress != r2.VirtualAddress) { return false; } - Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex); - Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex); - if (B1 == B2) + Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex); + Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex); + if (b1 == b2) return true; - if (auto *D1 = dyn_cast(B1)) - if (auto *D2 = dyn_cast(B2)) - return D1->getValue() == D2->getValue() && - D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2]; + if (auto *d1 = dyn_cast(b1)) + if (auto *d2 = dyn_cast(b2)) + return d1->getValue() == d2->getValue() && + d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2]; return false; }; - if (!std::equal(A->getRelocs().begin(), A->getRelocs().end(), - B->getRelocs().begin(), Eq)) + if (!std::equal(a->getRelocs().begin(), a->getRelocs().end(), + b->getRelocs().begin(), eq)) return false; // Compare section attributes and contents. - return A->getOutputCharacteristics() == B->getOutputCharacteristics() && - A->getSectionName() == B->getSectionName() && - A->Header->SizeOfRawData == B->Header->SizeOfRawData && - A->Checksum == B->Checksum && A->getContents() == B->getContents() && - assocEquals(A, B); + return a->getOutputCharacteristics() == b->getOutputCharacteristics() && + a->getSectionName() == b->getSectionName() && + a->header->SizeOfRawData == b->header->SizeOfRawData && + a->checksum == b->checksum && a->getContents() == b->getContents() && + assocEquals(a, b); } // Compare "moving" part of two sections, namely relocation targets. -bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) { +bool ICF::equalsVariable(const SectionChunk *a, const SectionChunk *b) { // Compare relocations. - auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) { - Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex); - Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex); - if (B1 == B2) + auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) { + Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex); + Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex); + if (b1 == b2) return true; - if (auto *D1 = dyn_cast(B1)) - if (auto *D2 = dyn_cast(B2)) - return D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2]; + if (auto *d1 = dyn_cast(b1)) + if (auto *d2 = dyn_cast(b2)) + return d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2]; return false; }; - return std::equal(A->getRelocs().begin(), A->getRelocs().end(), - B->getRelocs().begin(), Eq) && - assocEquals(A, B); + return std::equal(a->getRelocs().begin(), a->getRelocs().end(), + b->getRelocs().begin(), eq) && + assocEquals(a, b); } // Find the first Chunk after Begin that has a different class from Begin. -size_t ICF::findBoundary(size_t Begin, size_t End) { - for (size_t I = Begin + 1; I < End; ++I) - if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2]) - return I; - return End; +size_t ICF::findBoundary(size_t begin, size_t end) { + for (size_t i = begin + 1; i < end; ++i) + if (chunks[begin]->eqClass[cnt % 2] != chunks[i]->eqClass[cnt % 2]) + return i; + return end; } -void ICF::forEachClassRange(size_t Begin, size_t End, - std::function Fn) { - while (Begin < End) { - size_t Mid = findBoundary(Begin, End); - Fn(Begin, Mid); - Begin = Mid; +void ICF::forEachClassRange(size_t begin, size_t end, + std::function fn) { + while (begin < end) { + size_t mid = findBoundary(begin, end); + fn(begin, mid); + begin = mid; } } // Call Fn on each class group. -void ICF::forEachClass(std::function Fn) { +void ICF::forEachClass(std::function fn) { // If the number of sections are too small to use threading, // call Fn sequentially. - if (Chunks.size() < 1024) { - forEachClassRange(0, Chunks.size(), Fn); - ++Cnt; + if (chunks.size() < 1024) { + forEachClassRange(0, chunks.size(), fn); + ++cnt; return; } @@ -221,97 +221,97 @@ // The sharding must be completed before any calls to Fn are made // so that Fn can modify the Chunks in its shard without causing data // races. - const size_t NumShards = 256; - size_t Step = Chunks.size() / NumShards; - size_t Boundaries[NumShards + 1]; - Boundaries[0] = 0; - Boundaries[NumShards] = Chunks.size(); - parallelForEachN(1, NumShards, [&](size_t I) { - Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size()); + const size_t numShards = 256; + size_t step = chunks.size() / numShards; + size_t boundaries[numShards + 1]; + boundaries[0] = 0; + boundaries[numShards] = chunks.size(); + parallelForEachN(1, numShards, [&](size_t i) { + boundaries[i] = findBoundary((i - 1) * step, chunks.size()); }); - parallelForEachN(1, NumShards + 1, [&](size_t I) { - if (Boundaries[I - 1] < Boundaries[I]) { - forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn); + parallelForEachN(1, numShards + 1, [&](size_t i) { + if (boundaries[i - 1] < boundaries[i]) { + forEachClassRange(boundaries[i - 1], boundaries[i], fn); } }); - ++Cnt; + ++cnt; } // Merge identical COMDAT sections. // Two sections are considered the same if their section headers, // contents and relocations are all the same. -void ICF::run(ArrayRef Vec) { - ScopedTimer T(ICFTimer); +void ICF::run(ArrayRef vec) { + ScopedTimer t(icfTimer); // Collect only mergeable sections and group by hash value. - uint32_t NextId = 1; - for (Chunk *C : Vec) { - if (auto *SC = dyn_cast(C)) { - if (isEligible(SC)) - Chunks.push_back(SC); + uint32_t nextId = 1; + for (Chunk *c : vec) { + if (auto *sc = dyn_cast(c)) { + if (isEligible(sc)) + chunks.push_back(sc); else - SC->Class[0] = NextId++; + sc->eqClass[0] = nextId++; } } // Make sure that ICF doesn't merge sections that are being handled by string // tail merging. - for (MergeChunk *MC : MergeChunk::Instances) - if (MC) - for (SectionChunk *SC : MC->Sections) - SC->Class[0] = NextId++; + for (MergeChunk *mc : MergeChunk::instances) + if (mc) + for (SectionChunk *sc : mc->sections) + sc->eqClass[0] = nextId++; // Initially, we use hash values to partition sections. - parallelForEach(Chunks, [&](SectionChunk *SC) { - SC->Class[0] = xxHash64(SC->getContents()); + parallelForEach(chunks, [&](SectionChunk *sc) { + sc->eqClass[0] = xxHash64(sc->getContents()); }); // Combine the hashes of the sections referenced by each section into its // hash. - for (unsigned Cnt = 0; Cnt != 2; ++Cnt) { - parallelForEach(Chunks, [&](SectionChunk *SC) { - uint32_t Hash = SC->Class[Cnt % 2]; - for (Symbol *B : SC->symbols()) - if (auto *Sym = dyn_cast_or_null(B)) - Hash += Sym->getChunk()->Class[Cnt % 2]; + for (unsigned cnt = 0; cnt != 2; ++cnt) { + parallelForEach(chunks, [&](SectionChunk *sc) { + uint32_t hash = sc->eqClass[cnt % 2]; + for (Symbol *b : sc->symbols()) + if (auto *sym = dyn_cast_or_null(b)) + hash += sym->getChunk()->eqClass[cnt % 2]; // Set MSB to 1 to avoid collisions with non-hash classs. - SC->Class[(Cnt + 1) % 2] = Hash | (1U << 31); + sc->eqClass[(cnt + 1) % 2] = hash | (1U << 31); }); } // From now on, sections in Chunks are ordered so that sections in // the same group are consecutive in the vector. - llvm::stable_sort(Chunks, [](const SectionChunk *A, const SectionChunk *B) { - return A->Class[0] < B->Class[0]; + llvm::stable_sort(chunks, [](const SectionChunk *a, const SectionChunk *b) { + return a->eqClass[0] < b->eqClass[0]; }); // Compare static contents and assign unique IDs for each static content. - forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); }); + forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); }); // Split groups by comparing relocations until convergence is obtained. do { - Repeat = false; + repeat = false; forEachClass( - [&](size_t Begin, size_t End) { segregate(Begin, End, false); }); - } while (Repeat); + [&](size_t begin, size_t end) { segregate(begin, end, false); }); + } while (repeat); - log("ICF needed " + Twine(Cnt) + " iterations"); + log("ICF needed " + Twine(cnt) + " iterations"); // Merge sections in the same classs. - forEachClass([&](size_t Begin, size_t End) { - if (End - Begin == 1) + forEachClass([&](size_t begin, size_t end) { + if (end - begin == 1) return; - log("Selected " + Chunks[Begin]->getDebugName()); - for (size_t I = Begin + 1; I < End; ++I) { - log(" Removed " + Chunks[I]->getDebugName()); - Chunks[Begin]->replace(Chunks[I]); + log("Selected " + chunks[begin]->getDebugName()); + for (size_t i = begin + 1; i < end; ++i) { + log(" Removed " + chunks[i]->getDebugName()); + chunks[begin]->replace(chunks[i]); } }); } // Entry point to ICF. -void doICF(ArrayRef Chunks) { ICF().run(Chunks); } +void doICF(ArrayRef chunks) { ICF().run(chunks); } } // namespace coff } // namespace lld Index: lld/trunk/COFF/InputFiles.h =================================================================== --- lld/trunk/COFF/InputFiles.h +++ lld/trunk/COFF/InputFiles.h @@ -32,7 +32,7 @@ namespace lld { namespace coff { -std::vector getArchiveMembers(llvm::object::Archive *File); +std::vector getArchiveMembers(llvm::object::Archive *file); using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; using llvm::COFF::MachineTypes; @@ -57,11 +57,11 @@ class InputFile { public: enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind }; - Kind kind() const { return FileKind; } + Kind kind() const { return fileKind; } virtual ~InputFile() {} // Returns the filename. - StringRef getName() const { return MB.getBufferIdentifier(); } + StringRef getName() const { return mb.getBufferIdentifier(); } // Reads a file (the constructor doesn't do that). virtual void parse() = 0; @@ -69,118 +69,118 @@ // Returns the CPU type this file was compiled to. virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; } - MemoryBufferRef MB; + MemoryBufferRef mb; // An archive file name if this file is created from an archive. - StringRef ParentName; + StringRef parentName; // Returns .drectve section contents if exist. - StringRef getDirectives() { return Directives; } + StringRef getDirectives() { return directives; } protected: - InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} + InputFile(Kind k, MemoryBufferRef m) : mb(m), fileKind(k) {} - StringRef Directives; + StringRef directives; private: - const Kind FileKind; + const Kind fileKind; }; // .lib or .a file. class ArchiveFile : public InputFile { public: - explicit ArchiveFile(MemoryBufferRef M); - static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } + explicit ArchiveFile(MemoryBufferRef m); + static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } void parse() override; // Enqueues an archive member load for the given symbol. If we've already // enqueued a load for the same archive member, this function does nothing, // which ensures that we don't load the same member more than once. - void addMember(const Archive::Symbol *Sym); + void addMember(const Archive::Symbol *sym); private: - std::unique_ptr File; - llvm::DenseSet Seen; + std::unique_ptr file; + llvm::DenseSet seen; }; // .obj or .o file. This may be a member of an archive file. class ObjFile : public InputFile { public: - explicit ObjFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {} - static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } + explicit ObjFile(MemoryBufferRef m) : InputFile(ObjectKind, m) {} + static bool classof(const InputFile *f) { return f->kind() == ObjectKind; } void parse() override; MachineTypes getMachineType() override; - ArrayRef getChunks() { return Chunks; } - ArrayRef getDebugChunks() { return DebugChunks; } - ArrayRef getSXDataChunks() { return SXDataChunks; } - ArrayRef getGuardFidChunks() { return GuardFidChunks; } - ArrayRef getGuardLJmpChunks() { return GuardLJmpChunks; } - ArrayRef getSymbols() { return Symbols; } + ArrayRef getChunks() { return chunks; } + ArrayRef getDebugChunks() { return debugChunks; } + ArrayRef getSXDataChunks() { return sXDataChunks; } + ArrayRef getGuardFidChunks() { return guardFidChunks; } + ArrayRef getGuardLJmpChunks() { return guardLJmpChunks; } + ArrayRef getSymbols() { return symbols; } - ArrayRef getDebugSection(StringRef SecName); + ArrayRef getDebugSection(StringRef secName); // Returns a Symbol object for the SymbolIndex'th symbol in the // underlying object file. - Symbol *getSymbol(uint32_t SymbolIndex) { - return Symbols[SymbolIndex]; + Symbol *getSymbol(uint32_t symbolIndex) { + return symbols[symbolIndex]; } // Returns the underlying COFF file. - COFFObjectFile *getCOFFObj() { return COFFObj.get(); } + COFFObjectFile *getCOFFObj() { return coffObj.get(); } // Add a symbol for a range extension thunk. Return the new symbol table // index. This index can be used to modify a relocation. - uint32_t addRangeThunkSymbol(Symbol *Thunk) { - Symbols.push_back(Thunk); - return Symbols.size() - 1; + uint32_t addRangeThunkSymbol(Symbol *thunk) { + symbols.push_back(thunk); + return symbols.size() - 1; } - static std::vector Instances; + static std::vector instances; // Flags in the absolute @feat.00 symbol if it is present. These usually // indicate if an object was compiled with certain security features enabled // like stack guard, safeseh, /guard:cf, or other things. - uint32_t Feat00Flags = 0; + uint32_t feat00Flags = 0; // True if this object file is compatible with SEH. COFF-specific and // x86-only. COFF spec 5.10.1. The .sxdata section. - bool hasSafeSEH() { return Feat00Flags & 0x1; } + bool hasSafeSEH() { return feat00Flags & 0x1; } // True if this file was compiled with /guard:cf. - bool hasGuardCF() { return Feat00Flags & 0x800; } + bool hasGuardCF() { return feat00Flags & 0x800; } // Pointer to the PDB module descriptor builder. Various debug info records // will reference object files by "module index", which is here. Things like // source files and section contributions are also recorded here. Will be null // if we are not producing a PDB. - llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr; + llvm::pdb::DbiModuleDescriptorBuilder *moduleDBI = nullptr; - const coff_section *AddrsigSec = nullptr; + const coff_section *addrsigSec = nullptr; // When using Microsoft precompiled headers, this is the PCH's key. // The same key is used by both the precompiled object, and objects using the // precompiled object. Any difference indicates out-of-date objects. - llvm::Optional PCHSignature; + llvm::Optional pchSignature; // Whether this is an object file created from .res files. - bool IsResourceObjFile = false; + bool isResourceObjFile = false; // Whether this file was compiled with /hotpatch. - bool HotPatchable = false; + bool hotPatchable = false; // Whether the object was already merged into the final PDB. - bool MergedIntoPDB = false; + bool mergedIntoPDB = false; // If the OBJ has a .debug$T stream, this tells how it will be handled. - TpiSource *DebugTypesObj = nullptr; + TpiSource *debugTypesObj = nullptr; // The .debug$T stream if there's one. - llvm::Optional DebugTypes; + llvm::Optional debugTypes; private: - const coff_section* getSection(uint32_t I); - const coff_section *getSection(COFFSymbolRef Sym) { - return getSection(Sym.getSectionNumber()); + const coff_section* getSection(uint32_t i); + const coff_section *getSection(COFFSymbolRef sym) { + return getSection(sym.getSectionNumber()); } void initializeChunks(); @@ -189,26 +189,26 @@ void initializeDependencies(); SectionChunk * - readSection(uint32_t SectionNumber, - const llvm::object::coff_aux_section_definition *Def, - StringRef LeaderName); + readSection(uint32_t sectionNumber, + const llvm::object::coff_aux_section_definition *def, + StringRef leaderName); void readAssociativeDefinition( - COFFSymbolRef COFFSym, - const llvm::object::coff_aux_section_definition *Def); + COFFSymbolRef coffSym, + const llvm::object::coff_aux_section_definition *def); void readAssociativeDefinition( - COFFSymbolRef COFFSym, - const llvm::object::coff_aux_section_definition *Def, - uint32_t ParentSection); + COFFSymbolRef coffSym, + const llvm::object::coff_aux_section_definition *def, + uint32_t parentSection); void recordPrevailingSymbolForMingw( - COFFSymbolRef COFFSym, - llvm::DenseMap &PrevailingSectionMap); + COFFSymbolRef coffSym, + llvm::DenseMap &prevailingSectionMap); void maybeAssociateSEHForMingw( - COFFSymbolRef Sym, const llvm::object::coff_aux_section_definition *Def, - const llvm::DenseMap &PrevailingSectionMap); + COFFSymbolRef sym, const llvm::object::coff_aux_section_definition *def, + const llvm::DenseMap &prevailingSectionMap); // Given a new symbol Sym with comdat selection Selection, if the new // symbol is not (yet) Prevailing and the existing comdat leader set to @@ -216,48 +216,48 @@ // match the existing symbol and its selection. If either old or new // symbol have selection IMAGE_COMDAT_SELECT_LARGEST, Sym might replace // the existing leader. In that case, Prevailing is set to true. - void handleComdatSelection(COFFSymbolRef Sym, - llvm::COFF::COMDATType &Selection, - bool &Prevailing, DefinedRegular *Leader); + void handleComdatSelection(COFFSymbolRef sym, + llvm::COFF::COMDATType &selection, + bool &prevailing, DefinedRegular *leader); llvm::Optional - createDefined(COFFSymbolRef Sym, + createDefined(COFFSymbolRef sym, std::vector - &ComdatDefs, - bool &PrevailingComdat); - Symbol *createRegular(COFFSymbolRef Sym); - Symbol *createUndefined(COFFSymbolRef Sym); + &comdatDefs, + bool &prevailingComdat); + Symbol *createRegular(COFFSymbolRef sym); + Symbol *createUndefined(COFFSymbolRef sym); - std::unique_ptr COFFObj; + std::unique_ptr coffObj; // List of all chunks defined by this file. This includes both section // chunks and non-section chunks for common symbols. - std::vector Chunks; + std::vector chunks; // CodeView debug info sections. - std::vector DebugChunks; + std::vector debugChunks; // Chunks containing symbol table indices of exception handlers. Only used for // 32-bit x86. - std::vector SXDataChunks; + std::vector sXDataChunks; // Chunks containing symbol table indices of address taken symbols and longjmp // targets. These are not linked into the final binary when /guard:cf is set. - std::vector GuardFidChunks; - std::vector GuardLJmpChunks; + std::vector guardFidChunks; + std::vector guardLJmpChunks; // This vector contains the same chunks as Chunks, but they are // indexed such that you can get a SectionChunk by section index. // Nonexistent section indices are filled with null pointers. // (Because section number is 1-based, the first slot is always a // null pointer.) - std::vector SparseChunks; + std::vector sparseChunks; // This vector contains a list of all symbols defined or referenced by this // file. They are indexed such that you can get a Symbol by symbol // index. Nonexistent indices (which are occupied by auxiliary // symbols in the real symbol table) are filled with null pointers. - std::vector Symbols; + std::vector symbols; }; // This type represents import library members that contain DLL names @@ -265,23 +265,23 @@ // for details about the format. class ImportFile : public InputFile { public: - explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M) {} + explicit ImportFile(MemoryBufferRef m) : InputFile(ImportKind, m) {} - static bool classof(const InputFile *F) { return F->kind() == ImportKind; } + static bool classof(const InputFile *f) { return f->kind() == ImportKind; } - static std::vector Instances; + static std::vector instances; - Symbol *ImpSym = nullptr; - Symbol *ThunkSym = nullptr; - std::string DLLName; + Symbol *impSym = nullptr; + Symbol *thunkSym = nullptr; + std::string dllName; private: void parse() override; public: - StringRef ExternalName; - const coff_import_header *Hdr; - Chunk *Location = nullptr; + StringRef externalName; + const coff_import_header *hdr; + Chunk *location = nullptr; // We want to eliminate dllimported symbols if no one actually refers them. // These "Live" bits are used to keep track of which import library members @@ -291,29 +291,29 @@ // symbols provided by this import library member. We also track whether the // imported symbol is used separately from whether the thunk is used in order // to avoid creating unnecessary thunks. - bool Live = !Config->DoGC; - bool ThunkLive = !Config->DoGC; + bool live = !config->doGC; + bool thunkLive = !config->doGC; }; // Used for LTO. class BitcodeFile : public InputFile { public: - BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, - uint64_t OffsetInArchive); - static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } - ArrayRef getSymbols() { return Symbols; } + BitcodeFile(MemoryBufferRef mb, StringRef archiveName, + uint64_t offsetInArchive); + static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } + ArrayRef getSymbols() { return symbols; } MachineTypes getMachineType() override; - static std::vector Instances; - std::unique_ptr Obj; + static std::vector instances; + std::unique_ptr obj; private: void parse() override; - std::vector Symbols; + std::vector symbols; }; } // namespace coff -std::string toString(const coff::InputFile *File); +std::string toString(const coff::InputFile *file); } // namespace lld #endif Index: lld/trunk/COFF/InputFiles.cpp =================================================================== --- lld/trunk/COFF/InputFiles.cpp +++ lld/trunk/COFF/InputFiles.cpp @@ -49,80 +49,80 @@ namespace lld { namespace coff { -std::vector ObjFile::Instances; -std::vector ImportFile::Instances; -std::vector BitcodeFile::Instances; +std::vector ObjFile::instances; +std::vector ImportFile::instances; +std::vector BitcodeFile::instances; /// Checks that Source is compatible with being a weak alias to Target. /// If Source is Undefined and has no weak alias set, makes it a weak /// alias to Target. -static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, - Symbol *Source, Symbol *Target) { - if (auto *U = dyn_cast(Source)) { - if (U->WeakAlias && U->WeakAlias != Target) { +static void checkAndSetWeakAlias(SymbolTable *symtab, InputFile *f, + Symbol *source, Symbol *target) { + if (auto *u = dyn_cast(source)) { + if (u->weakAlias && u->weakAlias != target) { // Weak aliases as produced by GCC are named in the form // .weak.., where is the name // of another symbol emitted near the weak symbol. // Just use the definition from the first object file that defined // this weak symbol. - if (Config->MinGW) + if (config->mingw) return; - Symtab->reportDuplicate(Source, F); + symtab->reportDuplicate(source, f); } - U->WeakAlias = Target; + u->weakAlias = target; } } -ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} +ArchiveFile::ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {} void ArchiveFile::parse() { // Parse a MemoryBufferRef as an archive file. - File = CHECK(Archive::create(MB), this); + file = CHECK(Archive::create(mb), this); // Read the symbol table to construct Lazy objects. - for (const Archive::Symbol &Sym : File->symbols()) - Symtab->addLazy(this, Sym); + for (const Archive::Symbol &sym : file->symbols()) + symtab->addLazy(this, sym); } // Returns a buffer pointing to a member file containing a given symbol. -void ArchiveFile::addMember(const Archive::Symbol *Sym) { - const Archive::Child &C = - CHECK(Sym->getMember(), - "could not get the member for symbol " + Sym->getName()); +void ArchiveFile::addMember(const Archive::Symbol *sym) { + const Archive::Child &c = + CHECK(sym->getMember(), + "could not get the member for symbol " + sym->getName()); // Return an empty buffer if we have already returned the same buffer. - if (!Seen.insert(C.getChildOffset()).second) + if (!seen.insert(c.getChildOffset()).second) return; - Driver->enqueueArchiveMember(C, Sym->getName(), getName()); + driver->enqueueArchiveMember(c, sym->getName(), getName()); } -std::vector getArchiveMembers(Archive *File) { - std::vector V; - Error Err = Error::success(); - for (const ErrorOr &COrErr : File->children(Err)) { - Archive::Child C = - CHECK(COrErr, - File->getFileName() + ": could not get the child of the archive"); - MemoryBufferRef MBRef = - CHECK(C.getMemoryBufferRef(), - File->getFileName() + +std::vector getArchiveMembers(Archive *file) { + std::vector v; + Error err = Error::success(); + for (const ErrorOr &cOrErr : file->children(err)) { + Archive::Child c = + CHECK(cOrErr, + file->getFileName() + ": could not get the child of the archive"); + MemoryBufferRef mbref = + CHECK(c.getMemoryBufferRef(), + file->getFileName() + ": could not get the buffer for a child of the archive"); - V.push_back(MBRef); + v.push_back(mbref); } - if (Err) - fatal(File->getFileName() + - ": Archive::children failed: " + toString(std::move(Err))); - return V; + if (err) + fatal(file->getFileName() + + ": Archive::children failed: " + toString(std::move(err))); + return v; } void ObjFile::parse() { // Parse a memory buffer as a COFF file. - std::unique_ptr Bin = CHECK(createBinary(MB), this); + std::unique_ptr bin = CHECK(createBinary(mb), this); - if (auto *Obj = dyn_cast(Bin.get())) { - Bin.release(); - COFFObj.reset(Obj); + if (auto *obj = dyn_cast(bin.get())) { + bin.release(); + coffObj.reset(obj); } else { fatal(toString(this) + " is not a COFF file"); } @@ -134,11 +134,11 @@ initializeDependencies(); } -const coff_section* ObjFile::getSection(uint32_t I) { - const coff_section *Sec; - if (auto EC = COFFObj->getSection(I, Sec)) - fatal("getSection failed: #" + Twine(I) + ": " + EC.message()); - return Sec; +const coff_section* ObjFile::getSection(uint32_t i) { + const coff_section *sec; + if (auto ec = coffObj->getSection(i, sec)) + fatal("getSection failed: #" + Twine(i) + ": " + ec.message()); + return sec; } // We set SectionChunk pointers in the SparseChunks vector to this value @@ -147,42 +147,42 @@ // an associative section definition together with the parent comdat's leader, // we set the pointer to either nullptr (to mark the section as discarded) or a // valid SectionChunk for that section. -static SectionChunk *const PendingComdat = reinterpret_cast(1); +static SectionChunk *const pendingComdat = reinterpret_cast(1); void ObjFile::initializeChunks() { - uint32_t NumSections = COFFObj->getNumberOfSections(); - Chunks.reserve(NumSections); - SparseChunks.resize(NumSections + 1); - for (uint32_t I = 1; I < NumSections + 1; ++I) { - const coff_section *Sec = getSection(I); - if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT) - SparseChunks[I] = PendingComdat; + uint32_t numSections = coffObj->getNumberOfSections(); + chunks.reserve(numSections); + sparseChunks.resize(numSections + 1); + for (uint32_t i = 1; i < numSections + 1; ++i) { + const coff_section *sec = getSection(i); + if (sec->Characteristics & IMAGE_SCN_LNK_COMDAT) + sparseChunks[i] = pendingComdat; else - SparseChunks[I] = readSection(I, nullptr, ""); + sparseChunks[i] = readSection(i, nullptr, ""); } } -SectionChunk *ObjFile::readSection(uint32_t SectionNumber, - const coff_aux_section_definition *Def, - StringRef LeaderName) { - const coff_section *Sec = getSection(SectionNumber); +SectionChunk *ObjFile::readSection(uint32_t sectionNumber, + const coff_aux_section_definition *def, + StringRef leaderName) { + const coff_section *sec = getSection(sectionNumber); - StringRef Name; - if (Expected E = COFFObj->getSectionName(Sec)) - Name = *E; + StringRef name; + if (Expected e = coffObj->getSectionName(sec)) + name = *e; else - fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " + - toString(E.takeError())); + fatal("getSectionName failed: #" + Twine(sectionNumber) + ": " + + toString(e.takeError())); - if (Name == ".drectve") { - ArrayRef Data; - cantFail(COFFObj->getSectionContents(Sec, Data)); - Directives = StringRef((const char *)Data.data(), Data.size()); + if (name == ".drectve") { + ArrayRef data; + cantFail(coffObj->getSectionContents(sec, data)); + directives = StringRef((const char *)data.data(), data.size()); return nullptr; } - if (Name == ".llvm_addrsig") { - AddrsigSec = Sec; + if (name == ".llvm_addrsig") { + addrsigSec = sec; return nullptr; } @@ -197,166 +197,166 @@ // and then write it to a separate .pdb file. // Ignore DWARF debug info unless /debug is given. - if (!Config->Debug && Name.startswith(".debug_")) + if (!config->debug && name.startswith(".debug_")) return nullptr; - if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) + if (sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) return nullptr; - auto *C = make(this, Sec); - if (Def) - C->Checksum = Def->CheckSum; + auto *c = make(this, sec); + if (def) + c->checksum = def->CheckSum; // link.exe uses the presence of .rsrc$01 for LNK4078, so match that. - if (Name == ".rsrc$01") - IsResourceObjFile = true; + if (name == ".rsrc$01") + isResourceObjFile = true; // CodeView sections are stored to a different vector because they are not // linked in the regular manner. - if (C->isCodeView()) - DebugChunks.push_back(C); - else if (Name == ".gfids$y") - GuardFidChunks.push_back(C); - else if (Name == ".gljmp$y") - GuardLJmpChunks.push_back(C); - else if (Name == ".sxdata") - SXDataChunks.push_back(C); - else if (Config->TailMerge && Sec->NumberOfRelocations == 0 && - Name == ".rdata" && LeaderName.startswith("??_C@")) + if (c->isCodeView()) + debugChunks.push_back(c); + else if (name == ".gfids$y") + guardFidChunks.push_back(c); + else if (name == ".gljmp$y") + guardLJmpChunks.push_back(c); + else if (name == ".sxdata") + sXDataChunks.push_back(c); + else if (config->tailMerge && sec->NumberOfRelocations == 0 && + name == ".rdata" && leaderName.startswith("??_C@")) // COFF sections that look like string literal sections (i.e. no // relocations, in .rdata, leader symbol name matches the MSVC name mangling // for string literals) are subject to string tail merging. - MergeChunk::addSection(C); + MergeChunk::addSection(c); else - Chunks.push_back(C); + chunks.push_back(c); - return C; + return c; } void ObjFile::readAssociativeDefinition( - COFFSymbolRef Sym, const coff_aux_section_definition *Def) { - readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj())); + COFFSymbolRef sym, const coff_aux_section_definition *def) { + readAssociativeDefinition(sym, def, def->getNumber(sym.isBigObj())); } -void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym, - const coff_aux_section_definition *Def, - uint32_t ParentIndex) { - SectionChunk *Parent = SparseChunks[ParentIndex]; - int32_t SectionNumber = Sym.getSectionNumber(); - - auto Diag = [&]() { - StringRef Name, ParentName; - COFFObj->getSymbolName(Sym, Name); - - const coff_section *ParentSec = getSection(ParentIndex); - if (Expected E = COFFObj->getSectionName(ParentSec)) - ParentName = *E; - error(toString(this) + ": associative comdat " + Name + " (sec " + - Twine(SectionNumber) + ") has invalid reference to section " + - ParentName + " (sec " + Twine(ParentIndex) + ")"); +void ObjFile::readAssociativeDefinition(COFFSymbolRef sym, + const coff_aux_section_definition *def, + uint32_t parentIndex) { + SectionChunk *parent = sparseChunks[parentIndex]; + int32_t sectionNumber = sym.getSectionNumber(); + + auto diag = [&]() { + StringRef name, parentName; + coffObj->getSymbolName(sym, name); + + const coff_section *parentSec = getSection(parentIndex); + if (Expected e = coffObj->getSectionName(parentSec)) + parentName = *e; + error(toString(this) + ": associative comdat " + name + " (sec " + + Twine(sectionNumber) + ") has invalid reference to section " + + parentName + " (sec " + Twine(parentIndex) + ")"); }; - if (Parent == PendingComdat) { + if (parent == pendingComdat) { // This can happen if an associative comdat refers to another associative // comdat that appears after it (invalid per COFF spec) or to a section // without any symbols. - Diag(); + diag(); return; } // Check whether the parent is prevailing. If it is, so are we, and we read // the section; otherwise mark it as discarded. - if (Parent) { - SectionChunk *C = readSection(SectionNumber, Def, ""); - SparseChunks[SectionNumber] = C; - if (C) { - C->Selection = IMAGE_COMDAT_SELECT_ASSOCIATIVE; - Parent->addAssociative(C); + if (parent) { + SectionChunk *c = readSection(sectionNumber, def, ""); + sparseChunks[sectionNumber] = c; + if (c) { + c->selection = IMAGE_COMDAT_SELECT_ASSOCIATIVE; + parent->addAssociative(c); } } else { - SparseChunks[SectionNumber] = nullptr; + sparseChunks[sectionNumber] = nullptr; } } void ObjFile::recordPrevailingSymbolForMingw( - COFFSymbolRef Sym, DenseMap &PrevailingSectionMap) { + COFFSymbolRef sym, DenseMap &prevailingSectionMap) { // For comdat symbols in executable sections, where this is the copy // of the section chunk we actually include instead of discarding it, // add the symbol to a map to allow using it for implicitly // associating .[px]data$ sections to it. - int32_t SectionNumber = Sym.getSectionNumber(); - SectionChunk *SC = SparseChunks[SectionNumber]; - if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) { - StringRef Name; - COFFObj->getSymbolName(Sym, Name); + int32_t sectionNumber = sym.getSectionNumber(); + SectionChunk *sc = sparseChunks[sectionNumber]; + if (sc && sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) { + StringRef name; + coffObj->getSymbolName(sym, name); if (getMachineType() == I386) - Name.consume_front("_"); - PrevailingSectionMap[Name] = SectionNumber; + name.consume_front("_"); + prevailingSectionMap[name] = sectionNumber; } } void ObjFile::maybeAssociateSEHForMingw( - COFFSymbolRef Sym, const coff_aux_section_definition *Def, - const DenseMap &PrevailingSectionMap) { - StringRef Name; - COFFObj->getSymbolName(Sym, Name); - if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$") || - Name.consume_front(".eh_frame$")) { + COFFSymbolRef sym, const coff_aux_section_definition *def, + const DenseMap &prevailingSectionMap) { + StringRef name; + coffObj->getSymbolName(sym, name); + if (name.consume_front(".pdata$") || name.consume_front(".xdata$") || + name.consume_front(".eh_frame$")) { // For MinGW, treat .[px]data$ and .eh_frame$ as implicitly // associative to the symbol . - auto ParentSym = PrevailingSectionMap.find(Name); - if (ParentSym != PrevailingSectionMap.end()) - readAssociativeDefinition(Sym, Def, ParentSym->second); + auto parentSym = prevailingSectionMap.find(name); + if (parentSym != prevailingSectionMap.end()) + readAssociativeDefinition(sym, def, parentSym->second); } } -Symbol *ObjFile::createRegular(COFFSymbolRef Sym) { - SectionChunk *SC = SparseChunks[Sym.getSectionNumber()]; - if (Sym.isExternal()) { - StringRef Name; - COFFObj->getSymbolName(Sym, Name); - if (SC) - return Symtab->addRegular(this, Name, Sym.getGeneric(), SC); +Symbol *ObjFile::createRegular(COFFSymbolRef sym) { + SectionChunk *sc = sparseChunks[sym.getSectionNumber()]; + if (sym.isExternal()) { + StringRef name; + coffObj->getSymbolName(sym, name); + if (sc) + return symtab->addRegular(this, name, sym.getGeneric(), sc); // For MinGW symbols named .weak.* that point to a discarded section, // don't create an Undefined symbol. If nothing ever refers to the symbol, // everything should be fine. If something actually refers to the symbol // (e.g. the undefined weak alias), linking will fail due to undefined // references at the end. - if (Config->MinGW && Name.startswith(".weak.")) + if (config->mingw && name.startswith(".weak.")) return nullptr; - return Symtab->addUndefined(Name, this, false); + return symtab->addUndefined(name, this, false); } - if (SC) + if (sc) return make(this, /*Name*/ "", /*IsCOMDAT*/ false, - /*IsExternal*/ false, Sym.getGeneric(), SC); + /*IsExternal*/ false, sym.getGeneric(), sc); return nullptr; } void ObjFile::initializeSymbols() { - uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); - Symbols.resize(NumSymbols); + uint32_t numSymbols = coffObj->getNumberOfSymbols(); + symbols.resize(numSymbols); - SmallVector, 8> WeakAliases; - std::vector PendingIndexes; - PendingIndexes.reserve(NumSymbols); - - DenseMap PrevailingSectionMap; - std::vector ComdatDefs( - COFFObj->getNumberOfSections() + 1); - - for (uint32_t I = 0; I < NumSymbols; ++I) { - COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I)); - bool PrevailingComdat; - if (COFFSym.isUndefined()) { - Symbols[I] = createUndefined(COFFSym); - } else if (COFFSym.isWeakExternal()) { - Symbols[I] = createUndefined(COFFSym); - uint32_t TagIndex = COFFSym.getAux()->TagIndex; - WeakAliases.emplace_back(Symbols[I], TagIndex); - } else if (Optional OptSym = - createDefined(COFFSym, ComdatDefs, PrevailingComdat)) { - Symbols[I] = *OptSym; - if (Config->MinGW && PrevailingComdat) - recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap); + SmallVector, 8> weakAliases; + std::vector pendingIndexes; + pendingIndexes.reserve(numSymbols); + + DenseMap prevailingSectionMap; + std::vector comdatDefs( + coffObj->getNumberOfSections() + 1); + + for (uint32_t i = 0; i < numSymbols; ++i) { + COFFSymbolRef coffSym = check(coffObj->getSymbol(i)); + bool prevailingComdat; + if (coffSym.isUndefined()) { + symbols[i] = createUndefined(coffSym); + } else if (coffSym.isWeakExternal()) { + symbols[i] = createUndefined(coffSym); + uint32_t tagIndex = coffSym.getAux()->TagIndex; + weakAliases.emplace_back(symbols[i], tagIndex); + } else if (Optional optSym = + createDefined(coffSym, comdatDefs, prevailingComdat)) { + symbols[i] = *optSym; + if (config->mingw && prevailingComdat) + recordPrevailingSymbolForMingw(coffSym, prevailingSectionMap); } else { // createDefined() returns None if a symbol belongs to a section that // was pending at the point when the symbol was read. This can happen in @@ -366,71 +366,71 @@ // In both of these cases, we can expect the section to be resolved by // the time we finish visiting the remaining symbols in the symbol // table. So we postpone the handling of this symbol until that time. - PendingIndexes.push_back(I); + pendingIndexes.push_back(i); } - I += COFFSym.getNumberOfAuxSymbols(); + i += coffSym.getNumberOfAuxSymbols(); } - for (uint32_t I : PendingIndexes) { - COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); - if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) { - if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) - readAssociativeDefinition(Sym, Def); - else if (Config->MinGW) - maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap); - } - if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) { - StringRef Name; - COFFObj->getSymbolName(Sym, Name); - log("comdat section " + Name + + for (uint32_t i : pendingIndexes) { + COFFSymbolRef sym = check(coffObj->getSymbol(i)); + if (const coff_aux_section_definition *def = sym.getSectionDefinition()) { + if (def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) + readAssociativeDefinition(sym, def); + else if (config->mingw) + maybeAssociateSEHForMingw(sym, def, prevailingSectionMap); + } + if (sparseChunks[sym.getSectionNumber()] == pendingComdat) { + StringRef name; + coffObj->getSymbolName(sym, name); + log("comdat section " + name + " without leader and unassociated, discarding"); continue; } - Symbols[I] = createRegular(Sym); + symbols[i] = createRegular(sym); } - for (auto &KV : WeakAliases) { - Symbol *Sym = KV.first; - uint32_t Idx = KV.second; - checkAndSetWeakAlias(Symtab, this, Sym, Symbols[Idx]); + for (auto &kv : weakAliases) { + Symbol *sym = kv.first; + uint32_t idx = kv.second; + checkAndSetWeakAlias(symtab, this, sym, symbols[idx]); } } -Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) { - StringRef Name; - COFFObj->getSymbolName(Sym, Name); - return Symtab->addUndefined(Name, this, Sym.isWeakExternal()); +Symbol *ObjFile::createUndefined(COFFSymbolRef sym) { + StringRef name; + coffObj->getSymbolName(sym, name); + return symtab->addUndefined(name, this, sym.isWeakExternal()); } -void ObjFile::handleComdatSelection(COFFSymbolRef Sym, COMDATType &Selection, - bool &Prevailing, DefinedRegular *Leader) { - if (Prevailing) +void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection, + bool &prevailing, DefinedRegular *leader) { + if (prevailing) return; // There's already an existing comdat for this symbol: `Leader`. // Use the comdats's selection field to determine if the new // symbol in `Sym` should be discarded, produce a duplicate symbol // error, etc. - SectionChunk *LeaderChunk = nullptr; - COMDATType LeaderSelection = IMAGE_COMDAT_SELECT_ANY; + SectionChunk *leaderChunk = nullptr; + COMDATType leaderSelection = IMAGE_COMDAT_SELECT_ANY; - if (Leader->Data) { - LeaderChunk = Leader->getChunk(); - LeaderSelection = LeaderChunk->Selection; + if (leader->data) { + leaderChunk = leader->getChunk(); + leaderSelection = leaderChunk->selection; } else { // FIXME: comdats from LTO files don't know their selection; treat them // as "any". - Selection = LeaderSelection; + selection = leaderSelection; } - if ((Selection == IMAGE_COMDAT_SELECT_ANY && - LeaderSelection == IMAGE_COMDAT_SELECT_LARGEST) || - (Selection == IMAGE_COMDAT_SELECT_LARGEST && - LeaderSelection == IMAGE_COMDAT_SELECT_ANY)) { + if ((selection == IMAGE_COMDAT_SELECT_ANY && + leaderSelection == IMAGE_COMDAT_SELECT_LARGEST) || + (selection == IMAGE_COMDAT_SELECT_LARGEST && + leaderSelection == IMAGE_COMDAT_SELECT_ANY)) { // cl.exe picks "any" for vftables when building with /GR- and // "largest" when building with /GR. To be able to link object files // compiled with each flag, "any" and "largest" are merged as "largest". - LeaderSelection = Selection = IMAGE_COMDAT_SELECT_LARGEST; + leaderSelection = selection = IMAGE_COMDAT_SELECT_LARGEST; } // Other than that, comdat selections must match. This is a bit more @@ -440,18 +440,18 @@ // Making this symmetric independent of which selection is seen first // seems better though. // (This behavior matches ModuleLinker::getComdatResult().) - if (Selection != LeaderSelection) { - log(("conflicting comdat type for " + toString(*Leader) + ": " + - Twine((int)LeaderSelection) + " in " + toString(Leader->getFile()) + - " and " + Twine((int)Selection) + " in " + toString(this)) + if (selection != leaderSelection) { + log(("conflicting comdat type for " + toString(*leader) + ": " + + Twine((int)leaderSelection) + " in " + toString(leader->getFile()) + + " and " + Twine((int)selection) + " in " + toString(this)) .str()); - Symtab->reportDuplicate(Leader, this); + symtab->reportDuplicate(leader, this); return; } - switch (Selection) { + switch (selection) { case IMAGE_COMDAT_SELECT_NODUPLICATES: - Symtab->reportDuplicate(Leader, this); + symtab->reportDuplicate(leader, this); break; case IMAGE_COMDAT_SELECT_ANY: @@ -459,17 +459,17 @@ break; case IMAGE_COMDAT_SELECT_SAME_SIZE: - if (LeaderChunk->getSize() != getSection(Sym)->SizeOfRawData) - Symtab->reportDuplicate(Leader, this); + if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData) + symtab->reportDuplicate(leader, this); break; case IMAGE_COMDAT_SELECT_EXACT_MATCH: { - SectionChunk NewChunk(this, getSection(Sym)); + SectionChunk newChunk(this, getSection(sym)); // link.exe only compares section contents here and doesn't complain // if the two comdat sections have e.g. different alignment. // Match that. - if (LeaderChunk->getContents() != NewChunk.getContents()) - Symtab->reportDuplicate(Leader, this); + if (leaderChunk->getContents() != newChunk.getContents()) + symtab->reportDuplicate(leader, this); break; } @@ -481,20 +481,20 @@ llvm_unreachable("createDefined not called for associative comdats"); case IMAGE_COMDAT_SELECT_LARGEST: - if (LeaderChunk->getSize() < getSection(Sym)->SizeOfRawData) { + if (leaderChunk->getSize() < getSection(sym)->SizeOfRawData) { // Replace the existing comdat symbol with the new one. - StringRef Name; - COFFObj->getSymbolName(Sym, Name); + StringRef name; + coffObj->getSymbolName(sym, name); // FIXME: This is incorrect: With /opt:noref, the previous sections // make it into the final executable as well. Correct handling would // be to undo reading of the whole old section that's being replaced, // or doing one pass that determines what the final largest comdat // is for all IMAGE_COMDAT_SELECT_LARGEST comdats and then reading // only the largest one. - replaceSymbol(Leader, this, Name, /*IsCOMDAT*/ true, - /*IsExternal*/ true, Sym.getGeneric(), + replaceSymbol(leader, this, name, /*IsCOMDAT*/ true, + /*IsExternal*/ true, sym.getGeneric(), nullptr); - Prevailing = true; + prevailing = true; } break; @@ -504,50 +504,50 @@ } Optional ObjFile::createDefined( - COFFSymbolRef Sym, - std::vector &ComdatDefs, - bool &Prevailing) { - Prevailing = false; - auto GetName = [&]() { - StringRef S; - COFFObj->getSymbolName(Sym, S); - return S; + COFFSymbolRef sym, + std::vector &comdatDefs, + bool &prevailing) { + prevailing = false; + auto getName = [&]() { + StringRef s; + coffObj->getSymbolName(sym, s); + return s; }; - if (Sym.isCommon()) { - auto *C = make(Sym); - Chunks.push_back(C); - return Symtab->addCommon(this, GetName(), Sym.getValue(), Sym.getGeneric(), - C); + if (sym.isCommon()) { + auto *c = make(sym); + chunks.push_back(c); + return symtab->addCommon(this, getName(), sym.getValue(), sym.getGeneric(), + c); } - if (Sym.isAbsolute()) { - StringRef Name = GetName(); + if (sym.isAbsolute()) { + StringRef name = getName(); // Skip special symbols. - if (Name == "@comp.id") + if (name == "@comp.id") return nullptr; - if (Name == "@feat.00") { - Feat00Flags = Sym.getValue(); + if (name == "@feat.00") { + feat00Flags = sym.getValue(); return nullptr; } - if (Sym.isExternal()) - return Symtab->addAbsolute(Name, Sym); - return make(Name, Sym); + if (sym.isExternal()) + return symtab->addAbsolute(name, sym); + return make(name, sym); } - int32_t SectionNumber = Sym.getSectionNumber(); - if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) + int32_t sectionNumber = sym.getSectionNumber(); + if (sectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) return nullptr; - if (llvm::COFF::isReservedSectionNumber(SectionNumber)) - fatal(toString(this) + ": " + GetName() + - " should not refer to special section " + Twine(SectionNumber)); - - if ((uint32_t)SectionNumber >= SparseChunks.size()) - fatal(toString(this) + ": " + GetName() + - " should not refer to non-existent section " + Twine(SectionNumber)); + if (llvm::COFF::isReservedSectionNumber(sectionNumber)) + fatal(toString(this) + ": " + getName() + + " should not refer to special section " + Twine(sectionNumber)); + + if ((uint32_t)sectionNumber >= sparseChunks.size()) + fatal(toString(this) + ": " + getName() + + " should not refer to non-existent section " + Twine(sectionNumber)); // Comdat handling. // A comdat symbol consists of two symbol table entries. @@ -560,65 +560,65 @@ // symbol entry it reads ComdatDefs and then sets it back to nullptr. // Handle comdat leader. - if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) { - ComdatDefs[SectionNumber] = nullptr; - DefinedRegular *Leader; - - if (Sym.isExternal()) { - std::tie(Leader, Prevailing) = - Symtab->addComdat(this, GetName(), Sym.getGeneric()); + if (const coff_aux_section_definition *def = comdatDefs[sectionNumber]) { + comdatDefs[sectionNumber] = nullptr; + DefinedRegular *leader; + + if (sym.isExternal()) { + std::tie(leader, prevailing) = + symtab->addComdat(this, getName(), sym.getGeneric()); } else { - Leader = make(this, /*Name*/ "", /*IsCOMDAT*/ false, - /*IsExternal*/ false, Sym.getGeneric()); - Prevailing = true; + leader = make(this, /*Name*/ "", /*IsCOMDAT*/ false, + /*IsExternal*/ false, sym.getGeneric()); + prevailing = true; } - if (Def->Selection < (int)IMAGE_COMDAT_SELECT_NODUPLICATES || + if (def->Selection < (int)IMAGE_COMDAT_SELECT_NODUPLICATES || // Intentionally ends at IMAGE_COMDAT_SELECT_LARGEST: link.exe // doesn't understand IMAGE_COMDAT_SELECT_NEWEST either. - Def->Selection > (int)IMAGE_COMDAT_SELECT_LARGEST) { - fatal("unknown comdat type " + std::to_string((int)Def->Selection) + - " for " + GetName() + " in " + toString(this)); - } - COMDATType Selection = (COMDATType)Def->Selection; - - if (Leader->IsCOMDAT) - handleComdatSelection(Sym, Selection, Prevailing, Leader); - - if (Prevailing) { - SectionChunk *C = readSection(SectionNumber, Def, GetName()); - SparseChunks[SectionNumber] = C; - C->Sym = cast(Leader); - C->Selection = Selection; - cast(Leader)->Data = &C->Repl; + def->Selection > (int)IMAGE_COMDAT_SELECT_LARGEST) { + fatal("unknown comdat type " + std::to_string((int)def->Selection) + + " for " + getName() + " in " + toString(this)); + } + COMDATType selection = (COMDATType)def->Selection; + + if (leader->isCOMDAT) + handleComdatSelection(sym, selection, prevailing, leader); + + if (prevailing) { + SectionChunk *c = readSection(sectionNumber, def, getName()); + sparseChunks[sectionNumber] = c; + c->sym = cast(leader); + c->selection = selection; + cast(leader)->data = &c->repl; } else { - SparseChunks[SectionNumber] = nullptr; + sparseChunks[sectionNumber] = nullptr; } - return Leader; + return leader; } // Prepare to handle the comdat leader symbol by setting the section's // ComdatDefs pointer if we encounter a non-associative comdat. - if (SparseChunks[SectionNumber] == PendingComdat) { - if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) { - if (Def->Selection != IMAGE_COMDAT_SELECT_ASSOCIATIVE) - ComdatDefs[SectionNumber] = Def; + if (sparseChunks[sectionNumber] == pendingComdat) { + if (const coff_aux_section_definition *def = sym.getSectionDefinition()) { + if (def->Selection != IMAGE_COMDAT_SELECT_ASSOCIATIVE) + comdatDefs[sectionNumber] = def; } return None; } - return createRegular(Sym); + return createRegular(sym); } MachineTypes ObjFile::getMachineType() { - if (COFFObj) - return static_cast(COFFObj->getMachine()); + if (coffObj) + return static_cast(coffObj->getMachine()); return IMAGE_FILE_MACHINE_UNKNOWN; } -ArrayRef ObjFile::getDebugSection(StringRef SecName) { - if (SectionChunk *Sec = SectionChunk::findByName(DebugChunks, SecName)) - return Sec->consumeDebugMagic(); +ArrayRef ObjFile::getDebugSection(StringRef secName) { + if (SectionChunk *sec = SectionChunk::findByName(debugChunks, secName)) + return sec->consumeDebugMagic(); return {}; } @@ -628,43 +628,43 @@ // PCHSignature member. S_COMPILE3 stores compile-time cmd-line flags. This is // currently used to initialize the HotPatchable member. void ObjFile::initializeFlags() { - ArrayRef Data = getDebugSection(".debug$S"); - if (Data.empty()) + ArrayRef data = getDebugSection(".debug$S"); + if (data.empty()) return; - DebugSubsectionArray Subsections; + DebugSubsectionArray subsections; - BinaryStreamReader Reader(Data, support::little); - ExitOnError ExitOnErr; - ExitOnErr(Reader.readArray(Subsections, Data.size())); + BinaryStreamReader reader(data, support::little); + ExitOnError exitOnErr; + exitOnErr(reader.readArray(subsections, data.size())); - for (const DebugSubsectionRecord &SS : Subsections) { - if (SS.kind() != DebugSubsectionKind::Symbols) + for (const DebugSubsectionRecord &ss : subsections) { + if (ss.kind() != DebugSubsectionKind::Symbols) continue; - unsigned Offset = 0; + unsigned offset = 0; // Only parse the first two records. We are only looking for S_OBJNAME // and S_COMPILE3, and they usually appear at the beginning of the // stream. - for (unsigned I = 0; I < 2; ++I) { - Expected Sym = readSymbolFromStream(SS.getRecordData(), Offset); - if (!Sym) { - consumeError(Sym.takeError()); + for (unsigned i = 0; i < 2; ++i) { + Expected sym = readSymbolFromStream(ss.getRecordData(), offset); + if (!sym) { + consumeError(sym.takeError()); return; } - if (Sym->kind() == SymbolKind::S_COMPILE3) { - auto CS = - cantFail(SymbolDeserializer::deserializeAs(Sym.get())); - HotPatchable = - (CS.Flags & CompileSym3Flags::HotPatch) != CompileSym3Flags::None; + if (sym->kind() == SymbolKind::S_COMPILE3) { + auto cs = + cantFail(SymbolDeserializer::deserializeAs(sym.get())); + hotPatchable = + (cs.Flags & CompileSym3Flags::HotPatch) != CompileSym3Flags::None; } - if (Sym->kind() == SymbolKind::S_OBJNAME) { - auto ObjName = cantFail(SymbolDeserializer::deserializeAs( - Sym.get())); - PCHSignature = ObjName.Signature; + if (sym->kind() == SymbolKind::S_OBJNAME) { + auto objName = cantFail(SymbolDeserializer::deserializeAs( + sym.get())); + pchSignature = objName.Signature; } - Offset += Sym->length(); + offset += sym->length(); } } } @@ -677,112 +677,112 @@ // DebugTypes.h). Both cases only happen with cl.exe: clang-cl produces regular // output even with /Yc and /Yu and with /Zi. void ObjFile::initializeDependencies() { - if (!Config->Debug) + if (!config->debug) return; - bool IsPCH = false; + bool isPCH = false; - ArrayRef Data = getDebugSection(".debug$P"); - if (!Data.empty()) - IsPCH = true; + ArrayRef data = getDebugSection(".debug$P"); + if (!data.empty()) + isPCH = true; else - Data = getDebugSection(".debug$T"); + data = getDebugSection(".debug$T"); - if (Data.empty()) + if (data.empty()) return; - CVTypeArray Types; - BinaryStreamReader Reader(Data, support::little); - cantFail(Reader.readArray(Types, Reader.getLength())); + CVTypeArray types; + BinaryStreamReader reader(data, support::little); + cantFail(reader.readArray(types, reader.getLength())); - CVTypeArray::Iterator FirstType = Types.begin(); - if (FirstType == Types.end()) + CVTypeArray::Iterator firstType = types.begin(); + if (firstType == types.end()) return; - DebugTypes.emplace(Types); + debugTypes.emplace(types); - if (IsPCH) { - DebugTypesObj = makePrecompSource(this); + if (isPCH) { + debugTypesObj = makePrecompSource(this); return; } - if (FirstType->kind() == LF_TYPESERVER2) { - TypeServer2Record TS = cantFail( - TypeDeserializer::deserializeAs(FirstType->data())); - DebugTypesObj = makeUseTypeServerSource(this, &TS); + if (firstType->kind() == LF_TYPESERVER2) { + TypeServer2Record ts = cantFail( + TypeDeserializer::deserializeAs(firstType->data())); + debugTypesObj = makeUseTypeServerSource(this, &ts); return; } - if (FirstType->kind() == LF_PRECOMP) { - PrecompRecord Precomp = cantFail( - TypeDeserializer::deserializeAs(FirstType->data())); - DebugTypesObj = makeUsePrecompSource(this, &Precomp); + if (firstType->kind() == LF_PRECOMP) { + PrecompRecord precomp = cantFail( + TypeDeserializer::deserializeAs(firstType->data())); + debugTypesObj = makeUsePrecompSource(this, &precomp); return; } - DebugTypesObj = makeTpiSource(this); + debugTypesObj = makeTpiSource(this); } -StringRef ltrim1(StringRef S, const char *Chars) { - if (!S.empty() && strchr(Chars, S[0])) - return S.substr(1); - return S; +StringRef ltrim1(StringRef s, const char *chars) { + if (!s.empty() && strchr(chars, s[0])) + return s.substr(1); + return s; } void ImportFile::parse() { - const char *Buf = MB.getBufferStart(); - const auto *Hdr = reinterpret_cast(Buf); + const char *buf = mb.getBufferStart(); + const auto *hdr = reinterpret_cast(buf); // Check if the total size is valid. - if (MB.getBufferSize() != sizeof(*Hdr) + Hdr->SizeOfData) + if (mb.getBufferSize() != sizeof(*hdr) + hdr->SizeOfData) fatal("broken import library"); // Read names and create an __imp_ symbol. - StringRef Name = Saver.save(StringRef(Buf + sizeof(*Hdr))); - StringRef ImpName = Saver.save("__imp_" + Name); - const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1; - DLLName = StringRef(NameStart); - StringRef ExtName; - switch (Hdr->getNameType()) { + StringRef name = saver.save(StringRef(buf + sizeof(*hdr))); + StringRef impName = saver.save("__imp_" + name); + const char *nameStart = buf + sizeof(coff_import_header) + name.size() + 1; + dllName = StringRef(nameStart); + StringRef extName; + switch (hdr->getNameType()) { case IMPORT_ORDINAL: - ExtName = ""; + extName = ""; break; case IMPORT_NAME: - ExtName = Name; + extName = name; break; case IMPORT_NAME_NOPREFIX: - ExtName = ltrim1(Name, "?@_"); + extName = ltrim1(name, "?@_"); break; case IMPORT_NAME_UNDECORATE: - ExtName = ltrim1(Name, "?@_"); - ExtName = ExtName.substr(0, ExtName.find('@')); + extName = ltrim1(name, "?@_"); + extName = extName.substr(0, extName.find('@')); break; } - this->Hdr = Hdr; - ExternalName = ExtName; + this->hdr = hdr; + externalName = extName; - ImpSym = Symtab->addImportData(ImpName, this); + impSym = symtab->addImportData(impName, this); // If this was a duplicate, we logged an error but may continue; // in this case, ImpSym is nullptr. - if (!ImpSym) + if (!impSym) return; - if (Hdr->getType() == llvm::COFF::IMPORT_CONST) - static_cast(Symtab->addImportData(Name, this)); + if (hdr->getType() == llvm::COFF::IMPORT_CONST) + static_cast(symtab->addImportData(name, this)); // If type is function, we need to create a thunk which jump to an // address pointed by the __imp_ symbol. (This allows you to call // DLL functions just like regular non-DLL functions.) - if (Hdr->getType() == llvm::COFF::IMPORT_CODE) - ThunkSym = Symtab->addImportThunk( - Name, cast_or_null(ImpSym), Hdr->Machine); + if (hdr->getType() == llvm::COFF::IMPORT_CODE) + thunkSym = symtab->addImportThunk( + name, cast_or_null(impSym), hdr->Machine); } -BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, - uint64_t OffsetInArchive) - : InputFile(BitcodeKind, MB) { - std::string Path = MB.getBufferIdentifier().str(); +BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName, + uint64_t offsetInArchive) + : InputFile(BitcodeKind, mb) { + std::string path = mb.getBufferIdentifier().str(); // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two archives define two members with the same name, this @@ -790,53 +790,53 @@ // into consideration at LTO time (which very likely causes undefined // symbols later in the link stage). So we append file offset to make // filename unique. - MemoryBufferRef MBRef( - MB.getBuffer(), - Saver.save(ArchiveName + Path + - (ArchiveName.empty() ? "" : utostr(OffsetInArchive)))); + MemoryBufferRef mbref( + mb.getBuffer(), + saver.save(archiveName + path + + (archiveName.empty() ? "" : utostr(offsetInArchive)))); - Obj = check(lto::InputFile::create(MBRef)); + obj = check(lto::InputFile::create(mbref)); } void BitcodeFile::parse() { - std::vector> Comdat(Obj->getComdatTable().size()); - for (size_t I = 0; I != Obj->getComdatTable().size(); ++I) + std::vector> comdat(obj->getComdatTable().size()); + for (size_t i = 0; i != obj->getComdatTable().size(); ++i) // FIXME: lto::InputFile doesn't keep enough data to do correct comdat // selection handling. - Comdat[I] = Symtab->addComdat(this, Saver.save(Obj->getComdatTable()[I])); - for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) { - StringRef SymName = Saver.save(ObjSym.getName()); - int ComdatIndex = ObjSym.getComdatIndex(); - Symbol *Sym; - if (ObjSym.isUndefined()) { - Sym = Symtab->addUndefined(SymName, this, false); - } else if (ObjSym.isCommon()) { - Sym = Symtab->addCommon(this, SymName, ObjSym.getCommonSize()); - } else if (ObjSym.isWeak() && ObjSym.isIndirect()) { + comdat[i] = symtab->addComdat(this, saver.save(obj->getComdatTable()[i])); + for (const lto::InputFile::Symbol &objSym : obj->symbols()) { + StringRef symName = saver.save(objSym.getName()); + int comdatIndex = objSym.getComdatIndex(); + Symbol *sym; + if (objSym.isUndefined()) { + sym = symtab->addUndefined(symName, this, false); + } else if (objSym.isCommon()) { + sym = symtab->addCommon(this, symName, objSym.getCommonSize()); + } else if (objSym.isWeak() && objSym.isIndirect()) { // Weak external. - Sym = Symtab->addUndefined(SymName, this, true); - std::string Fallback = ObjSym.getCOFFWeakExternalFallback(); - Symbol *Alias = Symtab->addUndefined(Saver.save(Fallback)); - checkAndSetWeakAlias(Symtab, this, Sym, Alias); - } else if (ComdatIndex != -1) { - if (SymName == Obj->getComdatTable()[ComdatIndex]) - Sym = Comdat[ComdatIndex].first; - else if (Comdat[ComdatIndex].second) - Sym = Symtab->addRegular(this, SymName); + sym = symtab->addUndefined(symName, this, true); + std::string fallback = objSym.getCOFFWeakExternalFallback(); + Symbol *alias = symtab->addUndefined(saver.save(fallback)); + checkAndSetWeakAlias(symtab, this, sym, alias); + } else if (comdatIndex != -1) { + if (symName == obj->getComdatTable()[comdatIndex]) + sym = comdat[comdatIndex].first; + else if (comdat[comdatIndex].second) + sym = symtab->addRegular(this, symName); else - Sym = Symtab->addUndefined(SymName, this, false); + sym = symtab->addUndefined(symName, this, false); } else { - Sym = Symtab->addRegular(this, SymName); + sym = symtab->addRegular(this, symName); } - Symbols.push_back(Sym); - if (ObjSym.isUsed()) - Config->GCRoot.push_back(Sym); + symbols.push_back(sym); + if (objSym.isUsed()) + config->gCRoot.push_back(sym); } - Directives = Obj->getCOFFLinkerOpts(); + directives = obj->getCOFFLinkerOpts(); } MachineTypes BitcodeFile::getMachineType() { - switch (Triple(Obj->getTargetTriple()).getArch()) { + switch (Triple(obj->getTargetTriple()).getArch()) { case Triple::x86_64: return AMD64; case Triple::x86: @@ -853,18 +853,18 @@ } // namespace lld // Returns the last element of a path, which is supposed to be a filename. -static StringRef getBasename(StringRef Path) { - return sys::path::filename(Path, sys::path::Style::windows); +static StringRef getBasename(StringRef path) { + return sys::path::filename(path, sys::path::Style::windows); } // Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)". -std::string lld::toString(const coff::InputFile *File) { - if (!File) +std::string lld::toString(const coff::InputFile *file) { + if (!file) return ""; - if (File->ParentName.empty() || File->kind() == coff::InputFile::ImportKind) - return File->getName(); + if (file->parentName.empty() || file->kind() == coff::InputFile::ImportKind) + return file->getName(); - return (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + + return (getBasename(file->parentName) + "(" + getBasename(file->getName()) + ")") .str(); } Index: lld/trunk/COFF/LTO.h =================================================================== --- lld/trunk/COFF/LTO.h +++ lld/trunk/COFF/LTO.h @@ -42,13 +42,13 @@ BitcodeCompiler(); ~BitcodeCompiler(); - void add(BitcodeFile &F); + void add(BitcodeFile &f); std::vector compile(); private: - std::unique_ptr LTOObj; - std::vector> Buf; - std::vector> Files; + std::unique_ptr ltoObj; + std::vector> buf; + std::vector> files; }; } } Index: lld/trunk/COFF/LTO.cpp =================================================================== --- lld/trunk/COFF/LTO.cpp +++ lld/trunk/COFF/LTO.cpp @@ -42,112 +42,112 @@ using namespace lld::coff; static std::unique_ptr createLTO() { - lto::Config C; - C.Options = initTargetOptionsFromCodeGenFlags(); + lto::Config c; + c.Options = initTargetOptionsFromCodeGenFlags(); // Always emit a section per function/datum with LTO. LLVM LTO should get most // of the benefit of linker GC, but there are still opportunities for ICF. - C.Options.FunctionSections = true; - C.Options.DataSections = true; + c.Options.FunctionSections = true; + c.Options.DataSections = true; // Use static reloc model on 32-bit x86 because it usually results in more // compact code, and because there are also known code generation bugs when // using the PIC model (see PR34306). - if (Config->Machine == COFF::IMAGE_FILE_MACHINE_I386) - C.RelocModel = Reloc::Static; + if (config->machine == COFF::IMAGE_FILE_MACHINE_I386) + c.RelocModel = Reloc::Static; else - C.RelocModel = Reloc::PIC_; - C.DisableVerify = true; - C.DiagHandler = diagnosticHandler; - C.OptLevel = Config->LTOO; - C.CPU = getCPUStr(); - C.MAttrs = getMAttrs(); - C.CGOptLevel = args::getCGOptLevel(Config->LTOO); + c.RelocModel = Reloc::PIC_; + c.DisableVerify = true; + c.DiagHandler = diagnosticHandler; + c.OptLevel = config->ltoo; + c.CPU = getCPUStr(); + c.MAttrs = getMAttrs(); + c.CGOptLevel = args::getCGOptLevel(config->ltoo); - if (Config->SaveTemps) - checkError(C.addSaveTemps(std::string(Config->OutputFile) + ".", + if (config->saveTemps) + checkError(c.addSaveTemps(std::string(config->outputFile) + ".", /*UseInputModulePath*/ true)); - lto::ThinBackend Backend; - if (Config->ThinLTOJobs != 0) - Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs); - return llvm::make_unique(std::move(C), Backend, - Config->LTOPartitions); + lto::ThinBackend backend; + if (config->thinLTOJobs != 0) + backend = lto::createInProcessThinBackend(config->thinLTOJobs); + return llvm::make_unique(std::move(c), backend, + config->ltoPartitions); } -BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} +BitcodeCompiler::BitcodeCompiler() : ltoObj(createLTO()) {} BitcodeCompiler::~BitcodeCompiler() = default; -static void undefine(Symbol *S) { replaceSymbol(S, S->getName()); } +static void undefine(Symbol *s) { replaceSymbol(s, s->getName()); } -void BitcodeCompiler::add(BitcodeFile &F) { - lto::InputFile &Obj = *F.Obj; - unsigned SymNum = 0; - std::vector SymBodies = F.getSymbols(); - std::vector Resols(SymBodies.size()); +void BitcodeCompiler::add(BitcodeFile &f) { + lto::InputFile &obj = *f.obj; + unsigned symNum = 0; + std::vector symBodies = f.getSymbols(); + std::vector resols(symBodies.size()); // Provide a resolution to the LTO API for each symbol. - for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { - Symbol *Sym = SymBodies[SymNum]; - lto::SymbolResolution &R = Resols[SymNum]; - ++SymNum; + for (const lto::InputFile::Symbol &objSym : obj.symbols()) { + Symbol *sym = symBodies[symNum]; + lto::SymbolResolution &r = resols[symNum]; + ++symNum; // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile // reports two symbols for module ASM defined. Without this check, lld // flags an undefined in IR with a definition in ASM as prevailing. // Once IRObjectFile is fixed to report only one symbol this hack can // be removed. - R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F; - R.VisibleToRegularObj = Sym->IsUsedInRegularObj; - if (R.Prevailing) - undefine(Sym); + r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f; + r.VisibleToRegularObj = sym->isUsedInRegularObj; + if (r.Prevailing) + undefine(sym); } - checkError(LTOObj->add(std::move(F.Obj), Resols)); + checkError(ltoObj->add(std::move(f.obj), resols)); } // Merge all the bitcode files we have seen, codegen the result // and return the resulting objects. std::vector BitcodeCompiler::compile() { - unsigned MaxTasks = LTOObj->getMaxTasks(); - Buf.resize(MaxTasks); - Files.resize(MaxTasks); + unsigned maxTasks = ltoObj->getMaxTasks(); + buf.resize(maxTasks); + files.resize(maxTasks); // The /lldltocache option specifies the path to a directory in which to cache // native object files for ThinLTO incremental builds. If a path was // specified, configure LTO to use it as the cache directory. - lto::NativeObjectCache Cache; - if (!Config->LTOCache.empty()) - Cache = check(lto::localCache( - Config->LTOCache, [&](size_t Task, std::unique_ptr MB) { - Files[Task] = std::move(MB); + lto::NativeObjectCache cache; + if (!config->ltoCache.empty()) + cache = check(lto::localCache( + config->ltoCache, [&](size_t task, std::unique_ptr mb) { + files[task] = std::move(mb); })); - checkError(LTOObj->run( - [&](size_t Task) { + checkError(ltoObj->run( + [&](size_t task) { return llvm::make_unique( - llvm::make_unique(Buf[Task])); + llvm::make_unique(buf[task])); }, - Cache)); + cache)); - if (!Config->LTOCache.empty()) - pruneCache(Config->LTOCache, Config->LTOCachePolicy); + if (!config->ltoCache.empty()) + pruneCache(config->ltoCache, config->ltoCachePolicy); - std::vector Ret; - for (unsigned I = 0; I != MaxTasks; ++I) { - if (Buf[I].empty()) + std::vector ret; + for (unsigned i = 0; i != maxTasks; ++i) { + if (buf[i].empty()) continue; - if (Config->SaveTemps) { - if (I == 0) - saveBuffer(Buf[I], Config->OutputFile + ".lto.obj"); + if (config->saveTemps) { + if (i == 0) + saveBuffer(buf[i], config->outputFile + ".lto.obj"); else - saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.obj"); + saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.obj"); } - Ret.emplace_back(Buf[I].data(), Buf[I].size()); + ret.emplace_back(buf[i].data(), buf[i].size()); } - for (std::unique_ptr &File : Files) - if (File) - Ret.push_back(File->getBuffer()); + for (std::unique_ptr &file : files) + if (file) + ret.push_back(file->getBuffer()); - return Ret; + return ret; } Index: lld/trunk/COFF/MapFile.h =================================================================== --- lld/trunk/COFF/MapFile.h +++ lld/trunk/COFF/MapFile.h @@ -14,7 +14,7 @@ namespace lld { namespace coff { class OutputSection; -void writeMapFile(llvm::ArrayRef OutputSections); +void writeMapFile(llvm::ArrayRef outputSections); } } Index: lld/trunk/COFF/MapFile.cpp =================================================================== --- lld/trunk/COFF/MapFile.cpp +++ lld/trunk/COFF/MapFile.cpp @@ -35,90 +35,90 @@ using SymbolMapTy = DenseMap>; -static const std::string Indent8 = " "; // 8 spaces -static const std::string Indent16 = " "; // 16 spaces +static const std::string indent8 = " "; // 8 spaces +static const std::string indent16 = " "; // 16 spaces // Print out the first three columns of a line. -static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size, - uint64_t Align) { - OS << format("%08llx %08llx %5lld ", Addr, Size, Align); +static void writeHeader(raw_ostream &os, uint64_t addr, uint64_t size, + uint64_t align) { + os << format("%08llx %08llx %5lld ", addr, size, align); } // Returns a list of all symbols that we want to print out. static std::vector getSymbols() { - std::vector V; - for (ObjFile *File : ObjFile::Instances) - for (Symbol *B : File->getSymbols()) - if (auto *Sym = dyn_cast_or_null(B)) - if (Sym && !Sym->getCOFFSymbol().isSectionDefinition()) - V.push_back(Sym); - return V; + std::vector v; + for (ObjFile *file : ObjFile::instances) + for (Symbol *b : file->getSymbols()) + if (auto *sym = dyn_cast_or_null(b)) + if (sym && !sym->getCOFFSymbol().isSectionDefinition()) + v.push_back(sym); + return v; } // Returns a map from sections to their symbols. -static SymbolMapTy getSectionSyms(ArrayRef Syms) { - SymbolMapTy Ret; - for (DefinedRegular *S : Syms) - Ret[S->getChunk()].push_back(S); +static SymbolMapTy getSectionSyms(ArrayRef syms) { + SymbolMapTy ret; + for (DefinedRegular *s : syms) + ret[s->getChunk()].push_back(s); // Sort symbols by address. - for (auto &It : Ret) { - SmallVectorImpl &V = It.second; - std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) { - return A->getRVA() < B->getRVA(); + for (auto &it : ret) { + SmallVectorImpl &v = it.second; + std::sort(v.begin(), v.end(), [](DefinedRegular *a, DefinedRegular *b) { + return a->getRVA() < b->getRVA(); }); } - return Ret; + return ret; } // Construct a map from symbols to their stringified representations. static DenseMap -getSymbolStrings(ArrayRef Syms) { - std::vector Str(Syms.size()); - parallelForEachN((size_t)0, Syms.size(), [&](size_t I) { - raw_string_ostream OS(Str[I]); - writeHeader(OS, Syms[I]->getRVA(), 0, 0); - OS << Indent16 << toString(*Syms[I]); +getSymbolStrings(ArrayRef syms) { + std::vector str(syms.size()); + parallelForEachN((size_t)0, syms.size(), [&](size_t i) { + raw_string_ostream os(str[i]); + writeHeader(os, syms[i]->getRVA(), 0, 0); + os << indent16 << toString(*syms[i]); }); - DenseMap Ret; - for (size_t I = 0, E = Syms.size(); I < E; ++I) - Ret[Syms[I]] = std::move(Str[I]); - return Ret; + DenseMap ret; + for (size_t i = 0, e = syms.size(); i < e; ++i) + ret[syms[i]] = std::move(str[i]); + return ret; } -void coff::writeMapFile(ArrayRef OutputSections) { - if (Config->MapFile.empty()) +void coff::writeMapFile(ArrayRef outputSections) { + if (config->mapFile.empty()) return; - std::error_code EC; - raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); - if (EC) - fatal("cannot open " + Config->MapFile + ": " + EC.message()); + std::error_code ec; + raw_fd_ostream os(config->mapFile, ec, sys::fs::F_None); + if (ec) + fatal("cannot open " + config->mapFile + ": " + ec.message()); // Collect symbol info that we want to print out. - std::vector Syms = getSymbols(); - SymbolMapTy SectionSyms = getSectionSyms(Syms); - DenseMap SymStr = getSymbolStrings(Syms); + std::vector syms = getSymbols(); + SymbolMapTy sectionSyms = getSectionSyms(syms); + DenseMap symStr = getSymbolStrings(syms); // Print out the header line. - OS << "Address Size Align Out In Symbol\n"; + os << "Address Size Align Out In Symbol\n"; // Print out file contents. - for (OutputSection *Sec : OutputSections) { - writeHeader(OS, Sec->getRVA(), Sec->getVirtualSize(), /*Align=*/PageSize); - OS << Sec->Name << '\n'; - - for (Chunk *C : Sec->Chunks) { - auto *SC = dyn_cast(C); - if (!SC) + for (OutputSection *sec : outputSections) { + writeHeader(os, sec->getRVA(), sec->getVirtualSize(), /*Align=*/pageSize); + os << sec->name << '\n'; + + for (Chunk *c : sec->chunks) { + auto *sc = dyn_cast(c); + if (!sc) continue; - writeHeader(OS, SC->getRVA(), SC->getSize(), SC->getAlignment()); - OS << Indent8 << SC->File->getName() << ":(" << SC->getSectionName() + writeHeader(os, sc->getRVA(), sc->getSize(), sc->getAlignment()); + os << indent8 << sc->file->getName() << ":(" << sc->getSectionName() << ")\n"; - for (DefinedRegular *Sym : SectionSyms[SC]) - OS << SymStr[Sym] << '\n'; + for (DefinedRegular *sym : sectionSyms[sc]) + os << symStr[sym] << '\n'; } } } Index: lld/trunk/COFF/MarkLive.h =================================================================== --- lld/trunk/COFF/MarkLive.h +++ lld/trunk/COFF/MarkLive.h @@ -17,7 +17,7 @@ class Chunk; -void markLive(ArrayRef Chunks); +void markLive(ArrayRef chunks); } // namespace coff } // namespace lld Index: lld/trunk/COFF/MarkLive.cpp =================================================================== --- lld/trunk/COFF/MarkLive.cpp +++ lld/trunk/COFF/MarkLive.cpp @@ -15,57 +15,57 @@ namespace lld { namespace coff { -static Timer GCTimer("GC", Timer::root()); +static Timer gCTimer("GC", Timer::root()); // Set live bit on for each reachable chunk. Unmarked (unreachable) // COMDAT chunks will be ignored by Writer, so they will be excluded // from the final output. -void markLive(ArrayRef Chunks) { - ScopedTimer T(GCTimer); +void markLive(ArrayRef chunks) { + ScopedTimer t(gCTimer); // We build up a worklist of sections which have been marked as live. We only // push into the worklist when we discover an unmarked section, and we mark // as we push, so sections never appear twice in the list. - SmallVector Worklist; + SmallVector worklist; // COMDAT section chunks are dead by default. Add non-COMDAT chunks. - for (Chunk *C : Chunks) - if (auto *SC = dyn_cast(C)) - if (SC->Live) - Worklist.push_back(SC); + for (Chunk *c : chunks) + if (auto *sc = dyn_cast(c)) + if (sc->live) + worklist.push_back(sc); - auto Enqueue = [&](SectionChunk *C) { - if (C->Live) + auto enqueue = [&](SectionChunk *c) { + if (c->live) return; - C->Live = true; - Worklist.push_back(C); + c->live = true; + worklist.push_back(c); }; - auto AddSym = [&](Symbol *B) { - if (auto *Sym = dyn_cast(B)) - Enqueue(Sym->getChunk()); - else if (auto *Sym = dyn_cast(B)) - Sym->File->Live = true; - else if (auto *Sym = dyn_cast(B)) - Sym->WrappedSym->File->Live = Sym->WrappedSym->File->ThunkLive = true; + auto addSym = [&](Symbol *b) { + if (auto *sym = dyn_cast(b)) + enqueue(sym->getChunk()); + else if (auto *sym = dyn_cast(b)) + sym->file->live = true; + else if (auto *sym = dyn_cast(b)) + sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true; }; // Add GC root chunks. - for (Symbol *B : Config->GCRoot) - AddSym(B); + for (Symbol *b : config->gCRoot) + addSym(b); - while (!Worklist.empty()) { - SectionChunk *SC = Worklist.pop_back_val(); - assert(SC->Live && "We mark as live when pushing onto the worklist!"); + while (!worklist.empty()) { + SectionChunk *sc = worklist.pop_back_val(); + assert(sc->live && "We mark as live when pushing onto the worklist!"); // Mark all symbols listed in the relocation table for this section. - for (Symbol *B : SC->symbols()) - if (B) - AddSym(B); + for (Symbol *b : sc->symbols()) + if (b) + addSym(b); // Mark associative sections if any. - for (SectionChunk &C : SC->children()) - Enqueue(&C); + for (SectionChunk &c : sc->children()) + enqueue(&c); } } Index: lld/trunk/COFF/MinGW.h =================================================================== --- lld/trunk/COFF/MinGW.h +++ lld/trunk/COFF/MinGW.h @@ -22,18 +22,18 @@ public: AutoExporter(); - void addWholeArchive(StringRef Path); + void addWholeArchive(StringRef path); - llvm::StringSet<> ExcludeSymbols; - llvm::StringSet<> ExcludeSymbolPrefixes; - llvm::StringSet<> ExcludeSymbolSuffixes; - llvm::StringSet<> ExcludeLibs; - llvm::StringSet<> ExcludeObjects; + llvm::StringSet<> excludeSymbols; + llvm::StringSet<> excludeSymbolPrefixes; + llvm::StringSet<> excludeSymbolSuffixes; + llvm::StringSet<> excludeLibs; + llvm::StringSet<> excludeObjects; - bool shouldExport(Defined *Sym) const; + bool shouldExport(Defined *sym) const; }; -void writeDefFile(StringRef Name); +void writeDefFile(StringRef name); } // namespace coff } // namespace lld Index: lld/trunk/COFF/MinGW.cpp =================================================================== --- lld/trunk/COFF/MinGW.cpp +++ lld/trunk/COFF/MinGW.cpp @@ -19,7 +19,7 @@ using namespace llvm::COFF; AutoExporter::AutoExporter() { - ExcludeLibs = { + excludeLibs = { "libgcc", "libgcc_s", "libstdc++", @@ -41,12 +41,12 @@ "libucrtbase", }; - ExcludeObjects = { + excludeObjects = { "crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o", "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o", }; - ExcludeSymbolPrefixes = { + excludeSymbolPrefixes = { // Import symbols "__imp_", "__IMPORT_DESCRIPTOR_", @@ -59,13 +59,13 @@ ".", }; - ExcludeSymbolSuffixes = { + excludeSymbolSuffixes = { "_iname", "_NULL_THUNK_DATA", }; - if (Config->Machine == I386) { - ExcludeSymbols = { + if (config->machine == I386) { + excludeSymbols = { "__NULL_IMPORT_DESCRIPTOR", "__pei386_runtime_relocator", "_do_pseudo_reloc", @@ -80,9 +80,9 @@ "_DllEntryPoint@12", "_DllMainCRTStartup@12", }; - ExcludeSymbolPrefixes.insert("__head_"); + excludeSymbolPrefixes.insert("__head_"); } else { - ExcludeSymbols = { + excludeSymbols = { "__NULL_IMPORT_DESCRIPTOR", "_pei386_runtime_relocator", "do_pseudo_reloc", @@ -97,70 +97,70 @@ "DllEntryPoint", "DllMainCRTStartup", }; - ExcludeSymbolPrefixes.insert("_head_"); + excludeSymbolPrefixes.insert("_head_"); } } -void AutoExporter::addWholeArchive(StringRef Path) { - StringRef LibName = sys::path::filename(Path); +void AutoExporter::addWholeArchive(StringRef path) { + StringRef libName = sys::path::filename(path); // Drop the file extension, to match the processing below. - LibName = LibName.substr(0, LibName.rfind('.')); - ExcludeLibs.erase(LibName); + libName = libName.substr(0, libName.rfind('.')); + excludeLibs.erase(libName); } -bool AutoExporter::shouldExport(Defined *Sym) const { - if (!Sym || !Sym->isLive() || !Sym->getChunk()) +bool AutoExporter::shouldExport(Defined *sym) const { + if (!sym || !sym->isLive() || !sym->getChunk()) return false; // Only allow the symbol kinds that make sense to export; in particular, // disallow import symbols. - if (!isa(Sym) && !isa(Sym)) + if (!isa(sym) && !isa(sym)) return false; - if (ExcludeSymbols.count(Sym->getName())) + if (excludeSymbols.count(sym->getName())) return false; - for (StringRef Prefix : ExcludeSymbolPrefixes.keys()) - if (Sym->getName().startswith(Prefix)) + for (StringRef prefix : excludeSymbolPrefixes.keys()) + if (sym->getName().startswith(prefix)) return false; - for (StringRef Suffix : ExcludeSymbolSuffixes.keys()) - if (Sym->getName().endswith(Suffix)) + for (StringRef suffix : excludeSymbolSuffixes.keys()) + if (sym->getName().endswith(suffix)) return false; // If a corresponding __imp_ symbol exists and is defined, don't export it. - if (Symtab->find(("__imp_" + Sym->getName()).str())) + if (symtab->find(("__imp_" + sym->getName()).str())) return false; // Check that file is non-null before dereferencing it, symbols not // originating in regular object files probably shouldn't be exported. - if (!Sym->getFile()) + if (!sym->getFile()) return false; - StringRef LibName = sys::path::filename(Sym->getFile()->ParentName); + StringRef libName = sys::path::filename(sym->getFile()->parentName); // Drop the file extension. - LibName = LibName.substr(0, LibName.rfind('.')); - if (!LibName.empty()) - return !ExcludeLibs.count(LibName); + libName = libName.substr(0, libName.rfind('.')); + if (!libName.empty()) + return !excludeLibs.count(libName); - StringRef FileName = sys::path::filename(Sym->getFile()->getName()); - return !ExcludeObjects.count(FileName); + StringRef fileName = sys::path::filename(sym->getFile()->getName()); + return !excludeObjects.count(fileName); } -void coff::writeDefFile(StringRef Name) { - std::error_code EC; - raw_fd_ostream OS(Name, EC, sys::fs::F_None); - if (EC) - fatal("cannot open " + Name + ": " + EC.message()); - - OS << "EXPORTS\n"; - for (Export &E : Config->Exports) { - OS << " " << E.ExportName << " " - << "@" << E.Ordinal; - if (auto *Def = dyn_cast_or_null(E.Sym)) { - if (Def && Def->getChunk() && - !(Def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)) - OS << " DATA"; +void coff::writeDefFile(StringRef name) { + std::error_code ec; + raw_fd_ostream os(name, ec, sys::fs::F_None); + if (ec) + fatal("cannot open " + name + ": " + ec.message()); + + os << "EXPORTS\n"; + for (Export &e : config->exports) { + os << " " << e.exportName << " " + << "@" << e.ordinal; + if (auto *def = dyn_cast_or_null(e.sym)) { + if (def && def->getChunk() && + !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)) + os << " DATA"; } - OS << "\n"; + os << "\n"; } } Index: lld/trunk/COFF/PDB.h =================================================================== --- lld/trunk/COFF/PDB.h +++ lld/trunk/COFF/PDB.h @@ -24,13 +24,13 @@ class SectionChunk; class SymbolTable; -void createPDB(SymbolTable *Symtab, - llvm::ArrayRef OutputSections, - llvm::ArrayRef SectionTable, - llvm::codeview::DebugInfo *BuildId); +void createPDB(SymbolTable *symtab, + llvm::ArrayRef outputSections, + llvm::ArrayRef sectionTable, + llvm::codeview::DebugInfo *buildId); -std::pair getFileLine(const SectionChunk *C, - uint32_t Addr); +std::pair getFileLine(const SectionChunk *c, + uint32_t addr); } } Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -66,16 +66,16 @@ using llvm::object::coff_section; -static ExitOnError ExitOnErr; +static ExitOnError exitOnErr; -static Timer TotalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root()); +static Timer totalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root()); -static Timer AddObjectsTimer("Add Objects", TotalPdbLinkTimer); -static Timer TypeMergingTimer("Type Merging", AddObjectsTimer); -static Timer SymbolMergingTimer("Symbol Merging", AddObjectsTimer); -static Timer GlobalsLayoutTimer("Globals Stream Layout", TotalPdbLinkTimer); -static Timer TpiStreamLayoutTimer("TPI Stream Layout", TotalPdbLinkTimer); -static Timer DiskCommitTimer("Commit to Disk", TotalPdbLinkTimer); +static Timer addObjectsTimer("Add Objects", totalPdbLinkTimer); +static Timer typeMergingTimer("Type Merging", addObjectsTimer); +static Timer symbolMergingTimer("Symbol Merging", addObjectsTimer); +static Timer globalsLayoutTimer("Globals Stream Layout", totalPdbLinkTimer); +static Timer tpiStreamLayoutTimer("TPI Stream Layout", totalPdbLinkTimer); +static Timer diskCommitTimer("Commit to Disk", totalPdbLinkTimer); namespace { class DebugSHandler; @@ -84,16 +84,16 @@ friend DebugSHandler; public: - PDBLinker(SymbolTable *Symtab) - : Alloc(), Symtab(Symtab), Builder(Alloc), TMerger(Alloc) { + PDBLinker(SymbolTable *symtab) + : alloc(), symtab(symtab), builder(alloc), tMerger(alloc) { // This isn't strictly necessary, but link.exe usually puts an empty string // as the first "valid" string in the string table, so we do the same in // order to maintain as much byte-for-byte compatibility as possible. - PDBStrTab.insert(""); + pdbStrTab.insert(""); } /// Emit the basic PDB structure: initial streams, headers, etc. - void initialize(llvm::codeview::DebugInfo *BuildId); + void initialize(llvm::codeview::DebugInfo *buildId); /// Add natvis files specified on the command line. void addNatvisFiles(); @@ -102,12 +102,12 @@ void addObjectsToPDB(); /// Link info for each import file in the symbol table into the PDB. - void addImportFilesToPDB(ArrayRef OutputSections); + void addImportFilesToPDB(ArrayRef outputSections); /// Link CodeView from a single object file into the target (output) PDB. /// When a precompiled headers object is linked, its TPI map might be provided /// externally. - void addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap = nullptr); + void addObjFile(ObjFile *file, CVIndexMap *externIndexMap = nullptr); /// Produce a mapping from the type and item indices used in the object /// file to those in the destination PDB. @@ -120,16 +120,16 @@ /// If the object does not use a type server PDB (compiled with /Z7), we merge /// all the type and item records from the .debug$S stream and fill in the /// caller-provided ObjectIndexMap. - Expected mergeDebugT(ObjFile *File, - CVIndexMap *ObjectIndexMap); + Expected mergeDebugT(ObjFile *file, + CVIndexMap *objectIndexMap); /// Reads and makes available a PDB. - Expected maybeMergeTypeServerPDB(ObjFile *File); + Expected maybeMergeTypeServerPDB(ObjFile *file); /// Merges a precompiled headers TPI map into the current TPI map. The /// precompiled headers object will also be loaded and remapped in the /// process. - Error mergeInPrecompHeaderObj(ObjFile *File, CVIndexMap *ObjectIndexMap); + Error mergeInPrecompHeaderObj(ObjFile *file, CVIndexMap *objectIndexMap); /// Reads and makes available a precompiled headers object. /// @@ -140,87 +140,87 @@ /// /// If the precompiled headers object was already loaded, this function will /// simply return its (remapped) TPI map. - Expected aquirePrecompObj(ObjFile *File); + Expected aquirePrecompObj(ObjFile *file); /// Adds a precompiled headers object signature -> TPI mapping. std::pair - registerPrecompiledHeaders(uint32_t Signature); + registerPrecompiledHeaders(uint32_t signature); - void mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, - std::vector &StringTableRefs, - BinaryStreamRef SymData); + void mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap, + std::vector &stringTableRefs, + BinaryStreamRef symData); /// Add the section map and section contributions to the PDB. - void addSections(ArrayRef OutputSections, - ArrayRef SectionTable); + void addSections(ArrayRef outputSections, + ArrayRef sectionTable); /// Write the PDB to disk and store the Guid generated for it in *Guid. - void commit(codeview::GUID *Guid); + void commit(codeview::GUID *guid); // Print statistics regarding the final PDB void printStats(); private: - BumpPtrAllocator Alloc; + BumpPtrAllocator alloc; - SymbolTable *Symtab; + SymbolTable *symtab; - pdb::PDBFileBuilder Builder; + pdb::PDBFileBuilder builder; - TypeMerger TMerger; + TypeMerger tMerger; /// PDBs use a single global string table for filenames in the file checksum /// table. - DebugStringTableSubsection PDBStrTab; + DebugStringTableSubsection pdbStrTab; - llvm::SmallString<128> NativePath; + llvm::SmallString<128> nativePath; - std::vector SectionMap; + std::vector sectionMap; /// Type index mappings of type server PDBs that we've loaded so far. - std::map TypeServerIndexMappings; + std::map typeServerIndexMappings; /// Type index mappings of precompiled objects type map that we've loaded so /// far. - std::map PrecompTypeIndexMappings; + std::map precompTypeIndexMappings; // For statistics - uint64_t GlobalSymbols = 0; - uint64_t ModuleSymbols = 0; - uint64_t PublicSymbols = 0; + uint64_t globalSymbols = 0; + uint64_t moduleSymbols = 0; + uint64_t publicSymbols = 0; }; class DebugSHandler { - PDBLinker &Linker; + PDBLinker &linker; /// The object file whose .debug$S sections we're processing. - ObjFile &File; + ObjFile &file; /// The result of merging type indices. - const CVIndexMap &IndexMap; + const CVIndexMap &indexMap; /// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by /// index from other records in the .debug$S section. All of these strings /// need to be added to the global PDB string table, and all references to /// these strings need to have their indices re-written to refer to the /// global PDB string table. - DebugStringTableSubsectionRef CVStrTab; + DebugStringTableSubsectionRef cVStrTab; /// The DEBUG_S_FILECHKSMS subsection. As above, these are referred to /// by other records in the .debug$S section and need to be merged into the /// PDB. - DebugChecksumsSubsectionRef Checksums; + DebugChecksumsSubsectionRef checksums; /// The DEBUG_S_INLINEELINES subsection. There can be only one of these per /// object file. - DebugInlineeLinesSubsectionRef InlineeLines; + DebugInlineeLinesSubsectionRef inlineeLines; /// The DEBUG_S_FRAMEDATA subsection(s). There can be more than one of /// these and they need not appear in any specific order. However, they /// contain string table references which need to be re-written, so we /// collect them all here and re-write them after all subsections have been /// discovered and processed. - std::vector NewFpoFrames; + std::vector newFpoFrames; /// Pointers to raw memory that we determine have string table references /// that need to be re-written. We first process all .debug$S subsections @@ -228,16 +228,16 @@ /// up this list as we go. At the end, we use the string table (which must /// have been discovered by now else it is an error) to re-write these /// references. - std::vector StringTableReferences; + std::vector stringTableReferences; public: - DebugSHandler(PDBLinker &Linker, ObjFile &File, const CVIndexMap &IndexMap) - : Linker(Linker), File(File), IndexMap(IndexMap) {} + DebugSHandler(PDBLinker &linker, ObjFile &file, const CVIndexMap &indexMap) + : linker(linker), file(file), indexMap(indexMap) {} - void handleDebugS(lld::coff::SectionChunk &DebugS); + void handleDebugS(lld::coff::SectionChunk &debugS); std::shared_ptr - mergeInlineeLines(DebugChecksumsSubsection *NewChecksums); + mergeInlineeLines(DebugChecksumsSubsection *newChecksums); void finish(); }; @@ -246,7 +246,7 @@ // Visual Studio's debugger requires absolute paths in various places in the // PDB to work without additional configuration: // https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box -static void pdbMakeAbsolute(SmallVectorImpl &FileName) { +static void pdbMakeAbsolute(SmallVectorImpl &fileName) { // The default behavior is to produce paths that are valid within the context // of the machine that you perform the link on. If the linker is running on // a POSIX system, we will output absolute POSIX paths. If the linker is @@ -254,16 +254,16 @@ // user desires any other kind of behavior, they should explicitly pass // /pdbsourcepath, in which case we will treat the exact string the user // passed in as the gospel and not normalize, canonicalize it. - if (sys::path::is_absolute(FileName, sys::path::Style::windows) || - sys::path::is_absolute(FileName, sys::path::Style::posix)) + if (sys::path::is_absolute(fileName, sys::path::Style::windows) || + sys::path::is_absolute(fileName, sys::path::Style::posix)) return; // It's not absolute in any path syntax. Relative paths necessarily refer to // the local file system, so we can make it native without ending up with a // nonsensical path. - if (Config->PDBSourcePath.empty()) { - sys::path::native(FileName); - sys::fs::make_absolute(FileName); + if (config->pdbSourcePath.empty()) { + sys::path::native(fileName); + sys::fs::make_absolute(fileName); return; } @@ -271,238 +271,238 @@ // Since PDB's are more of a Windows thing, we make this conservative and only // decide that it's a unix path if we're fairly certain. Specifically, if // it starts with a forward slash. - SmallString<128> AbsoluteFileName = Config->PDBSourcePath; - sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/") + SmallString<128> absoluteFileName = config->pdbSourcePath; + sys::path::Style guessedStyle = absoluteFileName.startswith("/") ? sys::path::Style::posix : sys::path::Style::windows; - sys::path::append(AbsoluteFileName, GuessedStyle, FileName); - sys::path::native(AbsoluteFileName, GuessedStyle); - sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle); + sys::path::append(absoluteFileName, guessedStyle, fileName); + sys::path::native(absoluteFileName, guessedStyle); + sys::path::remove_dots(absoluteFileName, true, guessedStyle); - FileName = std::move(AbsoluteFileName); + fileName = std::move(absoluteFileName); } // A COFF .debug$H section is currently a clang extension. This function checks // if a .debug$H section is in a format that we expect / understand, so that we // can ignore any sections which are coincidentally also named .debug$H but do // not contain a format we recognize. -static bool canUseDebugH(ArrayRef DebugH) { - if (DebugH.size() < sizeof(object::debug_h_header)) +static bool canUseDebugH(ArrayRef debugH) { + if (debugH.size() < sizeof(object::debug_h_header)) return false; - auto *Header = - reinterpret_cast(DebugH.data()); - DebugH = DebugH.drop_front(sizeof(object::debug_h_header)); - return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC && - Header->Version == 0 && - Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) && - (DebugH.size() % 8 == 0); + auto *header = + reinterpret_cast(debugH.data()); + debugH = debugH.drop_front(sizeof(object::debug_h_header)); + return header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC && + header->Version == 0 && + header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) && + (debugH.size() % 8 == 0); } -static Optional> getDebugH(ObjFile *File) { - SectionChunk *Sec = - SectionChunk::findByName(File->getDebugChunks(), ".debug$H"); - if (!Sec) +static Optional> getDebugH(ObjFile *file) { + SectionChunk *sec = + SectionChunk::findByName(file->getDebugChunks(), ".debug$H"); + if (!sec) return llvm::None; - ArrayRef Contents = Sec->getContents(); - if (!canUseDebugH(Contents)) + ArrayRef contents = sec->getContents(); + if (!canUseDebugH(contents)) return None; - return Contents; + return contents; } static ArrayRef -getHashesFromDebugH(ArrayRef DebugH) { - assert(canUseDebugH(DebugH)); +getHashesFromDebugH(ArrayRef debugH) { + assert(canUseDebugH(debugH)); - DebugH = DebugH.drop_front(sizeof(object::debug_h_header)); - uint32_t Count = DebugH.size() / sizeof(GloballyHashedType); - return {reinterpret_cast(DebugH.data()), Count}; + debugH = debugH.drop_front(sizeof(object::debug_h_header)); + uint32_t count = debugH.size() / sizeof(GloballyHashedType); + return {reinterpret_cast(debugH.data()), count}; } -static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, - TypeCollection &TypeTable) { +static void addTypeInfo(pdb::TpiStreamBuilder &tpiBuilder, + TypeCollection &typeTable) { // Start the TPI or IPI stream header. - TpiBuilder.setVersionHeader(pdb::PdbTpiV80); + tpiBuilder.setVersionHeader(pdb::PdbTpiV80); // Flatten the in memory type table and hash each type. - TypeTable.ForEachRecord([&](TypeIndex TI, const CVType &Type) { - auto Hash = pdb::hashTypeRecord(Type); - if (auto E = Hash.takeError()) + typeTable.ForEachRecord([&](TypeIndex ti, const CVType &type) { + auto hash = pdb::hashTypeRecord(type); + if (auto e = hash.takeError()) fatal("type hashing error"); - TpiBuilder.addTypeRecord(Type.RecordData, *Hash); + tpiBuilder.addTypeRecord(type.RecordData, *hash); }); } Expected -PDBLinker::mergeDebugT(ObjFile *File, CVIndexMap *ObjectIndexMap) { - ScopedTimer T(TypeMergingTimer); +PDBLinker::mergeDebugT(ObjFile *file, CVIndexMap *objectIndexMap) { + ScopedTimer t(typeMergingTimer); - if (!File->DebugTypesObj) - return *ObjectIndexMap; // no Types stream + if (!file->debugTypesObj) + return *objectIndexMap; // no Types stream // Precompiled headers objects need to save the index map for further // reference by other objects which use the precompiled headers. - if (File->DebugTypesObj->Kind == TpiSource::PCH) { - uint32_t PCHSignature = File->PCHSignature.getValueOr(0); - if (PCHSignature == 0) + if (file->debugTypesObj->kind == TpiSource::PCH) { + uint32_t pchSignature = file->pchSignature.getValueOr(0); + if (pchSignature == 0) fatal("No signature found for the precompiled headers OBJ (" + - File->getName() + ")"); + file->getName() + ")"); // When a precompiled headers object comes first on the command-line, we // update the mapping here. Otherwise, if an object referencing the // precompiled headers object comes first, the mapping is created in // aquirePrecompObj(), thus we would skip this block. - if (!ObjectIndexMap->IsPrecompiledTypeMap) { - auto R = registerPrecompiledHeaders(PCHSignature); - if (R.second) + if (!objectIndexMap->isPrecompiledTypeMap) { + auto r = registerPrecompiledHeaders(pchSignature); + if (r.second) fatal( "A precompiled headers OBJ with the same signature was already " "provided! (" + - File->getName() + ")"); + file->getName() + ")"); - ObjectIndexMap = &R.first; + objectIndexMap = &r.first; } } - if (File->DebugTypesObj->Kind == TpiSource::UsingPDB) { + if (file->debugTypesObj->kind == TpiSource::UsingPDB) { // Look through type servers. If we've already seen this type server, // don't merge any type information. - return maybeMergeTypeServerPDB(File); + return maybeMergeTypeServerPDB(file); } - CVTypeArray &Types = *File->DebugTypes; + CVTypeArray &types = *file->debugTypes; - if (File->DebugTypesObj->Kind == TpiSource::UsingPCH) { + if (file->debugTypesObj->kind == TpiSource::UsingPCH) { // This object was compiled with /Yu, so process the corresponding // precompiled headers object (/Yc) first. Some type indices in the current // object are referencing data in the precompiled headers object, so we need // both to be loaded. - Error E = mergeInPrecompHeaderObj(File, ObjectIndexMap); - if (E) - return std::move(E); + Error e = mergeInPrecompHeaderObj(file, objectIndexMap); + if (e) + return std::move(e); // Drop LF_PRECOMP record from the input stream, as it has been replaced // with the precompiled headers Type stream in the mergeInPrecompHeaderObj() // call above. Note that we can't just call Types.drop_front(), as we // explicitly want to rebase the stream. - CVTypeArray::Iterator FirstType = Types.begin(); - Types.setUnderlyingStream( - Types.getUnderlyingStream().drop_front(FirstType->RecordData.size())); + CVTypeArray::Iterator firstType = types.begin(); + types.setUnderlyingStream( + types.getUnderlyingStream().drop_front(firstType->RecordData.size())); } // Fill in the temporary, caller-provided ObjectIndexMap. - if (Config->DebugGHashes) { - ArrayRef Hashes; - std::vector OwnedHashes; - if (Optional> DebugH = getDebugH(File)) - Hashes = getHashesFromDebugH(*DebugH); + if (config->debugGHashes) { + ArrayRef hashes; + std::vector ownedHashes; + if (Optional> debugH = getDebugH(file)) + hashes = getHashesFromDebugH(*debugH); else { - OwnedHashes = GloballyHashedType::hashTypes(Types); - Hashes = OwnedHashes; + ownedHashes = GloballyHashedType::hashTypes(types); + hashes = ownedHashes; } - if (auto Err = mergeTypeAndIdRecords( - TMerger.GlobalIDTable, TMerger.GlobalTypeTable, - ObjectIndexMap->TPIMap, Types, Hashes, File->PCHSignature)) + if (auto err = mergeTypeAndIdRecords( + tMerger.globalIDTable, tMerger.globalTypeTable, + objectIndexMap->tpiMap, types, hashes, file->pchSignature)) fatal("codeview::mergeTypeAndIdRecords failed: " + - toString(std::move(Err))); + toString(std::move(err))); } else { - if (auto Err = mergeTypeAndIdRecords(TMerger.IDTable, TMerger.TypeTable, - ObjectIndexMap->TPIMap, Types, - File->PCHSignature)) + if (auto err = mergeTypeAndIdRecords(tMerger.iDTable, tMerger.typeTable, + objectIndexMap->tpiMap, types, + file->pchSignature)) fatal("codeview::mergeTypeAndIdRecords failed: " + - toString(std::move(Err))); + toString(std::move(err))); } - return *ObjectIndexMap; + return *objectIndexMap; } -Expected PDBLinker::maybeMergeTypeServerPDB(ObjFile *File) { - Expected PDBSession = findTypeServerSource(File); - if (!PDBSession) - return PDBSession.takeError(); +Expected PDBLinker::maybeMergeTypeServerPDB(ObjFile *file) { + Expected pdbSession = findTypeServerSource(file); + if (!pdbSession) + return pdbSession.takeError(); - pdb::PDBFile &PDBFile = PDBSession.get()->getPDBFile(); - pdb::InfoStream &Info = cantFail(PDBFile.getPDBInfoStream()); + pdb::PDBFile &pdbFile = pdbSession.get()->getPDBFile(); + pdb::InfoStream &info = cantFail(pdbFile.getPDBInfoStream()); - auto It = TypeServerIndexMappings.emplace(Info.getGuid(), CVIndexMap()); - CVIndexMap &IndexMap = It.first->second; - if (!It.second) - return IndexMap; // already merged + auto it = typeServerIndexMappings.emplace(info.getGuid(), CVIndexMap()); + CVIndexMap &indexMap = it.first->second; + if (!it.second) + return indexMap; // already merged // Mark this map as a type server map. - IndexMap.IsTypeServerMap = true; + indexMap.isTypeServerMap = true; - Expected ExpectedTpi = PDBFile.getPDBTpiStream(); - if (auto E = ExpectedTpi.takeError()) - fatal("Type server does not have TPI stream: " + toString(std::move(E))); - pdb::TpiStream *MaybeIpi = nullptr; - if (PDBFile.hasPDBIpiStream()) { - Expected ExpectedIpi = PDBFile.getPDBIpiStream(); - if (auto E = ExpectedIpi.takeError()) - fatal("Error getting type server IPI stream: " + toString(std::move(E))); - MaybeIpi = &*ExpectedIpi; + Expected expectedTpi = pdbFile.getPDBTpiStream(); + if (auto e = expectedTpi.takeError()) + fatal("Type server does not have TPI stream: " + toString(std::move(e))); + pdb::TpiStream *maybeIpi = nullptr; + if (pdbFile.hasPDBIpiStream()) { + Expected expectedIpi = pdbFile.getPDBIpiStream(); + if (auto e = expectedIpi.takeError()) + fatal("Error getting type server IPI stream: " + toString(std::move(e))); + maybeIpi = &*expectedIpi; } - if (Config->DebugGHashes) { + if (config->debugGHashes) { // PDBs do not actually store global hashes, so when merging a type server // PDB we have to synthesize global hashes. To do this, we first synthesize // global hashes for the TPI stream, since it is independent, then we // synthesize hashes for the IPI stream, using the hashes for the TPI stream // as inputs. - auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray()); - Optional EndPrecomp; + auto tpiHashes = GloballyHashedType::hashTypes(expectedTpi->typeArray()); + Optional endPrecomp; // Merge TPI first, because the IPI stream will reference type indices. - if (auto Err = - mergeTypeRecords(TMerger.GlobalTypeTable, IndexMap.TPIMap, - ExpectedTpi->typeArray(), TpiHashes, EndPrecomp)) - fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); + if (auto err = + mergeTypeRecords(tMerger.globalTypeTable, indexMap.tpiMap, + expectedTpi->typeArray(), tpiHashes, endPrecomp)) + fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); // Merge IPI. - if (MaybeIpi) { - auto IpiHashes = - GloballyHashedType::hashIds(MaybeIpi->typeArray(), TpiHashes); - if (auto Err = - mergeIdRecords(TMerger.GlobalIDTable, IndexMap.TPIMap, - IndexMap.IPIMap, MaybeIpi->typeArray(), IpiHashes)) - fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err))); + if (maybeIpi) { + auto ipiHashes = + GloballyHashedType::hashIds(maybeIpi->typeArray(), tpiHashes); + if (auto err = + mergeIdRecords(tMerger.globalIDTable, indexMap.tpiMap, + indexMap.ipiMap, maybeIpi->typeArray(), ipiHashes)) + fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); } } else { // Merge TPI first, because the IPI stream will reference type indices. - if (auto Err = mergeTypeRecords(TMerger.TypeTable, IndexMap.TPIMap, - ExpectedTpi->typeArray())) - fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); + if (auto err = mergeTypeRecords(tMerger.typeTable, indexMap.tpiMap, + expectedTpi->typeArray())) + fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err))); // Merge IPI. - if (MaybeIpi) { - if (auto Err = mergeIdRecords(TMerger.IDTable, IndexMap.TPIMap, - IndexMap.IPIMap, MaybeIpi->typeArray())) - fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err))); + if (maybeIpi) { + if (auto err = mergeIdRecords(tMerger.iDTable, indexMap.tpiMap, + indexMap.ipiMap, maybeIpi->typeArray())) + fatal("codeview::mergeIdRecords failed: " + toString(std::move(err))); } } - return IndexMap; + return indexMap; } -Error PDBLinker::mergeInPrecompHeaderObj(ObjFile *File, - CVIndexMap *ObjectIndexMap) { - const PrecompRecord &Precomp = - retrieveDependencyInfo(File->DebugTypesObj); +Error PDBLinker::mergeInPrecompHeaderObj(ObjFile *file, + CVIndexMap *objectIndexMap) { + const PrecompRecord &precomp = + retrieveDependencyInfo(file->debugTypesObj); - Expected E = aquirePrecompObj(File); - if (!E) - return E.takeError(); + Expected e = aquirePrecompObj(file); + if (!e) + return e.takeError(); - const CVIndexMap &PrecompIndexMap = *E; - assert(PrecompIndexMap.IsPrecompiledTypeMap); + const CVIndexMap &precompIndexMap = *e; + assert(precompIndexMap.isPrecompiledTypeMap); - if (PrecompIndexMap.TPIMap.empty()) + if (precompIndexMap.tpiMap.empty()) return Error::success(); - assert(Precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex); - assert(Precomp.getTypesCount() <= PrecompIndexMap.TPIMap.size()); + assert(precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex); + assert(precomp.getTypesCount() <= precompIndexMap.tpiMap.size()); // Use the previously remapped index map from the precompiled headers. - ObjectIndexMap->TPIMap.append(PrecompIndexMap.TPIMap.begin(), - PrecompIndexMap.TPIMap.begin() + - Precomp.getTypesCount()); + objectIndexMap->tpiMap.append(precompIndexMap.tpiMap.begin(), + precompIndexMap.tpiMap.begin() + + precomp.getTypesCount()); return Error::success(); } @@ -515,103 +515,103 @@ } // Find by name an OBJ provided on the command line -static ObjFile *findObjByName(StringRef FileNameOnly) { - SmallString<128> CurrentPath; +static ObjFile *findObjByName(StringRef fileNameOnly) { + SmallString<128> currentPath; - for (ObjFile *F : ObjFile::Instances) { - StringRef CurrentFileName = sys::path::filename(F->getName()); + for (ObjFile *f : ObjFile::instances) { + StringRef currentFileName = sys::path::filename(f->getName()); // Compare based solely on the file name (link.exe behavior) - if (equals_path(CurrentFileName, FileNameOnly)) - return F; + if (equals_path(currentFileName, fileNameOnly)) + return f; } return nullptr; } std::pair -PDBLinker::registerPrecompiledHeaders(uint32_t Signature) { - auto Insertion = PrecompTypeIndexMappings.insert({Signature, CVIndexMap()}); - CVIndexMap &IndexMap = Insertion.first->second; - if (!Insertion.second) - return {IndexMap, true}; +PDBLinker::registerPrecompiledHeaders(uint32_t signature) { + auto insertion = precompTypeIndexMappings.insert({signature, CVIndexMap()}); + CVIndexMap &indexMap = insertion.first->second; + if (!insertion.second) + return {indexMap, true}; // Mark this map as a precompiled types map. - IndexMap.IsPrecompiledTypeMap = true; - return {IndexMap, false}; + indexMap.isPrecompiledTypeMap = true; + return {indexMap, false}; } -Expected PDBLinker::aquirePrecompObj(ObjFile *File) { - const PrecompRecord &Precomp = - retrieveDependencyInfo(File->DebugTypesObj); +Expected PDBLinker::aquirePrecompObj(ObjFile *file) { + const PrecompRecord &precomp = + retrieveDependencyInfo(file->debugTypesObj); // First, check if we already loaded the precompiled headers object with this // signature. Return the type index mapping if we've already seen it. - auto R = registerPrecompiledHeaders(Precomp.getSignature()); - if (R.second) - return R.first; + auto r = registerPrecompiledHeaders(precomp.getSignature()); + if (r.second) + return r.first; - CVIndexMap &IndexMap = R.first; + CVIndexMap &indexMap = r.first; // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly, // the paths embedded in the OBJs are in the Windows format. - SmallString<128> PrecompFileName = sys::path::filename( - Precomp.getPrecompFilePath(), sys::path::Style::windows); + SmallString<128> precompFileName = sys::path::filename( + precomp.getPrecompFilePath(), sys::path::Style::windows); // link.exe requires that a precompiled headers object must always be provided // on the command-line, even if that's not necessary. - auto PrecompFile = findObjByName(PrecompFileName); - if (!PrecompFile) + auto precompFile = findObjByName(precompFileName); + if (!precompFile) return createFileError( - PrecompFileName.str(), + precompFileName.str(), make_error(pdb::pdb_error_code::external_cmdline_ref)); - addObjFile(PrecompFile, &IndexMap); + addObjFile(precompFile, &indexMap); - if (!PrecompFile->PCHSignature) - fatal(PrecompFile->getName() + " is not a precompiled headers object"); + if (!precompFile->pchSignature) + fatal(precompFile->getName() + " is not a precompiled headers object"); - if (Precomp.getSignature() != PrecompFile->PCHSignature.getValueOr(0)) + if (precomp.getSignature() != precompFile->pchSignature.getValueOr(0)) return createFileError( - Precomp.getPrecompFilePath().str(), + precomp.getPrecompFilePath().str(), make_error(pdb::pdb_error_code::signature_out_of_date)); - return IndexMap; + return indexMap; } -static bool remapTypeIndex(TypeIndex &TI, ArrayRef TypeIndexMap) { - if (TI.isSimple()) +static bool remapTypeIndex(TypeIndex &ti, ArrayRef typeIndexMap) { + if (ti.isSimple()) return true; - if (TI.toArrayIndex() >= TypeIndexMap.size()) + if (ti.toArrayIndex() >= typeIndexMap.size()) return false; - TI = TypeIndexMap[TI.toArrayIndex()]; + ti = typeIndexMap[ti.toArrayIndex()]; return true; } -static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind, - MutableArrayRef RecordBytes, - const CVIndexMap &IndexMap, - ArrayRef TypeRefs) { - MutableArrayRef Contents = - RecordBytes.drop_front(sizeof(RecordPrefix)); - for (const TiReference &Ref : TypeRefs) { - unsigned ByteSize = Ref.Count * sizeof(TypeIndex); - if (Contents.size() < Ref.Offset + ByteSize) +static void remapTypesInSymbolRecord(ObjFile *file, SymbolKind symKind, + MutableArrayRef recordBytes, + const CVIndexMap &indexMap, + ArrayRef typeRefs) { + MutableArrayRef contents = + recordBytes.drop_front(sizeof(RecordPrefix)); + for (const TiReference &ref : typeRefs) { + unsigned byteSize = ref.Count * sizeof(TypeIndex); + if (contents.size() < ref.Offset + byteSize) fatal("symbol record too short"); // This can be an item index or a type index. Choose the appropriate map. - ArrayRef TypeOrItemMap = IndexMap.TPIMap; - bool IsItemIndex = Ref.Kind == TiRefKind::IndexRef; - if (IsItemIndex && IndexMap.IsTypeServerMap) - TypeOrItemMap = IndexMap.IPIMap; - - MutableArrayRef TIs( - reinterpret_cast(Contents.data() + Ref.Offset), Ref.Count); - for (TypeIndex &TI : TIs) { - if (!remapTypeIndex(TI, TypeOrItemMap)) { - log("ignoring symbol record of kind 0x" + utohexstr(SymKind) + " in " + - File->getName() + " with bad " + (IsItemIndex ? "item" : "type") + - " index 0x" + utohexstr(TI.getIndex())); - TI = TypeIndex(SimpleTypeKind::NotTranslated); + ArrayRef typeOrItemMap = indexMap.tpiMap; + bool isItemIndex = ref.Kind == TiRefKind::IndexRef; + if (isItemIndex && indexMap.isTypeServerMap) + typeOrItemMap = indexMap.ipiMap; + + MutableArrayRef tIs( + reinterpret_cast(contents.data() + ref.Offset), ref.Count); + for (TypeIndex &ti : tIs) { + if (!remapTypeIndex(ti, typeOrItemMap)) { + log("ignoring symbol record of kind 0x" + utohexstr(symKind) + " in " + + file->getName() + " with bad " + (isItemIndex ? "item" : "type") + + " index 0x" + utohexstr(ti.getIndex())); + ti = TypeIndex(SimpleTypeKind::NotTranslated); continue; } } @@ -619,26 +619,26 @@ } static void -recordStringTableReferenceAtOffset(MutableArrayRef Contents, - uint32_t Offset, - std::vector &StrTableRefs) { - Contents = - Contents.drop_front(Offset).take_front(sizeof(support::ulittle32_t)); - ulittle32_t *Index = reinterpret_cast(Contents.data()); - StrTableRefs.push_back(Index); +recordStringTableReferenceAtOffset(MutableArrayRef contents, + uint32_t offset, + std::vector &strTableRefs) { + contents = + contents.drop_front(offset).take_front(sizeof(support::ulittle32_t)); + ulittle32_t *index = reinterpret_cast(contents.data()); + strTableRefs.push_back(index); } static void -recordStringTableReferences(SymbolKind Kind, MutableArrayRef Contents, - std::vector &StrTableRefs) { +recordStringTableReferences(SymbolKind kind, MutableArrayRef contents, + std::vector &strTableRefs) { // For now we only handle S_FILESTATIC, but we may need the same logic for // S_DEFRANGE and S_DEFRANGE_SUBFIELD. However, I cannot seem to generate any // PDBs that contain these types of records, so because of the uncertainty // they are omitted here until we can prove that it's necessary. - switch (Kind) { + switch (kind) { case SymbolKind::S_FILESTATIC: // FileStaticSym::ModFileOffset - recordStringTableReferenceAtOffset(Contents, 8, StrTableRefs); + recordStringTableReferenceAtOffset(contents, 8, strTableRefs); break; case SymbolKind::S_DEFRANGE: case SymbolKind::S_DEFRANGE_SUBFIELD: @@ -650,21 +650,21 @@ } } -static SymbolKind symbolKind(ArrayRef RecordData) { - const RecordPrefix *Prefix = - reinterpret_cast(RecordData.data()); - return static_cast(uint16_t(Prefix->RecordKind)); +static SymbolKind symbolKind(ArrayRef recordData) { + const RecordPrefix *prefix = + reinterpret_cast(recordData.data()); + return static_cast(uint16_t(prefix->RecordKind)); } /// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32 -static void translateIdSymbols(MutableArrayRef &RecordData, - TypeCollection &IDTable) { - RecordPrefix *Prefix = reinterpret_cast(RecordData.data()); +static void translateIdSymbols(MutableArrayRef &recordData, + TypeCollection &iDTable) { + RecordPrefix *prefix = reinterpret_cast(recordData.data()); - SymbolKind Kind = symbolKind(RecordData); + SymbolKind kind = symbolKind(recordData); - if (Kind == SymbolKind::S_PROC_ID_END) { - Prefix->RecordKind = SymbolKind::S_END; + if (kind == SymbolKind::S_PROC_ID_END) { + prefix->RecordKind = SymbolKind::S_END; return; } @@ -673,89 +673,89 @@ // to the PDB file's ID stream index space, but we need to convert this to a // symbol that refers to the type stream index space. So we remap again from // ID index space to type index space. - if (Kind == SymbolKind::S_GPROC32_ID || Kind == SymbolKind::S_LPROC32_ID) { - SmallVector Refs; - auto Content = RecordData.drop_front(sizeof(RecordPrefix)); - CVSymbol Sym(RecordData); - discoverTypeIndicesInSymbol(Sym, Refs); - assert(Refs.size() == 1); - assert(Refs.front().Count == 1); + if (kind == SymbolKind::S_GPROC32_ID || kind == SymbolKind::S_LPROC32_ID) { + SmallVector refs; + auto content = recordData.drop_front(sizeof(RecordPrefix)); + CVSymbol sym(recordData); + discoverTypeIndicesInSymbol(sym, refs); + assert(refs.size() == 1); + assert(refs.front().Count == 1); - TypeIndex *TI = - reinterpret_cast(Content.data() + Refs[0].Offset); + TypeIndex *ti = + reinterpret_cast(content.data() + refs[0].Offset); // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in // the IPI stream, whose `FunctionType` member refers to the TPI stream. // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and // in both cases we just need the second type index. - if (!TI->isSimple() && !TI->isNoneType()) { - CVType FuncIdData = IDTable.getType(*TI); - SmallVector Indices; - discoverTypeIndices(FuncIdData, Indices); - assert(Indices.size() == 2); - *TI = Indices[1]; + if (!ti->isSimple() && !ti->isNoneType()) { + CVType funcIdData = iDTable.getType(*ti); + SmallVector indices; + discoverTypeIndices(funcIdData, indices); + assert(indices.size() == 2); + *ti = indices[1]; } - Kind = (Kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32 + kind = (kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32 : SymbolKind::S_LPROC32; - Prefix->RecordKind = uint16_t(Kind); + prefix->RecordKind = uint16_t(kind); } } /// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. /// The object file may not be aligned. static MutableArrayRef -copyAndAlignSymbol(const CVSymbol &Sym, MutableArrayRef &AlignedMem) { - size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); - assert(Size >= 4 && "record too short"); - assert(Size <= MaxRecordLength && "record too long"); - assert(AlignedMem.size() >= Size && "didn't preallocate enough"); +copyAndAlignSymbol(const CVSymbol &sym, MutableArrayRef &alignedMem) { + size_t size = alignTo(sym.length(), alignOf(CodeViewContainer::Pdb)); + assert(size >= 4 && "record too short"); + assert(size <= MaxRecordLength && "record too long"); + assert(alignedMem.size() >= size && "didn't preallocate enough"); // Copy the symbol record and zero out any padding bytes. - MutableArrayRef NewData = AlignedMem.take_front(Size); - AlignedMem = AlignedMem.drop_front(Size); - memcpy(NewData.data(), Sym.data().data(), Sym.length()); - memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); + MutableArrayRef newData = alignedMem.take_front(size); + alignedMem = alignedMem.drop_front(size); + memcpy(newData.data(), sym.data().data(), sym.length()); + memset(newData.data() + sym.length(), 0, size - sym.length()); // Update the record prefix length. It should point to the beginning of the // next record. - auto *Prefix = reinterpret_cast(NewData.data()); - Prefix->RecordLen = Size - 2; - return NewData; + auto *prefix = reinterpret_cast(newData.data()); + prefix->RecordLen = size - 2; + return newData; } struct ScopeRecord { - ulittle32_t PtrParent; - ulittle32_t PtrEnd; + ulittle32_t ptrParent; + ulittle32_t ptrEnd; }; struct SymbolScope { - ScopeRecord *OpeningRecord; - uint32_t ScopeOffset; + ScopeRecord *openingRecord; + uint32_t scopeOffset; }; -static void scopeStackOpen(SmallVectorImpl &Stack, - uint32_t CurOffset, CVSymbol &Sym) { - assert(symbolOpensScope(Sym.kind())); - SymbolScope S; - S.ScopeOffset = CurOffset; - S.OpeningRecord = const_cast( - reinterpret_cast(Sym.content().data())); - S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset; - Stack.push_back(S); +static void scopeStackOpen(SmallVectorImpl &stack, + uint32_t curOffset, CVSymbol &sym) { + assert(symbolOpensScope(sym.kind())); + SymbolScope s; + s.scopeOffset = curOffset; + s.openingRecord = const_cast( + reinterpret_cast(sym.content().data())); + s.openingRecord->ptrParent = stack.empty() ? 0 : stack.back().scopeOffset; + stack.push_back(s); } -static void scopeStackClose(SmallVectorImpl &Stack, - uint32_t CurOffset, InputFile *File) { - if (Stack.empty()) { - warn("symbol scopes are not balanced in " + File->getName()); +static void scopeStackClose(SmallVectorImpl &stack, + uint32_t curOffset, InputFile *file) { + if (stack.empty()) { + warn("symbol scopes are not balanced in " + file->getName()); return; } - SymbolScope S = Stack.pop_back_val(); - S.OpeningRecord->PtrEnd = CurOffset; + SymbolScope s = stack.pop_back_val(); + s.openingRecord->ptrEnd = curOffset; } -static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) { - switch (Sym.kind()) { +static bool symbolGoesInModuleStream(const CVSymbol &sym, bool isGlobalScope) { + switch (sym.kind()) { case SymbolKind::S_GDATA32: case SymbolKind::S_CONSTANT: // We really should not be seeing S_PROCREF and S_LPROCREF in the first place @@ -767,7 +767,7 @@ return false; // S_UDT records go in the module stream if it is not a global S_UDT. case SymbolKind::S_UDT: - return !IsGlobalScope; + return !isGlobalScope; // S_GDATA32 does not go in the module stream, but S_LDATA32 does. case SymbolKind::S_LDATA32: default: @@ -775,8 +775,8 @@ } } -static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) { - switch (Sym.kind()) { +static bool symbolGoesInGlobalsStream(const CVSymbol &sym, bool isGlobalScope) { + switch (sym.kind()) { case SymbolKind::S_CONSTANT: case SymbolKind::S_GDATA32: // S_LDATA32 goes in both the module stream and the globals stream. @@ -791,36 +791,36 @@ return true; // S_UDT records go in the globals stream if it is a global S_UDT. case SymbolKind::S_UDT: - return IsGlobalScope; + return isGlobalScope; default: return false; } } -static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex, - unsigned SymOffset, const CVSymbol &Sym) { - switch (Sym.kind()) { +static void addGlobalSymbol(pdb::GSIStreamBuilder &builder, uint16_t modIndex, + unsigned symOffset, const CVSymbol &sym) { + switch (sym.kind()) { case SymbolKind::S_CONSTANT: case SymbolKind::S_UDT: case SymbolKind::S_GDATA32: case SymbolKind::S_LDATA32: case SymbolKind::S_PROCREF: case SymbolKind::S_LPROCREF: - Builder.addGlobalSymbol(Sym); + builder.addGlobalSymbol(sym); break; case SymbolKind::S_GPROC32: case SymbolKind::S_LPROC32: { - SymbolRecordKind K = SymbolRecordKind::ProcRefSym; - if (Sym.kind() == SymbolKind::S_LPROC32) - K = SymbolRecordKind::LocalProcRef; - ProcRefSym PS(K); - PS.Module = ModIndex; + SymbolRecordKind k = SymbolRecordKind::ProcRefSym; + if (sym.kind() == SymbolKind::S_LPROC32) + k = SymbolRecordKind::LocalProcRef; + ProcRefSym ps(k); + ps.Module = modIndex; // For some reason, MSVC seems to add one to this value. - ++PS.Module; - PS.Name = getSymbolName(Sym); - PS.SumName = 0; - PS.SymOffset = SymOffset; - Builder.addGlobalSymbol(PS); + ++ps.Module; + ps.Name = getSymbolName(sym); + ps.SumName = 0; + ps.SymOffset = symOffset; + builder.addGlobalSymbol(ps); break; } default: @@ -828,219 +828,219 @@ } } -void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, - std::vector &StringTableRefs, - BinaryStreamRef SymData) { - ArrayRef SymsBuffer; - cantFail(SymData.readBytes(0, SymData.getLength(), SymsBuffer)); - SmallVector Scopes; +void PDBLinker::mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap, + std::vector &stringTableRefs, + BinaryStreamRef symData) { + ArrayRef symsBuffer; + cantFail(symData.readBytes(0, symData.getLength(), symsBuffer)); + SmallVector scopes; // Iterate every symbol to check if any need to be realigned, and if so, how // much space we need to allocate for them. - bool NeedsRealignment = false; - unsigned TotalRealignedSize = 0; - auto EC = forEachCodeViewRecord( - SymsBuffer, [&](CVSymbol Sym) -> llvm::Error { - unsigned RealignedSize = - alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); - NeedsRealignment |= RealignedSize != Sym.length(); - TotalRealignedSize += RealignedSize; + bool needsRealignment = false; + unsigned totalRealignedSize = 0; + auto ec = forEachCodeViewRecord( + symsBuffer, [&](CVSymbol sym) -> llvm::Error { + unsigned realignedSize = + alignTo(sym.length(), alignOf(CodeViewContainer::Pdb)); + needsRealignment |= realignedSize != sym.length(); + totalRealignedSize += realignedSize; return Error::success(); }); // If any of the symbol record lengths was corrupt, ignore them all, warn // about it, and move on. - if (EC) { - warn("corrupt symbol records in " + File->getName()); - consumeError(std::move(EC)); + if (ec) { + warn("corrupt symbol records in " + file->getName()); + consumeError(std::move(ec)); return; } // If any symbol needed realignment, allocate enough contiguous memory for // them all. Typically symbol subsections are small enough that this will not // cause fragmentation. - MutableArrayRef AlignedSymbolMem; - if (NeedsRealignment) { - void *AlignedData = - Alloc.Allocate(TotalRealignedSize, alignOf(CodeViewContainer::Pdb)); - AlignedSymbolMem = makeMutableArrayRef( - reinterpret_cast(AlignedData), TotalRealignedSize); + MutableArrayRef alignedSymbolMem; + if (needsRealignment) { + void *alignedData = + alloc.Allocate(totalRealignedSize, alignOf(CodeViewContainer::Pdb)); + alignedSymbolMem = makeMutableArrayRef( + reinterpret_cast(alignedData), totalRealignedSize); } // Iterate again, this time doing the real work. - unsigned CurSymOffset = File->ModuleDBI->getNextSymbolOffset(); - ArrayRef BulkSymbols; + unsigned curSymOffset = file->moduleDBI->getNextSymbolOffset(); + ArrayRef bulkSymbols; cantFail(forEachCodeViewRecord( - SymsBuffer, [&](CVSymbol Sym) -> llvm::Error { + symsBuffer, [&](CVSymbol sym) -> llvm::Error { // Align the record if required. - MutableArrayRef RecordBytes; - if (NeedsRealignment) { - RecordBytes = copyAndAlignSymbol(Sym, AlignedSymbolMem); - Sym = CVSymbol(RecordBytes); + MutableArrayRef recordBytes; + if (needsRealignment) { + recordBytes = copyAndAlignSymbol(sym, alignedSymbolMem); + sym = CVSymbol(recordBytes); } else { // Otherwise, we can actually mutate the symbol directly, since we // copied it to apply relocations. - RecordBytes = makeMutableArrayRef( - const_cast(Sym.data().data()), Sym.length()); + recordBytes = makeMutableArrayRef( + const_cast(sym.data().data()), sym.length()); } // Discover type index references in the record. Skip it if we don't // know where they are. - SmallVector TypeRefs; - if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) { + SmallVector typeRefs; + if (!discoverTypeIndicesInSymbol(sym, typeRefs)) { log("ignoring unknown symbol record with kind 0x" + - utohexstr(Sym.kind())); + utohexstr(sym.kind())); return Error::success(); } // Re-map all the type index references. - remapTypesInSymbolRecord(File, Sym.kind(), RecordBytes, IndexMap, - TypeRefs); + remapTypesInSymbolRecord(file, sym.kind(), recordBytes, indexMap, + typeRefs); // An object file may have S_xxx_ID symbols, but these get converted to // "real" symbols in a PDB. - translateIdSymbols(RecordBytes, TMerger.getIDTable()); - Sym = CVSymbol(RecordBytes); + translateIdSymbols(recordBytes, tMerger.getIDTable()); + sym = CVSymbol(recordBytes); // If this record refers to an offset in the object file's string table, // add that item to the global PDB string table and re-write the index. - recordStringTableReferences(Sym.kind(), RecordBytes, StringTableRefs); + recordStringTableReferences(sym.kind(), recordBytes, stringTableRefs); // Fill in "Parent" and "End" fields by maintaining a stack of scopes. - if (symbolOpensScope(Sym.kind())) - scopeStackOpen(Scopes, CurSymOffset, Sym); - else if (symbolEndsScope(Sym.kind())) - scopeStackClose(Scopes, CurSymOffset, File); + if (symbolOpensScope(sym.kind())) + scopeStackOpen(scopes, curSymOffset, sym); + else if (symbolEndsScope(sym.kind())) + scopeStackClose(scopes, curSymOffset, file); // Add the symbol to the globals stream if necessary. Do this before // adding the symbol to the module since we may need to get the next // symbol offset, and writing to the module's symbol stream will update // that offset. - if (symbolGoesInGlobalsStream(Sym, Scopes.empty())) { - addGlobalSymbol(Builder.getGsiBuilder(), - File->ModuleDBI->getModuleIndex(), CurSymOffset, Sym); - ++GlobalSymbols; + if (symbolGoesInGlobalsStream(sym, scopes.empty())) { + addGlobalSymbol(builder.getGsiBuilder(), + file->moduleDBI->getModuleIndex(), curSymOffset, sym); + ++globalSymbols; } - if (symbolGoesInModuleStream(Sym, Scopes.empty())) { + if (symbolGoesInModuleStream(sym, scopes.empty())) { // Add symbols to the module in bulk. If this symbol is contiguous // with the previous run of symbols to add, combine the ranges. If // not, close the previous range of symbols and start a new one. - if (Sym.data().data() == BulkSymbols.end()) { - BulkSymbols = makeArrayRef(BulkSymbols.data(), - BulkSymbols.size() + Sym.length()); + if (sym.data().data() == bulkSymbols.end()) { + bulkSymbols = makeArrayRef(bulkSymbols.data(), + bulkSymbols.size() + sym.length()); } else { - File->ModuleDBI->addSymbolsInBulk(BulkSymbols); - BulkSymbols = RecordBytes; + file->moduleDBI->addSymbolsInBulk(bulkSymbols); + bulkSymbols = recordBytes; } - CurSymOffset += Sym.length(); - ++ModuleSymbols; + curSymOffset += sym.length(); + ++moduleSymbols; } return Error::success(); })); // Add any remaining symbols we've accumulated. - File->ModuleDBI->addSymbolsInBulk(BulkSymbols); + file->moduleDBI->addSymbolsInBulk(bulkSymbols); } // Allocate memory for a .debug$S / .debug$F section and relocate it. -static ArrayRef relocateDebugChunk(BumpPtrAllocator &Alloc, - SectionChunk &DebugChunk) { - uint8_t *Buffer = Alloc.Allocate(DebugChunk.getSize()); - assert(DebugChunk.getOutputSectionIdx() == 0 && +static ArrayRef relocateDebugChunk(BumpPtrAllocator &alloc, + SectionChunk &debugChunk) { + uint8_t *buffer = alloc.Allocate(debugChunk.getSize()); + assert(debugChunk.getOutputSectionIdx() == 0 && "debug sections should not be in output sections"); - DebugChunk.writeTo(Buffer); - return makeArrayRef(Buffer, DebugChunk.getSize()); + debugChunk.writeTo(buffer); + return makeArrayRef(buffer, debugChunk.getSize()); } -static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) { - OutputSection *OS = C ? C->getOutputSection() : nullptr; - pdb::SectionContrib SC; - memset(&SC, 0, sizeof(SC)); - SC.ISect = OS ? OS->SectionIndex : llvm::pdb::kInvalidStreamIndex; - SC.Off = C && OS ? C->getRVA() - OS->getRVA() : 0; - SC.Size = C ? C->getSize() : -1; - if (auto *SecChunk = dyn_cast_or_null(C)) { - SC.Characteristics = SecChunk->Header->Characteristics; - SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex(); - ArrayRef Contents = SecChunk->getContents(); - JamCRC CRC(0); - ArrayRef CharContents = makeArrayRef( - reinterpret_cast(Contents.data()), Contents.size()); - CRC.update(CharContents); - SC.DataCrc = CRC.getCRC(); +static pdb::SectionContrib createSectionContrib(const Chunk *c, uint32_t modi) { + OutputSection *os = c ? c->getOutputSection() : nullptr; + pdb::SectionContrib sc; + memset(&sc, 0, sizeof(sc)); + sc.ISect = os ? os->sectionIndex : llvm::pdb::kInvalidStreamIndex; + sc.Off = c && os ? c->getRVA() - os->getRVA() : 0; + sc.Size = c ? c->getSize() : -1; + if (auto *secChunk = dyn_cast_or_null(c)) { + sc.Characteristics = secChunk->header->Characteristics; + sc.Imod = secChunk->file->moduleDBI->getModuleIndex(); + ArrayRef contents = secChunk->getContents(); + JamCRC crc(0); + ArrayRef charContents = makeArrayRef( + reinterpret_cast(contents.data()), contents.size()); + crc.update(charContents); + sc.DataCrc = crc.getCRC(); } else { - SC.Characteristics = OS ? OS->Header.Characteristics : 0; - SC.Imod = Modi; + sc.Characteristics = os ? os->header.Characteristics : 0; + sc.Imod = modi; } - SC.RelocCrc = 0; // FIXME + sc.RelocCrc = 0; // FIXME - return SC; + return sc; } static uint32_t -translateStringTableIndex(uint32_t ObjIndex, - const DebugStringTableSubsectionRef &ObjStrTable, - DebugStringTableSubsection &PdbStrTable) { - auto ExpectedString = ObjStrTable.getString(ObjIndex); - if (!ExpectedString) { +translateStringTableIndex(uint32_t objIndex, + const DebugStringTableSubsectionRef &objStrTable, + DebugStringTableSubsection &pdbStrTable) { + auto expectedString = objStrTable.getString(objIndex); + if (!expectedString) { warn("Invalid string table reference"); - consumeError(ExpectedString.takeError()); + consumeError(expectedString.takeError()); return 0; } - return PdbStrTable.insert(*ExpectedString); + return pdbStrTable.insert(*expectedString); } -void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) { - DebugSubsectionArray Subsections; +void DebugSHandler::handleDebugS(lld::coff::SectionChunk &debugS) { + DebugSubsectionArray subsections; - ArrayRef RelocatedDebugContents = SectionChunk::consumeDebugMagic( - relocateDebugChunk(Linker.Alloc, DebugS), DebugS.getSectionName()); + ArrayRef relocatedDebugContents = SectionChunk::consumeDebugMagic( + relocateDebugChunk(linker.alloc, debugS), debugS.getSectionName()); - BinaryStreamReader Reader(RelocatedDebugContents, support::little); - ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); + BinaryStreamReader reader(relocatedDebugContents, support::little); + exitOnErr(reader.readArray(subsections, relocatedDebugContents.size())); - for (const DebugSubsectionRecord &SS : Subsections) { + for (const DebugSubsectionRecord &ss : subsections) { // Ignore subsections with the 'ignore' bit. Some versions of the Visual C++ // runtime have subsections with this bit set. - if (uint32_t(SS.kind()) & codeview::SubsectionIgnoreFlag) + if (uint32_t(ss.kind()) & codeview::SubsectionIgnoreFlag) continue; - switch (SS.kind()) { + switch (ss.kind()) { case DebugSubsectionKind::StringTable: { - assert(!CVStrTab.valid() && + assert(!cVStrTab.valid() && "Encountered multiple string table subsections!"); - ExitOnErr(CVStrTab.initialize(SS.getRecordData())); + exitOnErr(cVStrTab.initialize(ss.getRecordData())); break; } case DebugSubsectionKind::FileChecksums: - assert(!Checksums.valid() && + assert(!checksums.valid() && "Encountered multiple checksum subsections!"); - ExitOnErr(Checksums.initialize(SS.getRecordData())); + exitOnErr(checksums.initialize(ss.getRecordData())); break; case DebugSubsectionKind::Lines: // We can add the relocated line table directly to the PDB without // modification because the file checksum offsets will stay the same. - File.ModuleDBI->addDebugSubsection(SS); + file.moduleDBI->addDebugSubsection(ss); break; case DebugSubsectionKind::InlineeLines: - assert(!InlineeLines.valid() && + assert(!inlineeLines.valid() && "Encountered multiple inlinee lines subsections!"); - ExitOnErr(InlineeLines.initialize(SS.getRecordData())); + exitOnErr(inlineeLines.initialize(ss.getRecordData())); break; case DebugSubsectionKind::FrameData: { // We need to re-write string table indices here, so save off all // frame data subsections until we've processed the entire list of // subsections so that we can be sure we have the string table. - DebugFrameDataSubsectionRef FDS; - ExitOnErr(FDS.initialize(SS.getRecordData())); - NewFpoFrames.push_back(std::move(FDS)); + DebugFrameDataSubsectionRef fds; + exitOnErr(fds.initialize(ss.getRecordData())); + newFpoFrames.push_back(std::move(fds)); break; } case DebugSubsectionKind::Symbols: { - Linker.mergeSymbolRecords(&File, IndexMap, StringTableReferences, - SS.getRecordData()); + linker.mergeSymbolRecords(&file, indexMap, stringTableReferences, + ss.getRecordData()); break; } @@ -1063,69 +1063,69 @@ default: warn("ignoring unknown debug$S subsection kind 0x" + - utohexstr(uint32_t(SS.kind())) + " in file " + toString(&File)); + utohexstr(uint32_t(ss.kind())) + " in file " + toString(&file)); break; } } } static Expected -getFileName(const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { - auto Iter = Checksums.getArray().at(FileID); - if (Iter == Checksums.getArray().end()) +getFileName(const DebugStringTableSubsectionRef &strings, + const DebugChecksumsSubsectionRef &checksums, uint32_t fileID) { + auto iter = checksums.getArray().at(fileID); + if (iter == checksums.getArray().end()) return make_error(cv_error_code::no_records); - uint32_t Offset = Iter->FileNameOffset; - return Strings.getString(Offset); + uint32_t offset = iter->FileNameOffset; + return strings.getString(offset); } std::shared_ptr -DebugSHandler::mergeInlineeLines(DebugChecksumsSubsection *NewChecksums) { - auto NewInlineeLines = std::make_shared( - *NewChecksums, InlineeLines.hasExtraFiles()); - - for (const InlineeSourceLine &Line : InlineeLines) { - TypeIndex Inlinee = Line.Header->Inlinee; - uint32_t FileID = Line.Header->FileID; - uint32_t SourceLine = Line.Header->SourceLineNum; - - ArrayRef TypeOrItemMap = - IndexMap.IsTypeServerMap ? IndexMap.IPIMap : IndexMap.TPIMap; - if (!remapTypeIndex(Inlinee, TypeOrItemMap)) { - log("ignoring inlinee line record in " + File.getName() + - " with bad inlinee index 0x" + utohexstr(Inlinee.getIndex())); +DebugSHandler::mergeInlineeLines(DebugChecksumsSubsection *newChecksums) { + auto newInlineeLines = std::make_shared( + *newChecksums, inlineeLines.hasExtraFiles()); + + for (const InlineeSourceLine &line : inlineeLines) { + TypeIndex inlinee = line.Header->Inlinee; + uint32_t fileID = line.Header->FileID; + uint32_t sourceLine = line.Header->SourceLineNum; + + ArrayRef typeOrItemMap = + indexMap.isTypeServerMap ? indexMap.ipiMap : indexMap.tpiMap; + if (!remapTypeIndex(inlinee, typeOrItemMap)) { + log("ignoring inlinee line record in " + file.getName() + + " with bad inlinee index 0x" + utohexstr(inlinee.getIndex())); continue; } - SmallString<128> Filename = - ExitOnErr(getFileName(CVStrTab, Checksums, FileID)); - pdbMakeAbsolute(Filename); - NewInlineeLines->addInlineSite(Inlinee, Filename, SourceLine); - - if (InlineeLines.hasExtraFiles()) { - for (uint32_t ExtraFileId : Line.ExtraFiles) { - Filename = ExitOnErr(getFileName(CVStrTab, Checksums, ExtraFileId)); - pdbMakeAbsolute(Filename); - NewInlineeLines->addExtraFile(Filename); + SmallString<128> filename = + exitOnErr(getFileName(cVStrTab, checksums, fileID)); + pdbMakeAbsolute(filename); + newInlineeLines->addInlineSite(inlinee, filename, sourceLine); + + if (inlineeLines.hasExtraFiles()) { + for (uint32_t extraFileId : line.ExtraFiles) { + filename = exitOnErr(getFileName(cVStrTab, checksums, extraFileId)); + pdbMakeAbsolute(filename); + newInlineeLines->addExtraFile(filename); } } } - return NewInlineeLines; + return newInlineeLines; } void DebugSHandler::finish() { - pdb::DbiStreamBuilder &DbiBuilder = Linker.Builder.getDbiBuilder(); + pdb::DbiStreamBuilder &dbiBuilder = linker.builder.getDbiBuilder(); // We should have seen all debug subsections across the entire object file now // which means that if a StringTable subsection and Checksums subsection were // present, now is the time to handle them. - if (!CVStrTab.valid()) { - if (Checksums.valid()) + if (!cVStrTab.valid()) { + if (checksums.valid()) fatal(".debug$S sections with a checksums subsection must also contain a " "string table subsection"); - if (!StringTableReferences.empty()) + if (!stringTableReferences.empty()) warn("No StringTable subsection was encountered, but there are string " "table references"); return; @@ -1133,231 +1133,231 @@ // Rewrite string table indices in the Fpo Data and symbol records to refer to // the global PDB string table instead of the object file string table. - for (DebugFrameDataSubsectionRef &FDS : NewFpoFrames) { - const ulittle32_t *Reloc = FDS.getRelocPtr(); - for (codeview::FrameData FD : FDS) { - FD.RvaStart += *Reloc; - FD.FrameFunc = - translateStringTableIndex(FD.FrameFunc, CVStrTab, Linker.PDBStrTab); - DbiBuilder.addNewFpoData(FD); + for (DebugFrameDataSubsectionRef &fds : newFpoFrames) { + const ulittle32_t *reloc = fds.getRelocPtr(); + for (codeview::FrameData fd : fds) { + fd.RvaStart += *reloc; + fd.FrameFunc = + translateStringTableIndex(fd.FrameFunc, cVStrTab, linker.pdbStrTab); + dbiBuilder.addNewFpoData(fd); } } - for (ulittle32_t *Ref : StringTableReferences) - *Ref = translateStringTableIndex(*Ref, CVStrTab, Linker.PDBStrTab); + for (ulittle32_t *ref : stringTableReferences) + *ref = translateStringTableIndex(*ref, cVStrTab, linker.pdbStrTab); // Make a new file checksum table that refers to offsets in the PDB-wide // string table. Generally the string table subsection appears after the // checksum table, so we have to do this after looping over all the // subsections. - auto NewChecksums = make_unique(Linker.PDBStrTab); - for (FileChecksumEntry &FC : Checksums) { - SmallString<128> Filename = - ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); - pdbMakeAbsolute(Filename); - ExitOnErr(DbiBuilder.addModuleSourceFile(*File.ModuleDBI, Filename)); - NewChecksums->addChecksum(Filename, FC.Kind, FC.Checksum); + auto newChecksums = make_unique(linker.pdbStrTab); + for (FileChecksumEntry &fc : checksums) { + SmallString<128> filename = + exitOnErr(cVStrTab.getString(fc.FileNameOffset)); + pdbMakeAbsolute(filename); + exitOnErr(dbiBuilder.addModuleSourceFile(*file.moduleDBI, filename)); + newChecksums->addChecksum(filename, fc.Kind, fc.Checksum); } // Rewrite inlinee item indices if present. - if (InlineeLines.valid()) - File.ModuleDBI->addDebugSubsection(mergeInlineeLines(NewChecksums.get())); + if (inlineeLines.valid()) + file.moduleDBI->addDebugSubsection(mergeInlineeLines(newChecksums.get())); - File.ModuleDBI->addDebugSubsection(std::move(NewChecksums)); + file.moduleDBI->addDebugSubsection(std::move(newChecksums)); } -void PDBLinker::addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap) { - if (File->MergedIntoPDB) +void PDBLinker::addObjFile(ObjFile *file, CVIndexMap *externIndexMap) { + if (file->mergedIntoPDB) return; - File->MergedIntoPDB = true; + file->mergedIntoPDB = true; // Before we can process symbol substreams from .debug$S, we need to process // type information, file checksums, and the string table. Add type info to // the PDB first, so that we can get the map from object file type and item // indices to PDB type and item indices. - CVIndexMap ObjectIndexMap; - auto IndexMapResult = - mergeDebugT(File, ExternIndexMap ? ExternIndexMap : &ObjectIndexMap); + CVIndexMap objectIndexMap; + auto indexMapResult = + mergeDebugT(file, externIndexMap ? externIndexMap : &objectIndexMap); // If the .debug$T sections fail to merge, assume there is no debug info. - if (!IndexMapResult) { - if (!Config->WarnDebugInfoUnusable) { - consumeError(IndexMapResult.takeError()); + if (!indexMapResult) { + if (!config->warnDebugInfoUnusable) { + consumeError(indexMapResult.takeError()); return; } - warn("Cannot use debug info for '" + toString(File) + "' [LNK4099]\n" + + warn("Cannot use debug info for '" + toString(file) + "' [LNK4099]\n" + ">>> failed to load reference " + - StringRef(toString(IndexMapResult.takeError()))); + StringRef(toString(indexMapResult.takeError()))); return; } - ScopedTimer T(SymbolMergingTimer); + ScopedTimer t(symbolMergingTimer); - pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); - DebugSHandler DSH(*this, *File, *IndexMapResult); + pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder(); + DebugSHandler dsh(*this, *file, *indexMapResult); // Now do all live .debug$S and .debug$F sections. - for (SectionChunk *DebugChunk : File->getDebugChunks()) { - if (!DebugChunk->Live || DebugChunk->getSize() == 0) + for (SectionChunk *debugChunk : file->getDebugChunks()) { + if (!debugChunk->live || debugChunk->getSize() == 0) continue; - if (DebugChunk->getSectionName() == ".debug$S") { - DSH.handleDebugS(*DebugChunk); + if (debugChunk->getSectionName() == ".debug$S") { + dsh.handleDebugS(*debugChunk); continue; } - if (DebugChunk->getSectionName() == ".debug$F") { - ArrayRef RelocatedDebugContents = - relocateDebugChunk(Alloc, *DebugChunk); - - FixedStreamArray FpoRecords; - BinaryStreamReader Reader(RelocatedDebugContents, support::little); - uint32_t Count = RelocatedDebugContents.size() / sizeof(object::FpoData); - ExitOnErr(Reader.readArray(FpoRecords, Count)); + if (debugChunk->getSectionName() == ".debug$F") { + ArrayRef relocatedDebugContents = + relocateDebugChunk(alloc, *debugChunk); + + FixedStreamArray fpoRecords; + BinaryStreamReader reader(relocatedDebugContents, support::little); + uint32_t count = relocatedDebugContents.size() / sizeof(object::FpoData); + exitOnErr(reader.readArray(fpoRecords, count)); // These are already relocated and don't refer to the string table, so we // can just copy it. - for (const object::FpoData &FD : FpoRecords) - DbiBuilder.addOldFpoData(FD); + for (const object::FpoData &fd : fpoRecords) + dbiBuilder.addOldFpoData(fd); continue; } } // Do any post-processing now that all .debug$S sections have been processed. - DSH.finish(); + dsh.finish(); } // Add a module descriptor for every object file. We need to put an absolute // path to the object into the PDB. If this is a plain object, we make its // path absolute. If it's an object in an archive, we make the archive path // absolute. -static void createModuleDBI(pdb::PDBFileBuilder &Builder) { - pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); - SmallString<128> ObjName; - - for (ObjFile *File : ObjFile::Instances) { - - bool InArchive = !File->ParentName.empty(); - ObjName = InArchive ? File->ParentName : File->getName(); - pdbMakeAbsolute(ObjName); - StringRef ModName = InArchive ? File->getName() : StringRef(ObjName); - - File->ModuleDBI = &ExitOnErr(DbiBuilder.addModuleInfo(ModName)); - File->ModuleDBI->setObjFileName(ObjName); - - ArrayRef Chunks = File->getChunks(); - uint32_t Modi = File->ModuleDBI->getModuleIndex(); - - for (Chunk *C : Chunks) { - auto *SecChunk = dyn_cast(C); - if (!SecChunk || !SecChunk->Live) +static void createModuleDBI(pdb::PDBFileBuilder &builder) { + pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder(); + SmallString<128> objName; + + for (ObjFile *file : ObjFile::instances) { + + bool inArchive = !file->parentName.empty(); + objName = inArchive ? file->parentName : file->getName(); + pdbMakeAbsolute(objName); + StringRef modName = inArchive ? file->getName() : StringRef(objName); + + file->moduleDBI = &exitOnErr(dbiBuilder.addModuleInfo(modName)); + file->moduleDBI->setObjFileName(objName); + + ArrayRef chunks = file->getChunks(); + uint32_t modi = file->moduleDBI->getModuleIndex(); + + for (Chunk *c : chunks) { + auto *secChunk = dyn_cast(c); + if (!secChunk || !secChunk->live) continue; - pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi); - File->ModuleDBI->setFirstSectionContrib(SC); + pdb::SectionContrib sc = createSectionContrib(secChunk, modi); + file->moduleDBI->setFirstSectionContrib(sc); break; } } } -static PublicSym32 createPublic(Defined *Def) { - PublicSym32 Pub(SymbolKind::S_PUB32); - Pub.Name = Def->getName(); - if (auto *D = dyn_cast(Def)) { - if (D->getCOFFSymbol().isFunctionDefinition()) - Pub.Flags = PublicSymFlags::Function; - } else if (isa(Def)) { - Pub.Flags = PublicSymFlags::Function; +static PublicSym32 createPublic(Defined *def) { + PublicSym32 pub(SymbolKind::S_PUB32); + pub.Name = def->getName(); + if (auto *d = dyn_cast(def)) { + if (d->getCOFFSymbol().isFunctionDefinition()) + pub.Flags = PublicSymFlags::Function; + } else if (isa(def)) { + pub.Flags = PublicSymFlags::Function; } - OutputSection *OS = Def->getChunk()->getOutputSection(); - assert(OS && "all publics should be in final image"); - Pub.Offset = Def->getRVA() - OS->getRVA(); - Pub.Segment = OS->SectionIndex; - return Pub; + OutputSection *os = def->getChunk()->getOutputSection(); + assert(os && "all publics should be in final image"); + pub.Offset = def->getRVA() - os->getRVA(); + pub.Segment = os->sectionIndex; + return pub; } // Add all object files to the PDB. Merge .debug$T sections into IpiData and // TpiData. void PDBLinker::addObjectsToPDB() { - ScopedTimer T1(AddObjectsTimer); + ScopedTimer t1(addObjectsTimer); - createModuleDBI(Builder); + createModuleDBI(builder); - for (ObjFile *File : ObjFile::Instances) - addObjFile(File); + for (ObjFile *file : ObjFile::instances) + addObjFile(file); - Builder.getStringTableBuilder().setStrings(PDBStrTab); - T1.stop(); + builder.getStringTableBuilder().setStrings(pdbStrTab); + t1.stop(); // Construct TPI and IPI stream contents. - ScopedTimer T2(TpiStreamLayoutTimer); - addTypeInfo(Builder.getTpiBuilder(), TMerger.getTypeTable()); - addTypeInfo(Builder.getIpiBuilder(), TMerger.getIDTable()); - T2.stop(); + ScopedTimer t2(tpiStreamLayoutTimer); + addTypeInfo(builder.getTpiBuilder(), tMerger.getTypeTable()); + addTypeInfo(builder.getIpiBuilder(), tMerger.getIDTable()); + t2.stop(); - ScopedTimer T3(GlobalsLayoutTimer); + ScopedTimer t3(globalsLayoutTimer); // Compute the public and global symbols. - auto &GsiBuilder = Builder.getGsiBuilder(); - std::vector Publics; - Symtab->forEachSymbol([&Publics](Symbol *S) { + auto &gsiBuilder = builder.getGsiBuilder(); + std::vector publics; + symtab->forEachSymbol([&publics](Symbol *s) { // Only emit defined, live symbols that have a chunk. - auto *Def = dyn_cast(S); - if (Def && Def->isLive() && Def->getChunk()) - Publics.push_back(createPublic(Def)); + auto *def = dyn_cast(s); + if (def && def->isLive() && def->getChunk()) + publics.push_back(createPublic(def)); }); - if (!Publics.empty()) { - PublicSymbols = Publics.size(); + if (!publics.empty()) { + publicSymbols = publics.size(); // Sort the public symbols and add them to the stream. - parallelSort(Publics, [](const PublicSym32 &L, const PublicSym32 &R) { - return L.Name < R.Name; + parallelSort(publics, [](const PublicSym32 &l, const PublicSym32 &r) { + return l.Name < r.Name; }); - for (const PublicSym32 &Pub : Publics) - GsiBuilder.addPublicSymbol(Pub); + for (const PublicSym32 &pub : publics) + gsiBuilder.addPublicSymbol(pub); } } void PDBLinker::printStats() { - if (!Config->ShowSummary) + if (!config->showSummary) return; - SmallString<256> Buffer; - raw_svector_ostream Stream(Buffer); + SmallString<256> buffer; + raw_svector_ostream stream(buffer); - Stream << center_justify("Summary", 80) << '\n' + stream << center_justify("Summary", 80) << '\n' << std::string(80, '-') << '\n'; - auto Print = [&](uint64_t V, StringRef S) { - Stream << format_decimal(V, 15) << " " << S << '\n'; + auto print = [&](uint64_t v, StringRef s) { + stream << format_decimal(v, 15) << " " << s << '\n'; }; - Print(ObjFile::Instances.size(), + print(ObjFile::instances.size(), "Input OBJ files (expanded from all cmd-line inputs)"); - Print(TypeServerIndexMappings.size(), "PDB type server dependencies"); - Print(PrecompTypeIndexMappings.size(), "Precomp OBJ dependencies"); - Print(TMerger.getTypeTable().size() + TMerger.getIDTable().size(), + print(typeServerIndexMappings.size(), "PDB type server dependencies"); + print(precompTypeIndexMappings.size(), "Precomp OBJ dependencies"); + print(tMerger.getTypeTable().size() + tMerger.getIDTable().size(), "Merged TPI records"); - Print(PDBStrTab.size(), "Output PDB strings"); - Print(GlobalSymbols, "Global symbol records"); - Print(ModuleSymbols, "Module symbol records"); - Print(PublicSymbols, "Public symbol records"); + print(pdbStrTab.size(), "Output PDB strings"); + print(globalSymbols, "Global symbol records"); + print(moduleSymbols, "Module symbol records"); + print(publicSymbols, "Public symbol records"); - message(Buffer); + message(buffer); } void PDBLinker::addNatvisFiles() { - for (StringRef File : Config->NatvisFiles) { - ErrorOr> DataOrErr = - MemoryBuffer::getFile(File); - if (!DataOrErr) { - warn("Cannot open input file: " + File); + for (StringRef file : config->natvisFiles) { + ErrorOr> dataOrErr = + MemoryBuffer::getFile(file); + if (!dataOrErr) { + warn("Cannot open input file: " + file); continue; } - Builder.addInjectedSource(File, std::move(*DataOrErr)); + builder.addInjectedSource(file, std::move(*dataOrErr)); } } -static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) { - switch (Machine) { +static codeview::CPUType toCodeViewMachine(COFF::MachineTypes machine) { + switch (machine) { case COFF::IMAGE_FILE_MACHINE_AMD64: return codeview::CPUType::X64; case COFF::IMAGE_FILE_MACHINE_ARM: @@ -1376,329 +1376,329 @@ // Mimic MSVC which surrounds arguments containing whitespace with quotes. // Double double-quotes are handled, so that the resulting string can be // executed again on the cmd-line. -static std::string quote(ArrayRef Args) { - std::string R; - R.reserve(256); - for (StringRef A : Args) { - if (!R.empty()) - R.push_back(' '); - bool HasWS = A.find(' ') != StringRef::npos; - bool HasQ = A.find('"') != StringRef::npos; - if (HasWS || HasQ) - R.push_back('"'); - if (HasQ) { - SmallVector S; - A.split(S, '"'); - R.append(join(S, "\"\"")); +static std::string quote(ArrayRef args) { + std::string r; + r.reserve(256); + for (StringRef a : args) { + if (!r.empty()) + r.push_back(' '); + bool hasWS = a.find(' ') != StringRef::npos; + bool hasQ = a.find('"') != StringRef::npos; + if (hasWS || hasQ) + r.push_back('"'); + if (hasQ) { + SmallVector s; + a.split(s, '"'); + r.append(join(s, "\"\"")); } else { - R.append(A); + r.append(a); } - if (HasWS || HasQ) - R.push_back('"'); + if (hasWS || hasQ) + r.push_back('"'); } - return R; + return r; } -static void fillLinkerVerRecord(Compile3Sym &CS) { - CS.Machine = toCodeViewMachine(Config->Machine); +static void fillLinkerVerRecord(Compile3Sym &cs) { + cs.Machine = toCodeViewMachine(config->machine); // Interestingly, if we set the string to 0.0.0.0, then when trying to view // local variables WinDbg emits an error that private symbols are not present. // By setting this to a valid MSVC linker version string, local variables are // displayed properly. As such, even though it is not representative of // LLVM's version information, we need this for compatibility. - CS.Flags = CompileSym3Flags::None; - CS.VersionBackendBuild = 25019; - CS.VersionBackendMajor = 14; - CS.VersionBackendMinor = 10; - CS.VersionBackendQFE = 0; + cs.Flags = CompileSym3Flags::None; + cs.VersionBackendBuild = 25019; + cs.VersionBackendMajor = 14; + cs.VersionBackendMinor = 10; + cs.VersionBackendQFE = 0; // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the // linker module (which is by definition a backend), so we don't need to do // anything here. Also, it seems we can use "LLVM Linker" for the linker name // without any problems. Only the backend version has to be hardcoded to a // magic number. - CS.VersionFrontendBuild = 0; - CS.VersionFrontendMajor = 0; - CS.VersionFrontendMinor = 0; - CS.VersionFrontendQFE = 0; - CS.Version = "LLVM Linker"; - CS.setLanguage(SourceLanguage::Link); -} - -static void addCommonLinkerModuleSymbols(StringRef Path, - pdb::DbiModuleDescriptorBuilder &Mod, - BumpPtrAllocator &Allocator) { - ObjNameSym ONS(SymbolRecordKind::ObjNameSym); - EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); - Compile3Sym CS(SymbolRecordKind::Compile3Sym); - fillLinkerVerRecord(CS); - - ONS.Name = "* Linker *"; - ONS.Signature = 0; - - ArrayRef Args = makeArrayRef(Config->Argv).drop_front(); - std::string ArgStr = quote(Args); - EBS.Fields.push_back("cwd"); + cs.VersionFrontendBuild = 0; + cs.VersionFrontendMajor = 0; + cs.VersionFrontendMinor = 0; + cs.VersionFrontendQFE = 0; + cs.Version = "LLVM Linker"; + cs.setLanguage(SourceLanguage::Link); +} + +static void addCommonLinkerModuleSymbols(StringRef path, + pdb::DbiModuleDescriptorBuilder &mod, + BumpPtrAllocator &allocator) { + ObjNameSym ons(SymbolRecordKind::ObjNameSym); + EnvBlockSym ebs(SymbolRecordKind::EnvBlockSym); + Compile3Sym cs(SymbolRecordKind::Compile3Sym); + fillLinkerVerRecord(cs); + + ons.Name = "* Linker *"; + ons.Signature = 0; + + ArrayRef args = makeArrayRef(config->argv).drop_front(); + std::string argStr = quote(args); + ebs.Fields.push_back("cwd"); SmallString<64> cwd; - if (Config->PDBSourcePath.empty()) + if (config->pdbSourcePath.empty()) sys::fs::current_path(cwd); else - cwd = Config->PDBSourcePath; - EBS.Fields.push_back(cwd); - EBS.Fields.push_back("exe"); - SmallString<64> exe = Config->Argv[0]; + cwd = config->pdbSourcePath; + ebs.Fields.push_back(cwd); + ebs.Fields.push_back("exe"); + SmallString<64> exe = config->argv[0]; pdbMakeAbsolute(exe); - EBS.Fields.push_back(exe); - EBS.Fields.push_back("pdb"); - EBS.Fields.push_back(Path); - EBS.Fields.push_back("cmd"); - EBS.Fields.push_back(ArgStr); - Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( - ONS, Allocator, CodeViewContainer::Pdb)); - Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( - CS, Allocator, CodeViewContainer::Pdb)); - Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( - EBS, Allocator, CodeViewContainer::Pdb)); -} - -static void addLinkerModuleCoffGroup(PartialSection *Sec, - pdb::DbiModuleDescriptorBuilder &Mod, - OutputSection &OS, - BumpPtrAllocator &Allocator) { + ebs.Fields.push_back(exe); + ebs.Fields.push_back("pdb"); + ebs.Fields.push_back(path); + ebs.Fields.push_back("cmd"); + ebs.Fields.push_back(argStr); + mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + ons, allocator, CodeViewContainer::Pdb)); + mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + cs, allocator, CodeViewContainer::Pdb)); + mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + ebs, allocator, CodeViewContainer::Pdb)); +} + +static void addLinkerModuleCoffGroup(PartialSection *sec, + pdb::DbiModuleDescriptorBuilder &mod, + OutputSection &os, + BumpPtrAllocator &allocator) { // If there's a section, there's at least one chunk - assert(!Sec->Chunks.empty()); - const Chunk *firstChunk = *Sec->Chunks.begin(); - const Chunk *lastChunk = *Sec->Chunks.rbegin(); + assert(!sec->chunks.empty()); + const Chunk *firstChunk = *sec->chunks.begin(); + const Chunk *lastChunk = *sec->chunks.rbegin(); // Emit COFF group - CoffGroupSym CGS(SymbolRecordKind::CoffGroupSym); - CGS.Name = Sec->Name; - CGS.Segment = OS.SectionIndex; - CGS.Offset = firstChunk->getRVA() - OS.getRVA(); - CGS.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA(); - CGS.Characteristics = Sec->Characteristics; + CoffGroupSym cgs(SymbolRecordKind::CoffGroupSym); + cgs.Name = sec->name; + cgs.Segment = os.sectionIndex; + cgs.Offset = firstChunk->getRVA() - os.getRVA(); + cgs.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA(); + cgs.Characteristics = sec->characteristics; // Somehow .idata sections & sections groups in the debug symbol stream have // the "write" flag set. However the section header for the corresponding // .idata section doesn't have it. - if (CGS.Name.startswith(".idata")) - CGS.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE; + if (cgs.Name.startswith(".idata")) + cgs.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE; - Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( - CGS, Allocator, CodeViewContainer::Pdb)); + mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + cgs, allocator, CodeViewContainer::Pdb)); } -static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod, - OutputSection &OS, - BumpPtrAllocator &Allocator) { - SectionSym Sym(SymbolRecordKind::SectionSym); - Sym.Alignment = 12; // 2^12 = 4KB - Sym.Characteristics = OS.Header.Characteristics; - Sym.Length = OS.getVirtualSize(); - Sym.Name = OS.Name; - Sym.Rva = OS.getRVA(); - Sym.SectionNumber = OS.SectionIndex; - Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( - Sym, Allocator, CodeViewContainer::Pdb)); +static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &mod, + OutputSection &os, + BumpPtrAllocator &allocator) { + SectionSym sym(SymbolRecordKind::SectionSym); + sym.Alignment = 12; // 2^12 = 4KB + sym.Characteristics = os.header.Characteristics; + sym.Length = os.getVirtualSize(); + sym.Name = os.name; + sym.Rva = os.getRVA(); + sym.SectionNumber = os.sectionIndex; + mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + sym, allocator, CodeViewContainer::Pdb)); // Skip COFF groups in MinGW because it adds a significant footprint to the // PDB, due to each function being in its own section - if (Config->MinGW) + if (config->mingw) return; // Output COFF groups for individual chunks of this section. - for (PartialSection *Sec : OS.ContribSections) { - addLinkerModuleCoffGroup(Sec, Mod, OS, Allocator); + for (PartialSection *sec : os.contribSections) { + addLinkerModuleCoffGroup(sec, mod, os, allocator); } } // Add all import files as modules to the PDB. -void PDBLinker::addImportFilesToPDB(ArrayRef OutputSections) { - if (ImportFile::Instances.empty()) +void PDBLinker::addImportFilesToPDB(ArrayRef outputSections) { + if (ImportFile::instances.empty()) return; - std::map DllToModuleDbi; + std::map dllToModuleDbi; - for (ImportFile *File : ImportFile::Instances) { - if (!File->Live) + for (ImportFile *file : ImportFile::instances) { + if (!file->live) continue; - if (!File->ThunkSym) + if (!file->thunkSym) continue; - if (!File->ThunkLive) + if (!file->thunkLive) continue; - std::string DLL = StringRef(File->DLLName).lower(); - llvm::pdb::DbiModuleDescriptorBuilder *&Mod = DllToModuleDbi[DLL]; - if (!Mod) { - pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); - SmallString<128> LibPath = File->ParentName; - pdbMakeAbsolute(LibPath); - sys::path::native(LibPath); + std::string dll = StringRef(file->dllName).lower(); + llvm::pdb::DbiModuleDescriptorBuilder *&mod = dllToModuleDbi[dll]; + if (!mod) { + pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder(); + SmallString<128> libPath = file->parentName; + pdbMakeAbsolute(libPath); + sys::path::native(libPath); // Name modules similar to MSVC's link.exe. // The first module is the simple dll filename - llvm::pdb::DbiModuleDescriptorBuilder &FirstMod = - ExitOnErr(DbiBuilder.addModuleInfo(File->DLLName)); - FirstMod.setObjFileName(LibPath); - pdb::SectionContrib SC = + llvm::pdb::DbiModuleDescriptorBuilder &firstMod = + exitOnErr(dbiBuilder.addModuleInfo(file->dllName)); + firstMod.setObjFileName(libPath); + pdb::SectionContrib sc = createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex); - FirstMod.setFirstSectionContrib(SC); + firstMod.setFirstSectionContrib(sc); // The second module is where the import stream goes. - Mod = &ExitOnErr(DbiBuilder.addModuleInfo("Import:" + File->DLLName)); - Mod->setObjFileName(LibPath); + mod = &exitOnErr(dbiBuilder.addModuleInfo("Import:" + file->dllName)); + mod->setObjFileName(libPath); } - DefinedImportThunk *Thunk = cast(File->ThunkSym); - Chunk *ThunkChunk = Thunk->getChunk(); - OutputSection *ThunkOS = ThunkChunk->getOutputSection(); - - ObjNameSym ONS(SymbolRecordKind::ObjNameSym); - Compile3Sym CS(SymbolRecordKind::Compile3Sym); - Thunk32Sym TS(SymbolRecordKind::Thunk32Sym); - ScopeEndSym ES(SymbolRecordKind::ScopeEndSym); - - ONS.Name = File->DLLName; - ONS.Signature = 0; - - fillLinkerVerRecord(CS); - - TS.Name = Thunk->getName(); - TS.Parent = 0; - TS.End = 0; - TS.Next = 0; - TS.Thunk = ThunkOrdinal::Standard; - TS.Length = ThunkChunk->getSize(); - TS.Segment = ThunkOS->SectionIndex; - TS.Offset = ThunkChunk->getRVA() - ThunkOS->getRVA(); - - Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( - ONS, Alloc, CodeViewContainer::Pdb)); - Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( - CS, Alloc, CodeViewContainer::Pdb)); - - SmallVector Scopes; - CVSymbol NewSym = codeview::SymbolSerializer::writeOneSymbol( - TS, Alloc, CodeViewContainer::Pdb); - scopeStackOpen(Scopes, Mod->getNextSymbolOffset(), NewSym); + DefinedImportThunk *thunk = cast(file->thunkSym); + Chunk *thunkChunk = thunk->getChunk(); + OutputSection *thunkOS = thunkChunk->getOutputSection(); + + ObjNameSym ons(SymbolRecordKind::ObjNameSym); + Compile3Sym cs(SymbolRecordKind::Compile3Sym); + Thunk32Sym ts(SymbolRecordKind::Thunk32Sym); + ScopeEndSym es(SymbolRecordKind::ScopeEndSym); + + ons.Name = file->dllName; + ons.Signature = 0; + + fillLinkerVerRecord(cs); + + ts.Name = thunk->getName(); + ts.Parent = 0; + ts.End = 0; + ts.Next = 0; + ts.Thunk = ThunkOrdinal::Standard; + ts.Length = thunkChunk->getSize(); + ts.Segment = thunkOS->sectionIndex; + ts.Offset = thunkChunk->getRVA() - thunkOS->getRVA(); + + mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( + ons, alloc, CodeViewContainer::Pdb)); + mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( + cs, alloc, CodeViewContainer::Pdb)); + + SmallVector scopes; + CVSymbol newSym = codeview::SymbolSerializer::writeOneSymbol( + ts, alloc, CodeViewContainer::Pdb); + scopeStackOpen(scopes, mod->getNextSymbolOffset(), newSym); - Mod->addSymbol(NewSym); + mod->addSymbol(newSym); - NewSym = codeview::SymbolSerializer::writeOneSymbol(ES, Alloc, + newSym = codeview::SymbolSerializer::writeOneSymbol(es, alloc, CodeViewContainer::Pdb); - scopeStackClose(Scopes, Mod->getNextSymbolOffset(), File); + scopeStackClose(scopes, mod->getNextSymbolOffset(), file); - Mod->addSymbol(NewSym); + mod->addSymbol(newSym); - pdb::SectionContrib SC = - createSectionContrib(Thunk->getChunk(), Mod->getModuleIndex()); - Mod->setFirstSectionContrib(SC); + pdb::SectionContrib sc = + createSectionContrib(thunk->getChunk(), mod->getModuleIndex()); + mod->setFirstSectionContrib(sc); } } // Creates a PDB file. -void coff::createPDB(SymbolTable *Symtab, - ArrayRef OutputSections, - ArrayRef SectionTable, - llvm::codeview::DebugInfo *BuildId) { - ScopedTimer T1(TotalPdbLinkTimer); - PDBLinker PDB(Symtab); - - PDB.initialize(BuildId); - PDB.addObjectsToPDB(); - PDB.addImportFilesToPDB(OutputSections); - PDB.addSections(OutputSections, SectionTable); - PDB.addNatvisFiles(); - - ScopedTimer T2(DiskCommitTimer); - codeview::GUID Guid; - PDB.commit(&Guid); - memcpy(&BuildId->PDB70.Signature, &Guid, 16); - - T2.stop(); - T1.stop(); - PDB.printStats(); +void coff::createPDB(SymbolTable *symtab, + ArrayRef outputSections, + ArrayRef sectionTable, + llvm::codeview::DebugInfo *buildId) { + ScopedTimer t1(totalPdbLinkTimer); + PDBLinker pdb(symtab); + + pdb.initialize(buildId); + pdb.addObjectsToPDB(); + pdb.addImportFilesToPDB(outputSections); + pdb.addSections(outputSections, sectionTable); + pdb.addNatvisFiles(); + + ScopedTimer t2(diskCommitTimer); + codeview::GUID guid; + pdb.commit(&guid); + memcpy(&buildId->PDB70.Signature, &guid, 16); + + t2.stop(); + t1.stop(); + pdb.printStats(); } -void PDBLinker::initialize(llvm::codeview::DebugInfo *BuildId) { - ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize +void PDBLinker::initialize(llvm::codeview::DebugInfo *buildId) { + exitOnErr(builder.initialize(4096)); // 4096 is blocksize - BuildId->Signature.CVSignature = OMF::Signature::PDB70; + buildId->Signature.CVSignature = OMF::Signature::PDB70; // Signature is set to a hash of the PDB contents when the PDB is done. - memset(BuildId->PDB70.Signature, 0, 16); - BuildId->PDB70.Age = 1; + memset(buildId->PDB70.Signature, 0, 16); + buildId->PDB70.Age = 1; // Create streams in MSF for predefined streams, namely // PDB, TPI, DBI and IPI. - for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I) - ExitOnErr(Builder.getMsfBuilder().addStream(0)); + for (int i = 0; i < (int)pdb::kSpecialStreamCount; ++i) + exitOnErr(builder.getMsfBuilder().addStream(0)); // Add an Info stream. - auto &InfoBuilder = Builder.getInfoBuilder(); - InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); - InfoBuilder.setHashPDBContentsToGUID(true); + auto &infoBuilder = builder.getInfoBuilder(); + infoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); + infoBuilder.setHashPDBContentsToGUID(true); // Add an empty DBI stream. - pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); - DbiBuilder.setAge(BuildId->PDB70.Age); - DbiBuilder.setVersionHeader(pdb::PdbDbiV70); - DbiBuilder.setMachineType(Config->Machine); + pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder(); + dbiBuilder.setAge(buildId->PDB70.Age); + dbiBuilder.setVersionHeader(pdb::PdbDbiV70); + dbiBuilder.setMachineType(config->machine); // Technically we are not link.exe 14.11, but there are known cases where // debugging tools on Windows expect Microsoft-specific version numbers or // they fail to work at all. Since we know we produce PDBs that are // compatible with LINK 14.11, we set that version number here. - DbiBuilder.setBuildNumber(14, 11); + dbiBuilder.setBuildNumber(14, 11); } -void PDBLinker::addSections(ArrayRef OutputSections, - ArrayRef SectionTable) { +void PDBLinker::addSections(ArrayRef outputSections, + ArrayRef sectionTable) { // It's not entirely clear what this is, but the * Linker * module uses it. - pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); - NativePath = Config->PDBPath; - pdbMakeAbsolute(NativePath); - uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); - auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); - LinkerModule.setPdbFilePathNI(PdbFilePathNI); - addCommonLinkerModuleSymbols(NativePath, LinkerModule, Alloc); + pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder(); + nativePath = config->pdbPath; + pdbMakeAbsolute(nativePath); + uint32_t pdbFilePathNI = dbiBuilder.addECName(nativePath); + auto &linkerModule = exitOnErr(dbiBuilder.addModuleInfo("* Linker *")); + linkerModule.setPdbFilePathNI(pdbFilePathNI); + addCommonLinkerModuleSymbols(nativePath, linkerModule, alloc); // Add section contributions. They must be ordered by ascending RVA. - for (OutputSection *OS : OutputSections) { - addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc); - for (Chunk *C : OS->Chunks) { - pdb::SectionContrib SC = - createSectionContrib(C, LinkerModule.getModuleIndex()); - Builder.getDbiBuilder().addSectionContrib(SC); + for (OutputSection *os : outputSections) { + addLinkerModuleSectionSymbol(linkerModule, *os, alloc); + for (Chunk *c : os->chunks) { + pdb::SectionContrib sc = + createSectionContrib(c, linkerModule.getModuleIndex()); + builder.getDbiBuilder().addSectionContrib(sc); } } // The * Linker * first section contrib is only used along with /INCREMENTAL, // to provide trampolines thunks for incremental function patching. Set this // as "unused" because LLD doesn't support /INCREMENTAL link. - pdb::SectionContrib SC = + pdb::SectionContrib sc = createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex); - LinkerModule.setFirstSectionContrib(SC); + linkerModule.setFirstSectionContrib(sc); // Add Section Map stream. - ArrayRef Sections = { - (const object::coff_section *)SectionTable.data(), - SectionTable.size() / sizeof(object::coff_section)}; - SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); - DbiBuilder.setSectionMap(SectionMap); + ArrayRef sections = { + (const object::coff_section *)sectionTable.data(), + sectionTable.size() / sizeof(object::coff_section)}; + sectionMap = pdb::DbiStreamBuilder::createSectionMap(sections); + dbiBuilder.setSectionMap(sectionMap); // Add COFF section header stream. - ExitOnErr( - DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); + exitOnErr( + dbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, sectionTable)); } -void PDBLinker::commit(codeview::GUID *Guid) { +void PDBLinker::commit(codeview::GUID *guid) { // Write to a file. - ExitOnErr(Builder.commit(Config->PDBPath, Guid)); + exitOnErr(builder.commit(config->pdbPath, guid)); } static uint32_t getSecrelReloc() { - switch (Config->Machine) { + switch (config->machine) { case AMD64: return COFF::IMAGE_REL_AMD64_SECREL; case I386: @@ -1717,78 +1717,78 @@ // that are used to interpret the line table, and the offset of Addr in the line // table are stored in the output arguments. Returns whether a line table was // found. -static bool findLineTable(const SectionChunk *C, uint32_t Addr, - DebugStringTableSubsectionRef &CVStrTab, - DebugChecksumsSubsectionRef &Checksums, - DebugLinesSubsectionRef &Lines, - uint32_t &OffsetInLinetable) { - ExitOnError ExitOnErr; - uint32_t SecrelReloc = getSecrelReloc(); +static bool findLineTable(const SectionChunk *c, uint32_t addr, + DebugStringTableSubsectionRef &cVStrTab, + DebugChecksumsSubsectionRef &checksums, + DebugLinesSubsectionRef &lines, + uint32_t &offsetInLinetable) { + ExitOnError exitOnErr; + uint32_t secrelReloc = getSecrelReloc(); - for (SectionChunk *DbgC : C->File->getDebugChunks()) { - if (DbgC->getSectionName() != ".debug$S") + for (SectionChunk *dbgC : c->file->getDebugChunks()) { + if (dbgC->getSectionName() != ".debug$S") continue; // Build a mapping of SECREL relocations in DbgC that refer to C. - DenseMap Secrels; - for (const coff_relocation &R : DbgC->getRelocs()) { - if (R.Type != SecrelReloc) + DenseMap secrels; + for (const coff_relocation &r : dbgC->getRelocs()) { + if (r.Type != secrelReloc) continue; - if (auto *S = dyn_cast_or_null( - C->File->getSymbols()[R.SymbolTableIndex])) - if (S->getChunk() == C) - Secrels[R.VirtualAddress] = S->getValue(); + if (auto *s = dyn_cast_or_null( + c->file->getSymbols()[r.SymbolTableIndex])) + if (s->getChunk() == c) + secrels[r.VirtualAddress] = s->getValue(); } - ArrayRef Contents = - SectionChunk::consumeDebugMagic(DbgC->getContents(), ".debug$S"); - DebugSubsectionArray Subsections; - BinaryStreamReader Reader(Contents, support::little); - ExitOnErr(Reader.readArray(Subsections, Contents.size())); + ArrayRef contents = + SectionChunk::consumeDebugMagic(dbgC->getContents(), ".debug$S"); + DebugSubsectionArray subsections; + BinaryStreamReader reader(contents, support::little); + exitOnErr(reader.readArray(subsections, contents.size())); - for (const DebugSubsectionRecord &SS : Subsections) { - switch (SS.kind()) { + for (const DebugSubsectionRecord &ss : subsections) { + switch (ss.kind()) { case DebugSubsectionKind::StringTable: { - assert(!CVStrTab.valid() && + assert(!cVStrTab.valid() && "Encountered multiple string table subsections!"); - ExitOnErr(CVStrTab.initialize(SS.getRecordData())); + exitOnErr(cVStrTab.initialize(ss.getRecordData())); break; } case DebugSubsectionKind::FileChecksums: - assert(!Checksums.valid() && + assert(!checksums.valid() && "Encountered multiple checksum subsections!"); - ExitOnErr(Checksums.initialize(SS.getRecordData())); + exitOnErr(checksums.initialize(ss.getRecordData())); break; case DebugSubsectionKind::Lines: { - ArrayRef Bytes; - auto Ref = SS.getRecordData(); - ExitOnErr(Ref.readLongestContiguousChunk(0, Bytes)); - size_t OffsetInDbgC = Bytes.data() - DbgC->getContents().data(); + ArrayRef bytes; + auto ref = ss.getRecordData(); + exitOnErr(ref.readLongestContiguousChunk(0, bytes)); + size_t offsetInDbgC = bytes.data() - dbgC->getContents().data(); // Check whether this line table refers to C. - auto I = Secrels.find(OffsetInDbgC); - if (I == Secrels.end()) + auto i = secrels.find(offsetInDbgC); + if (i == secrels.end()) break; // Check whether this line table covers Addr in C. - DebugLinesSubsectionRef LinesTmp; - ExitOnErr(LinesTmp.initialize(BinaryStreamReader(Ref))); - uint32_t OffsetInC = I->second + LinesTmp.header()->RelocOffset; - if (Addr < OffsetInC || Addr >= OffsetInC + LinesTmp.header()->CodeSize) + DebugLinesSubsectionRef linesTmp; + exitOnErr(linesTmp.initialize(BinaryStreamReader(ref))); + uint32_t offsetInC = i->second + linesTmp.header()->RelocOffset; + if (addr < offsetInC || addr >= offsetInC + linesTmp.header()->CodeSize) break; - assert(!Lines.header() && + assert(!lines.header() && "Encountered multiple line tables for function!"); - ExitOnErr(Lines.initialize(BinaryStreamReader(Ref))); - OffsetInLinetable = Addr - OffsetInC; + exitOnErr(lines.initialize(BinaryStreamReader(ref))); + offsetInLinetable = addr - offsetInC; break; } default: break; } - if (CVStrTab.valid() && Checksums.valid() && Lines.header()) + if (cVStrTab.valid() && checksums.valid() && lines.header()) return true; } } @@ -1799,38 +1799,38 @@ // Use CodeView line tables to resolve a file and line number for the given // offset into the given chunk and return them, or {"", 0} if a line table was // not found. -std::pair coff::getFileLine(const SectionChunk *C, - uint32_t Addr) { - ExitOnError ExitOnErr; - - DebugStringTableSubsectionRef CVStrTab; - DebugChecksumsSubsectionRef Checksums; - DebugLinesSubsectionRef Lines; - uint32_t OffsetInLinetable; +std::pair coff::getFileLine(const SectionChunk *c, + uint32_t addr) { + ExitOnError exitOnErr; + + DebugStringTableSubsectionRef cVStrTab; + DebugChecksumsSubsectionRef checksums; + DebugLinesSubsectionRef lines; + uint32_t offsetInLinetable; - if (!findLineTable(C, Addr, CVStrTab, Checksums, Lines, OffsetInLinetable)) + if (!findLineTable(c, addr, cVStrTab, checksums, lines, offsetInLinetable)) return {"", 0}; - Optional NameIndex; - Optional LineNumber; - for (LineColumnEntry &Entry : Lines) { - for (const LineNumberEntry &LN : Entry.LineNumbers) { - LineInfo LI(LN.Flags); - if (LN.Offset > OffsetInLinetable) { - if (!NameIndex) { - NameIndex = Entry.NameIndex; - LineNumber = LI.getStartLine(); + Optional nameIndex; + Optional lineNumber; + for (LineColumnEntry &entry : lines) { + for (const LineNumberEntry &ln : entry.LineNumbers) { + LineInfo li(ln.Flags); + if (ln.Offset > offsetInLinetable) { + if (!nameIndex) { + nameIndex = entry.NameIndex; + lineNumber = li.getStartLine(); } - StringRef Filename = - ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex)); - return {Filename, *LineNumber}; + StringRef filename = + exitOnErr(getFileName(cVStrTab, checksums, *nameIndex)); + return {filename, *lineNumber}; } - NameIndex = Entry.NameIndex; - LineNumber = LI.getStartLine(); + nameIndex = entry.NameIndex; + lineNumber = li.getStartLine(); } } - if (!NameIndex) + if (!nameIndex) return {"", 0}; - StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex)); - return {Filename, *LineNumber}; + StringRef filename = exitOnErr(getFileName(cVStrTab, checksums, *nameIndex)); + return {filename, *lineNumber}; } Index: lld/trunk/COFF/SymbolTable.h =================================================================== --- lld/trunk/COFF/SymbolTable.h +++ lld/trunk/COFF/SymbolTable.h @@ -47,7 +47,7 @@ // There is one add* function per symbol type. class SymbolTable { public: - void addFile(InputFile *File); + void addFile(InputFile *file); // Try to resolve any undefined symbols and update the symbol table // accordingly, then print an error message for any remaining undefined @@ -55,20 +55,20 @@ void reportRemainingUndefines(); void loadMinGWAutomaticImports(); - bool handleMinGWAutomaticImport(Symbol *Sym, StringRef Name); + bool handleMinGWAutomaticImport(Symbol *sym, StringRef name); // Returns a list of chunks of selected symbols. std::vector getChunks(); // Returns a symbol for a given name. Returns a nullptr if not found. - Symbol *find(StringRef Name); - Symbol *findUnderscore(StringRef Name); + Symbol *find(StringRef name); + Symbol *findUnderscore(StringRef name); // Occasionally we have to resolve an undefined symbol to its // mangled symbol. This function tries to find a mangled name // for U from the symbol table, and if found, set the symbol as // a weak alias for U. - Symbol *findMangle(StringRef Name); + Symbol *findMangle(StringRef name); // Build a set of COFF objects representing the combined contents of // BitcodeFiles and add them to the symbol table. Called after all files are @@ -77,53 +77,53 @@ std::vector compileBitcodeFiles(); // Creates an Undefined symbol for a given name. - Symbol *addUndefined(StringRef Name); + Symbol *addUndefined(StringRef name); - Symbol *addSynthetic(StringRef N, Chunk *C); - Symbol *addAbsolute(StringRef N, uint64_t VA); + Symbol *addSynthetic(StringRef n, Chunk *c); + Symbol *addAbsolute(StringRef n, uint64_t va); - Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias); - void addLazy(ArchiveFile *F, const Archive::Symbol Sym); - Symbol *addAbsolute(StringRef N, COFFSymbolRef S); - Symbol *addRegular(InputFile *F, StringRef N, - const llvm::object::coff_symbol_generic *S = nullptr, - SectionChunk *C = nullptr); + Symbol *addUndefined(StringRef name, InputFile *f, bool isWeakAlias); + void addLazy(ArchiveFile *f, const Archive::Symbol sym); + Symbol *addAbsolute(StringRef n, COFFSymbolRef s); + Symbol *addRegular(InputFile *f, StringRef n, + const llvm::object::coff_symbol_generic *s = nullptr, + SectionChunk *c = nullptr); std::pair - addComdat(InputFile *F, StringRef N, - const llvm::object::coff_symbol_generic *S = nullptr); - Symbol *addCommon(InputFile *F, StringRef N, uint64_t Size, - const llvm::object::coff_symbol_generic *S = nullptr, - CommonChunk *C = nullptr); - Symbol *addImportData(StringRef N, ImportFile *F); - Symbol *addImportThunk(StringRef Name, DefinedImportData *S, - uint16_t Machine); + addComdat(InputFile *f, StringRef n, + const llvm::object::coff_symbol_generic *s = nullptr); + Symbol *addCommon(InputFile *f, StringRef n, uint64_t size, + const llvm::object::coff_symbol_generic *s = nullptr, + CommonChunk *c = nullptr); + Symbol *addImportData(StringRef n, ImportFile *f); + Symbol *addImportThunk(StringRef name, DefinedImportData *s, + uint16_t machine); - void reportDuplicate(Symbol *Existing, InputFile *NewFile); + void reportDuplicate(Symbol *existing, InputFile *newFile); // A list of chunks which to be added to .rdata. - std::vector LocalImportChunks; + std::vector localImportChunks; // Iterates symbols in non-determinstic hash table order. - template void forEachSymbol(T Callback) { - for (auto &Pair : SymMap) - Callback(Pair.second); + template void forEachSymbol(T callback) { + for (auto &pair : symMap) + callback(pair.second); } private: /// Inserts symbol if not already present. - std::pair insert(StringRef Name); + std::pair insert(StringRef name); /// Same as insert(Name), but also sets IsUsedInRegularObj. - std::pair insert(StringRef Name, InputFile *F); + std::pair insert(StringRef name, InputFile *f); - std::vector getSymsWithPrefix(StringRef Prefix); + std::vector getSymsWithPrefix(StringRef prefix); - llvm::DenseMap SymMap; - std::unique_ptr LTO; + llvm::DenseMap symMap; + std::unique_ptr lto; }; -extern SymbolTable *Symtab; +extern SymbolTable *symtab; -std::vector getSymbolLocations(ObjFile *File, uint32_t SymIndex); +std::vector getSymbolLocations(ObjFile *file, uint32_t symIndex); } // namespace coff } // namespace lld Index: lld/trunk/COFF/SymbolTable.cpp =================================================================== --- lld/trunk/COFF/SymbolTable.cpp +++ lld/trunk/COFF/SymbolTable.cpp @@ -26,168 +26,168 @@ namespace lld { namespace coff { -static Timer LTOTimer("LTO", Timer::root()); +static Timer ltoTimer("LTO", Timer::root()); -SymbolTable *Symtab; +SymbolTable *symtab; -void SymbolTable::addFile(InputFile *File) { - log("Reading " + toString(File)); - File->parse(); - - MachineTypes MT = File->getMachineType(); - if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) { - Config->Machine = MT; - } else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) { - error(toString(File) + ": machine type " + machineToStr(MT) + - " conflicts with " + machineToStr(Config->Machine)); +void SymbolTable::addFile(InputFile *file) { + log("Reading " + toString(file)); + file->parse(); + + MachineTypes mt = file->getMachineType(); + if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) { + config->machine = mt; + } else if (mt != IMAGE_FILE_MACHINE_UNKNOWN && config->machine != mt) { + error(toString(file) + ": machine type " + machineToStr(mt) + + " conflicts with " + machineToStr(config->machine)); return; } - if (auto *F = dyn_cast(File)) { - ObjFile::Instances.push_back(F); - } else if (auto *F = dyn_cast(File)) { - BitcodeFile::Instances.push_back(F); - } else if (auto *F = dyn_cast(File)) { - ImportFile::Instances.push_back(F); + if (auto *f = dyn_cast(file)) { + ObjFile::instances.push_back(f); + } else if (auto *f = dyn_cast(file)) { + BitcodeFile::instances.push_back(f); + } else if (auto *f = dyn_cast(file)) { + ImportFile::instances.push_back(f); } - Driver->parseDirectives(File); + driver->parseDirectives(file); } -static void errorOrWarn(const Twine &S) { - if (Config->ForceUnresolved) - warn(S); +static void errorOrWarn(const Twine &s) { + if (config->forceUnresolved) + warn(s); else - error(S); + error(s); } // Returns the symbol in SC whose value is <= Addr that is closest to Addr. // This is generally the global variable or function whose definition contains // Addr. -static Symbol *getSymbol(SectionChunk *SC, uint32_t Addr) { - DefinedRegular *Candidate = nullptr; +static Symbol *getSymbol(SectionChunk *sc, uint32_t addr) { + DefinedRegular *candidate = nullptr; - for (Symbol *S : SC->File->getSymbols()) { - auto *D = dyn_cast_or_null(S); - if (!D || D->getChunk() != SC || D->getValue() > Addr || - (Candidate && D->getValue() < Candidate->getValue())) + for (Symbol *s : sc->file->getSymbols()) { + auto *d = dyn_cast_or_null(s); + if (!d || d->getChunk() != sc || d->getValue() > addr || + (candidate && d->getValue() < candidate->getValue())) continue; - Candidate = D; + candidate = d; } - return Candidate; + return candidate; } // Given a file and the index of a symbol in that file, returns a description // of all references to that symbol from that file. If no debug information is // available, returns just the name of the file, else one string per actual // reference as described in the debug info. -std::vector getSymbolLocations(ObjFile *File, uint32_t SymIndex) { +std::vector getSymbolLocations(ObjFile *file, uint32_t symIndex) { struct Location { - Symbol *Sym; - std::pair FileLine; + Symbol *sym; + std::pair fileLine; }; - std::vector Locations; + std::vector locations; - for (Chunk *C : File->getChunks()) { - auto *SC = dyn_cast(C); - if (!SC) + for (Chunk *c : file->getChunks()) { + auto *sc = dyn_cast(c); + if (!sc) continue; - for (const coff_relocation &R : SC->getRelocs()) { - if (R.SymbolTableIndex != SymIndex) + for (const coff_relocation &r : sc->getRelocs()) { + if (r.SymbolTableIndex != symIndex) continue; - std::pair FileLine = - getFileLine(SC, R.VirtualAddress); - Symbol *Sym = getSymbol(SC, R.VirtualAddress); - if (!FileLine.first.empty() || Sym) - Locations.push_back({Sym, FileLine}); + std::pair fileLine = + getFileLine(sc, r.VirtualAddress); + Symbol *sym = getSymbol(sc, r.VirtualAddress); + if (!fileLine.first.empty() || sym) + locations.push_back({sym, fileLine}); } } - if (Locations.empty()) - return std::vector({"\n>>> referenced by " + toString(File)}); + if (locations.empty()) + return std::vector({"\n>>> referenced by " + toString(file)}); - std::vector SymbolLocations(Locations.size()); - size_t I = 0; - for (Location Loc : Locations) { - llvm::raw_string_ostream OS(SymbolLocations[I++]); - OS << "\n>>> referenced by "; - if (!Loc.FileLine.first.empty()) - OS << Loc.FileLine.first << ":" << Loc.FileLine.second + std::vector symbolLocations(locations.size()); + size_t i = 0; + for (Location loc : locations) { + llvm::raw_string_ostream os(symbolLocations[i++]); + os << "\n>>> referenced by "; + if (!loc.fileLine.first.empty()) + os << loc.fileLine.first << ":" << loc.fileLine.second << "\n>>> "; - OS << toString(File); - if (Loc.Sym) - OS << ":(" << toString(*Loc.Sym) << ')'; + os << toString(file); + if (loc.sym) + os << ":(" << toString(*loc.sym) << ')'; } - return SymbolLocations; + return symbolLocations; } // For an undefined symbol, stores all files referencing it and the index of // the undefined symbol in each file. struct UndefinedDiag { - Symbol *Sym; + Symbol *sym; struct File { - ObjFile *OFile; - uint64_t SymIndex; + ObjFile *oFile; + uint64_t symIndex; }; - std::vector Files; + std::vector files; }; -static void reportUndefinedSymbol(const UndefinedDiag &UndefDiag) { - std::string Out; - llvm::raw_string_ostream OS(Out); - OS << "undefined symbol: " << toString(*UndefDiag.Sym); - - const size_t MaxUndefReferences = 10; - size_t I = 0, NumRefs = 0; - for (const UndefinedDiag::File &Ref : UndefDiag.Files) { - std::vector SymbolLocations = - getSymbolLocations(Ref.OFile, Ref.SymIndex); - NumRefs += SymbolLocations.size(); - for (const std::string &S : SymbolLocations) { - if (I >= MaxUndefReferences) +static void reportUndefinedSymbol(const UndefinedDiag &undefDiag) { + std::string out; + llvm::raw_string_ostream os(out); + os << "undefined symbol: " << toString(*undefDiag.sym); + + const size_t maxUndefReferences = 10; + size_t i = 0, numRefs = 0; + for (const UndefinedDiag::File &ref : undefDiag.files) { + std::vector symbolLocations = + getSymbolLocations(ref.oFile, ref.symIndex); + numRefs += symbolLocations.size(); + for (const std::string &s : symbolLocations) { + if (i >= maxUndefReferences) break; - OS << S; - I++; + os << s; + i++; } } - if (I < NumRefs) - OS << "\n>>> referenced " << NumRefs - I << " more times"; - errorOrWarn(OS.str()); + if (i < numRefs) + os << "\n>>> referenced " << numRefs - i << " more times"; + errorOrWarn(os.str()); } void SymbolTable::loadMinGWAutomaticImports() { - for (auto &I : SymMap) { - Symbol *Sym = I.second; - auto *Undef = dyn_cast(Sym); - if (!Undef) + for (auto &i : symMap) { + Symbol *sym = i.second; + auto *undef = dyn_cast(sym); + if (!undef) continue; - if (!Sym->IsUsedInRegularObj) + if (!sym->isUsedInRegularObj) continue; - StringRef Name = Undef->getName(); + StringRef name = undef->getName(); - if (Name.startswith("__imp_")) + if (name.startswith("__imp_")) continue; // If we have an undefined symbol, but we have a Lazy representing a // symbol we could load from file, make sure to load that. - Lazy *L = dyn_cast_or_null(find(("__imp_" + Name).str())); - if (!L || L->PendingArchiveLoad) + Lazy *l = dyn_cast_or_null(find(("__imp_" + name).str())); + if (!l || l->pendingArchiveLoad) continue; - log("Loading lazy " + L->getName() + " from " + L->File->getName() + + log("Loading lazy " + l->getName() + " from " + l->file->getName() + " for automatic import"); - L->PendingArchiveLoad = true; - L->File->addMember(&L->Sym); + l->pendingArchiveLoad = true; + l->file->addMember(&l->sym); } } -bool SymbolTable::handleMinGWAutomaticImport(Symbol *Sym, StringRef Name) { - if (Name.startswith("__imp_")) +bool SymbolTable::handleMinGWAutomaticImport(Symbol *sym, StringRef name) { + if (name.startswith("__imp_")) return false; - Defined *Imp = dyn_cast_or_null(find(("__imp_" + Name).str())); - if (!Imp) + Defined *imp = dyn_cast_or_null(find(("__imp_" + name).str())); + if (!imp) return false; // Replace the reference directly to a variable with a reference @@ -196,406 +196,406 @@ // will add runtime pseudo relocations for every relocation against // this Symbol. The runtime pseudo relocation framework expects the // reference itself to point at the IAT entry. - size_t ImpSize = 0; - if (isa(Imp)) { - log("Automatically importing " + Name + " from " + - cast(Imp)->getDLLName()); - ImpSize = sizeof(DefinedImportData); - } else if (isa(Imp)) { - log("Automatically importing " + Name + " from " + - toString(cast(Imp)->File)); - ImpSize = sizeof(DefinedRegular); + size_t impSize = 0; + if (isa(imp)) { + log("Automatically importing " + name + " from " + + cast(imp)->getDLLName()); + impSize = sizeof(DefinedImportData); + } else if (isa(imp)) { + log("Automatically importing " + name + " from " + + toString(cast(imp)->file)); + impSize = sizeof(DefinedRegular); } else { - warn("unable to automatically import " + Name + " from " + Imp->getName() + - " from " + toString(cast(Imp)->File) + + warn("unable to automatically import " + name + " from " + imp->getName() + + " from " + toString(cast(imp)->file) + "; unexpected symbol type"); return false; } - Sym->replaceKeepingName(Imp, ImpSize); - Sym->IsRuntimePseudoReloc = true; + sym->replaceKeepingName(imp, impSize); + sym->isRuntimePseudoReloc = true; // There may exist symbols named .refptr. which only consist // of a single pointer to . If it turns out is // automatically imported, we don't need to keep the .refptr. // pointer at all, but redirect all accesses to it to the IAT entry // for __imp_ instead, and drop the whole .refptr. chunk. - DefinedRegular *Refptr = - dyn_cast_or_null(find((".refptr." + Name).str())); - if (Refptr && Refptr->getChunk()->getSize() == Config->Wordsize) { - SectionChunk *SC = dyn_cast_or_null(Refptr->getChunk()); - if (SC && SC->getRelocs().size() == 1 && *SC->symbols().begin() == Sym) { - log("Replacing .refptr." + Name + " with " + Imp->getName()); - Refptr->getChunk()->Live = false; - Refptr->replaceKeepingName(Imp, ImpSize); + DefinedRegular *refptr = + dyn_cast_or_null(find((".refptr." + name).str())); + if (refptr && refptr->getChunk()->getSize() == config->wordsize) { + SectionChunk *sc = dyn_cast_or_null(refptr->getChunk()); + if (sc && sc->getRelocs().size() == 1 && *sc->symbols().begin() == sym) { + log("Replacing .refptr." + name + " with " + imp->getName()); + refptr->getChunk()->live = false; + refptr->replaceKeepingName(imp, impSize); } } return true; } void SymbolTable::reportRemainingUndefines() { - SmallPtrSet Undefs; - DenseMap LocalImports; + SmallPtrSet undefs; + DenseMap localImports; - for (auto &I : SymMap) { - Symbol *Sym = I.second; - auto *Undef = dyn_cast(Sym); - if (!Undef) + for (auto &i : symMap) { + Symbol *sym = i.second; + auto *undef = dyn_cast(sym); + if (!undef) continue; - if (!Sym->IsUsedInRegularObj) + if (!sym->isUsedInRegularObj) continue; - StringRef Name = Undef->getName(); + StringRef name = undef->getName(); // A weak alias may have been resolved, so check for that. - if (Defined *D = Undef->getWeakAlias()) { + if (Defined *d = undef->getWeakAlias()) { // We want to replace Sym with D. However, we can't just blindly // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an // internal symbol, and internal symbols are stored as "unparented" // Symbols. For that reason we need to check which type of symbol we // are dealing with and copy the correct number of bytes. - if (isa(D)) - memcpy(Sym, D, sizeof(DefinedRegular)); - else if (isa(D)) - memcpy(Sym, D, sizeof(DefinedAbsolute)); + if (isa(d)) + memcpy(sym, d, sizeof(DefinedRegular)); + else if (isa(d)) + memcpy(sym, d, sizeof(DefinedAbsolute)); else - memcpy(Sym, D, sizeof(SymbolUnion)); + memcpy(sym, d, sizeof(SymbolUnion)); continue; } // If we can resolve a symbol by removing __imp_ prefix, do that. // This odd rule is for compatibility with MSVC linker. - if (Name.startswith("__imp_")) { - Symbol *Imp = find(Name.substr(strlen("__imp_"))); - if (Imp && isa(Imp)) { - auto *D = cast(Imp); - replaceSymbol(Sym, Name, D); - LocalImportChunks.push_back(cast(Sym)->getChunk()); - LocalImports[Sym] = D; + if (name.startswith("__imp_")) { + Symbol *imp = find(name.substr(strlen("__imp_"))); + if (imp && isa(imp)) { + auto *d = cast(imp); + replaceSymbol(sym, name, d); + localImportChunks.push_back(cast(sym)->getChunk()); + localImports[sym] = d; continue; } } // We don't want to report missing Microsoft precompiled headers symbols. // A proper message will be emitted instead in PDBLinker::aquirePrecompObj - if (Name.contains("_PchSym_")) + if (name.contains("_PchSym_")) continue; - if (Config->MinGW && handleMinGWAutomaticImport(Sym, Name)) + if (config->mingw && handleMinGWAutomaticImport(sym, name)) continue; // Remaining undefined symbols are not fatal if /force is specified. // They are replaced with dummy defined symbols. - if (Config->ForceUnresolved) - replaceSymbol(Sym, Name, 0); - Undefs.insert(Sym); + if (config->forceUnresolved) + replaceSymbol(sym, name, 0); + undefs.insert(sym); } - if (Undefs.empty() && LocalImports.empty()) + if (undefs.empty() && localImports.empty()) return; - for (Symbol *B : Config->GCRoot) { - if (Undefs.count(B)) - errorOrWarn(": undefined symbol: " + toString(*B)); - if (Config->WarnLocallyDefinedImported) - if (Symbol *Imp = LocalImports.lookup(B)) - warn(": locally defined symbol imported: " + toString(*Imp) + - " (defined in " + toString(Imp->getFile()) + ") [LNK4217]"); - } - - std::vector UndefDiags; - DenseMap FirstDiag; - - for (ObjFile *File : ObjFile::Instances) { - size_t SymIndex = (size_t)-1; - for (Symbol *Sym : File->getSymbols()) { - ++SymIndex; - if (!Sym) + for (Symbol *b : config->gCRoot) { + if (undefs.count(b)) + errorOrWarn(": undefined symbol: " + toString(*b)); + if (config->warnLocallyDefinedImported) + if (Symbol *imp = localImports.lookup(b)) + warn(": locally defined symbol imported: " + toString(*imp) + + " (defined in " + toString(imp->getFile()) + ") [LNK4217]"); + } + + std::vector undefDiags; + DenseMap firstDiag; + + for (ObjFile *file : ObjFile::instances) { + size_t symIndex = (size_t)-1; + for (Symbol *sym : file->getSymbols()) { + ++symIndex; + if (!sym) continue; - if (Undefs.count(Sym)) { - auto it = FirstDiag.find(Sym); - if (it == FirstDiag.end()) { - FirstDiag[Sym] = UndefDiags.size(); - UndefDiags.push_back({Sym, {{File, SymIndex}}}); + if (undefs.count(sym)) { + auto it = firstDiag.find(sym); + if (it == firstDiag.end()) { + firstDiag[sym] = undefDiags.size(); + undefDiags.push_back({sym, {{file, symIndex}}}); } else { - UndefDiags[it->second].Files.push_back({File, SymIndex}); + undefDiags[it->second].files.push_back({file, symIndex}); } } - if (Config->WarnLocallyDefinedImported) - if (Symbol *Imp = LocalImports.lookup(Sym)) - warn(toString(File) + - ": locally defined symbol imported: " + toString(*Imp) + - " (defined in " + toString(Imp->getFile()) + ") [LNK4217]"); + if (config->warnLocallyDefinedImported) + if (Symbol *imp = localImports.lookup(sym)) + warn(toString(file) + + ": locally defined symbol imported: " + toString(*imp) + + " (defined in " + toString(imp->getFile()) + ") [LNK4217]"); } } - for (const UndefinedDiag& UndefDiag : UndefDiags) - reportUndefinedSymbol(UndefDiag); + for (const UndefinedDiag& undefDiag : undefDiags) + reportUndefinedSymbol(undefDiag); } -std::pair SymbolTable::insert(StringRef Name) { - bool Inserted = false; - Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; - if (!Sym) { - Sym = reinterpret_cast(make()); - Sym->IsUsedInRegularObj = false; - Sym->PendingArchiveLoad = false; - Inserted = true; - } - return {Sym, Inserted}; -} - -std::pair SymbolTable::insert(StringRef Name, InputFile *File) { - std::pair Result = insert(Name); - if (!File || !isa(File)) - Result.first->IsUsedInRegularObj = true; - return Result; -} - -Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F, - bool IsWeakAlias) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, F); - if (WasInserted || (isa(S) && IsWeakAlias)) { - replaceSymbol(S, Name); - return S; - } - if (auto *L = dyn_cast(S)) { - if (!S->PendingArchiveLoad) { - S->PendingArchiveLoad = true; - L->File->addMember(&L->Sym); +std::pair SymbolTable::insert(StringRef name) { + bool inserted = false; + Symbol *&sym = symMap[CachedHashStringRef(name)]; + if (!sym) { + sym = reinterpret_cast(make()); + sym->isUsedInRegularObj = false; + sym->pendingArchiveLoad = false; + inserted = true; + } + return {sym, inserted}; +} + +std::pair SymbolTable::insert(StringRef name, InputFile *file) { + std::pair result = insert(name); + if (!file || !isa(file)) + result.first->isUsedInRegularObj = true; + return result; +} + +Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f, + bool isWeakAlias) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, f); + if (wasInserted || (isa(s) && isWeakAlias)) { + replaceSymbol(s, name); + return s; + } + if (auto *l = dyn_cast(s)) { + if (!s->pendingArchiveLoad) { + s->pendingArchiveLoad = true; + l->file->addMember(&l->sym); } } - return S; + return s; } -void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) { - StringRef Name = Sym.getName(); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name); - if (WasInserted) { - replaceSymbol(S, F, Sym); +void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol sym) { + StringRef name = sym.getName(); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name); + if (wasInserted) { + replaceSymbol(s, f, sym); return; } - auto *U = dyn_cast(S); - if (!U || U->WeakAlias || S->PendingArchiveLoad) + auto *u = dyn_cast(s); + if (!u || u->weakAlias || s->pendingArchiveLoad) return; - S->PendingArchiveLoad = true; - F->addMember(&Sym); + s->pendingArchiveLoad = true; + f->addMember(&sym); } -void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { - std::string Msg = "duplicate symbol: " + toString(*Existing) + " in " + - toString(Existing->getFile()) + " and in " + - toString(NewFile); +void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile) { + std::string msg = "duplicate symbol: " + toString(*existing) + " in " + + toString(existing->getFile()) + " and in " + + toString(newFile); - if (Config->ForceMultiple) - warn(Msg); + if (config->forceMultiple) + warn(msg); else - error(Msg); + error(msg); } -Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, nullptr); - S->IsUsedInRegularObj = true; - if (WasInserted || isa(S) || isa(S)) - replaceSymbol(S, N, Sym); - else if (!isa(S)) - reportDuplicate(S, nullptr); - return S; -} - -Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, nullptr); - S->IsUsedInRegularObj = true; - if (WasInserted || isa(S) || isa(S)) - replaceSymbol(S, N, VA); - else if (!isa(S)) - reportDuplicate(S, nullptr); - return S; -} - -Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, nullptr); - S->IsUsedInRegularObj = true; - if (WasInserted || isa(S) || isa(S)) - replaceSymbol(S, N, C); - else if (!isa(S)) - reportDuplicate(S, nullptr); - return S; -} - -Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, - const coff_symbol_generic *Sym, - SectionChunk *C) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, F); - if (WasInserted || !isa(S)) - replaceSymbol(S, F, N, /*IsCOMDAT*/ false, - /*IsExternal*/ true, Sym, C); +Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, nullptr); + s->isUsedInRegularObj = true; + if (wasInserted || isa(s) || isa(s)) + replaceSymbol(s, n, sym); + else if (!isa(s)) + reportDuplicate(s, nullptr); + return s; +} + +Symbol *SymbolTable::addAbsolute(StringRef n, uint64_t va) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, nullptr); + s->isUsedInRegularObj = true; + if (wasInserted || isa(s) || isa(s)) + replaceSymbol(s, n, va); + else if (!isa(s)) + reportDuplicate(s, nullptr); + return s; +} + +Symbol *SymbolTable::addSynthetic(StringRef n, Chunk *c) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, nullptr); + s->isUsedInRegularObj = true; + if (wasInserted || isa(s) || isa(s)) + replaceSymbol(s, n, c); + else if (!isa(s)) + reportDuplicate(s, nullptr); + return s; +} + +Symbol *SymbolTable::addRegular(InputFile *f, StringRef n, + const coff_symbol_generic *sym, + SectionChunk *c) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, f); + if (wasInserted || !isa(s)) + replaceSymbol(s, f, n, /*IsCOMDAT*/ false, + /*IsExternal*/ true, sym, c); else - reportDuplicate(S, F); - return S; + reportDuplicate(s, f); + return s; } std::pair -SymbolTable::addComdat(InputFile *F, StringRef N, - const coff_symbol_generic *Sym) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, F); - if (WasInserted || !isa(S)) { - replaceSymbol(S, F, N, /*IsCOMDAT*/ true, - /*IsExternal*/ true, Sym, nullptr); - return {cast(S), true}; - } - auto *ExistingSymbol = cast(S); - if (!ExistingSymbol->IsCOMDAT) - reportDuplicate(S, F); - return {ExistingSymbol, false}; -} - -Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, - const coff_symbol_generic *Sym, CommonChunk *C) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, F); - if (WasInserted || !isa(S)) - replaceSymbol(S, F, N, Size, Sym, C); - else if (auto *DC = dyn_cast(S)) - if (Size > DC->getSize()) - replaceSymbol(S, F, N, Size, Sym, C); - return S; -} - -Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(N, nullptr); - S->IsUsedInRegularObj = true; - if (WasInserted || isa(S) || isa(S)) { - replaceSymbol(S, N, F); - return S; +SymbolTable::addComdat(InputFile *f, StringRef n, + const coff_symbol_generic *sym) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, f); + if (wasInserted || !isa(s)) { + replaceSymbol(s, f, n, /*IsCOMDAT*/ true, + /*IsExternal*/ true, sym, nullptr); + return {cast(s), true}; + } + auto *existingSymbol = cast(s); + if (!existingSymbol->isCOMDAT) + reportDuplicate(s, f); + return {existingSymbol, false}; +} + +Symbol *SymbolTable::addCommon(InputFile *f, StringRef n, uint64_t size, + const coff_symbol_generic *sym, CommonChunk *c) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, f); + if (wasInserted || !isa(s)) + replaceSymbol(s, f, n, size, sym, c); + else if (auto *dc = dyn_cast(s)) + if (size > dc->getSize()) + replaceSymbol(s, f, n, size, sym, c); + return s; +} + +Symbol *SymbolTable::addImportData(StringRef n, ImportFile *f) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(n, nullptr); + s->isUsedInRegularObj = true; + if (wasInserted || isa(s) || isa(s)) { + replaceSymbol(s, n, f); + return s; } - reportDuplicate(S, F); + reportDuplicate(s, f); return nullptr; } -Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID, - uint16_t Machine) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, nullptr); - S->IsUsedInRegularObj = true; - if (WasInserted || isa(S) || isa(S)) { - replaceSymbol(S, Name, ID, Machine); - return S; +Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id, + uint16_t machine) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, nullptr); + s->isUsedInRegularObj = true; + if (wasInserted || isa(s) || isa(s)) { + replaceSymbol(s, name, id, machine); + return s; } - reportDuplicate(S, ID->File); + reportDuplicate(s, id->file); return nullptr; } std::vector SymbolTable::getChunks() { - std::vector Res; - for (ObjFile *File : ObjFile::Instances) { - ArrayRef V = File->getChunks(); - Res.insert(Res.end(), V.begin(), V.end()); + std::vector res; + for (ObjFile *file : ObjFile::instances) { + ArrayRef v = file->getChunks(); + res.insert(res.end(), v.begin(), v.end()); } - return Res; + return res; } -Symbol *SymbolTable::find(StringRef Name) { - return SymMap.lookup(CachedHashStringRef(Name)); +Symbol *SymbolTable::find(StringRef name) { + return symMap.lookup(CachedHashStringRef(name)); } -Symbol *SymbolTable::findUnderscore(StringRef Name) { - if (Config->Machine == I386) - return find(("_" + Name).str()); - return find(Name); +Symbol *SymbolTable::findUnderscore(StringRef name) { + if (config->machine == I386) + return find(("_" + name).str()); + return find(name); } // Return all symbols that start with Prefix, possibly ignoring the first // character of Prefix or the first character symbol. -std::vector SymbolTable::getSymsWithPrefix(StringRef Prefix) { - std::vector Syms; - for (auto Pair : SymMap) { - StringRef Name = Pair.first.val(); - if (Name.startswith(Prefix) || Name.startswith(Prefix.drop_front()) || - Name.drop_front().startswith(Prefix) || - Name.drop_front().startswith(Prefix.drop_front())) { - Syms.push_back(Pair.second); +std::vector SymbolTable::getSymsWithPrefix(StringRef prefix) { + std::vector syms; + for (auto pair : symMap) { + StringRef name = pair.first.val(); + if (name.startswith(prefix) || name.startswith(prefix.drop_front()) || + name.drop_front().startswith(prefix) || + name.drop_front().startswith(prefix.drop_front())) { + syms.push_back(pair.second); } } - return Syms; + return syms; } -Symbol *SymbolTable::findMangle(StringRef Name) { - if (Symbol *Sym = find(Name)) - if (!isa(Sym)) - return Sym; +Symbol *SymbolTable::findMangle(StringRef name) { + if (Symbol *sym = find(name)) + if (!isa(sym)) + return sym; // Efficient fuzzy string lookup is impossible with a hash table, so iterate // the symbol table once and collect all possibly matching symbols into this // vector. Then compare each possibly matching symbol with each possible // mangling. - std::vector Syms = getSymsWithPrefix(Name); - auto FindByPrefix = [&Syms](const Twine &T) -> Symbol * { - std::string Prefix = T.str(); - for (auto *S : Syms) - if (S->getName().startswith(Prefix)) - return S; + std::vector syms = getSymsWithPrefix(name); + auto findByPrefix = [&syms](const Twine &t) -> Symbol * { + std::string prefix = t.str(); + for (auto *s : syms) + if (s->getName().startswith(prefix)) + return s; return nullptr; }; // For non-x86, just look for C++ functions. - if (Config->Machine != I386) - return FindByPrefix("?" + Name + "@@Y"); + if (config->machine != I386) + return findByPrefix("?" + name + "@@Y"); - if (!Name.startswith("_")) + if (!name.startswith("_")) return nullptr; // Search for x86 stdcall function. - if (Symbol *S = FindByPrefix(Name + "@")) - return S; + if (Symbol *s = findByPrefix(name + "@")) + return s; // Search for x86 fastcall function. - if (Symbol *S = FindByPrefix("@" + Name.substr(1) + "@")) - return S; + if (Symbol *s = findByPrefix("@" + name.substr(1) + "@")) + return s; // Search for x86 vectorcall function. - if (Symbol *S = FindByPrefix(Name.substr(1) + "@@")) - return S; + if (Symbol *s = findByPrefix(name.substr(1) + "@@")) + return s; // Search for x86 C++ non-member function. - return FindByPrefix("?" + Name.substr(1) + "@@Y"); + return findByPrefix("?" + name.substr(1) + "@@Y"); } -Symbol *SymbolTable::addUndefined(StringRef Name) { - return addUndefined(Name, nullptr, false); +Symbol *SymbolTable::addUndefined(StringRef name) { + return addUndefined(name, nullptr, false); } std::vector SymbolTable::compileBitcodeFiles() { - LTO.reset(new BitcodeCompiler); - for (BitcodeFile *F : BitcodeFile::Instances) - LTO->add(*F); - return LTO->compile(); + lto.reset(new BitcodeCompiler); + for (BitcodeFile *f : BitcodeFile::instances) + lto->add(*f); + return lto->compile(); } void SymbolTable::addCombinedLTOObjects() { - if (BitcodeFile::Instances.empty()) + if (BitcodeFile::instances.empty()) return; - ScopedTimer T(LTOTimer); - for (StringRef Object : compileBitcodeFiles()) { - auto *Obj = make(MemoryBufferRef(Object, "lto.tmp")); - Obj->parse(); - ObjFile::Instances.push_back(Obj); + ScopedTimer t(ltoTimer); + for (StringRef object : compileBitcodeFiles()) { + auto *obj = make(MemoryBufferRef(object, "lto.tmp")); + obj->parse(); + ObjFile::instances.push_back(obj); } } Index: lld/trunk/COFF/Symbols.h =================================================================== --- lld/trunk/COFF/Symbols.h +++ lld/trunk/COFF/Symbols.h @@ -57,12 +57,12 @@ LastDefinedKind = DefinedSyntheticKind, }; - Kind kind() const { return static_cast(SymbolKind); } + Kind kind() const { return static_cast(symbolKind); } // Returns the symbol name. StringRef getName(); - void replaceKeepingName(Symbol *Other, size_t Size); + void replaceKeepingName(Symbol *other, size_t size); // Returns the file from which this symbol was created. InputFile *getFile(); @@ -73,50 +73,50 @@ protected: friend SymbolTable; - explicit Symbol(Kind K, StringRef N = "") - : SymbolKind(K), IsExternal(true), IsCOMDAT(false), - WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false), - IsRuntimePseudoReloc(false), NameSize(N.size()), - NameData(N.empty() ? nullptr : N.data()) {} + explicit Symbol(Kind k, StringRef n = "") + : symbolKind(k), isExternal(true), isCOMDAT(false), + writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false), + isRuntimePseudoReloc(false), nameSize(n.size()), + nameData(n.empty() ? nullptr : n.data()) {} - const unsigned SymbolKind : 8; - unsigned IsExternal : 1; + const unsigned symbolKind : 8; + unsigned isExternal : 1; public: // This bit is used by the \c DefinedRegular subclass. - unsigned IsCOMDAT : 1; + unsigned isCOMDAT : 1; // This bit is used by Writer::createSymbolAndStringTable() to prevent // symbols from being written to the symbol table more than once. - unsigned WrittenToSymtab : 1; + unsigned writtenToSymtab : 1; // True if this symbol was referenced by a regular (non-bitcode) object. - unsigned IsUsedInRegularObj : 1; + unsigned isUsedInRegularObj : 1; // True if we've seen both a lazy and an undefined symbol with this symbol // name, which means that we have enqueued an archive member load and should // not load any more archive members to resolve the same symbol. - unsigned PendingArchiveLoad : 1; + unsigned pendingArchiveLoad : 1; /// True if we've already added this symbol to the list of GC roots. - unsigned IsGCRoot : 1; + unsigned isGCRoot : 1; - unsigned IsRuntimePseudoReloc : 1; + unsigned isRuntimePseudoReloc : 1; protected: // Symbol name length. Assume symbol lengths fit in a 32-bit integer. - uint32_t NameSize; + uint32_t nameSize; - const char *NameData; + const char *nameData; }; // The base class for any defined symbols, including absolute symbols, // etc. class Defined : public Symbol { public: - Defined(Kind K, StringRef N) : Symbol(K, N) {} + Defined(Kind k, StringRef n) : Symbol(k, n) {} - static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; } + static bool classof(const Symbol *s) { return s->kind() <= LastDefinedKind; } // Returns the RVA (relative virtual address) of this symbol. The // writer sets and uses RVAs. @@ -135,114 +135,114 @@ friend Symbol; public: - DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S) - : Defined(K, N), File(F), Sym(S) {} + DefinedCOFF(Kind k, InputFile *f, StringRef n, const coff_symbol_generic *s) + : Defined(k, n), file(f), sym(s) {} - static bool classof(const Symbol *S) { - return S->kind() <= LastDefinedCOFFKind; + static bool classof(const Symbol *s) { + return s->kind() <= LastDefinedCOFFKind; } - InputFile *getFile() { return File; } + InputFile *getFile() { return file; } COFFSymbolRef getCOFFSymbol(); - InputFile *File; + InputFile *file; protected: - const coff_symbol_generic *Sym; + const coff_symbol_generic *sym; }; // Regular defined symbols read from object file symbol tables. class DefinedRegular : public DefinedCOFF { public: - DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT, - bool IsExternal = false, - const coff_symbol_generic *S = nullptr, - SectionChunk *C = nullptr) - : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) { - this->IsExternal = IsExternal; - this->IsCOMDAT = IsCOMDAT; + DefinedRegular(InputFile *f, StringRef n, bool isCOMDAT, + bool isExternal = false, + const coff_symbol_generic *s = nullptr, + SectionChunk *c = nullptr) + : DefinedCOFF(DefinedRegularKind, f, n, s), data(c ? &c->repl : nullptr) { + this->isExternal = isExternal; + this->isCOMDAT = isCOMDAT; } - static bool classof(const Symbol *S) { - return S->kind() == DefinedRegularKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedRegularKind; } - uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; } - SectionChunk *getChunk() const { return *Data; } - uint32_t getValue() const { return Sym->Value; } + uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; } + SectionChunk *getChunk() const { return *data; } + uint32_t getValue() const { return sym->Value; } - SectionChunk **Data; + SectionChunk **data; }; class DefinedCommon : public DefinedCOFF { public: - DefinedCommon(InputFile *F, StringRef N, uint64_t Size, - const coff_symbol_generic *S = nullptr, - CommonChunk *C = nullptr) - : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) { - this->IsExternal = true; + DefinedCommon(InputFile *f, StringRef n, uint64_t size, + const coff_symbol_generic *s = nullptr, + CommonChunk *c = nullptr) + : DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) { + this->isExternal = true; } - static bool classof(const Symbol *S) { - return S->kind() == DefinedCommonKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedCommonKind; } - uint64_t getRVA() { return Data->getRVA(); } - CommonChunk *getChunk() { return Data; } + uint64_t getRVA() { return data->getRVA(); } + CommonChunk *getChunk() { return data; } private: friend SymbolTable; - uint64_t getSize() const { return Size; } - CommonChunk *Data; - uint64_t Size; + uint64_t getSize() const { return size; } + CommonChunk *data; + uint64_t size; }; // Absolute symbols. class DefinedAbsolute : public Defined { public: - DefinedAbsolute(StringRef N, COFFSymbolRef S) - : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) { - IsExternal = S.isExternal(); + DefinedAbsolute(StringRef n, COFFSymbolRef s) + : Defined(DefinedAbsoluteKind, n), va(s.getValue()) { + isExternal = s.isExternal(); } - DefinedAbsolute(StringRef N, uint64_t V) - : Defined(DefinedAbsoluteKind, N), VA(V) {} + DefinedAbsolute(StringRef n, uint64_t v) + : Defined(DefinedAbsoluteKind, n), va(v) {} - static bool classof(const Symbol *S) { - return S->kind() == DefinedAbsoluteKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedAbsoluteKind; } - uint64_t getRVA() { return VA - Config->ImageBase; } - void setVA(uint64_t V) { VA = V; } + uint64_t getRVA() { return va - config->imageBase; } + void setVA(uint64_t v) { va = v; } // Section index relocations against absolute symbols resolve to // this 16 bit number, and it is the largest valid section index // plus one. This variable keeps it. - static uint16_t NumOutputSections; + static uint16_t numOutputSections; private: - uint64_t VA; + uint64_t va; }; // This symbol is used for linker-synthesized symbols like __ImageBase and // __safe_se_handler_table. class DefinedSynthetic : public Defined { public: - explicit DefinedSynthetic(StringRef Name, Chunk *C) - : Defined(DefinedSyntheticKind, Name), C(C) {} + explicit DefinedSynthetic(StringRef name, Chunk *c) + : Defined(DefinedSyntheticKind, name), c(c) {} - static bool classof(const Symbol *S) { - return S->kind() == DefinedSyntheticKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedSyntheticKind; } // A null chunk indicates that this is __ImageBase. Otherwise, this is some // other synthesized chunk, like SEHTableChunk. - uint32_t getRVA() { return C ? C->getRVA() : 0; } - Chunk *getChunk() { return C; } + uint32_t getRVA() { return c ? c->getRVA() : 0; } + Chunk *getChunk() { return c; } private: - Chunk *C; + Chunk *c; }; // This class represents a symbol defined in an archive file. It is @@ -252,32 +252,32 @@ // the same name, it will ask the Lazy to load a file. class Lazy : public Symbol { public: - Lazy(ArchiveFile *F, const Archive::Symbol S) - : Symbol(LazyKind, S.getName()), File(F), Sym(S) {} + Lazy(ArchiveFile *f, const Archive::Symbol s) + : Symbol(LazyKind, s.getName()), file(f), sym(s) {} - static bool classof(const Symbol *S) { return S->kind() == LazyKind; } + static bool classof(const Symbol *s) { return s->kind() == LazyKind; } - ArchiveFile *File; + ArchiveFile *file; private: friend SymbolTable; private: - const Archive::Symbol Sym; + const Archive::Symbol sym; }; // Undefined symbols. class Undefined : public Symbol { public: - explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {} + explicit Undefined(StringRef n) : Symbol(UndefinedKind, n) {} - static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } + static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; } // An undefined symbol can have a fallback symbol which gives an // undefined symbol a second chance if it would remain undefined. // If it remains undefined, it'll be replaced with whatever the // Alias pointer points to. - Symbol *WeakAlias = nullptr; + Symbol *weakAlias = nullptr; // If this symbol is external weak, try to resolve it to a defined // symbol by searching the chain of fallback symbols. Returns the symbol if @@ -293,23 +293,23 @@ // table in an output. The former has "__imp_" prefix. class DefinedImportData : public Defined { public: - DefinedImportData(StringRef N, ImportFile *F) - : Defined(DefinedImportDataKind, N), File(F) { + DefinedImportData(StringRef n, ImportFile *f) + : Defined(DefinedImportDataKind, n), file(f) { } - static bool classof(const Symbol *S) { - return S->kind() == DefinedImportDataKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedImportDataKind; } - uint64_t getRVA() { return File->Location->getRVA(); } - Chunk *getChunk() { return File->Location; } - void setLocation(Chunk *AddressTable) { File->Location = AddressTable; } + uint64_t getRVA() { return file->location->getRVA(); } + Chunk *getChunk() { return file->location; } + void setLocation(Chunk *addressTable) { file->location = addressTable; } - StringRef getDLLName() { return File->DLLName; } - StringRef getExternalName() { return File->ExternalName; } - uint16_t getOrdinal() { return File->Hdr->OrdinalHint; } + StringRef getDLLName() { return file->dllName; } + StringRef getExternalName() { return file->externalName; } + uint16_t getOrdinal() { return file->hdr->OrdinalHint; } - ImportFile *File; + ImportFile *file; }; // This class represents a symbol for a jump table entry which jumps @@ -319,19 +319,19 @@ // a regular name. A function pointer is given as a DefinedImportData. class DefinedImportThunk : public Defined { public: - DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); + DefinedImportThunk(StringRef name, DefinedImportData *s, uint16_t machine); - static bool classof(const Symbol *S) { - return S->kind() == DefinedImportThunkKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedImportThunkKind; } - uint64_t getRVA() { return Data->getRVA(); } - Chunk *getChunk() { return Data; } + uint64_t getRVA() { return data->getRVA(); } + Chunk *getChunk() { return data; } - DefinedImportData *WrappedSym; + DefinedImportData *wrappedSym; private: - Chunk *Data; + Chunk *data; }; // If you have a symbol "foo" in your object file, a symbol name @@ -341,18 +341,18 @@ // This is here just for compatibility with MSVC. class DefinedLocalImport : public Defined { public: - DefinedLocalImport(StringRef N, Defined *S) - : Defined(DefinedLocalImportKind, N), Data(make(S)) {} + DefinedLocalImport(StringRef n, Defined *s) + : Defined(DefinedLocalImportKind, n), data(make(s)) {} - static bool classof(const Symbol *S) { - return S->kind() == DefinedLocalImportKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedLocalImportKind; } - uint64_t getRVA() { return Data->getRVA(); } - Chunk *getChunk() { return Data; } + uint64_t getRVA() { return data->getRVA(); } + Chunk *getChunk() { return data; } private: - LocalImportChunk *Data; + LocalImportChunk *data; }; inline uint64_t Defined::getRVA() { @@ -405,19 +405,19 @@ // object. We allocate memory using this class and instantiate a symbol // using the placement new. union SymbolUnion { - alignas(DefinedRegular) char A[sizeof(DefinedRegular)]; - alignas(DefinedCommon) char B[sizeof(DefinedCommon)]; - alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)]; - alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)]; - alignas(Lazy) char E[sizeof(Lazy)]; - alignas(Undefined) char F[sizeof(Undefined)]; - alignas(DefinedImportData) char G[sizeof(DefinedImportData)]; - alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)]; - alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)]; + alignas(DefinedRegular) char a[sizeof(DefinedRegular)]; + alignas(DefinedCommon) char b[sizeof(DefinedCommon)]; + alignas(DefinedAbsolute) char c[sizeof(DefinedAbsolute)]; + alignas(DefinedSynthetic) char d[sizeof(DefinedSynthetic)]; + alignas(Lazy) char e[sizeof(Lazy)]; + alignas(Undefined) char f[sizeof(Undefined)]; + alignas(DefinedImportData) char g[sizeof(DefinedImportData)]; + alignas(DefinedImportThunk) char h[sizeof(DefinedImportThunk)]; + alignas(DefinedLocalImport) char i[sizeof(DefinedLocalImport)]; }; template -void replaceSymbol(Symbol *S, ArgT &&... Arg) { +void replaceSymbol(Symbol *s, ArgT &&... arg) { static_assert(std::is_trivially_destructible(), "Symbol types must be trivially destructible"); static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small"); @@ -425,11 +425,11 @@ "SymbolUnion not aligned enough"); assert(static_cast(static_cast(nullptr)) == nullptr && "Not a Symbol"); - new (S) T(std::forward(Arg)...); + new (s) T(std::forward(arg)...); } } // namespace coff -std::string toString(coff::Symbol &B); +std::string toString(coff::Symbol &b); } // namespace lld #endif Index: lld/trunk/COFF/Symbols.cpp =================================================================== --- lld/trunk/COFF/Symbols.cpp +++ lld/trunk/COFF/Symbols.cpp @@ -24,11 +24,11 @@ "symbols should be optimized for memory usage"); // Returns a symbol name for an error message. -std::string lld::toString(coff::Symbol &B) { - if (Config->Demangle) - if (Optional S = lld::demangleMSVC(B.getName())) - return *S; - return B.getName(); +std::string lld::toString(coff::Symbol &b) { + if (config->demangle) + if (Optional s = lld::demangleMSVC(b.getName())) + return *s; + return b.getName(); } namespace lld { @@ -42,75 +42,75 @@ // name. Object files contain lots of non-external symbols, and creating // StringRefs for them (which involves lots of strlen() on the string table) // is a waste of time. - if (NameData == nullptr) { - auto *D = cast(this); - StringRef NameStr; - cast(D->File)->getCOFFObj()->getSymbolName(D->Sym, NameStr); - NameData = NameStr.data(); - NameSize = NameStr.size(); - assert(NameSize == NameStr.size() && "name length truncated"); + if (nameData == nullptr) { + auto *d = cast(this); + StringRef nameStr; + cast(d->file)->getCOFFObj()->getSymbolName(d->sym, nameStr); + nameData = nameStr.data(); + nameSize = nameStr.size(); + assert(nameSize == nameStr.size() && "name length truncated"); } - return StringRef(NameData, NameSize); + return StringRef(nameData, nameSize); } InputFile *Symbol::getFile() { - if (auto *Sym = dyn_cast(this)) - return Sym->File; - if (auto *Sym = dyn_cast(this)) - return Sym->File; + if (auto *sym = dyn_cast(this)) + return sym->file; + if (auto *sym = dyn_cast(this)) + return sym->file; return nullptr; } bool Symbol::isLive() const { - if (auto *R = dyn_cast(this)) - return R->getChunk()->Live; - if (auto *Imp = dyn_cast(this)) - return Imp->File->Live; - if (auto *Imp = dyn_cast(this)) - return Imp->WrappedSym->File->ThunkLive; + if (auto *r = dyn_cast(this)) + return r->getChunk()->live; + if (auto *imp = dyn_cast(this)) + return imp->file->live; + if (auto *imp = dyn_cast(this)) + return imp->wrappedSym->file->thunkLive; // Assume any other kind of symbol is live. return true; } // MinGW specific. -void Symbol::replaceKeepingName(Symbol *Other, size_t Size) { - StringRef OrigName = getName(); - memcpy(this, Other, Size); - NameData = OrigName.data(); - NameSize = OrigName.size(); +void Symbol::replaceKeepingName(Symbol *other, size_t size) { + StringRef origName = getName(); + memcpy(this, other, size); + nameData = origName.data(); + nameSize = origName.size(); } COFFSymbolRef DefinedCOFF::getCOFFSymbol() { - size_t SymSize = cast(File)->getCOFFObj()->getSymbolTableEntrySize(); - if (SymSize == sizeof(coff_symbol16)) - return COFFSymbolRef(reinterpret_cast(Sym)); - assert(SymSize == sizeof(coff_symbol32)); - return COFFSymbolRef(reinterpret_cast(Sym)); -} - -uint16_t DefinedAbsolute::NumOutputSections; - -static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) { - if (Machine == AMD64) - return make(S); - if (Machine == I386) - return make(S); - if (Machine == ARM64) - return make(S); - assert(Machine == ARMNT); - return make(S); -} - -DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S, - uint16_t Machine) - : Defined(DefinedImportThunkKind, Name), WrappedSym(S), - Data(makeImportThunk(S, Machine)) {} + size_t symSize = cast(file)->getCOFFObj()->getSymbolTableEntrySize(); + if (symSize == sizeof(coff_symbol16)) + return COFFSymbolRef(reinterpret_cast(sym)); + assert(symSize == sizeof(coff_symbol32)); + return COFFSymbolRef(reinterpret_cast(sym)); +} + +uint16_t DefinedAbsolute::numOutputSections; + +static Chunk *makeImportThunk(DefinedImportData *s, uint16_t machine) { + if (machine == AMD64) + return make(s); + if (machine == I386) + return make(s); + if (machine == ARM64) + return make(s); + assert(machine == ARMNT); + return make(s); +} + +DefinedImportThunk::DefinedImportThunk(StringRef name, DefinedImportData *s, + uint16_t machine) + : Defined(DefinedImportThunkKind, name), wrappedSym(s), + data(makeImportThunk(s, machine)) {} Defined *Undefined::getWeakAlias() { // A weak alias may be a weak alias to another symbol, so check recursively. - for (Symbol *A = WeakAlias; A; A = cast(A)->WeakAlias) - if (auto *D = dyn_cast(A)) - return D; + for (Symbol *a = weakAlias; a; a = cast(a)->weakAlias) + if (auto *d = dyn_cast(a)) + return d; return nullptr; } } // namespace coff Index: lld/trunk/COFF/TypeMerger.h =================================================================== --- lld/trunk/COFF/TypeMerger.h +++ lld/trunk/COFF/TypeMerger.h @@ -19,47 +19,47 @@ class TypeMerger { public: - TypeMerger(llvm::BumpPtrAllocator &Alloc) - : TypeTable(Alloc), IDTable(Alloc), GlobalTypeTable(Alloc), - GlobalIDTable(Alloc) {} + TypeMerger(llvm::BumpPtrAllocator &alloc) + : typeTable(alloc), iDTable(alloc), globalTypeTable(alloc), + globalIDTable(alloc) {} /// Get the type table or the global type table if /DEBUG:GHASH is enabled. inline llvm::codeview::TypeCollection &getTypeTable() { - if (Config->DebugGHashes) - return GlobalTypeTable; - return TypeTable; + if (config->debugGHashes) + return globalTypeTable; + return typeTable; } /// Get the ID table or the global ID table if /DEBUG:GHASH is enabled. inline llvm::codeview::TypeCollection &getIDTable() { - if (Config->DebugGHashes) - return GlobalIDTable; - return IDTable; + if (config->debugGHashes) + return globalIDTable; + return iDTable; } /// Type records that will go into the PDB TPI stream. - llvm::codeview::MergingTypeTableBuilder TypeTable; + llvm::codeview::MergingTypeTableBuilder typeTable; /// Item records that will go into the PDB IPI stream. - llvm::codeview::MergingTypeTableBuilder IDTable; + llvm::codeview::MergingTypeTableBuilder iDTable; /// Type records that will go into the PDB TPI stream (for /DEBUG:GHASH) - llvm::codeview::GlobalTypeTableBuilder GlobalTypeTable; + llvm::codeview::GlobalTypeTableBuilder globalTypeTable; /// Item records that will go into the PDB IPI stream (for /DEBUG:GHASH) - llvm::codeview::GlobalTypeTableBuilder GlobalIDTable; + llvm::codeview::GlobalTypeTableBuilder globalIDTable; }; /// Map from type index and item index in a type server PDB to the /// corresponding index in the destination PDB. struct CVIndexMap { - llvm::SmallVector TPIMap; - llvm::SmallVector IPIMap; - bool IsTypeServerMap = false; - bool IsPrecompiledTypeMap = false; + llvm::SmallVector tpiMap; + llvm::SmallVector ipiMap; + bool isTypeServerMap = false; + bool isPrecompiledTypeMap = false; }; } // namespace coff } // namespace lld #endif \ No newline at end of file Index: lld/trunk/COFF/Writer.h =================================================================== --- lld/trunk/COFF/Writer.h +++ lld/trunk/COFF/Writer.h @@ -18,17 +18,17 @@ namespace lld { namespace coff { -static const int PageSize = 4096; +static const int pageSize = 4096; void writeResult(); class PartialSection { public: - PartialSection(StringRef N, uint32_t Chars) - : Name(N), Characteristics(Chars) {} - StringRef Name; - unsigned Characteristics; - std::vector Chunks; + PartialSection(StringRef n, uint32_t chars) + : name(n), characteristics(chars) {} + StringRef name; + unsigned characteristics; + std::vector chunks; }; // OutputSection represents a section in an output file. It's a @@ -38,45 +38,45 @@ // non-overlapping file offsets and RVAs. class OutputSection { public: - OutputSection(llvm::StringRef N, uint32_t Chars) : Name(N) { - Header.Characteristics = Chars; + OutputSection(llvm::StringRef n, uint32_t chars) : name(n) { + header.Characteristics = chars; } - void addChunk(Chunk *C); - void insertChunkAtStart(Chunk *C); - void merge(OutputSection *Other); - void setPermissions(uint32_t C); - uint64_t getRVA() { return Header.VirtualAddress; } - uint64_t getFileOff() { return Header.PointerToRawData; } - void writeHeaderTo(uint8_t *Buf); - void addContributingPartialSection(PartialSection *Sec); + void addChunk(Chunk *c); + void insertChunkAtStart(Chunk *c); + void merge(OutputSection *other); + void setPermissions(uint32_t c); + uint64_t getRVA() { return header.VirtualAddress; } + uint64_t getFileOff() { return header.PointerToRawData; } + void writeHeaderTo(uint8_t *buf); + void addContributingPartialSection(PartialSection *sec); // Returns the size of this section in an executable memory image. // This may be smaller than the raw size (the raw size is multiple // of disk sector size, so there may be padding at end), or may be // larger (if that's the case, the loader reserves spaces after end // of raw data). - uint64_t getVirtualSize() { return Header.VirtualSize; } + uint64_t getVirtualSize() { return header.VirtualSize; } // Returns the size of the section in the output file. - uint64_t getRawSize() { return Header.SizeOfRawData; } + uint64_t getRawSize() { return header.SizeOfRawData; } // Set offset into the string table storing this section name. // Used only when the name is longer than 8 bytes. - void setStringTableOff(uint32_t V) { StringTableOff = V; } + void setStringTableOff(uint32_t v) { stringTableOff = v; } // N.B. The section index is one based. - uint32_t SectionIndex = 0; + uint32_t sectionIndex = 0; - llvm::StringRef Name; - llvm::object::coff_section Header = {}; + llvm::StringRef name; + llvm::object::coff_section header = {}; - std::vector Chunks; - std::vector OrigChunks; + std::vector chunks; + std::vector origChunks; - std::vector ContribSections; + std::vector contribSections; private: - uint32_t StringTableOff = 0; + uint32_t stringTableOff = 0; }; } // namespace coff Index: lld/trunk/COFF/Writer.cpp =================================================================== --- lld/trunk/COFF/Writer.cpp +++ lld/trunk/COFF/Writer.cpp @@ -63,105 +63,105 @@ $ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin $ xxd -i /tmp/DOSProgram.bin */ -static unsigned char DOSProgram[] = { +static unsigned char dosProgram[] = { 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00 }; -static_assert(sizeof(DOSProgram) % 8 == 0, +static_assert(sizeof(dosProgram) % 8 == 0, "DOSProgram size must be multiple of 8"); -static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram); -static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8"); +static const int dosStubSize = sizeof(dos_header) + sizeof(dosProgram); +static_assert(dosStubSize % 8 == 0, "DOSStub size must be multiple of 8"); -static const int NumberOfDataDirectory = 16; +static const int numberOfDataDirectory = 16; // Global vector of all output sections. After output sections are finalized, // this can be indexed by Chunk::getOutputSection. -static std::vector OutputSections; +static std::vector outputSections; OutputSection *Chunk::getOutputSection() const { - return OSIdx == 0 ? nullptr : OutputSections[OSIdx - 1]; + return osidx == 0 ? nullptr : outputSections[osidx - 1]; } namespace { class DebugDirectoryChunk : public NonSectionChunk { public: - DebugDirectoryChunk(const std::vector &R, bool WriteRepro) - : Records(R), WriteRepro(WriteRepro) {} + DebugDirectoryChunk(const std::vector &r, bool writeRepro) + : records(r), writeRepro(writeRepro) {} size_t getSize() const override { - return (Records.size() + int(WriteRepro)) * sizeof(debug_directory); + return (records.size() + int(writeRepro)) * sizeof(debug_directory); } - void writeTo(uint8_t *B) const override { - auto *D = reinterpret_cast(B); + void writeTo(uint8_t *b) const override { + auto *d = reinterpret_cast(b); - for (const Chunk *Record : Records) { - OutputSection *OS = Record->getOutputSection(); - uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA()); - fillEntry(D, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, Record->getSize(), - Record->getRVA(), Offs); - ++D; + for (const Chunk *record : records) { + OutputSection *os = record->getOutputSection(); + uint64_t offs = os->getFileOff() + (record->getRVA() - os->getRVA()); + fillEntry(d, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, record->getSize(), + record->getRVA(), offs); + ++d; } - if (WriteRepro) { + if (writeRepro) { // FIXME: The COFF spec allows either a 0-sized entry to just say // "the timestamp field is really a hash", or a 4-byte size field // followed by that many bytes containing a longer hash (with the // lowest 4 bytes usually being the timestamp in little-endian order). // Consider storing the full 8 bytes computed by xxHash64 here. - fillEntry(D, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0); + fillEntry(d, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0); } } - void setTimeDateStamp(uint32_t TimeDateStamp) { - for (support::ulittle32_t *TDS : TimeDateStamps) - *TDS = TimeDateStamp; + void setTimeDateStamp(uint32_t timeDateStamp) { + for (support::ulittle32_t *tds : timeDateStamps) + *tds = timeDateStamp; } private: - void fillEntry(debug_directory *D, COFF::DebugType DebugType, size_t Size, - uint64_t RVA, uint64_t Offs) const { - D->Characteristics = 0; - D->TimeDateStamp = 0; - D->MajorVersion = 0; - D->MinorVersion = 0; - D->Type = DebugType; - D->SizeOfData = Size; - D->AddressOfRawData = RVA; - D->PointerToRawData = Offs; - - TimeDateStamps.push_back(&D->TimeDateStamp); - } - - mutable std::vector TimeDateStamps; - const std::vector &Records; - bool WriteRepro; + void fillEntry(debug_directory *d, COFF::DebugType debugType, size_t size, + uint64_t rva, uint64_t offs) const { + d->Characteristics = 0; + d->TimeDateStamp = 0; + d->MajorVersion = 0; + d->MinorVersion = 0; + d->Type = debugType; + d->SizeOfData = size; + d->AddressOfRawData = rva; + d->PointerToRawData = offs; + + timeDateStamps.push_back(&d->TimeDateStamp); + } + + mutable std::vector timeDateStamps; + const std::vector &records; + bool writeRepro; }; class CVDebugRecordChunk : public NonSectionChunk { public: size_t getSize() const override { - return sizeof(codeview::DebugInfo) + Config->PDBAltPath.size() + 1; + return sizeof(codeview::DebugInfo) + config->pdbAltPath.size() + 1; } - void writeTo(uint8_t *B) const override { + void writeTo(uint8_t *b) const override { // Save off the DebugInfo entry to backfill the file signature (build id) // in Writer::writeBuildId - BuildId = reinterpret_cast(B); + buildId = reinterpret_cast(b); // variable sized field (PDB Path) - char *P = reinterpret_cast(B + sizeof(*BuildId)); - if (!Config->PDBAltPath.empty()) - memcpy(P, Config->PDBAltPath.data(), Config->PDBAltPath.size()); - P[Config->PDBAltPath.size()] = '\0'; + char *p = reinterpret_cast(b + sizeof(*buildId)); + if (!config->pdbAltPath.empty()) + memcpy(p, config->pdbAltPath.data(), config->pdbAltPath.size()); + p[config->pdbAltPath.size()] = '\0'; } - mutable codeview::DebugInfo *BuildId = nullptr; + mutable codeview::DebugInfo *buildId = nullptr; }; // PartialSection represents a group of chunks that contribute to an @@ -169,15 +169,15 @@ // characteristics constitutes the OutputSection. class PartialSectionKey { public: - StringRef Name; - unsigned Characteristics; + StringRef name; + unsigned characteristics; - bool operator<(const PartialSectionKey &Other) const { - int C = Name.compare(Other.Name); - if (C == 1) + bool operator<(const PartialSectionKey &other) const { + int c = name.compare(other.name); + if (c == 1) return false; - if (C == 0) - return Characteristics < Other.Characteristics; + if (c == 0) + return characteristics < other.characteristics; return true; } }; @@ -185,7 +185,7 @@ // The writer writes a SymbolTable result to a file. class Writer { public: - Writer() : Buffer(errorHandler().OutputBuffer) {} + Writer() : buffer(errorHandler().outputBuffer) {} void run(); private: @@ -202,72 +202,72 @@ void removeEmptySections(); void assignOutputSectionIndices(); void createSymbolAndStringTable(); - void openFile(StringRef OutputPath); + void openFile(StringRef outputPath); template void writeHeader(); void createSEHTable(); void createRuntimePseudoRelocs(); void insertCtorDtorSymbols(); void createGuardCFTables(); - void markSymbolsForRVATable(ObjFile *File, - ArrayRef SymIdxChunks, - SymbolRVASet &TableSymbols); - void maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym, - StringRef CountSym); + void markSymbolsForRVATable(ObjFile *file, + ArrayRef symIdxChunks, + SymbolRVASet &tableSymbols); + void maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym, + StringRef countSym); void setSectionPermissions(); void writeSections(); void writeBuildId(); void sortExceptionTable(); - void sortCRTSectionChunks(std::vector &Chunks); + void sortCRTSectionChunks(std::vector &chunks); void addSyntheticIdata(); - void fixPartialSectionChars(StringRef Name, uint32_t Chars); + void fixPartialSectionChars(StringRef name, uint32_t chars); bool fixGnuImportChunks(); - PartialSection *createPartialSection(StringRef Name, uint32_t OutChars); - PartialSection *findPartialSection(StringRef Name, uint32_t OutChars); + PartialSection *createPartialSection(StringRef name, uint32_t outChars); + PartialSection *findPartialSection(StringRef name, uint32_t outChars); - llvm::Optional createSymbol(Defined *D); - size_t addEntryToStringTable(StringRef Str); + llvm::Optional createSymbol(Defined *d); + size_t addEntryToStringTable(StringRef str); - OutputSection *findSection(StringRef Name); + OutputSection *findSection(StringRef name); void addBaserels(); - void addBaserelBlocks(std::vector &V); + void addBaserelBlocks(std::vector &v); uint32_t getSizeOfInitializedData(); - std::unique_ptr &Buffer; - std::map PartialSections; - std::vector Strtab; - std::vector OutputSymtab; - IdataContents Idata; - Chunk *ImportTableStart = nullptr; - uint64_t ImportTableSize = 0; - Chunk *IATStart = nullptr; - uint64_t IATSize = 0; - DelayLoadContents DelayIdata; - EdataContents Edata; - bool SetNoSEHCharacteristic = false; - - DebugDirectoryChunk *DebugDirectory = nullptr; - std::vector DebugRecords; - CVDebugRecordChunk *BuildId = nullptr; - ArrayRef SectionTable; - - uint64_t FileSize; - uint32_t PointerToSymbolTable = 0; - uint64_t SizeOfImage; - uint64_t SizeOfHeaders; - - OutputSection *TextSec; - OutputSection *RdataSec; - OutputSection *BuildidSec; - OutputSection *DataSec; - OutputSection *PdataSec; - OutputSection *IdataSec; - OutputSection *EdataSec; - OutputSection *DidatSec; - OutputSection *RsrcSec; - OutputSection *RelocSec; - OutputSection *CtorsSec; - OutputSection *DtorsSec; + std::unique_ptr &buffer; + std::map partialSections; + std::vector strtab; + std::vector outputSymtab; + IdataContents idata; + Chunk *importTableStart = nullptr; + uint64_t importTableSize = 0; + Chunk *iatStart = nullptr; + uint64_t iatSize = 0; + DelayLoadContents delayIdata; + EdataContents edata; + bool setNoSEHCharacteristic = false; + + DebugDirectoryChunk *debugDirectory = nullptr; + std::vector debugRecords; + CVDebugRecordChunk *buildId = nullptr; + ArrayRef sectionTable; + + uint64_t fileSize; + uint32_t pointerToSymbolTable = 0; + uint64_t sizeOfImage; + uint64_t sizeOfHeaders; + + OutputSection *textSec; + OutputSection *rdataSec; + OutputSection *buildidSec; + OutputSection *dataSec; + OutputSection *pdataSec; + OutputSection *idataSec; + OutputSection *edataSec; + OutputSection *didatSec; + OutputSection *rsrcSec; + OutputSection *relocSec; + OutputSection *ctorsSec; + OutputSection *dtorsSec; // The first and last .pdata sections in the output file. // @@ -278,57 +278,57 @@ // are entirely linker-generated we can keep track of their locations using // the chunks that the linker creates. All .pdata chunks come from input // files, so we need to keep track of them separately. - Chunk *FirstPdata = nullptr; - Chunk *LastPdata; + Chunk *firstPdata = nullptr; + Chunk *lastPdata; }; } // anonymous namespace namespace lld { namespace coff { -static Timer CodeLayoutTimer("Code Layout", Timer::root()); -static Timer DiskCommitTimer("Commit Output File", Timer::root()); +static Timer codeLayoutTimer("Code Layout", Timer::root()); +static Timer diskCommitTimer("Commit Output File", Timer::root()); void writeResult() { Writer().run(); } -void OutputSection::addChunk(Chunk *C) { - Chunks.push_back(C); +void OutputSection::addChunk(Chunk *c) { + chunks.push_back(c); } -void OutputSection::insertChunkAtStart(Chunk *C) { - Chunks.insert(Chunks.begin(), C); +void OutputSection::insertChunkAtStart(Chunk *c) { + chunks.insert(chunks.begin(), c); } -void OutputSection::setPermissions(uint32_t C) { - Header.Characteristics &= ~PermMask; - Header.Characteristics |= C; +void OutputSection::setPermissions(uint32_t c) { + header.Characteristics &= ~permMask; + header.Characteristics |= c; } -void OutputSection::merge(OutputSection *Other) { - Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end()); - Other->Chunks.clear(); - ContribSections.insert(ContribSections.end(), Other->ContribSections.begin(), - Other->ContribSections.end()); - Other->ContribSections.clear(); +void OutputSection::merge(OutputSection *other) { + chunks.insert(chunks.end(), other->chunks.begin(), other->chunks.end()); + other->chunks.clear(); + contribSections.insert(contribSections.end(), other->contribSections.begin(), + other->contribSections.end()); + other->contribSections.clear(); } // Write the section header to a given buffer. -void OutputSection::writeHeaderTo(uint8_t *Buf) { - auto *Hdr = reinterpret_cast(Buf); - *Hdr = Header; - if (StringTableOff) { +void OutputSection::writeHeaderTo(uint8_t *buf) { + auto *hdr = reinterpret_cast(buf); + *hdr = header; + if (stringTableOff) { // If name is too long, write offset into the string table as a name. - sprintf(Hdr->Name, "/%d", StringTableOff); + sprintf(hdr->Name, "/%d", stringTableOff); } else { - assert(!Config->Debug || Name.size() <= COFF::NameSize || - (Hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0); - strncpy(Hdr->Name, Name.data(), - std::min(Name.size(), (size_t)COFF::NameSize)); + assert(!config->debug || name.size() <= COFF::NameSize || + (hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0); + strncpy(hdr->Name, name.data(), + std::min(name.size(), (size_t)COFF::NameSize)); } } -void OutputSection::addContributingPartialSection(PartialSection *Sec) { - ContribSections.push_back(Sec); +void OutputSection::addContributingPartialSection(PartialSection *sec) { + contribSections.push_back(sec); } } // namespace coff @@ -336,27 +336,27 @@ // Check whether the target address S is in range from a relocation // of type RelType at address P. -static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) { - if (Config->Machine == ARMNT) { - int64_t Diff = AbsoluteDifference(S, P + 4) + Margin; - switch (RelType) { +static bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin) { + if (config->machine == ARMNT) { + int64_t diff = AbsoluteDifference(s, p + 4) + margin; + switch (relType) { case IMAGE_REL_ARM_BRANCH20T: - return isInt<21>(Diff); + return isInt<21>(diff); case IMAGE_REL_ARM_BRANCH24T: case IMAGE_REL_ARM_BLX23T: - return isInt<25>(Diff); + return isInt<25>(diff); default: return true; } - } else if (Config->Machine == ARM64) { - int64_t Diff = AbsoluteDifference(S, P) + Margin; - switch (RelType) { + } else if (config->machine == ARM64) { + int64_t diff = AbsoluteDifference(s, p) + margin; + switch (relType) { case IMAGE_REL_ARM64_BRANCH26: - return isInt<28>(Diff); + return isInt<28>(diff); case IMAGE_REL_ARM64_BRANCH19: - return isInt<21>(Diff); + return isInt<21>(diff); case IMAGE_REL_ARM64_BRANCH14: - return isInt<16>(Diff); + return isInt<16>(diff); default: return true; } @@ -368,25 +368,25 @@ // Return the last thunk for the given target if it is in range, // or create a new one. static std::pair -getThunk(DenseMap &LastThunks, Defined *Target, uint64_t P, - uint16_t Type, int Margin) { - Defined *&LastThunk = LastThunks[Target->getRVA()]; - if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin)) - return {LastThunk, false}; - Chunk *C; - switch (Config->Machine) { +getThunk(DenseMap &lastThunks, Defined *target, uint64_t p, + uint16_t type, int margin) { + Defined *&lastThunk = lastThunks[target->getRVA()]; + if (lastThunk && isInRange(type, lastThunk->getRVA(), p, margin)) + return {lastThunk, false}; + Chunk *c; + switch (config->machine) { case ARMNT: - C = make(Target); + c = make(target); break; case ARM64: - C = make(Target); + c = make(target); break; default: llvm_unreachable("Unexpected architecture"); } - Defined *D = make("", C); - LastThunk = D; - return {D, true}; + Defined *d = make("", c); + lastThunk = d; + return {d, true}; } // This checks all relocations, and for any relocation which isn't in range @@ -400,124 +400,124 @@ // After adding thunks, we verify that all relocations are in range (with // no extra margin requirements). If this failed, we restart (throwing away // the previously created thunks) and retry with a wider margin. -static bool createThunks(OutputSection *OS, int Margin) { - bool AddressesChanged = false; - DenseMap LastThunks; - DenseMap, uint32_t> ThunkSymtabIndices; - size_t ThunksSize = 0; +static bool createThunks(OutputSection *os, int margin) { + bool addressesChanged = false; + DenseMap lastThunks; + DenseMap, uint32_t> thunkSymtabIndices; + size_t thunksSize = 0; // Recheck Chunks.size() each iteration, since we can insert more // elements into it. - for (size_t I = 0; I != OS->Chunks.size(); ++I) { - SectionChunk *SC = dyn_cast_or_null(OS->Chunks[I]); - if (!SC) + for (size_t i = 0; i != os->chunks.size(); ++i) { + SectionChunk *sc = dyn_cast_or_null(os->chunks[i]); + if (!sc) continue; - size_t ThunkInsertionSpot = I + 1; + size_t thunkInsertionSpot = i + 1; // Try to get a good enough estimate of where new thunks will be placed. // Offset this by the size of the new thunks added so far, to make the // estimate slightly better. - size_t ThunkInsertionRVA = SC->getRVA() + SC->getSize() + ThunksSize; - ObjFile *File = SC->File; - std::vector> RelocReplacements; - ArrayRef OriginalRelocs = - File->getCOFFObj()->getRelocations(SC->Header); - for (size_t J = 0, E = OriginalRelocs.size(); J < E; ++J) { - const coff_relocation &Rel = OriginalRelocs[J]; - Symbol *RelocTarget = File->getSymbol(Rel.SymbolTableIndex); + size_t thunkInsertionRVA = sc->getRVA() + sc->getSize() + thunksSize; + ObjFile *file = sc->file; + std::vector> relocReplacements; + ArrayRef originalRelocs = + file->getCOFFObj()->getRelocations(sc->header); + for (size_t j = 0, e = originalRelocs.size(); j < e; ++j) { + const coff_relocation &rel = originalRelocs[j]; + Symbol *relocTarget = file->getSymbol(rel.SymbolTableIndex); // The estimate of the source address P should be pretty accurate, // but we don't know whether the target Symbol address should be // offset by ThunkSize or not (or by some of ThunksSize but not all of // it), giving us some uncertainty once we have added one thunk. - uint64_t P = SC->getRVA() + Rel.VirtualAddress + ThunksSize; + uint64_t p = sc->getRVA() + rel.VirtualAddress + thunksSize; - Defined *Sym = dyn_cast_or_null(RelocTarget); - if (!Sym) + Defined *sym = dyn_cast_or_null(relocTarget); + if (!sym) continue; - uint64_t S = Sym->getRVA(); + uint64_t s = sym->getRVA(); - if (isInRange(Rel.Type, S, P, Margin)) + if (isInRange(rel.Type, s, p, margin)) continue; // If the target isn't in range, hook it up to an existing or new // thunk. - Defined *Thunk; - bool WasNew; - std::tie(Thunk, WasNew) = getThunk(LastThunks, Sym, P, Rel.Type, Margin); - if (WasNew) { - Chunk *ThunkChunk = Thunk->getChunk(); - ThunkChunk->setRVA( - ThunkInsertionRVA); // Estimate of where it will be located. - OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk); - ThunkInsertionSpot++; - ThunksSize += ThunkChunk->getSize(); - ThunkInsertionRVA += ThunkChunk->getSize(); - AddressesChanged = true; + Defined *thunk; + bool wasNew; + std::tie(thunk, wasNew) = getThunk(lastThunks, sym, p, rel.Type, margin); + if (wasNew) { + Chunk *thunkChunk = thunk->getChunk(); + thunkChunk->setRVA( + thunkInsertionRVA); // Estimate of where it will be located. + os->chunks.insert(os->chunks.begin() + thunkInsertionSpot, thunkChunk); + thunkInsertionSpot++; + thunksSize += thunkChunk->getSize(); + thunkInsertionRVA += thunkChunk->getSize(); + addressesChanged = true; } // To redirect the relocation, add a symbol to the parent object file's // symbol table, and replace the relocation symbol table index with the // new index. - auto Insertion = ThunkSymtabIndices.insert({{File, Thunk}, ~0U}); - uint32_t &ThunkSymbolIndex = Insertion.first->second; - if (Insertion.second) - ThunkSymbolIndex = File->addRangeThunkSymbol(Thunk); - RelocReplacements.push_back({J, ThunkSymbolIndex}); + auto insertion = thunkSymtabIndices.insert({{file, thunk}, ~0U}); + uint32_t &thunkSymbolIndex = insertion.first->second; + if (insertion.second) + thunkSymbolIndex = file->addRangeThunkSymbol(thunk); + relocReplacements.push_back({j, thunkSymbolIndex}); } // Get a writable copy of this section's relocations so they can be // modified. If the relocations point into the object file, allocate new // memory. Otherwise, this must be previously allocated memory that can be // modified in place. - ArrayRef CurRelocs = SC->getRelocs(); - MutableArrayRef NewRelocs; - if (OriginalRelocs.data() == CurRelocs.data()) { - NewRelocs = makeMutableArrayRef( - BAlloc.Allocate(OriginalRelocs.size()), - OriginalRelocs.size()); + ArrayRef curRelocs = sc->getRelocs(); + MutableArrayRef newRelocs; + if (originalRelocs.data() == curRelocs.data()) { + newRelocs = makeMutableArrayRef( + bAlloc.Allocate(originalRelocs.size()), + originalRelocs.size()); } else { - NewRelocs = makeMutableArrayRef( - const_cast(CurRelocs.data()), CurRelocs.size()); + newRelocs = makeMutableArrayRef( + const_cast(curRelocs.data()), curRelocs.size()); } // Copy each relocation, but replace the symbol table indices which need // thunks. - auto NextReplacement = RelocReplacements.begin(); - auto EndReplacement = RelocReplacements.end(); - for (size_t I = 0, E = OriginalRelocs.size(); I != E; ++I) { - NewRelocs[I] = OriginalRelocs[I]; - if (NextReplacement != EndReplacement && NextReplacement->first == I) { - NewRelocs[I].SymbolTableIndex = NextReplacement->second; - ++NextReplacement; + auto nextReplacement = relocReplacements.begin(); + auto endReplacement = relocReplacements.end(); + for (size_t i = 0, e = originalRelocs.size(); i != e; ++i) { + newRelocs[i] = originalRelocs[i]; + if (nextReplacement != endReplacement && nextReplacement->first == i) { + newRelocs[i].SymbolTableIndex = nextReplacement->second; + ++nextReplacement; } } - SC->setRelocs(NewRelocs); + sc->setRelocs(newRelocs); } - return AddressesChanged; + return addressesChanged; } // Verify that all relocations are in range, with no extra margin requirements. -static bool verifyRanges(const std::vector Chunks) { - for (Chunk *C : Chunks) { - SectionChunk *SC = dyn_cast_or_null(C); - if (!SC) +static bool verifyRanges(const std::vector chunks) { + for (Chunk *c : chunks) { + SectionChunk *sc = dyn_cast_or_null(c); + if (!sc) continue; - ArrayRef Relocs = SC->getRelocs(); - for (size_t J = 0, E = Relocs.size(); J < E; ++J) { - const coff_relocation &Rel = Relocs[J]; - Symbol *RelocTarget = SC->File->getSymbol(Rel.SymbolTableIndex); + ArrayRef relocs = sc->getRelocs(); + for (size_t j = 0, e = relocs.size(); j < e; ++j) { + const coff_relocation &rel = relocs[j]; + Symbol *relocTarget = sc->file->getSymbol(rel.SymbolTableIndex); - Defined *Sym = dyn_cast_or_null(RelocTarget); - if (!Sym) + Defined *sym = dyn_cast_or_null(relocTarget); + if (!sym) continue; - uint64_t P = SC->getRVA() + Rel.VirtualAddress; - uint64_t S = Sym->getRVA(); + uint64_t p = sc->getRVA() + rel.VirtualAddress; + uint64_t s = sym->getRVA(); - if (!isInRange(Rel.Type, S, P, 0)) + if (!isInRange(rel.Type, s, p, 0)) return false; } } @@ -527,68 +527,68 @@ // Assign addresses and add thunks if necessary. void Writer::finalizeAddresses() { assignAddresses(); - if (Config->Machine != ARMNT && Config->Machine != ARM64) + if (config->machine != ARMNT && config->machine != ARM64) return; - size_t OrigNumChunks = 0; - for (OutputSection *Sec : OutputSections) { - Sec->OrigChunks = Sec->Chunks; - OrigNumChunks += Sec->Chunks.size(); + size_t origNumChunks = 0; + for (OutputSection *sec : outputSections) { + sec->origChunks = sec->chunks; + origNumChunks += sec->chunks.size(); } - int Pass = 0; - int Margin = 1024 * 100; + int pass = 0; + int margin = 1024 * 100; while (true) { // First check whether we need thunks at all, or if the previous pass of // adding them turned out ok. - bool RangesOk = true; - size_t NumChunks = 0; - for (OutputSection *Sec : OutputSections) { - if (!verifyRanges(Sec->Chunks)) { - RangesOk = false; + bool rangesOk = true; + size_t numChunks = 0; + for (OutputSection *sec : outputSections) { + if (!verifyRanges(sec->chunks)) { + rangesOk = false; break; } - NumChunks += Sec->Chunks.size(); + numChunks += sec->chunks.size(); } - if (RangesOk) { - if (Pass > 0) - log("Added " + Twine(NumChunks - OrigNumChunks) + " thunks with " + - "margin " + Twine(Margin) + " in " + Twine(Pass) + " passes"); + if (rangesOk) { + if (pass > 0) + log("Added " + Twine(numChunks - origNumChunks) + " thunks with " + + "margin " + Twine(margin) + " in " + Twine(pass) + " passes"); return; } - if (Pass >= 10) - fatal("adding thunks hasn't converged after " + Twine(Pass) + " passes"); + if (pass >= 10) + fatal("adding thunks hasn't converged after " + Twine(pass) + " passes"); - if (Pass > 0) { + if (pass > 0) { // If the previous pass didn't work out, reset everything back to the // original conditions before retrying with a wider margin. This should // ideally never happen under real circumstances. - for (OutputSection *Sec : OutputSections) - Sec->Chunks = Sec->OrigChunks; - Margin *= 2; + for (OutputSection *sec : outputSections) + sec->chunks = sec->origChunks; + margin *= 2; } // Try adding thunks everywhere where it is needed, with a margin // to avoid things going out of range due to the added thunks. - bool AddressesChanged = false; - for (OutputSection *Sec : OutputSections) - AddressesChanged |= createThunks(Sec, Margin); + bool addressesChanged = false; + for (OutputSection *sec : outputSections) + addressesChanged |= createThunks(sec, margin); // If the verification above thought we needed thunks, we should have // added some. - assert(AddressesChanged); + assert(addressesChanged); // Recalculate the layout for the whole image (and verify the ranges at // the start of the next round). assignAddresses(); - Pass++; + pass++; } } // The main function of the writer. void Writer::run() { - ScopedTimer T1(CodeLayoutTimer); + ScopedTimer t1(codeLayoutTimer); createImportTables(); createSections(); @@ -603,12 +603,12 @@ setSectionPermissions(); createSymbolAndStringTable(); - if (FileSize > UINT32_MAX) - fatal("image size (" + Twine(FileSize) + ") " + + if (fileSize > UINT32_MAX) + fatal("image size (" + Twine(fileSize) + ") " + "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")"); - openFile(Config->OutputFile); - if (Config->is64()) { + openFile(config->outputFile); + if (config->is64()) { writeHeader(); } else { writeHeader(); @@ -616,58 +616,58 @@ writeSections(); sortExceptionTable(); - T1.stop(); + t1.stop(); - if (!Config->PDBPath.empty() && Config->Debug) { - assert(BuildId); - createPDB(Symtab, OutputSections, SectionTable, BuildId->BuildId); + if (!config->pdbPath.empty() && config->debug) { + assert(buildId); + createPDB(symtab, outputSections, sectionTable, buildId->buildId); } writeBuildId(); - writeMapFile(OutputSections); + writeMapFile(outputSections); - ScopedTimer T2(DiskCommitTimer); - if (auto E = Buffer->commit()) - fatal("failed to write the output file: " + toString(std::move(E))); + ScopedTimer t2(diskCommitTimer); + if (auto e = buffer->commit()) + fatal("failed to write the output file: " + toString(std::move(e))); } -static StringRef getOutputSectionName(StringRef Name) { - StringRef S = Name.split('$').first; +static StringRef getOutputSectionName(StringRef name) { + StringRef s = name.split('$').first; // Treat a later period as a separator for MinGW, for sections like // ".ctors.01234". - return S.substr(0, S.find('.', 1)); + return s.substr(0, s.find('.', 1)); } // For /order. -static void sortBySectionOrder(std::vector &Chunks) { - auto GetPriority = [](const Chunk *C) { - if (auto *Sec = dyn_cast(C)) - if (Sec->Sym) - return Config->Order.lookup(Sec->Sym->getName()); +static void sortBySectionOrder(std::vector &chunks) { + auto getPriority = [](const Chunk *c) { + if (auto *sec = dyn_cast(c)) + if (sec->sym) + return config->order.lookup(sec->sym->getName()); return 0; }; - llvm::stable_sort(Chunks, [=](const Chunk *A, const Chunk *B) { - return GetPriority(A) < GetPriority(B); + llvm::stable_sort(chunks, [=](const Chunk *a, const Chunk *b) { + return getPriority(a) < getPriority(b); }); } // Change the characteristics of existing PartialSections that belong to the // section Name to Chars. -void Writer::fixPartialSectionChars(StringRef Name, uint32_t Chars) { - for (auto It : PartialSections) { - PartialSection *PSec = It.second; - StringRef CurName = PSec->Name; - if (!CurName.consume_front(Name) || - (!CurName.empty() && !CurName.startswith("$"))) +void Writer::fixPartialSectionChars(StringRef name, uint32_t chars) { + for (auto it : partialSections) { + PartialSection *pSec = it.second; + StringRef curName = pSec->name; + if (!curName.consume_front(name) || + (!curName.empty() && !curName.startswith("$"))) continue; - if (PSec->Characteristics == Chars) + if (pSec->characteristics == chars) continue; - PartialSection *DestSec = createPartialSection(PSec->Name, Chars); - DestSec->Chunks.insert(DestSec->Chunks.end(), PSec->Chunks.begin(), - PSec->Chunks.end()); - PSec->Chunks.clear(); + PartialSection *destSec = createPartialSection(pSec->name, chars); + destSec->chunks.insert(destSec->chunks.end(), pSec->chunks.begin(), + pSec->chunks.end()); + pSec->chunks.clear(); } } @@ -682,249 +682,249 @@ // to be grouped by library, and sorted alphabetically within each library // (which makes sure the header comes first and the trailer last). bool Writer::fixGnuImportChunks() { - uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; + uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; // Make sure all .idata$* section chunks are mapped as RDATA in order to // be sorted into the same sections as our own synthesized .idata chunks. - fixPartialSectionChars(".idata", RDATA); + fixPartialSectionChars(".idata", rdata); - bool HasIdata = false; + bool hasIdata = false; // Sort all .idata$* chunks, grouping chunks from the same library, // with alphabetical ordering of the object fils within a library. - for (auto It : PartialSections) { - PartialSection *PSec = It.second; - if (!PSec->Name.startswith(".idata")) + for (auto it : partialSections) { + PartialSection *pSec = it.second; + if (!pSec->name.startswith(".idata")) continue; - if (!PSec->Chunks.empty()) - HasIdata = true; - llvm::stable_sort(PSec->Chunks, [&](Chunk *S, Chunk *T) { - SectionChunk *SC1 = dyn_cast_or_null(S); - SectionChunk *SC2 = dyn_cast_or_null(T); - if (!SC1 || !SC2) { + if (!pSec->chunks.empty()) + hasIdata = true; + llvm::stable_sort(pSec->chunks, [&](Chunk *s, Chunk *t) { + SectionChunk *sc1 = dyn_cast_or_null(s); + SectionChunk *sc2 = dyn_cast_or_null(t); + if (!sc1 || !sc2) { // if SC1, order them ascending. If SC2 or both null, // S is not less than T. - return SC1 != nullptr; + return sc1 != nullptr; } // Make a string with "libraryname/objectfile" for sorting, achieving // both grouping by library and sorting of objects within a library, // at once. - std::string Key1 = - (SC1->File->ParentName + "/" + SC1->File->getName()).str(); - std::string Key2 = - (SC2->File->ParentName + "/" + SC2->File->getName()).str(); - return Key1 < Key2; + std::string key1 = + (sc1->file->parentName + "/" + sc1->file->getName()).str(); + std::string key2 = + (sc2->file->parentName + "/" + sc2->file->getName()).str(); + return key1 < key2; }); } - return HasIdata; + return hasIdata; } // Add generated idata chunks, for imported symbols and DLLs, and a // terminator in .idata$2. void Writer::addSyntheticIdata() { - uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; - Idata.create(); + uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; + idata.create(); // Add the .idata content in the right section groups, to allow // chunks from other linked in object files to be grouped together. // See Microsoft PE/COFF spec 5.4 for details. - auto Add = [&](StringRef N, std::vector &V) { - PartialSection *PSec = createPartialSection(N, RDATA); - PSec->Chunks.insert(PSec->Chunks.end(), V.begin(), V.end()); + auto add = [&](StringRef n, std::vector &v) { + PartialSection *pSec = createPartialSection(n, rdata); + pSec->chunks.insert(pSec->chunks.end(), v.begin(), v.end()); }; // The loader assumes a specific order of data. // Add each type in the correct order. - Add(".idata$2", Idata.Dirs); - Add(".idata$4", Idata.Lookups); - Add(".idata$5", Idata.Addresses); - Add(".idata$6", Idata.Hints); - Add(".idata$7", Idata.DLLNames); + add(".idata$2", idata.dirs); + add(".idata$4", idata.lookups); + add(".idata$5", idata.addresses); + add(".idata$6", idata.hints); + add(".idata$7", idata.dllNames); } // Locate the first Chunk and size of the import directory list and the // IAT. void Writer::locateImportTables() { - uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; + uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; - if (PartialSection *ImportDirs = findPartialSection(".idata$2", RDATA)) { - if (!ImportDirs->Chunks.empty()) - ImportTableStart = ImportDirs->Chunks.front(); - for (Chunk *C : ImportDirs->Chunks) - ImportTableSize += C->getSize(); + if (PartialSection *importDirs = findPartialSection(".idata$2", rdata)) { + if (!importDirs->chunks.empty()) + importTableStart = importDirs->chunks.front(); + for (Chunk *c : importDirs->chunks) + importTableSize += c->getSize(); } - if (PartialSection *ImportAddresses = findPartialSection(".idata$5", RDATA)) { - if (!ImportAddresses->Chunks.empty()) - IATStart = ImportAddresses->Chunks.front(); - for (Chunk *C : ImportAddresses->Chunks) - IATSize += C->getSize(); + if (PartialSection *importAddresses = findPartialSection(".idata$5", rdata)) { + if (!importAddresses->chunks.empty()) + iatStart = importAddresses->chunks.front(); + for (Chunk *c : importAddresses->chunks) + iatSize += c->getSize(); } } // Create output section objects and add them to OutputSections. void Writer::createSections() { // First, create the builtin sections. - const uint32_t DATA = IMAGE_SCN_CNT_INITIALIZED_DATA; - const uint32_t BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA; - const uint32_t CODE = IMAGE_SCN_CNT_CODE; - const uint32_t DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE; - const uint32_t R = IMAGE_SCN_MEM_READ; - const uint32_t W = IMAGE_SCN_MEM_WRITE; - const uint32_t X = IMAGE_SCN_MEM_EXECUTE; - - SmallDenseMap, OutputSection *> Sections; - auto CreateSection = [&](StringRef Name, uint32_t OutChars) { - OutputSection *&Sec = Sections[{Name, OutChars}]; - if (!Sec) { - Sec = make(Name, OutChars); - OutputSections.push_back(Sec); + const uint32_t data = IMAGE_SCN_CNT_INITIALIZED_DATA; + const uint32_t bss = IMAGE_SCN_CNT_UNINITIALIZED_DATA; + const uint32_t code = IMAGE_SCN_CNT_CODE; + const uint32_t discardable = IMAGE_SCN_MEM_DISCARDABLE; + const uint32_t r = IMAGE_SCN_MEM_READ; + const uint32_t w = IMAGE_SCN_MEM_WRITE; + const uint32_t x = IMAGE_SCN_MEM_EXECUTE; + + SmallDenseMap, OutputSection *> sections; + auto createSection = [&](StringRef name, uint32_t outChars) { + OutputSection *&sec = sections[{name, outChars}]; + if (!sec) { + sec = make(name, outChars); + outputSections.push_back(sec); } - return Sec; + return sec; }; // Try to match the section order used by link.exe. - TextSec = CreateSection(".text", CODE | R | X); - CreateSection(".bss", BSS | R | W); - RdataSec = CreateSection(".rdata", DATA | R); - BuildidSec = CreateSection(".buildid", DATA | R); - DataSec = CreateSection(".data", DATA | R | W); - PdataSec = CreateSection(".pdata", DATA | R); - IdataSec = CreateSection(".idata", DATA | R); - EdataSec = CreateSection(".edata", DATA | R); - DidatSec = CreateSection(".didat", DATA | R); - RsrcSec = CreateSection(".rsrc", DATA | R); - RelocSec = CreateSection(".reloc", DATA | DISCARDABLE | R); - CtorsSec = CreateSection(".ctors", DATA | R | W); - DtorsSec = CreateSection(".dtors", DATA | R | W); + textSec = createSection(".text", code | r | x); + createSection(".bss", bss | r | w); + rdataSec = createSection(".rdata", data | r); + buildidSec = createSection(".buildid", data | r); + dataSec = createSection(".data", data | r | w); + pdataSec = createSection(".pdata", data | r); + idataSec = createSection(".idata", data | r); + edataSec = createSection(".edata", data | r); + didatSec = createSection(".didat", data | r); + rsrcSec = createSection(".rsrc", data | r); + relocSec = createSection(".reloc", data | discardable | r); + ctorsSec = createSection(".ctors", data | r | w); + dtorsSec = createSection(".dtors", data | r | w); // Then bin chunks by name and output characteristics. - for (Chunk *C : Symtab->getChunks()) { - auto *SC = dyn_cast(C); - if (SC && !SC->Live) { - if (Config->Verbose) - SC->printDiscardedMessage(); + for (Chunk *c : symtab->getChunks()) { + auto *sc = dyn_cast(c); + if (sc && !sc->live) { + if (config->verbose) + sc->printDiscardedMessage(); continue; } - StringRef Name = C->getSectionName(); + StringRef name = c->getSectionName(); // On MinGW, comdat groups are formed by putting the comdat group name // after the '$' in the section name. Such a section name suffix shouldn't // imply separate alphabetical sorting of those section chunks though. - if (Config->MinGW && SC && SC->isCOMDAT()) - Name = Name.split('$').first; - PartialSection *PSec = createPartialSection(Name, - C->getOutputCharacteristics()); - PSec->Chunks.push_back(C); + if (config->mingw && sc && sc->isCOMDAT()) + name = name.split('$').first; + PartialSection *pSec = createPartialSection(name, + c->getOutputCharacteristics()); + pSec->chunks.push_back(c); } - fixPartialSectionChars(".rsrc", DATA | R); + fixPartialSectionChars(".rsrc", data | r); // Even in non MinGW cases, we might need to link against GNU import // libraries. - bool HasIdata = fixGnuImportChunks(); - if (!Idata.empty()) - HasIdata = true; + bool hasIdata = fixGnuImportChunks(); + if (!idata.empty()) + hasIdata = true; - if (HasIdata) + if (hasIdata) addSyntheticIdata(); // Process an /order option. - if (!Config->Order.empty()) - for (auto It : PartialSections) - sortBySectionOrder(It.second->Chunks); + if (!config->order.empty()) + for (auto it : partialSections) + sortBySectionOrder(it.second->chunks); - if (HasIdata) + if (hasIdata) locateImportTables(); // Then create an OutputSection for each section. // '$' and all following characters in input section names are // discarded when determining output section. So, .text$foo // contributes to .text, for example. See PE/COFF spec 3.2. - for (auto It : PartialSections) { - PartialSection *PSec = It.second; - StringRef Name = getOutputSectionName(PSec->Name); - uint32_t OutChars = PSec->Characteristics; + for (auto it : partialSections) { + PartialSection *pSec = it.second; + StringRef name = getOutputSectionName(pSec->name); + uint32_t outChars = pSec->characteristics; - if (Name == ".CRT") { + if (name == ".CRT") { // In link.exe, there is a special case for the I386 target where .CRT // sections are treated as if they have output characteristics DATA | R if // their characteristics are DATA | R | W. This implements the same // special case for all architectures. - OutChars = DATA | R; + outChars = data | r; - log("Processing section " + PSec->Name + " -> " + Name); + log("Processing section " + pSec->name + " -> " + name); - sortCRTSectionChunks(PSec->Chunks); + sortCRTSectionChunks(pSec->chunks); } - OutputSection *Sec = CreateSection(Name, OutChars); - for (Chunk *C : PSec->Chunks) - Sec->addChunk(C); + OutputSection *sec = createSection(name, outChars); + for (Chunk *c : pSec->chunks) + sec->addChunk(c); - Sec->addContributingPartialSection(PSec); + sec->addContributingPartialSection(pSec); } // Finally, move some output sections to the end. - auto SectionOrder = [&](const OutputSection *S) { + auto sectionOrder = [&](const OutputSection *s) { // Move DISCARDABLE (or non-memory-mapped) sections to the end of file // because the loader cannot handle holes. Stripping can remove other // discardable ones than .reloc, which is first of them (created early). - if (S->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) + if (s->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) return 2; // .rsrc should come at the end of the non-discardable sections because its // size may change by the Win32 UpdateResources() function, causing // subsequent sections to move (see https://crbug.com/827082). - if (S == RsrcSec) + if (s == rsrcSec) return 1; return 0; }; - llvm::stable_sort(OutputSections, - [&](const OutputSection *S, const OutputSection *T) { - return SectionOrder(S) < SectionOrder(T); + llvm::stable_sort(outputSections, + [&](const OutputSection *s, const OutputSection *t) { + return sectionOrder(s) < sectionOrder(t); }); } void Writer::createMiscChunks() { - for (MergeChunk *P : MergeChunk::Instances) { - if (P) { - P->finalizeContents(); - RdataSec->addChunk(P); + for (MergeChunk *p : MergeChunk::instances) { + if (p) { + p->finalizeContents(); + rdataSec->addChunk(p); } } // Create thunks for locally-dllimported symbols. - if (!Symtab->LocalImportChunks.empty()) { - for (Chunk *C : Symtab->LocalImportChunks) - RdataSec->addChunk(C); + if (!symtab->localImportChunks.empty()) { + for (Chunk *c : symtab->localImportChunks) + rdataSec->addChunk(c); } // Create Debug Information Chunks - OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec; - if (Config->Debug || Config->Repro) { - DebugDirectory = make(DebugRecords, Config->Repro); - DebugInfoSec->addChunk(DebugDirectory); + OutputSection *debugInfoSec = config->mingw ? buildidSec : rdataSec; + if (config->debug || config->repro) { + debugDirectory = make(debugRecords, config->repro); + debugInfoSec->addChunk(debugDirectory); } - if (Config->Debug) { + if (config->debug) { // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We // output a PDB no matter what, and this chunk provides the only means of // allowing a debugger to match a PDB and an executable. So we need it even // if we're ultimately not going to write CodeView data to the PDB. - BuildId = make(); - DebugRecords.push_back(BuildId); + buildId = make(); + debugRecords.push_back(buildId); - for (Chunk *C : DebugRecords) - DebugInfoSec->addChunk(C); + for (Chunk *c : debugRecords) + debugInfoSec->addChunk(c); } // Create SEH table. x86-only. - if (Config->Machine == I386) + if (config->machine == I386) createSEHTable(); // Create /guard:cf tables if requested. - if (Config->GuardCF != GuardCFLevel::Off) + if (config->guardCF != GuardCFLevel::Off) createGuardCFTables(); - if (Config->MinGW) { + if (config->mingw) { createRuntimePseudoRelocs(); insertCtorDtorSymbols(); @@ -939,123 +939,123 @@ // Initialize DLLOrder so that import entries are ordered in // the same order as in the command line. (That affects DLL // initialization order, and this ordering is MSVC-compatible.) - for (ImportFile *File : ImportFile::Instances) { - if (!File->Live) + for (ImportFile *file : ImportFile::instances) { + if (!file->live) continue; - std::string DLL = StringRef(File->DLLName).lower(); - if (Config->DLLOrder.count(DLL) == 0) - Config->DLLOrder[DLL] = Config->DLLOrder.size(); - - if (File->ImpSym && !isa(File->ImpSym)) - fatal(toString(*File->ImpSym) + " was replaced"); - DefinedImportData *ImpSym = cast_or_null(File->ImpSym); - if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) { - if (!File->ThunkSym) - fatal("cannot delay-load " + toString(File) + - " due to import of data: " + toString(*ImpSym)); - DelayIdata.add(ImpSym); + std::string dll = StringRef(file->dllName).lower(); + if (config->dllOrder.count(dll) == 0) + config->dllOrder[dll] = config->dllOrder.size(); + + if (file->impSym && !isa(file->impSym)) + fatal(toString(*file->impSym) + " was replaced"); + DefinedImportData *impSym = cast_or_null(file->impSym); + if (config->delayLoads.count(StringRef(file->dllName).lower())) { + if (!file->thunkSym) + fatal("cannot delay-load " + toString(file) + + " due to import of data: " + toString(*impSym)); + delayIdata.add(impSym); } else { - Idata.add(ImpSym); + idata.add(impSym); } } } void Writer::appendImportThunks() { - if (ImportFile::Instances.empty()) + if (ImportFile::instances.empty()) return; - for (ImportFile *File : ImportFile::Instances) { - if (!File->Live) + for (ImportFile *file : ImportFile::instances) { + if (!file->live) continue; - if (!File->ThunkSym) + if (!file->thunkSym) continue; - if (!isa(File->ThunkSym)) - fatal(toString(*File->ThunkSym) + " was replaced"); - DefinedImportThunk *Thunk = cast(File->ThunkSym); - if (File->ThunkLive) - TextSec->addChunk(Thunk->getChunk()); - } - - if (!DelayIdata.empty()) { - Defined *Helper = cast(Config->DelayLoadHelper); - DelayIdata.create(Helper); - for (Chunk *C : DelayIdata.getChunks()) - DidatSec->addChunk(C); - for (Chunk *C : DelayIdata.getDataChunks()) - DataSec->addChunk(C); - for (Chunk *C : DelayIdata.getCodeChunks()) - TextSec->addChunk(C); + if (!isa(file->thunkSym)) + fatal(toString(*file->thunkSym) + " was replaced"); + DefinedImportThunk *thunk = cast(file->thunkSym); + if (file->thunkLive) + textSec->addChunk(thunk->getChunk()); + } + + if (!delayIdata.empty()) { + Defined *helper = cast(config->delayLoadHelper); + delayIdata.create(helper); + for (Chunk *c : delayIdata.getChunks()) + didatSec->addChunk(c); + for (Chunk *c : delayIdata.getDataChunks()) + dataSec->addChunk(c); + for (Chunk *c : delayIdata.getCodeChunks()) + textSec->addChunk(c); } } void Writer::createExportTable() { - if (Config->Exports.empty()) + if (config->exports.empty()) return; - for (Chunk *C : Edata.Chunks) - EdataSec->addChunk(C); + for (Chunk *c : edata.chunks) + edataSec->addChunk(c); } void Writer::removeUnusedSections() { // Remove sections that we can be sure won't get content, to avoid // allocating space for their section headers. - auto IsUnused = [this](OutputSection *S) { - if (S == RelocSec) + auto isUnused = [this](OutputSection *s) { + if (s == relocSec) return false; // This section is populated later. // MergeChunks have zero size at this point, as their size is finalized // later. Only remove sections that have no Chunks at all. - return S->Chunks.empty(); + return s->chunks.empty(); }; - OutputSections.erase( - std::remove_if(OutputSections.begin(), OutputSections.end(), IsUnused), - OutputSections.end()); + outputSections.erase( + std::remove_if(outputSections.begin(), outputSections.end(), isUnused), + outputSections.end()); } // The Windows loader doesn't seem to like empty sections, // so we remove them if any. void Writer::removeEmptySections() { - auto IsEmpty = [](OutputSection *S) { return S->getVirtualSize() == 0; }; - OutputSections.erase( - std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty), - OutputSections.end()); + auto isEmpty = [](OutputSection *s) { return s->getVirtualSize() == 0; }; + outputSections.erase( + std::remove_if(outputSections.begin(), outputSections.end(), isEmpty), + outputSections.end()); } void Writer::assignOutputSectionIndices() { // Assign final output section indices, and assign each chunk to its output // section. - uint32_t Idx = 1; - for (OutputSection *OS : OutputSections) { - OS->SectionIndex = Idx; - for (Chunk *C : OS->Chunks) - C->setOutputSectionIdx(Idx); - ++Idx; + uint32_t idx = 1; + for (OutputSection *os : outputSections) { + os->sectionIndex = idx; + for (Chunk *c : os->chunks) + c->setOutputSectionIdx(idx); + ++idx; } // Merge chunks are containers of chunks, so assign those an output section // too. - for (MergeChunk *MC : MergeChunk::Instances) - if (MC) - for (SectionChunk *SC : MC->Sections) - if (SC && SC->Live) - SC->setOutputSectionIdx(MC->getOutputSectionIdx()); -} - -size_t Writer::addEntryToStringTable(StringRef Str) { - assert(Str.size() > COFF::NameSize); - size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field - Strtab.insert(Strtab.end(), Str.begin(), Str.end()); - Strtab.push_back('\0'); - return OffsetOfEntry; -} - -Optional Writer::createSymbol(Defined *Def) { - coff_symbol16 Sym; - switch (Def->kind()) { + for (MergeChunk *mc : MergeChunk::instances) + if (mc) + for (SectionChunk *sc : mc->sections) + if (sc && sc->live) + sc->setOutputSectionIdx(mc->getOutputSectionIdx()); +} + +size_t Writer::addEntryToStringTable(StringRef str) { + assert(str.size() > COFF::NameSize); + size_t offsetOfEntry = strtab.size() + 4; // +4 for the size field + strtab.insert(strtab.end(), str.begin(), str.end()); + strtab.push_back('\0'); + return offsetOfEntry; +} + +Optional Writer::createSymbol(Defined *def) { + coff_symbol16 sym; + switch (def->kind()) { case Symbol::DefinedAbsoluteKind: - Sym.Value = Def->getRVA(); - Sym.SectionNumber = IMAGE_SYM_ABSOLUTE; + sym.Value = def->getRVA(); + sym.SectionNumber = IMAGE_SYM_ABSOLUTE; break; case Symbol::DefinedSyntheticKind: // Relative symbols are unrepresentable in a COFF symbol table. @@ -1063,38 +1063,38 @@ default: { // Don't write symbols that won't be written to the output to the symbol // table. - Chunk *C = Def->getChunk(); - if (!C) + Chunk *c = def->getChunk(); + if (!c) return None; - OutputSection *OS = C->getOutputSection(); - if (!OS) + OutputSection *os = c->getOutputSection(); + if (!os) return None; - Sym.Value = Def->getRVA() - OS->getRVA(); - Sym.SectionNumber = OS->SectionIndex; + sym.Value = def->getRVA() - os->getRVA(); + sym.SectionNumber = os->sectionIndex; break; } } - StringRef Name = Def->getName(); - if (Name.size() > COFF::NameSize) { - Sym.Name.Offset.Zeroes = 0; - Sym.Name.Offset.Offset = addEntryToStringTable(Name); + StringRef name = def->getName(); + if (name.size() > COFF::NameSize) { + sym.Name.Offset.Zeroes = 0; + sym.Name.Offset.Offset = addEntryToStringTable(name); } else { - memset(Sym.Name.ShortName, 0, COFF::NameSize); - memcpy(Sym.Name.ShortName, Name.data(), Name.size()); + memset(sym.Name.ShortName, 0, COFF::NameSize); + memcpy(sym.Name.ShortName, name.data(), name.size()); } - if (auto *D = dyn_cast(Def)) { - COFFSymbolRef Ref = D->getCOFFSymbol(); - Sym.Type = Ref.getType(); - Sym.StorageClass = Ref.getStorageClass(); + if (auto *d = dyn_cast(def)) { + COFFSymbolRef ref = d->getCOFFSymbol(); + sym.Type = ref.getType(); + sym.StorageClass = ref.getStorageClass(); } else { - Sym.Type = IMAGE_SYM_TYPE_NULL; - Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL; + sym.Type = IMAGE_SYM_TYPE_NULL; + sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL; } - Sym.NumberOfAuxSymbols = 0; - return Sym; + sym.NumberOfAuxSymbols = 0; + return sym; } void Writer::createSymbolAndStringTable() { @@ -1106,120 +1106,120 @@ // solution where discardable sections have long names preserved and // non-discardable sections have their names truncated, to ensure that any // section which is mapped at runtime also has its name mapped at runtime. - for (OutputSection *Sec : OutputSections) { - if (Sec->Name.size() <= COFF::NameSize) + for (OutputSection *sec : outputSections) { + if (sec->name.size() <= COFF::NameSize) continue; - if ((Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) + if ((sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) continue; - Sec->setStringTableOff(addEntryToStringTable(Sec->Name)); + sec->setStringTableOff(addEntryToStringTable(sec->name)); } - if (Config->DebugDwarf || Config->DebugSymtab) { - for (ObjFile *File : ObjFile::Instances) { - for (Symbol *B : File->getSymbols()) { - auto *D = dyn_cast_or_null(B); - if (!D || D->WrittenToSymtab) + if (config->debugDwarf || config->debugSymtab) { + for (ObjFile *file : ObjFile::instances) { + for (Symbol *b : file->getSymbols()) { + auto *d = dyn_cast_or_null(b); + if (!d || d->writtenToSymtab) continue; - D->WrittenToSymtab = true; + d->writtenToSymtab = true; - if (Optional Sym = createSymbol(D)) - OutputSymtab.push_back(*Sym); + if (Optional sym = createSymbol(d)) + outputSymtab.push_back(*sym); } } } - if (OutputSymtab.empty() && Strtab.empty()) + if (outputSymtab.empty() && strtab.empty()) return; // We position the symbol table to be adjacent to the end of the last section. - uint64_t FileOff = FileSize; - PointerToSymbolTable = FileOff; - FileOff += OutputSymtab.size() * sizeof(coff_symbol16); - FileOff += 4 + Strtab.size(); - FileSize = alignTo(FileOff, Config->FileAlign); + uint64_t fileOff = fileSize; + pointerToSymbolTable = fileOff; + fileOff += outputSymtab.size() * sizeof(coff_symbol16); + fileOff += 4 + strtab.size(); + fileSize = alignTo(fileOff, config->fileAlign); } void Writer::mergeSections() { - if (!PdataSec->Chunks.empty()) { - FirstPdata = PdataSec->Chunks.front(); - LastPdata = PdataSec->Chunks.back(); + if (!pdataSec->chunks.empty()) { + firstPdata = pdataSec->chunks.front(); + lastPdata = pdataSec->chunks.back(); } - for (auto &P : Config->Merge) { - StringRef ToName = P.second; - if (P.first == ToName) + for (auto &p : config->merge) { + StringRef toName = p.second; + if (p.first == toName) continue; - StringSet<> Names; + StringSet<> names; while (1) { - if (!Names.insert(ToName).second) - fatal("/merge: cycle found for section '" + P.first + "'"); - auto I = Config->Merge.find(ToName); - if (I == Config->Merge.end()) + if (!names.insert(toName).second) + fatal("/merge: cycle found for section '" + p.first + "'"); + auto i = config->merge.find(toName); + if (i == config->merge.end()) break; - ToName = I->second; + toName = i->second; } - OutputSection *From = findSection(P.first); - OutputSection *To = findSection(ToName); - if (!From) + OutputSection *from = findSection(p.first); + OutputSection *to = findSection(toName); + if (!from) continue; - if (!To) { - From->Name = ToName; + if (!to) { + from->name = toName; continue; } - To->merge(From); + to->merge(from); } } // Visits all sections to assign incremental, non-overlapping RVAs and // file offsets. void Writer::assignAddresses() { - SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) + - sizeof(data_directory) * NumberOfDataDirectory + - sizeof(coff_section) * OutputSections.size(); - SizeOfHeaders += - Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); - SizeOfHeaders = alignTo(SizeOfHeaders, Config->FileAlign); - uint64_t RVA = PageSize; // The first page is kept unmapped. - FileSize = SizeOfHeaders; + sizeOfHeaders = dosStubSize + sizeof(PEMagic) + sizeof(coff_file_header) + + sizeof(data_directory) * numberOfDataDirectory + + sizeof(coff_section) * outputSections.size(); + sizeOfHeaders += + config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); + sizeOfHeaders = alignTo(sizeOfHeaders, config->fileAlign); + uint64_t rva = pageSize; // The first page is kept unmapped. + fileSize = sizeOfHeaders; - for (OutputSection *Sec : OutputSections) { - if (Sec == RelocSec) + for (OutputSection *sec : outputSections) { + if (sec == relocSec) addBaserels(); - uint64_t RawSize = 0, VirtualSize = 0; - Sec->Header.VirtualAddress = RVA; + uint64_t rawSize = 0, virtualSize = 0; + sec->header.VirtualAddress = rva; // If /FUNCTIONPADMIN is used, functions are padded in order to create a // hotpatchable image. - const bool IsCodeSection = - (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE) && - (Sec->Header.Characteristics & IMAGE_SCN_MEM_READ) && - (Sec->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE); - uint32_t Padding = IsCodeSection ? Config->FunctionPadMin : 0; - - for (Chunk *C : Sec->Chunks) { - if (Padding && C->isHotPatchable()) - VirtualSize += Padding; - VirtualSize = alignTo(VirtualSize, C->getAlignment()); - C->setRVA(RVA + VirtualSize); - VirtualSize += C->getSize(); - if (C->HasData) - RawSize = alignTo(VirtualSize, Config->FileAlign); - } - if (VirtualSize > UINT32_MAX) - error("section larger than 4 GiB: " + Sec->Name); - Sec->Header.VirtualSize = VirtualSize; - Sec->Header.SizeOfRawData = RawSize; - if (RawSize != 0) - Sec->Header.PointerToRawData = FileSize; - RVA += alignTo(VirtualSize, PageSize); - FileSize += alignTo(RawSize, Config->FileAlign); + const bool isCodeSection = + (sec->header.Characteristics & IMAGE_SCN_CNT_CODE) && + (sec->header.Characteristics & IMAGE_SCN_MEM_READ) && + (sec->header.Characteristics & IMAGE_SCN_MEM_EXECUTE); + uint32_t padding = isCodeSection ? config->functionPadMin : 0; + + for (Chunk *c : sec->chunks) { + if (padding && c->isHotPatchable()) + virtualSize += padding; + virtualSize = alignTo(virtualSize, c->getAlignment()); + c->setRVA(rva + virtualSize); + virtualSize += c->getSize(); + if (c->hasData) + rawSize = alignTo(virtualSize, config->fileAlign); + } + if (virtualSize > UINT32_MAX) + error("section larger than 4 GiB: " + sec->name); + sec->header.VirtualSize = virtualSize; + sec->header.SizeOfRawData = rawSize; + if (rawSize != 0) + sec->header.PointerToRawData = fileSize; + rva += alignTo(virtualSize, pageSize); + fileSize += alignTo(rawSize, config->fileAlign); } - SizeOfImage = alignTo(RVA, PageSize); + sizeOfImage = alignTo(rva, pageSize); // Assign addresses to sections in MergeChunks. - for (MergeChunk *MC : MergeChunk::Instances) - if (MC) - MC->assignSubsectionRVAs(); + for (MergeChunk *mc : MergeChunk::instances) + if (mc) + mc->assignSubsectionRVAs(); } template void Writer::writeHeader() { @@ -1228,249 +1228,249 @@ // under DOS, that program gets run (usually to just print an error message). // When run under Windows, the loader looks at AddressOfNewExeHeader and uses // the PE header instead. - uint8_t *Buf = Buffer->getBufferStart(); - auto *DOS = reinterpret_cast(Buf); - Buf += sizeof(dos_header); - DOS->Magic[0] = 'M'; - DOS->Magic[1] = 'Z'; - DOS->UsedBytesInTheLastPage = DOSStubSize % 512; - DOS->FileSizeInPages = divideCeil(DOSStubSize, 512); - DOS->HeaderSizeInParagraphs = sizeof(dos_header) / 16; + uint8_t *buf = buffer->getBufferStart(); + auto *dos = reinterpret_cast(buf); + buf += sizeof(dos_header); + dos->Magic[0] = 'M'; + dos->Magic[1] = 'Z'; + dos->UsedBytesInTheLastPage = dosStubSize % 512; + dos->FileSizeInPages = divideCeil(dosStubSize, 512); + dos->HeaderSizeInParagraphs = sizeof(dos_header) / 16; - DOS->AddressOfRelocationTable = sizeof(dos_header); - DOS->AddressOfNewExeHeader = DOSStubSize; + dos->AddressOfRelocationTable = sizeof(dos_header); + dos->AddressOfNewExeHeader = dosStubSize; // Write DOS program. - memcpy(Buf, DOSProgram, sizeof(DOSProgram)); - Buf += sizeof(DOSProgram); + memcpy(buf, dosProgram, sizeof(dosProgram)); + buf += sizeof(dosProgram); // Write PE magic - memcpy(Buf, PEMagic, sizeof(PEMagic)); - Buf += sizeof(PEMagic); + memcpy(buf, PEMagic, sizeof(PEMagic)); + buf += sizeof(PEMagic); // Write COFF header - auto *COFF = reinterpret_cast(Buf); - Buf += sizeof(*COFF); - COFF->Machine = Config->Machine; - COFF->NumberOfSections = OutputSections.size(); - COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; - if (Config->LargeAddressAware) - COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; - if (!Config->is64()) - COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE; - if (Config->DLL) - COFF->Characteristics |= IMAGE_FILE_DLL; - if (!Config->Relocatable) - COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED; - if (Config->SwaprunCD) - COFF->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP; - if (Config->SwaprunNet) - COFF->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP; - COFF->SizeOfOptionalHeader = - sizeof(PEHeaderTy) + sizeof(data_directory) * NumberOfDataDirectory; + auto *coff = reinterpret_cast(buf); + buf += sizeof(*coff); + coff->Machine = config->machine; + coff->NumberOfSections = outputSections.size(); + coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE; + if (config->largeAddressAware) + coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; + if (!config->is64()) + coff->Characteristics |= IMAGE_FILE_32BIT_MACHINE; + if (config->dll) + coff->Characteristics |= IMAGE_FILE_DLL; + if (!config->relocatable) + coff->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED; + if (config->swaprunCD) + coff->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP; + if (config->swaprunNet) + coff->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP; + coff->SizeOfOptionalHeader = + sizeof(PEHeaderTy) + sizeof(data_directory) * numberOfDataDirectory; // Write PE header - auto *PE = reinterpret_cast(Buf); - Buf += sizeof(*PE); - PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32; + auto *pe = reinterpret_cast(buf); + buf += sizeof(*pe); + pe->Magic = config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32; // If {Major,Minor}LinkerVersion is left at 0.0, then for some // reason signing the resulting PE file with Authenticode produces a // signature that fails to validate on Windows 7 (but is OK on 10). // Set it to 14.0, which is what VS2015 outputs, and which avoids // that problem. - PE->MajorLinkerVersion = 14; - PE->MinorLinkerVersion = 0; + pe->MajorLinkerVersion = 14; + pe->MinorLinkerVersion = 0; - PE->ImageBase = Config->ImageBase; - PE->SectionAlignment = PageSize; - PE->FileAlignment = Config->FileAlign; - PE->MajorImageVersion = Config->MajorImageVersion; - PE->MinorImageVersion = Config->MinorImageVersion; - PE->MajorOperatingSystemVersion = Config->MajorOSVersion; - PE->MinorOperatingSystemVersion = Config->MinorOSVersion; - PE->MajorSubsystemVersion = Config->MajorOSVersion; - PE->MinorSubsystemVersion = Config->MinorOSVersion; - PE->Subsystem = Config->Subsystem; - PE->SizeOfImage = SizeOfImage; - PE->SizeOfHeaders = SizeOfHeaders; - if (!Config->NoEntry) { - Defined *Entry = cast(Config->Entry); - PE->AddressOfEntryPoint = Entry->getRVA(); + pe->ImageBase = config->imageBase; + pe->SectionAlignment = pageSize; + pe->FileAlignment = config->fileAlign; + pe->MajorImageVersion = config->majorImageVersion; + pe->MinorImageVersion = config->minorImageVersion; + pe->MajorOperatingSystemVersion = config->majorOSVersion; + pe->MinorOperatingSystemVersion = config->minorOSVersion; + pe->MajorSubsystemVersion = config->majorOSVersion; + pe->MinorSubsystemVersion = config->minorOSVersion; + pe->Subsystem = config->subsystem; + pe->SizeOfImage = sizeOfImage; + pe->SizeOfHeaders = sizeOfHeaders; + if (!config->noEntry) { + Defined *entry = cast(config->entry); + pe->AddressOfEntryPoint = entry->getRVA(); // Pointer to thumb code must have the LSB set, so adjust it. - if (Config->Machine == ARMNT) - PE->AddressOfEntryPoint |= 1; + if (config->machine == ARMNT) + pe->AddressOfEntryPoint |= 1; } - PE->SizeOfStackReserve = Config->StackReserve; - PE->SizeOfStackCommit = Config->StackCommit; - PE->SizeOfHeapReserve = Config->HeapReserve; - PE->SizeOfHeapCommit = Config->HeapCommit; - if (Config->AppContainer) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER; - if (Config->DynamicBase) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; - if (Config->HighEntropyVA) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA; - if (!Config->AllowBind) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND; - if (Config->NxCompat) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT; - if (!Config->AllowIsolation) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION; - if (Config->GuardCF != GuardCFLevel::Off) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF; - if (Config->IntegrityCheck) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; - if (SetNoSEHCharacteristic) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH; - if (Config->TerminalServerAware) - PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; - PE->NumberOfRvaAndSize = NumberOfDataDirectory; - if (TextSec->getVirtualSize()) { - PE->BaseOfCode = TextSec->getRVA(); - PE->SizeOfCode = TextSec->getRawSize(); + pe->SizeOfStackReserve = config->stackReserve; + pe->SizeOfStackCommit = config->stackCommit; + pe->SizeOfHeapReserve = config->heapReserve; + pe->SizeOfHeapCommit = config->heapCommit; + if (config->appContainer) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER; + if (config->dynamicBase) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; + if (config->highEntropyVA) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA; + if (!config->allowBind) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND; + if (config->nxCompat) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT; + if (!config->allowIsolation) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION; + if (config->guardCF != GuardCFLevel::Off) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF; + if (config->integrityCheck) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY; + if (setNoSEHCharacteristic) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH; + if (config->terminalServerAware) + pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; + pe->NumberOfRvaAndSize = numberOfDataDirectory; + if (textSec->getVirtualSize()) { + pe->BaseOfCode = textSec->getRVA(); + pe->SizeOfCode = textSec->getRawSize(); } - PE->SizeOfInitializedData = getSizeOfInitializedData(); + pe->SizeOfInitializedData = getSizeOfInitializedData(); // Write data directory - auto *Dir = reinterpret_cast(Buf); - Buf += sizeof(*Dir) * NumberOfDataDirectory; - if (!Config->Exports.empty()) { - Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata.getRVA(); - Dir[EXPORT_TABLE].Size = Edata.getSize(); - } - if (ImportTableStart) { - Dir[IMPORT_TABLE].RelativeVirtualAddress = ImportTableStart->getRVA(); - Dir[IMPORT_TABLE].Size = ImportTableSize; - } - if (IATStart) { - Dir[IAT].RelativeVirtualAddress = IATStart->getRVA(); - Dir[IAT].Size = IATSize; - } - if (RsrcSec->getVirtualSize()) { - Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA(); - Dir[RESOURCE_TABLE].Size = RsrcSec->getVirtualSize(); - } - if (FirstPdata) { - Dir[EXCEPTION_TABLE].RelativeVirtualAddress = FirstPdata->getRVA(); - Dir[EXCEPTION_TABLE].Size = - LastPdata->getRVA() + LastPdata->getSize() - FirstPdata->getRVA(); - } - if (RelocSec->getVirtualSize()) { - Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = RelocSec->getRVA(); - Dir[BASE_RELOCATION_TABLE].Size = RelocSec->getVirtualSize(); - } - if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) { - if (Defined *B = dyn_cast(Sym)) { - Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA(); - Dir[TLS_TABLE].Size = Config->is64() + auto *dir = reinterpret_cast(buf); + buf += sizeof(*dir) * numberOfDataDirectory; + if (!config->exports.empty()) { + dir[EXPORT_TABLE].RelativeVirtualAddress = edata.getRVA(); + dir[EXPORT_TABLE].Size = edata.getSize(); + } + if (importTableStart) { + dir[IMPORT_TABLE].RelativeVirtualAddress = importTableStart->getRVA(); + dir[IMPORT_TABLE].Size = importTableSize; + } + if (iatStart) { + dir[IAT].RelativeVirtualAddress = iatStart->getRVA(); + dir[IAT].Size = iatSize; + } + if (rsrcSec->getVirtualSize()) { + dir[RESOURCE_TABLE].RelativeVirtualAddress = rsrcSec->getRVA(); + dir[RESOURCE_TABLE].Size = rsrcSec->getVirtualSize(); + } + if (firstPdata) { + dir[EXCEPTION_TABLE].RelativeVirtualAddress = firstPdata->getRVA(); + dir[EXCEPTION_TABLE].Size = + lastPdata->getRVA() + lastPdata->getSize() - firstPdata->getRVA(); + } + if (relocSec->getVirtualSize()) { + dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA(); + dir[BASE_RELOCATION_TABLE].Size = relocSec->getVirtualSize(); + } + if (Symbol *sym = symtab->findUnderscore("_tls_used")) { + if (Defined *b = dyn_cast(sym)) { + dir[TLS_TABLE].RelativeVirtualAddress = b->getRVA(); + dir[TLS_TABLE].Size = config->is64() ? sizeof(object::coff_tls_directory64) : sizeof(object::coff_tls_directory32); } } - if (DebugDirectory) { - Dir[DEBUG_DIRECTORY].RelativeVirtualAddress = DebugDirectory->getRVA(); - Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize(); - } - if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) { - if (auto *B = dyn_cast(Sym)) { - SectionChunk *SC = B->getChunk(); - assert(B->getRVA() >= SC->getRVA()); - uint64_t OffsetInChunk = B->getRVA() - SC->getRVA(); - if (!SC->HasData || OffsetInChunk + 4 > SC->getSize()) + if (debugDirectory) { + dir[DEBUG_DIRECTORY].RelativeVirtualAddress = debugDirectory->getRVA(); + dir[DEBUG_DIRECTORY].Size = debugDirectory->getSize(); + } + if (Symbol *sym = symtab->findUnderscore("_load_config_used")) { + if (auto *b = dyn_cast(sym)) { + SectionChunk *sc = b->getChunk(); + assert(b->getRVA() >= sc->getRVA()); + uint64_t offsetInChunk = b->getRVA() - sc->getRVA(); + if (!sc->hasData || offsetInChunk + 4 > sc->getSize()) fatal("_load_config_used is malformed"); - ArrayRef SecContents = SC->getContents(); - uint32_t LoadConfigSize = - *reinterpret_cast(&SecContents[OffsetInChunk]); - if (OffsetInChunk + LoadConfigSize > SC->getSize()) + ArrayRef secContents = sc->getContents(); + uint32_t loadConfigSize = + *reinterpret_cast(&secContents[offsetInChunk]); + if (offsetInChunk + loadConfigSize > sc->getSize()) fatal("_load_config_used is too large"); - Dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = B->getRVA(); - Dir[LOAD_CONFIG_TABLE].Size = LoadConfigSize; + dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = b->getRVA(); + dir[LOAD_CONFIG_TABLE].Size = loadConfigSize; } } - if (!DelayIdata.empty()) { - Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress = - DelayIdata.getDirRVA(); - Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize(); + if (!delayIdata.empty()) { + dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress = + delayIdata.getDirRVA(); + dir[DELAY_IMPORT_DESCRIPTOR].Size = delayIdata.getDirSize(); } // Write section table - for (OutputSection *Sec : OutputSections) { - Sec->writeHeaderTo(Buf); - Buf += sizeof(coff_section); + for (OutputSection *sec : outputSections) { + sec->writeHeaderTo(buf); + buf += sizeof(coff_section); } - SectionTable = ArrayRef( - Buf - OutputSections.size() * sizeof(coff_section), Buf); + sectionTable = ArrayRef( + buf - outputSections.size() * sizeof(coff_section), buf); - if (OutputSymtab.empty() && Strtab.empty()) + if (outputSymtab.empty() && strtab.empty()) return; - COFF->PointerToSymbolTable = PointerToSymbolTable; - uint32_t NumberOfSymbols = OutputSymtab.size(); - COFF->NumberOfSymbols = NumberOfSymbols; - auto *SymbolTable = reinterpret_cast( - Buffer->getBufferStart() + COFF->PointerToSymbolTable); - for (size_t I = 0; I != NumberOfSymbols; ++I) - SymbolTable[I] = OutputSymtab[I]; + coff->PointerToSymbolTable = pointerToSymbolTable; + uint32_t numberOfSymbols = outputSymtab.size(); + coff->NumberOfSymbols = numberOfSymbols; + auto *symbolTable = reinterpret_cast( + buffer->getBufferStart() + coff->PointerToSymbolTable); + for (size_t i = 0; i != numberOfSymbols; ++i) + symbolTable[i] = outputSymtab[i]; // Create the string table, it follows immediately after the symbol table. // The first 4 bytes is length including itself. - Buf = reinterpret_cast(&SymbolTable[NumberOfSymbols]); - write32le(Buf, Strtab.size() + 4); - if (!Strtab.empty()) - memcpy(Buf + 4, Strtab.data(), Strtab.size()); + buf = reinterpret_cast(&symbolTable[numberOfSymbols]); + write32le(buf, strtab.size() + 4); + if (!strtab.empty()) + memcpy(buf + 4, strtab.data(), strtab.size()); } -void Writer::openFile(StringRef Path) { - Buffer = CHECK( - FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable), - "failed to open " + Path); +void Writer::openFile(StringRef path) { + buffer = CHECK( + FileOutputBuffer::create(path, fileSize, FileOutputBuffer::F_executable), + "failed to open " + path); } void Writer::createSEHTable() { // Set the no SEH characteristic on x86 binaries unless we find exception // handlers. - SetNoSEHCharacteristic = true; + setNoSEHCharacteristic = true; - SymbolRVASet Handlers; - for (ObjFile *File : ObjFile::Instances) { + SymbolRVASet handlers; + for (ObjFile *file : ObjFile::instances) { // FIXME: We should error here instead of earlier unless /safeseh:no was // passed. - if (!File->hasSafeSEH()) + if (!file->hasSafeSEH()) return; - markSymbolsForRVATable(File, File->getSXDataChunks(), Handlers); + markSymbolsForRVATable(file, file->getSXDataChunks(), handlers); } // Remove the "no SEH" characteristic if all object files were built with // safeseh, we found some exception handlers, and there is a load config in // the object. - SetNoSEHCharacteristic = - Handlers.empty() || !Symtab->findUnderscore("_load_config_used"); + setNoSEHCharacteristic = + handlers.empty() || !symtab->findUnderscore("_load_config_used"); - maybeAddRVATable(std::move(Handlers), "__safe_se_handler_table", + maybeAddRVATable(std::move(handlers), "__safe_se_handler_table", "__safe_se_handler_count"); } // Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set // cannot contain duplicates. Therefore, the set is uniqued by Chunk and the // symbol's offset into that Chunk. -static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) { - Chunk *C = S->getChunk(); - if (auto *SC = dyn_cast(C)) - C = SC->Repl; // Look through ICF replacement. - uint32_t Off = S->getRVA() - (C ? C->getRVA() : 0); - RVASet.insert({C, Off}); +static void addSymbolToRVASet(SymbolRVASet &rvaSet, Defined *s) { + Chunk *c = s->getChunk(); + if (auto *sc = dyn_cast(c)) + c = sc->repl; // Look through ICF replacement. + uint32_t off = s->getRVA() - (c ? c->getRVA() : 0); + rvaSet.insert({c, off}); } // Given a symbol, add it to the GFIDs table if it is a live, defined, function // symbol in an executable section. -static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms, - Symbol *S) { - if (!S) +static void maybeAddAddressTakenFunction(SymbolRVASet &addressTakenSyms, + Symbol *s) { + if (!s) return; - switch (S->kind()) { + switch (s->kind()) { case Symbol::DefinedLocalImportKind: case Symbol::DefinedImportDataKind: // Defines an __imp_ pointer, so it is data, so it is ignored. @@ -1491,19 +1491,19 @@ case Symbol::DefinedImportThunkKind: // Thunks are always code, include them. - addSymbolToRVASet(AddressTakenSyms, cast(S)); + addSymbolToRVASet(addressTakenSyms, cast(s)); break; case Symbol::DefinedRegularKind: { // This is a regular, defined, symbol from a COFF file. Mark the symbol as // address taken if the symbol type is function and it's in an executable // section. - auto *D = cast(S); - if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { - SectionChunk *SC = dyn_cast(D->getChunk()); - if (SC && SC->Live && - SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) - addSymbolToRVASet(AddressTakenSyms, D); + auto *d = cast(s); + if (d->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { + SectionChunk *sc = dyn_cast(d->getChunk()); + if (sc && sc->live && + sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) + addSymbolToRVASet(addressTakenSyms, d); } break; } @@ -1512,23 +1512,23 @@ // Visit all relocations from all section contributions of this object file and // mark the relocation target as address-taken. -static void markSymbolsWithRelocations(ObjFile *File, - SymbolRVASet &UsedSymbols) { - for (Chunk *C : File->getChunks()) { +static void markSymbolsWithRelocations(ObjFile *file, + SymbolRVASet &usedSymbols) { + for (Chunk *c : file->getChunks()) { // We only care about live section chunks. Common chunks and other chunks // don't generally contain relocations. - SectionChunk *SC = dyn_cast(C); - if (!SC || !SC->Live) + SectionChunk *sc = dyn_cast(c); + if (!sc || !sc->live) continue; - for (const coff_relocation &Reloc : SC->getRelocs()) { - if (Config->Machine == I386 && Reloc.Type == COFF::IMAGE_REL_I386_REL32) + for (const coff_relocation &reloc : sc->getRelocs()) { + if (config->machine == I386 && reloc.Type == COFF::IMAGE_REL_I386_REL32) // Ignore relative relocations on x86. On x86_64 they can't be ignored // since they're also used to compute absolute addresses. continue; - Symbol *Ref = SC->File->getSymbol(Reloc.SymbolTableIndex); - maybeAddAddressTakenFunction(UsedSymbols, Ref); + Symbol *ref = sc->file->getSymbol(reloc.SymbolTableIndex); + maybeAddAddressTakenFunction(usedSymbols, ref); } } } @@ -1537,89 +1537,89 @@ // address-taken functions. It is sorted and uniqued, just like the safe SEH // table. void Writer::createGuardCFTables() { - SymbolRVASet AddressTakenSyms; - SymbolRVASet LongJmpTargets; - for (ObjFile *File : ObjFile::Instances) { + SymbolRVASet addressTakenSyms; + SymbolRVASet longJmpTargets; + for (ObjFile *file : ObjFile::instances) { // If the object was compiled with /guard:cf, the address taken symbols // are in .gfids$y sections, and the longjmp targets are in .gljmp$y // sections. If the object was not compiled with /guard:cf, we assume there // were no setjmp targets, and that all code symbols with relocations are // possibly address-taken. - if (File->hasGuardCF()) { - markSymbolsForRVATable(File, File->getGuardFidChunks(), AddressTakenSyms); - markSymbolsForRVATable(File, File->getGuardLJmpChunks(), LongJmpTargets); + if (file->hasGuardCF()) { + markSymbolsForRVATable(file, file->getGuardFidChunks(), addressTakenSyms); + markSymbolsForRVATable(file, file->getGuardLJmpChunks(), longJmpTargets); } else { - markSymbolsWithRelocations(File, AddressTakenSyms); + markSymbolsWithRelocations(file, addressTakenSyms); } } // Mark the image entry as address-taken. - if (Config->Entry) - maybeAddAddressTakenFunction(AddressTakenSyms, Config->Entry); + if (config->entry) + maybeAddAddressTakenFunction(addressTakenSyms, config->entry); // Mark exported symbols in executable sections as address-taken. - for (Export &E : Config->Exports) - maybeAddAddressTakenFunction(AddressTakenSyms, E.Sym); + for (Export &e : config->exports) + maybeAddAddressTakenFunction(addressTakenSyms, e.sym); // Ensure sections referenced in the gfid table are 16-byte aligned. - for (const ChunkAndOffset &C : AddressTakenSyms) - if (C.InputChunk->getAlignment() < 16) - C.InputChunk->setAlignment(16); + for (const ChunkAndOffset &c : addressTakenSyms) + if (c.inputChunk->getAlignment() < 16) + c.inputChunk->setAlignment(16); - maybeAddRVATable(std::move(AddressTakenSyms), "__guard_fids_table", + maybeAddRVATable(std::move(addressTakenSyms), "__guard_fids_table", "__guard_fids_count"); // Add the longjmp target table unless the user told us not to. - if (Config->GuardCF == GuardCFLevel::Full) - maybeAddRVATable(std::move(LongJmpTargets), "__guard_longjmp_table", + if (config->guardCF == GuardCFLevel::Full) + maybeAddRVATable(std::move(longJmpTargets), "__guard_longjmp_table", "__guard_longjmp_count"); // Set __guard_flags, which will be used in the load config to indicate that // /guard:cf was enabled. - uint32_t GuardFlags = uint32_t(coff_guard_flags::CFInstrumented) | + uint32_t guardFlags = uint32_t(coff_guard_flags::CFInstrumented) | uint32_t(coff_guard_flags::HasFidTable); - if (Config->GuardCF == GuardCFLevel::Full) - GuardFlags |= uint32_t(coff_guard_flags::HasLongJmpTable); - Symbol *FlagSym = Symtab->findUnderscore("__guard_flags"); - cast(FlagSym)->setVA(GuardFlags); + if (config->guardCF == GuardCFLevel::Full) + guardFlags |= uint32_t(coff_guard_flags::HasLongJmpTable); + Symbol *flagSym = symtab->findUnderscore("__guard_flags"); + cast(flagSym)->setVA(guardFlags); } // Take a list of input sections containing symbol table indices and add those // symbols to an RVA table. The challenge is that symbol RVAs are not known and // depend on the table size, so we can't directly build a set of integers. -void Writer::markSymbolsForRVATable(ObjFile *File, - ArrayRef SymIdxChunks, - SymbolRVASet &TableSymbols) { - for (SectionChunk *C : SymIdxChunks) { +void Writer::markSymbolsForRVATable(ObjFile *file, + ArrayRef symIdxChunks, + SymbolRVASet &tableSymbols) { + for (SectionChunk *c : symIdxChunks) { // Skip sections discarded by linker GC. This comes up when a .gfids section // is associated with something like a vtable and the vtable is discarded. // In this case, the associated gfids section is discarded, and we don't // mark the virtual member functions as address-taken by the vtable. - if (!C->Live) + if (!c->live) continue; // Validate that the contents look like symbol table indices. - ArrayRef Data = C->getContents(); - if (Data.size() % 4 != 0) { - warn("ignoring " + C->getSectionName() + - " symbol table index section in object " + toString(File)); + ArrayRef data = c->getContents(); + if (data.size() % 4 != 0) { + warn("ignoring " + c->getSectionName() + + " symbol table index section in object " + toString(file)); continue; } // Read each symbol table index and check if that symbol was included in the // final link. If so, add it to the table symbol set. - ArrayRef SymIndices( - reinterpret_cast(Data.data()), Data.size() / 4); - ArrayRef ObjSymbols = File->getSymbols(); - for (uint32_t SymIndex : SymIndices) { - if (SymIndex >= ObjSymbols.size()) { + ArrayRef symIndices( + reinterpret_cast(data.data()), data.size() / 4); + ArrayRef objSymbols = file->getSymbols(); + for (uint32_t symIndex : symIndices) { + if (symIndex >= objSymbols.size()) { warn("ignoring invalid symbol table index in section " + - C->getSectionName() + " in object " + toString(File)); + c->getSectionName() + " in object " + toString(file)); continue; } - if (Symbol *S = ObjSymbols[SymIndex]) { - if (S->isLive()) - addSymbolToRVASet(TableSymbols, cast(S)); + if (Symbol *s = objSymbols[symIndex]) { + if (s->isLive()) + addSymbolToRVASet(tableSymbols, cast(s)); } } } @@ -1628,18 +1628,18 @@ // Replace the absolute table symbol with a synthetic symbol pointing to // TableChunk so that we can emit base relocations for it and resolve section // relative relocations. -void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym, - StringRef CountSym) { - if (TableSymbols.empty()) +void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym, + StringRef countSym) { + if (tableSymbols.empty()) return; - RVATableChunk *TableChunk = make(std::move(TableSymbols)); - RdataSec->addChunk(TableChunk); + RVATableChunk *tableChunk = make(std::move(tableSymbols)); + rdataSec->addChunk(tableChunk); - Symbol *T = Symtab->findUnderscore(TableSym); - Symbol *C = Symtab->findUnderscore(CountSym); - replaceSymbol(T, T->getName(), TableChunk); - cast(C)->setVA(TableChunk->getSize() / 4); + Symbol *t = symtab->findUnderscore(tableSym); + Symbol *c = symtab->findUnderscore(countSym); + replaceSymbol(t, t->getName(), tableChunk); + cast(c)->setVA(tableChunk->getSize() / 4); } // MinGW specific. Gather all relocations that are imported from a DLL even @@ -1647,26 +1647,26 @@ // uses for fixing them up, and provide the synthetic symbols that the // runtime uses for finding the table. void Writer::createRuntimePseudoRelocs() { - std::vector Rels; + std::vector rels; - for (Chunk *C : Symtab->getChunks()) { - auto *SC = dyn_cast(C); - if (!SC || !SC->Live) + for (Chunk *c : symtab->getChunks()) { + auto *sc = dyn_cast(c); + if (!sc || !sc->live) continue; - SC->getRuntimePseudoRelocs(Rels); + sc->getRuntimePseudoRelocs(rels); } - if (!Rels.empty()) - log("Writing " + Twine(Rels.size()) + " runtime pseudo relocations"); - PseudoRelocTableChunk *Table = make(Rels); - RdataSec->addChunk(Table); - EmptyChunk *EndOfList = make(); - RdataSec->addChunk(EndOfList); - - Symbol *HeadSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__"); - Symbol *EndSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__"); - replaceSymbol(HeadSym, HeadSym->getName(), Table); - replaceSymbol(EndSym, EndSym->getName(), EndOfList); + if (!rels.empty()) + log("Writing " + Twine(rels.size()) + " runtime pseudo relocations"); + PseudoRelocTableChunk *table = make(rels); + rdataSec->addChunk(table); + EmptyChunk *endOfList = make(); + rdataSec->addChunk(endOfList); + + Symbol *headSym = symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__"); + Symbol *endSym = symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__"); + replaceSymbol(headSym, headSym->getName(), table); + replaceSymbol(endSym, endSym->getName(), endOfList); } // MinGW specific. @@ -1675,32 +1675,32 @@ // There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__ // and __DTOR_LIST__ respectively. void Writer::insertCtorDtorSymbols() { - AbsolutePointerChunk *CtorListHead = make(-1); - AbsolutePointerChunk *CtorListEnd = make(0); - AbsolutePointerChunk *DtorListHead = make(-1); - AbsolutePointerChunk *DtorListEnd = make(0); - CtorsSec->insertChunkAtStart(CtorListHead); - CtorsSec->addChunk(CtorListEnd); - DtorsSec->insertChunkAtStart(DtorListHead); - DtorsSec->addChunk(DtorListEnd); - - Symbol *CtorListSym = Symtab->findUnderscore("__CTOR_LIST__"); - Symbol *DtorListSym = Symtab->findUnderscore("__DTOR_LIST__"); - replaceSymbol(CtorListSym, CtorListSym->getName(), - CtorListHead); - replaceSymbol(DtorListSym, DtorListSym->getName(), - DtorListHead); + AbsolutePointerChunk *ctorListHead = make(-1); + AbsolutePointerChunk *ctorListEnd = make(0); + AbsolutePointerChunk *dtorListHead = make(-1); + AbsolutePointerChunk *dtorListEnd = make(0); + ctorsSec->insertChunkAtStart(ctorListHead); + ctorsSec->addChunk(ctorListEnd); + dtorsSec->insertChunkAtStart(dtorListHead); + dtorsSec->addChunk(dtorListEnd); + + Symbol *ctorListSym = symtab->findUnderscore("__CTOR_LIST__"); + Symbol *dtorListSym = symtab->findUnderscore("__DTOR_LIST__"); + replaceSymbol(ctorListSym, ctorListSym->getName(), + ctorListHead); + replaceSymbol(dtorListSym, dtorListSym->getName(), + dtorListHead); } // Handles /section options to allow users to overwrite // section attributes. void Writer::setSectionPermissions() { - for (auto &P : Config->Section) { - StringRef Name = P.first; - uint32_t Perm = P.second; - for (OutputSection *Sec : OutputSections) - if (Sec->Name == Name) - Sec->setPermissions(Perm); + for (auto &p : config->section) { + StringRef name = p.first; + uint32_t perm = p.second; + for (OutputSection *sec : outputSections) + if (sec->name == name) + sec->setPermissions(perm); } } @@ -1708,18 +1708,18 @@ void Writer::writeSections() { // Record the number of sections to apply section index relocations // against absolute symbols. See applySecIdx in Chunks.cpp.. - DefinedAbsolute::NumOutputSections = OutputSections.size(); + DefinedAbsolute::numOutputSections = outputSections.size(); - uint8_t *Buf = Buffer->getBufferStart(); - for (OutputSection *Sec : OutputSections) { - uint8_t *SecBuf = Buf + Sec->getFileOff(); + uint8_t *buf = buffer->getBufferStart(); + for (OutputSection *sec : outputSections) { + uint8_t *secBuf = buf + sec->getFileOff(); // Fill gaps between functions in .text with INT3 instructions // instead of leaving as NUL bytes (which can be interpreted as // ADD instructions). - if (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE) - memset(SecBuf, 0xCC, Sec->getRawSize()); - parallelForEach(Sec->Chunks, [&](Chunk *C) { - C->writeTo(SecBuf + C->getRVA() - Sec->getRVA()); + if (sec->header.Characteristics & IMAGE_SCN_CNT_CODE) + memset(secBuf, 0xCC, sec->getRawSize()); + parallelForEach(sec->chunks, [&](Chunk *c) { + c->writeTo(secBuf + c->getRVA() - sec->getRVA()); }); } } @@ -1731,8 +1731,8 @@ // 2) In all cases, the PE COFF file header also contains a timestamp. // For reproducibility, instead of a timestamp we want to use a hash of the // PE contents. - if (Config->Debug) { - assert(BuildId && "BuildId is not set!"); + if (config->debug) { + assert(buildId && "BuildId is not set!"); // BuildId->BuildId was filled in when the PDB was written. } @@ -1740,65 +1740,65 @@ // "timestamp" in the COFF file header, and the ones in the coff debug // directory. Now we can hash the file and write that hash to the various // timestamp fields in the file. - StringRef OutputFileData( - reinterpret_cast(Buffer->getBufferStart()), - Buffer->getBufferSize()); - - uint32_t Timestamp = Config->Timestamp; - uint64_t Hash = 0; - bool GenerateSyntheticBuildId = - Config->MinGW && Config->Debug && Config->PDBPath.empty(); + StringRef outputFileData( + reinterpret_cast(buffer->getBufferStart()), + buffer->getBufferSize()); + + uint32_t timestamp = config->timestamp; + uint64_t hash = 0; + bool generateSyntheticBuildId = + config->mingw && config->debug && config->pdbPath.empty(); - if (Config->Repro || GenerateSyntheticBuildId) - Hash = xxHash64(OutputFileData); + if (config->repro || generateSyntheticBuildId) + hash = xxHash64(outputFileData); - if (Config->Repro) - Timestamp = static_cast(Hash); + if (config->repro) + timestamp = static_cast(hash); - if (GenerateSyntheticBuildId) { + if (generateSyntheticBuildId) { // For MinGW builds without a PDB file, we still generate a build id // to allow associating a crash dump to the executable. - BuildId->BuildId->PDB70.CVSignature = OMF::Signature::PDB70; - BuildId->BuildId->PDB70.Age = 1; - memcpy(BuildId->BuildId->PDB70.Signature, &Hash, 8); + buildId->buildId->PDB70.CVSignature = OMF::Signature::PDB70; + buildId->buildId->PDB70.Age = 1; + memcpy(buildId->buildId->PDB70.Signature, &hash, 8); // xxhash only gives us 8 bytes, so put some fixed data in the other half. - memcpy(&BuildId->BuildId->PDB70.Signature[8], "LLD PDB.", 8); + memcpy(&buildId->buildId->PDB70.Signature[8], "LLD PDB.", 8); } - if (DebugDirectory) - DebugDirectory->setTimeDateStamp(Timestamp); + if (debugDirectory) + debugDirectory->setTimeDateStamp(timestamp); - uint8_t *Buf = Buffer->getBufferStart(); - Buf += DOSStubSize + sizeof(PEMagic); - object::coff_file_header *CoffHeader = - reinterpret_cast(Buf); - CoffHeader->TimeDateStamp = Timestamp; + uint8_t *buf = buffer->getBufferStart(); + buf += dosStubSize + sizeof(PEMagic); + object::coff_file_header *coffHeader = + reinterpret_cast(buf); + coffHeader->TimeDateStamp = timestamp; } // Sort .pdata section contents according to PE/COFF spec 5.5. void Writer::sortExceptionTable() { - if (!FirstPdata) + if (!firstPdata) return; // We assume .pdata contains function table entries only. - auto BufAddr = [&](Chunk *C) { - OutputSection *OS = C->getOutputSection(); - return Buffer->getBufferStart() + OS->getFileOff() + C->getRVA() - - OS->getRVA(); + auto bufAddr = [&](Chunk *c) { + OutputSection *os = c->getOutputSection(); + return buffer->getBufferStart() + os->getFileOff() + c->getRVA() - + os->getRVA(); }; - uint8_t *Begin = BufAddr(FirstPdata); - uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize(); - if (Config->Machine == AMD64) { - struct Entry { ulittle32_t Begin, End, Unwind; }; + uint8_t *begin = bufAddr(firstPdata); + uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize(); + if (config->machine == AMD64) { + struct Entry { ulittle32_t begin, end, unwind; }; parallelSort( - MutableArrayRef((Entry *)Begin, (Entry *)End), - [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); + MutableArrayRef((Entry *)begin, (Entry *)end), + [](const Entry &a, const Entry &b) { return a.begin < b.begin; }); return; } - if (Config->Machine == ARMNT || Config->Machine == ARM64) { - struct Entry { ulittle32_t Begin, Unwind; }; + if (config->machine == ARMNT || config->machine == ARM64) { + struct Entry { ulittle32_t begin, unwind; }; parallelSort( - MutableArrayRef((Entry *)Begin, (Entry *)End), - [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; }); + MutableArrayRef((Entry *)begin, (Entry *)end), + [](const Entry &a, const Entry &b) { return a.begin < b.begin; }); return; } errs() << "warning: don't know how to handle .pdata.\n"; @@ -1818,92 +1818,92 @@ // pointers in the order that they are listed in the object file (top to // bottom), otherwise global objects might not be initialized in the // correct order. -void Writer::sortCRTSectionChunks(std::vector &Chunks) { - auto SectionChunkOrder = [](const Chunk *A, const Chunk *B) { - auto SA = dyn_cast(A); - auto SB = dyn_cast(B); - assert(SA && SB && "Non-section chunks in CRT section!"); +void Writer::sortCRTSectionChunks(std::vector &chunks) { + auto sectionChunkOrder = [](const Chunk *a, const Chunk *b) { + auto sa = dyn_cast(a); + auto sb = dyn_cast(b); + assert(sa && sb && "Non-section chunks in CRT section!"); - StringRef SAObj = SA->File->MB.getBufferIdentifier(); - StringRef SBObj = SB->File->MB.getBufferIdentifier(); + StringRef sAObj = sa->file->mb.getBufferIdentifier(); + StringRef sBObj = sb->file->mb.getBufferIdentifier(); - return SAObj == SBObj && SA->getSectionNumber() < SB->getSectionNumber(); + return sAObj == sBObj && sa->getSectionNumber() < sb->getSectionNumber(); }; - llvm::stable_sort(Chunks, SectionChunkOrder); + llvm::stable_sort(chunks, sectionChunkOrder); - if (Config->Verbose) { - for (auto &C : Chunks) { - auto SC = dyn_cast(C); - log(" " + SC->File->MB.getBufferIdentifier().str() + - ", SectionID: " + Twine(SC->getSectionNumber())); + if (config->verbose) { + for (auto &c : chunks) { + auto sc = dyn_cast(c); + log(" " + sc->file->mb.getBufferIdentifier().str() + + ", SectionID: " + Twine(sc->getSectionNumber())); } } } -OutputSection *Writer::findSection(StringRef Name) { - for (OutputSection *Sec : OutputSections) - if (Sec->Name == Name) - return Sec; +OutputSection *Writer::findSection(StringRef name) { + for (OutputSection *sec : outputSections) + if (sec->name == name) + return sec; return nullptr; } uint32_t Writer::getSizeOfInitializedData() { - uint32_t Res = 0; - for (OutputSection *S : OutputSections) - if (S->Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) - Res += S->getRawSize(); - return Res; + uint32_t res = 0; + for (OutputSection *s : outputSections) + if (s->header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + res += s->getRawSize(); + return res; } // Add base relocations to .reloc section. void Writer::addBaserels() { - if (!Config->Relocatable) + if (!config->relocatable) return; - RelocSec->Chunks.clear(); - std::vector V; - for (OutputSection *Sec : OutputSections) { - if (Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) + relocSec->chunks.clear(); + std::vector v; + for (OutputSection *sec : outputSections) { + if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) continue; // Collect all locations for base relocations. - for (Chunk *C : Sec->Chunks) - C->getBaserels(&V); + for (Chunk *c : sec->chunks) + c->getBaserels(&v); // Add the addresses to .reloc section. - if (!V.empty()) - addBaserelBlocks(V); - V.clear(); + if (!v.empty()) + addBaserelBlocks(v); + v.clear(); } } // Add addresses to .reloc section. Note that addresses are grouped by page. -void Writer::addBaserelBlocks(std::vector &V) { - const uint32_t Mask = ~uint32_t(PageSize - 1); - uint32_t Page = V[0].RVA & Mask; - size_t I = 0, J = 1; - for (size_t E = V.size(); J < E; ++J) { - uint32_t P = V[J].RVA & Mask; - if (P == Page) +void Writer::addBaserelBlocks(std::vector &v) { + const uint32_t mask = ~uint32_t(pageSize - 1); + uint32_t page = v[0].rva & mask; + size_t i = 0, j = 1; + for (size_t e = v.size(); j < e; ++j) { + uint32_t p = v[j].rva & mask; + if (p == page) continue; - RelocSec->addChunk(make(Page, &V[I], &V[0] + J)); - I = J; - Page = P; + relocSec->addChunk(make(page, &v[i], &v[0] + j)); + i = j; + page = p; } - if (I == J) + if (i == j) return; - RelocSec->addChunk(make(Page, &V[I], &V[0] + J)); + relocSec->addChunk(make(page, &v[i], &v[0] + j)); } -PartialSection *Writer::createPartialSection(StringRef Name, - uint32_t OutChars) { - PartialSection *&PSec = PartialSections[{Name, OutChars}]; - if (PSec) - return PSec; - PSec = make(Name, OutChars); - return PSec; -} - -PartialSection *Writer::findPartialSection(StringRef Name, uint32_t OutChars) { - auto It = PartialSections.find({Name, OutChars}); - if (It != PartialSections.end()) - return It->second; +PartialSection *Writer::createPartialSection(StringRef name, + uint32_t outChars) { + PartialSection *&pSec = partialSections[{name, outChars}]; + if (pSec) + return pSec; + pSec = make(name, outChars); + return pSec; +} + +PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) { + auto it = partialSections.find({name, outChars}); + if (it != partialSections.end()) + return it->second; return nullptr; } Index: lld/trunk/Common/Args.cpp =================================================================== --- lld/trunk/Common/Args.cpp +++ lld/trunk/Common/Args.cpp @@ -19,64 +19,64 @@ // TODO(sbc): Remove this once CGOptLevel can be set completely based on bitcode // function metadata. -CodeGenOpt::Level lld::args::getCGOptLevel(int OptLevelLTO) { - if (OptLevelLTO == 3) +CodeGenOpt::Level lld::args::getCGOptLevel(int optLevelLTO) { + if (optLevelLTO == 3) return CodeGenOpt::Aggressive; - assert(OptLevelLTO < 3); + assert(optLevelLTO < 3); return CodeGenOpt::Default; } -int64_t lld::args::getInteger(opt::InputArgList &Args, unsigned Key, +int64_t lld::args::getInteger(opt::InputArgList &args, unsigned key, int64_t Default) { - auto *A = Args.getLastArg(Key); - if (!A) + auto *a = args.getLastArg(key); + if (!a) return Default; - int64_t V; - if (to_integer(A->getValue(), V, 10)) - return V; + int64_t v; + if (to_integer(a->getValue(), v, 10)) + return v; - StringRef Spelling = Args.getArgString(A->getIndex()); - error(Spelling + ": number expected, but got '" + A->getValue() + "'"); + StringRef spelling = args.getArgString(a->getIndex()); + error(spelling + ": number expected, but got '" + a->getValue() + "'"); return 0; } -std::vector lld::args::getStrings(opt::InputArgList &Args, int Id) { - std::vector V; - for (auto *Arg : Args.filtered(Id)) - V.push_back(Arg->getValue()); - return V; -} - -uint64_t lld::args::getZOptionValue(opt::InputArgList &Args, int Id, - StringRef Key, uint64_t Default) { - for (auto *Arg : Args.filtered_reverse(Id)) { - std::pair KV = StringRef(Arg->getValue()).split('='); - if (KV.first == Key) { - uint64_t Result = Default; - if (!to_integer(KV.second, Result)) - error("invalid " + Key + ": " + KV.second); - return Result; +std::vector lld::args::getStrings(opt::InputArgList &args, int id) { + std::vector v; + for (auto *arg : args.filtered(id)) + v.push_back(arg->getValue()); + return v; +} + +uint64_t lld::args::getZOptionValue(opt::InputArgList &args, int id, + StringRef key, uint64_t Default) { + for (auto *arg : args.filtered_reverse(id)) { + std::pair kv = StringRef(arg->getValue()).split('='); + if (kv.first == key) { + uint64_t result = Default; + if (!to_integer(kv.second, result)) + error("invalid " + key + ": " + kv.second); + return result; } } return Default; } -std::vector lld::args::getLines(MemoryBufferRef MB) { - SmallVector Arr; - MB.getBuffer().split(Arr, '\n'); - - std::vector Ret; - for (StringRef S : Arr) { - S = S.trim(); - if (!S.empty() && S[0] != '#') - Ret.push_back(S); +std::vector lld::args::getLines(MemoryBufferRef mb) { + SmallVector arr; + mb.getBuffer().split(arr, '\n'); + + std::vector ret; + for (StringRef s : arr) { + s = s.trim(); + if (!s.empty() && s[0] != '#') + ret.push_back(s); } - return Ret; + return ret; } -StringRef lld::args::getFilenameWithoutExe(StringRef Path) { - if (Path.endswith_lower(".exe")) - return sys::path::stem(Path); - return sys::path::filename(Path); +StringRef lld::args::getFilenameWithoutExe(StringRef path) { + if (path.endswith_lower(".exe")) + return sys::path::stem(path); + return sys::path::filename(path); } Index: lld/trunk/Common/ErrorHandler.cpp =================================================================== --- lld/trunk/Common/ErrorHandler.cpp +++ lld/trunk/Common/ErrorHandler.cpp @@ -26,29 +26,29 @@ // The functions defined in this file can be called from multiple threads, // but outs() or errs() are not thread-safe. We protect them using a mutex. -static std::mutex Mu; +static std::mutex mu; // Prints "\n" or does nothing, depending on Msg contents of // the previous call of this function. -static void newline(raw_ostream *ErrorOS, const Twine &Msg) { +static void newline(raw_ostream *errorOS, const Twine &msg) { // True if the previous error message contained "\n". // We want to separate multi-line error messages with a newline. - static bool Flag; + static bool flag; - if (Flag) - *ErrorOS << "\n"; - Flag = StringRef(Msg.str()).contains('\n'); + if (flag) + *errorOS << "\n"; + flag = StringRef(msg.str()).contains('\n'); } ErrorHandler &lld::errorHandler() { - static ErrorHandler Handler; - return Handler; + static ErrorHandler handler; + return handler; } -void lld::exitLld(int Val) { +void lld::exitLld(int val) { // Delete any temporary file, while keeping the memory mapping open. - if (errorHandler().OutputBuffer) - errorHandler().OutputBuffer->discard(); + if (errorHandler().outputBuffer) + errorHandler().outputBuffer->discard(); // Dealloc/destroy ManagedStatic variables before calling // _exit(). In a non-LTO build, this is a nop. In an LTO @@ -57,87 +57,87 @@ outs().flush(); errs().flush(); - _exit(Val); + _exit(val); } -void lld::diagnosticHandler(const DiagnosticInfo &DI) { - SmallString<128> S; - raw_svector_ostream OS(S); - DiagnosticPrinterRawOStream DP(OS); - DI.print(DP); - switch (DI.getSeverity()) { +void lld::diagnosticHandler(const DiagnosticInfo &di) { + SmallString<128> s; + raw_svector_ostream os(s); + DiagnosticPrinterRawOStream dp(os); + di.print(dp); + switch (di.getSeverity()) { case DS_Error: - error(S); + error(s); break; case DS_Warning: - warn(S); + warn(s); break; case DS_Remark: case DS_Note: - message(S); + message(s); break; } } -void lld::checkError(Error E) { - handleAllErrors(std::move(E), - [&](ErrorInfoBase &EIB) { error(EIB.message()); }); +void lld::checkError(Error e) { + handleAllErrors(std::move(e), + [&](ErrorInfoBase &eib) { error(eib.message()); }); } -void ErrorHandler::print(StringRef S, raw_ostream::Colors C) { - *ErrorOS << LogName << ": "; - if (ColorDiagnostics) { - ErrorOS->changeColor(C, true); - *ErrorOS << S; - ErrorOS->resetColor(); +void ErrorHandler::print(StringRef s, raw_ostream::Colors c) { + *errorOS << logName << ": "; + if (colorDiagnostics) { + errorOS->changeColor(c, true); + *errorOS << s; + errorOS->resetColor(); } else { - *ErrorOS << S; + *errorOS << s; } } -void ErrorHandler::log(const Twine &Msg) { - if (Verbose) { - std::lock_guard Lock(Mu); - *ErrorOS << LogName << ": " << Msg << "\n"; +void ErrorHandler::log(const Twine &msg) { + if (verbose) { + std::lock_guard lock(mu); + *errorOS << logName << ": " << msg << "\n"; } } -void ErrorHandler::message(const Twine &Msg) { - std::lock_guard Lock(Mu); - outs() << Msg << "\n"; +void ErrorHandler::message(const Twine &msg) { + std::lock_guard lock(mu); + outs() << msg << "\n"; outs().flush(); } -void ErrorHandler::warn(const Twine &Msg) { - if (FatalWarnings) { - error(Msg); +void ErrorHandler::warn(const Twine &msg) { + if (fatalWarnings) { + error(msg); return; } - std::lock_guard Lock(Mu); - newline(ErrorOS, Msg); + std::lock_guard lock(mu); + newline(errorOS, msg); print("warning: ", raw_ostream::MAGENTA); - *ErrorOS << Msg << "\n"; + *errorOS << msg << "\n"; } -void ErrorHandler::error(const Twine &Msg) { - std::lock_guard Lock(Mu); - newline(ErrorOS, Msg); +void ErrorHandler::error(const Twine &msg) { + std::lock_guard lock(mu); + newline(errorOS, msg); - if (ErrorLimit == 0 || ErrorCount < ErrorLimit) { + if (errorLimit == 0 || errorCount < errorLimit) { print("error: ", raw_ostream::RED); - *ErrorOS << Msg << "\n"; - } else if (ErrorCount == ErrorLimit) { + *errorOS << msg << "\n"; + } else if (errorCount == errorLimit) { print("error: ", raw_ostream::RED); - *ErrorOS << ErrorLimitExceededMsg << "\n"; - if (ExitEarly) + *errorOS << errorLimitExceededMsg << "\n"; + if (exitEarly) exitLld(1); } - ++ErrorCount; + ++errorCount; } -void ErrorHandler::fatal(const Twine &Msg) { - error(Msg); +void ErrorHandler::fatal(const Twine &msg) { + error(msg); exitLld(1); } Index: lld/trunk/Common/Filesystem.cpp =================================================================== --- lld/trunk/Common/Filesystem.cpp +++ lld/trunk/Common/Filesystem.cpp @@ -38,43 +38,43 @@ // // This function spawns a background thread to remove the file. // The calling thread returns almost immediately. -void lld::unlinkAsync(StringRef Path) { +void lld::unlinkAsync(StringRef path) { // Removing a file is async on windows. #if defined(_WIN32) sys::fs::remove(Path); #else - if (!ThreadsEnabled || !sys::fs::exists(Path) || - !sys::fs::is_regular_file(Path)) + if (!threadsEnabled || !sys::fs::exists(path) || + !sys::fs::is_regular_file(path)) return; // We cannot just remove path from a different thread because we are now going // to create path as a new file. // Instead we open the file and unlink it on this thread. The unlink is fast // since the open fd guarantees that it is not removing the last reference. - int FD; - std::error_code EC = sys::fs::openFileForRead(Path, FD); - sys::fs::remove(Path); + int fd; + std::error_code ec = sys::fs::openFileForRead(path, fd); + sys::fs::remove(path); - if (EC) + if (ec) return; // close and therefore remove TempPath in background. - std::mutex M; - std::condition_variable CV; - bool Started = false; - std::thread([&, FD] { + std::mutex m; + std::condition_variable cv; + bool started = false; + std::thread([&, fd] { { - std::lock_guard L(M); - Started = true; - CV.notify_all(); + std::lock_guard l(m); + started = true; + cv.notify_all(); } - ::close(FD); + ::close(fd); }).detach(); // GLIBC 2.26 and earlier have race condition that crashes an entire process // if the main thread calls exit(2) while other thread is starting up. - std::unique_lock L(M); - CV.wait(L, [&] { return Started; }); + std::unique_lock l(m); + cv.wait(l, [&] { return started; }); #endif } @@ -90,10 +90,10 @@ // FileOutputBuffer doesn't touch a desitnation file until commit() // is called. We use that class without calling commit() to predict // if the given file is writable. -std::error_code lld::tryCreateFile(StringRef Path) { - if (Path.empty()) +std::error_code lld::tryCreateFile(StringRef path) { + if (path.empty()) return std::error_code(); - if (Path == "-") + if (path == "-") return std::error_code(); - return errorToErrorCode(FileOutputBuffer::create(Path, 1).takeError()); + return errorToErrorCode(FileOutputBuffer::create(path, 1).takeError()); } Index: lld/trunk/Common/Memory.cpp =================================================================== --- lld/trunk/Common/Memory.cpp +++ lld/trunk/Common/Memory.cpp @@ -11,12 +11,12 @@ using namespace llvm; using namespace lld; -BumpPtrAllocator lld::BAlloc; -StringSaver lld::Saver{BAlloc}; -std::vector lld::SpecificAllocBase::Instances; +BumpPtrAllocator lld::bAlloc; +StringSaver lld::saver{bAlloc}; +std::vector lld::SpecificAllocBase::instances; void lld::freeArena() { - for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) - Alloc->reset(); - BAlloc.Reset(); + for (SpecificAllocBase *alloc : SpecificAllocBase::instances) + alloc->reset(); + bAlloc.Reset(); } Index: lld/trunk/Common/Reproduce.cpp =================================================================== --- lld/trunk/Common/Reproduce.cpp +++ lld/trunk/Common/Reproduce.cpp @@ -21,41 +21,41 @@ // assuming that the current directory is "/home/john/bar". // Returned string is a forward slash separated path even on Windows to avoid // a mess with backslash-as-escape and backslash-as-path-separator. -std::string lld::relativeToRoot(StringRef Path) { - SmallString<128> Abs = Path; - if (fs::make_absolute(Abs)) - return Path; - path::remove_dots(Abs, /*remove_dot_dot=*/true); +std::string lld::relativeToRoot(StringRef path) { + SmallString<128> abs = path; + if (fs::make_absolute(abs)) + return path; + path::remove_dots(abs, /*remove_dot_dot=*/true); // This is Windows specific. root_name() returns a drive letter // (e.g. "c:") or a UNC name (//net). We want to keep it as part // of the result. - SmallString<128> Res; - StringRef Root = path::root_name(Abs); - if (Root.endswith(":")) - Res = Root.drop_back(); - else if (Root.startswith("//")) - Res = Root.substr(2); + SmallString<128> res; + StringRef root = path::root_name(abs); + if (root.endswith(":")) + res = root.drop_back(); + else if (root.startswith("//")) + res = root.substr(2); - path::append(Res, path::relative_path(Abs)); - return path::convert_to_slash(Res); + path::append(res, path::relative_path(abs)); + return path::convert_to_slash(res); } // Quote a given string if it contains a space character. -std::string lld::quote(StringRef S) { - if (S.contains(' ')) - return ("\"" + S + "\"").str(); - return S; +std::string lld::quote(StringRef s) { + if (s.contains(' ')) + return ("\"" + s + "\"").str(); + return s; } // Converts an Arg to a string representation suitable for a response file. // To show an Arg in a diagnostic, use Arg::getAsString() instead. -std::string lld::toString(const opt::Arg &Arg) { - std::string K = Arg.getSpelling(); - if (Arg.getNumValues() == 0) - return K; - std::string V = quote(Arg.getValue()); - if (Arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) - return K + V; - return K + " " + V; +std::string lld::toString(const opt::Arg &arg) { + std::string k = arg.getSpelling(); + if (arg.getNumValues() == 0) + return k; + std::string v = quote(arg.getValue()); + if (arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) + return k + v; + return k + " " + v; } Index: lld/trunk/Common/Strings.cpp =================================================================== --- lld/trunk/Common/Strings.cpp +++ lld/trunk/Common/Strings.cpp @@ -19,85 +19,85 @@ using namespace lld; // Returns the demangled C++ symbol name for Name. -Optional lld::demangleItanium(StringRef Name) { +Optional lld::demangleItanium(StringRef name) { // itaniumDemangle can be used to demangle strings other than symbol // names which do not necessarily start with "_Z". Name can be // either a C or C++ symbol. Don't call itaniumDemangle if the name // does not look like a C++ symbol name to avoid getting unexpected // result for a C symbol that happens to match a mangled type name. - if (!Name.startswith("_Z")) + if (!name.startswith("_Z")) return None; - char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); - if (!Buf) + char *buf = itaniumDemangle(name.str().c_str(), nullptr, nullptr, nullptr); + if (!buf) return None; - std::string S(Buf); - free(Buf); - return S; + std::string s(buf); + free(buf); + return s; } -Optional lld::demangleMSVC(StringRef Name) { - std::string Prefix; - if (Name.consume_front("__imp_")) - Prefix = "__declspec(dllimport) "; +Optional lld::demangleMSVC(StringRef name) { + std::string prefix; + if (name.consume_front("__imp_")) + prefix = "__declspec(dllimport) "; // Demangle only C++ names. - if (!Name.startswith("?")) + if (!name.startswith("?")) return None; - char *Buf = microsoftDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); - if (!Buf) + char *buf = microsoftDemangle(name.str().c_str(), nullptr, nullptr, nullptr); + if (!buf) return None; - std::string S(Buf); - free(Buf); - return Prefix + S; + std::string s(buf); + free(buf); + return prefix + s; } -StringMatcher::StringMatcher(ArrayRef Pat) { - for (StringRef S : Pat) { - Expected Pat = GlobPattern::create(S); - if (!Pat) - error(toString(Pat.takeError())); +StringMatcher::StringMatcher(ArrayRef pat) { + for (StringRef s : pat) { + Expected pat = GlobPattern::create(s); + if (!pat) + error(toString(pat.takeError())); else - Patterns.push_back(*Pat); + patterns.push_back(*pat); } } -bool StringMatcher::match(StringRef S) const { - for (const GlobPattern &Pat : Patterns) - if (Pat.match(S)) +bool StringMatcher::match(StringRef s) const { + for (const GlobPattern &pat : patterns) + if (pat.match(s)) return true; return false; } // Converts a hex string (e.g. "deadbeef") to a vector. -std::vector lld::parseHex(StringRef S) { - std::vector Hex; - while (!S.empty()) { - StringRef B = S.substr(0, 2); - S = S.substr(2); - uint8_t H; - if (!to_integer(B, H, 16)) { - error("not a hexadecimal value: " + B); +std::vector lld::parseHex(StringRef s) { + std::vector hex; + while (!s.empty()) { + StringRef b = s.substr(0, 2); + s = s.substr(2); + uint8_t h; + if (!to_integer(b, h, 16)) { + error("not a hexadecimal value: " + b); return {}; } - Hex.push_back(H); + hex.push_back(h); } - return Hex; + return hex; } // Returns true if S is valid as a C language identifier. -bool lld::isValidCIdentifier(StringRef S) { - return !S.empty() && (isAlpha(S[0]) || S[0] == '_') && - std::all_of(S.begin() + 1, S.end(), - [](char C) { return C == '_' || isAlnum(C); }); +bool lld::isValidCIdentifier(StringRef s) { + return !s.empty() && (isAlpha(s[0]) || s[0] == '_') && + std::all_of(s.begin() + 1, s.end(), + [](char c) { return c == '_' || isAlnum(c); }); } // Write the contents of the a buffer to a file -void lld::saveBuffer(StringRef Buffer, const Twine &Path) { - std::error_code EC; - raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); - if (EC) - error("cannot create " + Path + ": " + EC.message()); - OS << Buffer; +void lld::saveBuffer(StringRef buffer, const Twine &path) { + std::error_code ec; + raw_fd_ostream os(path.str(), ec, sys::fs::OpenFlags::F_None); + if (ec) + error("cannot create " + path + ": " + ec.message()); + os << buffer; } Index: lld/trunk/Common/Threads.cpp =================================================================== --- lld/trunk/Common/Threads.cpp +++ lld/trunk/Common/Threads.cpp @@ -8,4 +8,4 @@ #include "lld/Common/Threads.h" -bool lld::ThreadsEnabled = true; +bool lld::threadsEnabled = true; Index: lld/trunk/Common/Timer.cpp =================================================================== --- lld/trunk/Common/Timer.cpp +++ lld/trunk/Common/Timer.cpp @@ -13,43 +13,43 @@ using namespace lld; using namespace llvm; -ScopedTimer::ScopedTimer(Timer &T) : T(&T) { T.start(); } +ScopedTimer::ScopedTimer(Timer &t) : t(&t) { t.start(); } void ScopedTimer::stop() { - if (!T) + if (!t) return; - T->stop(); - T = nullptr; + t->stop(); + t = nullptr; } ScopedTimer::~ScopedTimer() { stop(); } -Timer::Timer(llvm::StringRef Name) : Name(Name), Parent(nullptr) {} -Timer::Timer(llvm::StringRef Name, Timer &Parent) - : Name(Name), Parent(&Parent) {} +Timer::Timer(llvm::StringRef name) : name(name), parent(nullptr) {} +Timer::Timer(llvm::StringRef name, Timer &parent) + : name(name), parent(&parent) {} void Timer::start() { - if (Parent && Total.count() == 0) - Parent->Children.push_back(this); - StartTime = std::chrono::high_resolution_clock::now(); + if (parent && total.count() == 0) + parent->children.push_back(this); + startTime = std::chrono::high_resolution_clock::now(); } void Timer::stop() { - Total += (std::chrono::high_resolution_clock::now() - StartTime); + total += (std::chrono::high_resolution_clock::now() - startTime); } Timer &Timer::root() { - static Timer RootTimer("Total Link Time"); - return RootTimer; + static Timer rootTimer("Total Link Time"); + return rootTimer; } void Timer::print() { - double TotalDuration = static_cast(root().millis()); + double totalDuration = static_cast(root().millis()); // We want to print the grand total under all the intermediate phases, so we // print all children first, then print the total under that. - for (const auto &Child : Children) - Child->print(1, TotalDuration); + for (const auto &child : children) + child->print(1, totalDuration); message(std::string(49, '-')); @@ -58,22 +58,22 @@ double Timer::millis() const { return std::chrono::duration_cast>( - Total) + total) .count(); } -void Timer::print(int Depth, double TotalDuration, bool Recurse) const { - double P = 100.0 * millis() / TotalDuration; +void Timer::print(int depth, double totalDuration, bool recurse) const { + double p = 100.0 * millis() / totalDuration; - SmallString<32> Str; - llvm::raw_svector_ostream Stream(Str); - std::string S = std::string(Depth * 2, ' ') + Name + std::string(":"); - Stream << format("%-30s%5d ms (%5.1f%%)", S.c_str(), (int)millis(), P); - - message(Str); - - if (Recurse) { - for (const auto &Child : Children) - Child->print(Depth + 1, TotalDuration); + SmallString<32> str; + llvm::raw_svector_ostream stream(str); + std::string s = std::string(depth * 2, ' ') + name + std::string(":"); + stream << format("%-30s%5d ms (%5.1f%%)", s.c_str(), (int)millis(), p); + + message(str); + + if (recurse) { + for (const auto &child : children) + child->print(depth + 1, totalDuration); } } Index: lld/trunk/ELF/AArch64ErrataFix.cpp =================================================================== --- lld/trunk/ELF/AArch64ErrataFix.cpp +++ lld/trunk/ELF/AArch64ErrataFix.cpp @@ -398,9 +398,9 @@ patchee(p), patcheeOffset(off) { this->parent = p->getParent(); patchSym = addSyntheticLocal( - Saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0, + saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0, getSize(), *this); - addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, *this); + addSyntheticLocal(saver.save("$x"), STT_NOTYPE, 0, 0, *this); } uint64_t lld::elf::Patch843419Section::getLDSTAddr() const { @@ -485,8 +485,8 @@ void AArch64Err843419Patcher::insertPatches( InputSectionDescription &isd, std::vector &patches) { uint64_t isecLimit; - uint64_t prevISLimit = isd.sections.front()->outSecOff; - uint64_t patchUpperBound = prevISLimit + target->getThunkSectionSpacing(); + uint64_t prevIsecLimit = isd.sections.front()->outSecOff; + uint64_t patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); uint64_t outSecAddr = isd.sections.front()->getParent()->addr; // Set the OutSecOff of patches to the place where we want to insert them. @@ -498,14 +498,14 @@ isecLimit = isec->outSecOff + isec->getSize(); if (isecLimit > patchUpperBound) { while (patchIt != patchEnd) { - if ((*patchIt)->getLDSTAddr() - outSecAddr >= prevISLimit) + if ((*patchIt)->getLDSTAddr() - outSecAddr >= prevIsecLimit) break; - (*patchIt)->outSecOff = prevISLimit; + (*patchIt)->outSecOff = prevIsecLimit; ++patchIt; } - patchUpperBound = prevISLimit + target->getThunkSectionSpacing(); + patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); } - prevISLimit = isecLimit; + prevIsecLimit = isecLimit; } for (; patchIt != patchEnd; ++patchIt) { (*patchIt)->outSecOff = isecLimit; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -76,13 +76,13 @@ bool elf::link(ArrayRef args, bool canExitEarly, raw_ostream &error) { - errorHandler().LogName = args::getFilenameWithoutExe(args[0]); - errorHandler().ErrorLimitExceededMsg = + errorHandler().logName = args::getFilenameWithoutExe(args[0]); + errorHandler().errorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; - errorHandler().ErrorOS = &error; - errorHandler().ExitEarly = canExitEarly; - errorHandler().ColorDiagnostics = error.has_colors(); + errorHandler().errorOS = &error; + errorHandler().exitEarly = canExitEarly; + errorHandler().colorDiagnostics = error.has_colors(); inputSections.clear(); outputSections.clear(); @@ -399,7 +399,7 @@ opt::InputArgList args = parser.parse(argsArr.slice(1)); // Interpret this flag early because error() depends on them. - errorHandler().ErrorLimit = args::getInteger(args, OPT_error_limit, 20); + errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20); checkZOptions(args); // Handle -help @@ -783,10 +783,10 @@ // Initializes Config members by the command line options. static void readConfigs(opt::InputArgList &args) { - errorHandler().Verbose = args.hasArg(OPT_verbose); - errorHandler().FatalWarnings = + errorHandler().verbose = args.hasArg(OPT_verbose); + errorHandler().fatalWarnings = args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); - ThreadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); + threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); config->allowMultipleDefinition = args.hasFlag(OPT_allow_multiple_definition, @@ -939,7 +939,7 @@ // Parse LTO options. if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq)) - parseClangOption(Saver.save("-mcpu=" + StringRef(arg->getValue())), + parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())), arg->getSpelling()); for (auto *arg : args.filtered(OPT_plugin_opt)) @@ -1579,8 +1579,8 @@ if (!sym) continue; - Symbol *real = addUndefined(Saver.save("__real_" + name)); - Symbol *wrap = addUndefined(Saver.save("__wrap_" + name)); + Symbol *real = addUndefined(saver.save("__real_" + name)); + Symbol *wrap = addUndefined(saver.save("__wrap_" + name)); v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten Index: lld/trunk/ELF/DriverUtils.cpp =================================================================== --- lld/trunk/ELF/DriverUtils.cpp +++ lld/trunk/ELF/DriverUtils.cpp @@ -59,15 +59,15 @@ if (!arg) return; if (arg->getOption().getID() == OPT_color_diagnostics) { - errorHandler().ColorDiagnostics = true; + errorHandler().colorDiagnostics = true; } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { - errorHandler().ColorDiagnostics = false; + errorHandler().colorDiagnostics = false; } else { StringRef s = arg->getValue(); if (s == "always") - errorHandler().ColorDiagnostics = true; + errorHandler().colorDiagnostics = true; else if (s == "never") - errorHandler().ColorDiagnostics = false; + errorHandler().colorDiagnostics = false; else if (s != "auto") error("unknown option: --color-diagnostics=" + s); } @@ -101,7 +101,7 @@ for (size_t i = 0, e = args.size(); i != e; ++i) { StringRef s = args[i]; if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) { - v.push_back(Saver.save(s + "=" + args[i + 1]).data()); + v.push_back(saver.save(s + "=" + args[i + 1]).data()); ++i; } else { v.push_back(args[i]); @@ -124,7 +124,7 @@ // Expand response files (arguments in the form of @) // and then parse the argument again. - cl::ExpandResponseFiles(Saver, getQuotingStyle(args), vec); + cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec); concatLTOPluginOptions(vec); args = this->ParseArgs(vec, missingIndex, missingCount); Index: lld/trunk/ELF/ICF.cpp =================================================================== --- lld/trunk/ELF/ICF.cpp +++ lld/trunk/ELF/ICF.cpp @@ -392,7 +392,7 @@ void ICF::forEachClass(llvm::function_ref fn) { // If threading is disabled or the number of sections are // too small to use threading, call Fn sequentially. - if (!ThreadsEnabled || sections.size() < 1024) { + if (!threadsEnabled || sections.size() < 1024) { forEachClassRange(0, sections.size(), fn); ++cnt; return; Index: lld/trunk/ELF/InputFiles.cpp =================================================================== --- lld/trunk/ELF/InputFiles.cpp +++ lld/trunk/ELF/InputFiles.cpp @@ -92,7 +92,7 @@ // The --chroot option changes our virtual root directory. // This is useful when you are dealing with files created by --reproduce. if (!config->chroot.empty() && path.startswith("/")) - path = Saver.save(config->chroot + path); + path = saver.save(config->chroot + path); log(path); @@ -1366,7 +1366,7 @@ reinterpret_cast(verdefs[idx])->getAux()->vda_name; versionedNameBuffer.clear(); name = (name + "@" + verName).toStringRef(versionedNameBuffer); - symtab->addSymbol(SharedSymbol{*this, Saver.save(name), sym.getBinding(), + symtab->addSymbol(SharedSymbol{*this, saver.save(name), sym.getBinding(), sym.st_other, sym.getType(), sym.st_value, sym.st_size, alignment, idx}); } @@ -1432,8 +1432,8 @@ // symbols later in the link stage). So we append file offset to make // filename unique. StringRef name = archiveName.empty() - ? Saver.save(path) - : Saver.save(archiveName + "(" + path + " at " + + ? saver.save(path) + : saver.save(archiveName + "(" + path + " at " + utostr(offsetInArchive) + ")"); MemoryBufferRef mbref(mb.getBuffer(), name); @@ -1460,7 +1460,7 @@ static Symbol *createBitcodeSymbol(const std::vector &keptComdats, const lto::InputFile::Symbol &objSym, BitcodeFile &f) { - StringRef name = Saver.save(objSym.getName()); + StringRef name = saver.save(objSym.getName()); uint8_t binding = objSym.isWeak() ? STB_WEAK : STB_GLOBAL; uint8_t type = objSym.isTLS() ? STT_TLS : STT_NOTYPE; uint8_t visibility = mapVisibility(objSym.getVisibility()); @@ -1513,11 +1513,11 @@ if (!isAlnum(s[i])) s[i] = '_'; - symtab->addSymbol(Defined{nullptr, Saver.save(s + "_start"), STB_GLOBAL, + symtab->addSymbol(Defined{nullptr, saver.save(s + "_start"), STB_GLOBAL, STV_DEFAULT, STT_OBJECT, 0, 0, section}); - symtab->addSymbol(Defined{nullptr, Saver.save(s + "_end"), STB_GLOBAL, + symtab->addSymbol(Defined{nullptr, saver.save(s + "_end"), STB_GLOBAL, STV_DEFAULT, STT_OBJECT, data.size(), 0, section}); - symtab->addSymbol(Defined{nullptr, Saver.save(s + "_size"), STB_GLOBAL, + symtab->addSymbol(Defined{nullptr, saver.save(s + "_size"), STB_GLOBAL, STV_DEFAULT, STT_OBJECT, data.size(), 0, nullptr}); } @@ -1566,7 +1566,7 @@ for (const lto::InputFile::Symbol &sym : obj->symbols()) { if (sym.isUndefined()) continue; - symtab->addSymbol(LazyObject{*this, Saver.save(sym.getName())}); + symtab->addSymbol(LazyObject{*this, saver.save(sym.getName())}); } return; } Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -148,7 +148,7 @@ { static std::mutex mu; std::lock_guard lock(mu); - uncompressedBuf = BAlloc.Allocate(size); + uncompressedBuf = bAlloc.Allocate(size); } if (Error e = zlib::uncompress(toStringRef(rawData), uncompressedBuf, size)) @@ -231,7 +231,7 @@ // Restore the original section name. // (e.g. ".zdebug_info" -> ".debug_info") - name = Saver.save("." + name.substr(2)); + name = saver.save("." + name.substr(2)); return; } Index: lld/trunk/ELF/MarkLive.cpp =================================================================== --- lld/trunk/ELF/MarkLive.cpp +++ lld/trunk/ELF/MarkLive.cpp @@ -260,8 +260,8 @@ if (isReserved(sec) || script->shouldKeep(sec)) { enqueue(sec, 0); } else if (isValidCIdentifier(sec->name)) { - cNamedSections[Saver.save("__start_" + sec->name)].push_back(sec); - cNamedSections[Saver.save("__stop_" + sec->name)].push_back(sec); + cNamedSections[saver.save("__start_" + sec->name)].push_back(sec); + cNamedSections[saver.save("__stop_" + sec->name)].push_back(sec); } } Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -1639,18 +1639,18 @@ lastThunkLowerBound = isdEnd - thunkSectionSpacing; uint32_t isecLimit; - uint32_t prevISLimit = isdBegin; + uint32_t prevIsecLimit = isdBegin; uint32_t thunkUpperBound = isdBegin + thunkSectionSpacing; for (const InputSection *isec : isd->sections) { isecLimit = isec->outSecOff + isec->getSize(); if (isecLimit > thunkUpperBound) { - addThunkSection(os, isd, prevISLimit); - thunkUpperBound = prevISLimit + thunkSectionSpacing; + addThunkSection(os, isd, prevIsecLimit); + thunkUpperBound = prevIsecLimit + thunkSectionSpacing; } if (isecLimit > lastThunkLowerBound) break; - prevISLimit = isecLimit; + prevIsecLimit = isecLimit; } addThunkSection(os, isd, isecLimit); }); Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -280,7 +280,7 @@ SmallString<128> pathData; StringRef path = (config->sysroot + s).toStringRef(pathData); if (sys::fs::exists(path)) { - driver->addFile(Saver.save(path), /*WithLOption=*/false); + driver->addFile(saver.save(path), /*WithLOption=*/false); return; } } @@ -291,7 +291,7 @@ if (config->sysroot.empty()) driver->addFile(s.substr(1), /*WithLOption=*/false); else - driver->addFile(Saver.save(config->sysroot + "/" + s.substr(1)), + driver->addFile(saver.save(config->sysroot + "/" + s.substr(1)), /*WithLOption=*/false); } else if (s.startswith("-l")) { driver->addLibrary(s.substr(2)); @@ -299,7 +299,7 @@ driver->addFile(s, /*WithLOption=*/false); } else { if (Optional path = findFromSearchPaths(s)) - driver->addFile(Saver.save(*path), /*WithLOption=*/true); + driver->addFile(saver.save(*path), /*WithLOption=*/true); else setError("unable to find " + s); } Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -72,7 +72,7 @@ // This is only for testing. StringRef s = getenv("LLD_VERSION"); if (s.empty()) - s = Saver.save(Twine("Linker: ") + getLLDVersion()); + s = saver.save(Twine("Linker: ") + getLLDVersion()); // +1 to include the terminating '\0'. return {(const uint8_t *)s.data(), s.size() + 1}; @@ -254,7 +254,7 @@ InputSection *elf::createInterpSection() { // StringSaver guarantees that the returned string ends with '\0'. - StringRef s = Saver.save(config->dynamicLinker); + StringRef s = saver.save(config->dynamicLinker); ArrayRef contents = {(const uint8_t *)s.data(), s.size() + 1}; auto *sec = make(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents, @@ -2530,7 +2530,7 @@ // speed it up. size_t numShards = 32; size_t concurrency = 1; - if (ThreadsEnabled) + if (threadsEnabled) concurrency = std::min(PowerOf2Floor(hardware_concurrency()), numShards); @@ -2973,7 +2973,7 @@ // Concurrency level. Must be a power of 2 to avoid expensive modulo // operations in the following tight loop. size_t concurrency = 1; - if (ThreadsEnabled) + if (threadsEnabled) concurrency = std::min(PowerOf2Floor(hardware_concurrency()), numShards); Index: lld/trunk/ELF/Thunks.cpp =================================================================== --- lld/trunk/ELF/Thunks.cpp +++ lld/trunk/ELF/Thunks.cpp @@ -350,7 +350,7 @@ } void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__AArch64AbsLongThunk_" + destination.getName()), + addSymbol(saver.save("__AArch64AbsLongThunk_" + destination.getName()), STT_FUNC, 0, isec); addSymbol("$x", STT_NOTYPE, 0, isec); addSymbol("$d", STT_NOTYPE, 8, isec); @@ -376,7 +376,7 @@ } void AArch64ADRPThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__AArch64ADRPThunk_" + destination.getName()), STT_FUNC, + addSymbol(saver.save("__AArch64ADRPThunk_" + destination.getName()), STT_FUNC, 0, isec); addSymbol("$x", STT_NOTYPE, 0, isec); } @@ -476,7 +476,7 @@ } void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__ARMv7ABSLongThunk_" + destination.getName()), + addSymbol(saver.save("__ARMv7ABSLongThunk_" + destination.getName()), STT_FUNC, 0, isec); addSymbol("$a", STT_NOTYPE, 0, isec); } @@ -494,7 +494,7 @@ } void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + destination.getName()), + addSymbol(saver.save("__Thumbv7ABSLongThunk_" + destination.getName()), STT_FUNC, 1, isec); addSymbol("$t", STT_NOTYPE, 0, isec); } @@ -515,7 +515,7 @@ } void ARMV7PILongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__ARMV7PILongThunk_" + destination.getName()), STT_FUNC, + addSymbol(saver.save("__ARMV7PILongThunk_" + destination.getName()), STT_FUNC, 0, isec); addSymbol("$a", STT_NOTYPE, 0, isec); } @@ -536,7 +536,7 @@ } void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__ThumbV7PILongThunk_" + destination.getName()), + addSymbol(saver.save("__ThumbV7PILongThunk_" + destination.getName()), STT_FUNC, 1, isec); addSymbol("$t", STT_NOTYPE, 0, isec); } @@ -551,7 +551,7 @@ } void ARMV5ABSLongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__ARMv5ABSLongThunk_" + destination.getName()), + addSymbol(saver.save("__ARMv5ABSLongThunk_" + destination.getName()), STT_FUNC, 0, isec); addSymbol("$a", STT_NOTYPE, 0, isec); addSymbol("$d", STT_NOTYPE, 4, isec); @@ -577,7 +577,7 @@ } void ARMV5PILongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__ARMV5PILongThunk_" + destination.getName()), STT_FUNC, + addSymbol(saver.save("__ARMV5PILongThunk_" + destination.getName()), STT_FUNC, 0, isec); addSymbol("$a", STT_NOTYPE, 0, isec); addSymbol("$d", STT_NOTYPE, 12, isec); @@ -607,7 +607,7 @@ } void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__Thumbv6MABSLongThunk_" + destination.getName()), + addSymbol(saver.save("__Thumbv6MABSLongThunk_" + destination.getName()), STT_FUNC, 1, isec); addSymbol("$t", STT_NOTYPE, 0, isec); addSymbol("$d", STT_NOTYPE, 8, isec); @@ -633,7 +633,7 @@ } void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__Thumbv6MPILongThunk_" + destination.getName()), + addSymbol(saver.save("__Thumbv6MPILongThunk_" + destination.getName()), STT_FUNC, 1, isec); addSymbol("$t", STT_NOTYPE, 0, isec); addSymbol("$d", STT_NOTYPE, 12, isec); @@ -651,7 +651,7 @@ } void MipsThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0, + addSymbol(saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); } @@ -675,7 +675,7 @@ void MicroMipsThunk::addSymbols(ThunkSection &isec) { Defined *d = addSymbol( - Saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); + saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); d->stOther |= STO_MIPS_MICROMIPS; } @@ -699,7 +699,7 @@ void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) { Defined *d = addSymbol( - Saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); + saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); d->stOther |= STO_MIPS_MICROMIPS; } @@ -754,7 +754,7 @@ else os << ".plt_pic32."; os << destination.getName(); - addSymbol(Saver.save(os.str()), STT_FUNC, 0, isec); + addSymbol(saver.save(os.str()), STT_FUNC, 0, isec); } bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec, @@ -780,7 +780,7 @@ } void PPC64PltCallStub::addSymbols(ThunkSection &isec) { - Defined *s = addSymbol(Saver.save("__plt_" + destination.getName()), STT_FUNC, + Defined *s = addSymbol(saver.save("__plt_" + destination.getName()), STT_FUNC, 0, isec); s->needsTocRestore = true; } @@ -791,7 +791,7 @@ } void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) { - addSymbol(Saver.save("__long_branch_" + destination.getName()), STT_FUNC, 0, + addSymbol(saver.save("__long_branch_" + destination.getName()), STT_FUNC, 0, isec); } Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -42,7 +42,7 @@ // The writer writes a SymbolTable result to a file. template class Writer { public: - Writer() : buffer(errorHandler().OutputBuffer) {} + Writer() : buffer(errorHandler().outputBuffer) {} using Elf_Shdr = typename ELFT::Shdr; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Phdr = typename ELFT::Phdr; @@ -103,8 +103,8 @@ if (InputSectionBase *rel = isec->getRelocatedSection()) { OutputSection *out = rel->getOutputSection(); if (s->type == SHT_RELA) - return Saver.save(".rela" + out->name); - return Saver.save(".rel" + out->name); + return saver.save(".rela" + out->name); + return saver.save(".rel" + out->name); } } @@ -2006,8 +2006,8 @@ StringRef s = sec->name; if (!isValidCIdentifier(s)) return; - addOptionalRegular(Saver.save("__start_" + s), sec, 0, STV_PROTECTED); - addOptionalRegular(Saver.save("__stop_" + s), sec, -1, STV_PROTECTED); + addOptionalRegular(saver.save("__start_" + s), sec, 0, STV_PROTECTED); + addOptionalRegular(saver.save("__stop_" + s), sec, -1, STV_PROTECTED); } static bool needsPtLoad(OutputSection *sec) { Index: lld/trunk/MinGW/Driver.cpp =================================================================== --- lld/trunk/MinGW/Driver.cpp +++ lld/trunk/MinGW/Driver.cpp @@ -65,7 +65,7 @@ #undef PREFIX // Create table mapping all options defined in Options.td -static const opt::OptTable::Info InfoTable[] = { +static const opt::OptTable::Info infoTable[] = { #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, @@ -76,14 +76,14 @@ namespace { class MinGWOptTable : public opt::OptTable { public: - MinGWOptTable() : OptTable(InfoTable, false) {} - opt::InputArgList parse(ArrayRef Argv); + MinGWOptTable() : OptTable(infoTable, false) {} + opt::InputArgList parse(ArrayRef argv); }; } // namespace -static void printHelp(const char *Argv0) { +static void printHelp(const char *argv0) { MinGWOptTable().PrintHelp( - outs(), (std::string(Argv0) + " [options] file...").c_str(), "lld", + outs(), (std::string(argv0) + " [options] file...").c_str(), "lld", false /*ShowHidden*/, true /*ShowAllAliases*/); outs() << "\n"; } @@ -94,58 +94,58 @@ return cl::TokenizeGNUCommandLine; } -opt::InputArgList MinGWOptTable::parse(ArrayRef Argv) { - unsigned MissingIndex; - unsigned MissingCount; - - SmallVector Vec(Argv.data(), Argv.data() + Argv.size()); - cl::ExpandResponseFiles(Saver, getQuotingStyle(), Vec); - opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); - - if (MissingCount) - fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument"); - for (auto *Arg : Args.filtered(OPT_UNKNOWN)) - fatal("unknown argument: " + Arg->getAsString(Args)); - return Args; +opt::InputArgList MinGWOptTable::parse(ArrayRef argv) { + unsigned missingIndex; + unsigned missingCount; + + SmallVector vec(argv.data(), argv.data() + argv.size()); + cl::ExpandResponseFiles(saver, getQuotingStyle(), vec); + opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); + + if (missingCount) + fatal(StringRef(args.getArgString(missingIndex)) + ": missing argument"); + for (auto *arg : args.filtered(OPT_UNKNOWN)) + fatal("unknown argument: " + arg->getAsString(args)); + return args; } // Find a file by concatenating given paths. -static Optional findFile(StringRef Path1, const Twine &Path2) { - SmallString<128> S; - sys::path::append(S, Path1, Path2); - if (sys::fs::exists(S)) - return S.str().str(); +static Optional findFile(StringRef path1, const Twine &path2) { + SmallString<128> s; + sys::path::append(s, path1, path2); + if (sys::fs::exists(s)) + return s.str().str(); return None; } // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. static std::string -searchLibrary(StringRef Name, ArrayRef SearchPaths, bool BStatic) { - if (Name.startswith(":")) { - for (StringRef Dir : SearchPaths) - if (Optional S = findFile(Dir, Name.substr(1))) - return *S; - fatal("unable to find library -l" + Name); +searchLibrary(StringRef name, ArrayRef searchPaths, bool bStatic) { + if (name.startswith(":")) { + for (StringRef dir : searchPaths) + if (Optional s = findFile(dir, name.substr(1))) + return *s; + fatal("unable to find library -l" + name); } - for (StringRef Dir : SearchPaths) { - if (!BStatic) - if (Optional S = findFile(Dir, "lib" + Name + ".dll.a")) - return *S; - if (Optional S = findFile(Dir, "lib" + Name + ".a")) - return *S; + for (StringRef dir : searchPaths) { + if (!bStatic) + if (Optional s = findFile(dir, "lib" + name + ".dll.a")) + return *s; + if (Optional s = findFile(dir, "lib" + name + ".a")) + return *s; } - fatal("unable to find library -l" + Name); + fatal("unable to find library -l" + name); } // Convert Unix-ish command line arguments to Windows-ish ones and // then call coff::link. -bool mingw::link(ArrayRef ArgsArr, raw_ostream &Diag) { - MinGWOptTable Parser; - opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); +bool mingw::link(ArrayRef argsArr, raw_ostream &diag) { + MinGWOptTable parser; + opt::InputArgList args = parser.parse(argsArr.slice(1)); - if (Args.hasArg(OPT_help)) { - printHelp(ArgsArr[0]); + if (args.hasArg(OPT_help)) { + printHelp(argsArr[0]); return true; } @@ -154,199 +154,199 @@ // still the newest version in March 2017) or earlier to recognize LLD as // a GNU compatible linker. As long as an output for the -v option // contains "GNU" or "with BFD", they recognize us as GNU-compatible. - if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) + if (args.hasArg(OPT_v) || args.hasArg(OPT_version)) message(getLLDVersion() + " (compatible with GNU linkers)"); // The behavior of -v or --version is a bit strange, but this is // needed for compatibility with GNU linkers. - if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) + if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) return true; - if (Args.hasArg(OPT_version)) + if (args.hasArg(OPT_version)) return true; - if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l)) + if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) fatal("no input files"); - std::vector LinkArgs; - auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); }; + std::vector linkArgs; + auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); }; - Add("lld-link"); - Add("-lldmingw"); + add("lld-link"); + add("-lldmingw"); - if (auto *A = Args.getLastArg(OPT_entry)) { - StringRef S = A->getValue(); - if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_")) - Add("-entry:" + S.substr(1)); + if (auto *a = args.getLastArg(OPT_entry)) { + StringRef s = a->getValue(); + if (args.getLastArgValue(OPT_m) == "i386pe" && s.startswith("_")) + add("-entry:" + s.substr(1)); else - Add("-entry:" + S); + add("-entry:" + s); } - if (Args.hasArg(OPT_major_os_version, OPT_minor_os_version, + if (args.hasArg(OPT_major_os_version, OPT_minor_os_version, OPT_major_subsystem_version, OPT_minor_subsystem_version)) { - auto *MajOSVer = Args.getLastArg(OPT_major_os_version); - auto *MinOSVer = Args.getLastArg(OPT_minor_os_version); - auto *MajSubSysVer = Args.getLastArg(OPT_major_subsystem_version); - auto *MinSubSysVer = Args.getLastArg(OPT_minor_subsystem_version); - if (MajOSVer && MajSubSysVer && - StringRef(MajOSVer->getValue()) != StringRef(MajSubSysVer->getValue())) + auto *majOSVer = args.getLastArg(OPT_major_os_version); + auto *minOSVer = args.getLastArg(OPT_minor_os_version); + auto *majSubSysVer = args.getLastArg(OPT_major_subsystem_version); + auto *minSubSysVer = args.getLastArg(OPT_minor_subsystem_version); + if (majOSVer && majSubSysVer && + StringRef(majOSVer->getValue()) != StringRef(majSubSysVer->getValue())) warn("--major-os-version and --major-subsystem-version set to differing " "versions, not supported"); - if (MinOSVer && MinSubSysVer && - StringRef(MinOSVer->getValue()) != StringRef(MinSubSysVer->getValue())) + if (minOSVer && minSubSysVer && + StringRef(minOSVer->getValue()) != StringRef(minSubSysVer->getValue())) warn("--minor-os-version and --minor-subsystem-version set to differing " "versions, not supported"); - StringRef SubSys = Args.getLastArgValue(OPT_subs, "default"); - StringRef Major = MajOSVer ? MajOSVer->getValue() - : MajSubSysVer ? MajSubSysVer->getValue() : "6"; - StringRef Minor = MinOSVer ? MinOSVer->getValue() - : MinSubSysVer ? MinSubSysVer->getValue() : ""; - StringRef Sep = Minor.empty() ? "" : "."; - Add("-subsystem:" + SubSys + "," + Major + Sep + Minor); - } else if (auto *A = Args.getLastArg(OPT_subs)) { - Add("-subsystem:" + StringRef(A->getValue())); + StringRef subSys = args.getLastArgValue(OPT_subs, "default"); + StringRef major = majOSVer ? majOSVer->getValue() + : majSubSysVer ? majSubSysVer->getValue() : "6"; + StringRef minor = minOSVer ? minOSVer->getValue() + : minSubSysVer ? minSubSysVer->getValue() : ""; + StringRef sep = minor.empty() ? "" : "."; + add("-subsystem:" + subSys + "," + major + sep + minor); + } else if (auto *a = args.getLastArg(OPT_subs)) { + add("-subsystem:" + StringRef(a->getValue())); } - if (auto *A = Args.getLastArg(OPT_out_implib)) - Add("-implib:" + StringRef(A->getValue())); - if (auto *A = Args.getLastArg(OPT_stack)) - Add("-stack:" + StringRef(A->getValue())); - if (auto *A = Args.getLastArg(OPT_output_def)) - Add("-output-def:" + StringRef(A->getValue())); - if (auto *A = Args.getLastArg(OPT_image_base)) - Add("-base:" + StringRef(A->getValue())); - if (auto *A = Args.getLastArg(OPT_map)) - Add("-lldmap:" + StringRef(A->getValue())); - - if (auto *A = Args.getLastArg(OPT_o)) - Add("-out:" + StringRef(A->getValue())); - else if (Args.hasArg(OPT_shared)) - Add("-out:a.dll"); + if (auto *a = args.getLastArg(OPT_out_implib)) + add("-implib:" + StringRef(a->getValue())); + if (auto *a = args.getLastArg(OPT_stack)) + add("-stack:" + StringRef(a->getValue())); + if (auto *a = args.getLastArg(OPT_output_def)) + add("-output-def:" + StringRef(a->getValue())); + if (auto *a = args.getLastArg(OPT_image_base)) + add("-base:" + StringRef(a->getValue())); + if (auto *a = args.getLastArg(OPT_map)) + add("-lldmap:" + StringRef(a->getValue())); + + if (auto *a = args.getLastArg(OPT_o)) + add("-out:" + StringRef(a->getValue())); + else if (args.hasArg(OPT_shared)) + add("-out:a.dll"); else - Add("-out:a.exe"); + add("-out:a.exe"); - if (auto *A = Args.getLastArg(OPT_pdb)) { - Add("-debug"); - StringRef V = A->getValue(); - if (!V.empty()) - Add("-pdb:" + V); - } else if (Args.hasArg(OPT_strip_debug)) { - Add("-debug:symtab"); - } else if (!Args.hasArg(OPT_strip_all)) { - Add("-debug:dwarf"); + if (auto *a = args.getLastArg(OPT_pdb)) { + add("-debug"); + StringRef v = a->getValue(); + if (!v.empty()) + add("-pdb:" + v); + } else if (args.hasArg(OPT_strip_debug)) { + add("-debug:symtab"); + } else if (!args.hasArg(OPT_strip_all)) { + add("-debug:dwarf"); } - if (Args.hasArg(OPT_shared)) - Add("-dll"); - if (Args.hasArg(OPT_verbose)) - Add("-verbose"); - if (Args.hasArg(OPT_exclude_all_symbols)) - Add("-exclude-all-symbols"); - if (Args.hasArg(OPT_export_all_symbols)) - Add("-export-all-symbols"); - if (Args.hasArg(OPT_large_address_aware)) - Add("-largeaddressaware"); - if (Args.hasArg(OPT_kill_at)) - Add("-kill-at"); - if (Args.hasArg(OPT_appcontainer)) - Add("-appcontainer"); - - if (Args.getLastArgValue(OPT_m) != "thumb2pe" && - Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase)) - Add("-dynamicbase:no"); + if (args.hasArg(OPT_shared)) + add("-dll"); + if (args.hasArg(OPT_verbose)) + add("-verbose"); + if (args.hasArg(OPT_exclude_all_symbols)) + add("-exclude-all-symbols"); + if (args.hasArg(OPT_export_all_symbols)) + add("-export-all-symbols"); + if (args.hasArg(OPT_large_address_aware)) + add("-largeaddressaware"); + if (args.hasArg(OPT_kill_at)) + add("-kill-at"); + if (args.hasArg(OPT_appcontainer)) + add("-appcontainer"); + + if (args.getLastArgValue(OPT_m) != "thumb2pe" && + args.getLastArgValue(OPT_m) != "arm64pe" && !args.hasArg(OPT_dynamicbase)) + add("-dynamicbase:no"); - if (Args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) - Add("-timestamp:0"); + if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) + add("-timestamp:0"); - if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) - Add("-opt:ref"); + if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) + add("-opt:ref"); else - Add("-opt:noref"); + add("-opt:noref"); - if (auto *A = Args.getLastArg(OPT_icf)) { - StringRef S = A->getValue(); - if (S == "all") - Add("-opt:icf"); - else if (S == "safe" || S == "none") - Add("-opt:noicf"); + if (auto *a = args.getLastArg(OPT_icf)) { + StringRef s = a->getValue(); + if (s == "all") + add("-opt:icf"); + else if (s == "safe" || s == "none") + add("-opt:noicf"); else - fatal("unknown parameter: --icf=" + S); + fatal("unknown parameter: --icf=" + s); } else { - Add("-opt:noicf"); + add("-opt:noicf"); } - if (auto *A = Args.getLastArg(OPT_m)) { - StringRef S = A->getValue(); - if (S == "i386pe") - Add("-machine:x86"); - else if (S == "i386pep") - Add("-machine:x64"); - else if (S == "thumb2pe") - Add("-machine:arm"); - else if (S == "arm64pe") - Add("-machine:arm64"); + if (auto *a = args.getLastArg(OPT_m)) { + StringRef s = a->getValue(); + if (s == "i386pe") + add("-machine:x86"); + else if (s == "i386pep") + add("-machine:x64"); + else if (s == "thumb2pe") + add("-machine:arm"); + else if (s == "arm64pe") + add("-machine:arm64"); else - fatal("unknown parameter: -m" + S); + fatal("unknown parameter: -m" + s); } - for (auto *A : Args.filtered(OPT_mllvm)) - Add("-mllvm:" + StringRef(A->getValue())); + for (auto *a : args.filtered(OPT_mllvm)) + add("-mllvm:" + StringRef(a->getValue())); - for (auto *A : Args.filtered(OPT_Xlink)) - Add(A->getValue()); + for (auto *a : args.filtered(OPT_Xlink)) + add(a->getValue()); - if (Args.getLastArgValue(OPT_m) == "i386pe") - Add("-alternatename:__image_base__=___ImageBase"); + if (args.getLastArgValue(OPT_m) == "i386pe") + add("-alternatename:__image_base__=___ImageBase"); else - Add("-alternatename:__image_base__=__ImageBase"); + add("-alternatename:__image_base__=__ImageBase"); - for (auto *A : Args.filtered(OPT_require_defined)) - Add("-include:" + StringRef(A->getValue())); - for (auto *A : Args.filtered(OPT_undefined)) - Add("-includeoptional:" + StringRef(A->getValue())); - - std::vector SearchPaths; - for (auto *A : Args.filtered(OPT_L)) { - SearchPaths.push_back(A->getValue()); - Add("-libpath:" + StringRef(A->getValue())); + for (auto *a : args.filtered(OPT_require_defined)) + add("-include:" + StringRef(a->getValue())); + for (auto *a : args.filtered(OPT_undefined)) + add("-includeoptional:" + StringRef(a->getValue())); + + std::vector searchPaths; + for (auto *a : args.filtered(OPT_L)) { + searchPaths.push_back(a->getValue()); + add("-libpath:" + StringRef(a->getValue())); } - StringRef Prefix = ""; - bool Static = false; - for (auto *A : Args) { - switch (A->getOption().getID()) { + StringRef prefix = ""; + bool isStatic = false; + for (auto *a : args) { + switch (a->getOption().getID()) { case OPT_INPUT: - if (StringRef(A->getValue()).endswith_lower(".def")) - Add("-def:" + StringRef(A->getValue())); + if (StringRef(a->getValue()).endswith_lower(".def")) + add("-def:" + StringRef(a->getValue())); else - Add(Prefix + StringRef(A->getValue())); + add(prefix + StringRef(a->getValue())); break; case OPT_l: - Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static)); + add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic)); break; case OPT_whole_archive: - Prefix = "-wholearchive:"; + prefix = "-wholearchive:"; break; case OPT_no_whole_archive: - Prefix = ""; + prefix = ""; break; case OPT_Bstatic: - Static = true; + isStatic = true; break; case OPT_Bdynamic: - Static = false; + isStatic = false; break; } } - if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH)) - outs() << llvm::join(LinkArgs, " ") << "\n"; + if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH)) + outs() << llvm::join(linkArgs, " ") << "\n"; - if (Args.hasArg(OPT__HASH_HASH_HASH)) + if (args.hasArg(OPT__HASH_HASH_HASH)) return true; // Repack vector of strings to vector of const char pointers for coff::link. - std::vector Vec; - for (const std::string &S : LinkArgs) - Vec.push_back(S.c_str()); - return coff::link(Vec, true); + std::vector vec; + for (const std::string &s : linkArgs) + vec.push_back(s.c_str()); + return coff::link(vec, true); } Index: lld/trunk/include/lld/Common/Args.h =================================================================== --- lld/trunk/include/lld/Common/Args.h +++ lld/trunk/include/lld/Common/Args.h @@ -23,19 +23,19 @@ namespace lld { namespace args { -llvm::CodeGenOpt::Level getCGOptLevel(int OptLevelLTO); +llvm::CodeGenOpt::Level getCGOptLevel(int optLevelLTO); -int64_t getInteger(llvm::opt::InputArgList &Args, unsigned Key, +int64_t getInteger(llvm::opt::InputArgList &args, unsigned key, int64_t Default); -std::vector getStrings(llvm::opt::InputArgList &Args, int Id); +std::vector getStrings(llvm::opt::InputArgList &args, int id); -uint64_t getZOptionValue(llvm::opt::InputArgList &Args, int Id, StringRef Key, +uint64_t getZOptionValue(llvm::opt::InputArgList &args, int id, StringRef key, uint64_t Default); -std::vector getLines(MemoryBufferRef MB); +std::vector getLines(MemoryBufferRef mb); -StringRef getFilenameWithoutExe(StringRef Path); +StringRef getFilenameWithoutExe(StringRef path); } // namespace args } // namespace lld Index: lld/trunk/include/lld/Common/Driver.h =================================================================== --- lld/trunk/include/lld/Common/Driver.h +++ lld/trunk/include/lld/Common/Driver.h @@ -14,28 +14,28 @@ namespace lld { namespace coff { -bool link(llvm::ArrayRef Args, bool CanExitEarly, - llvm::raw_ostream &Diag = llvm::errs()); +bool link(llvm::ArrayRef args, bool canExitEarly, + llvm::raw_ostream &diag = llvm::errs()); } namespace mingw { -bool link(llvm::ArrayRef Args, - llvm::raw_ostream &Diag = llvm::errs()); +bool link(llvm::ArrayRef args, + llvm::raw_ostream &diag = llvm::errs()); } namespace elf { -bool link(llvm::ArrayRef Args, bool CanExitEarly, - llvm::raw_ostream &Diag = llvm::errs()); +bool link(llvm::ArrayRef args, bool canExitEarly, + llvm::raw_ostream &diag = llvm::errs()); } namespace mach_o { -bool link(llvm::ArrayRef Args, bool CanExitEarly, - llvm::raw_ostream &Diag = llvm::errs()); +bool link(llvm::ArrayRef args, bool canExitEarly, + llvm::raw_ostream &diag = llvm::errs()); } namespace wasm { -bool link(llvm::ArrayRef Args, bool CanExitEarly, - llvm::raw_ostream &Diag = llvm::errs()); +bool link(llvm::ArrayRef args, bool canExitEarly, + llvm::raw_ostream &diag = llvm::errs()); } } Index: lld/trunk/include/lld/Common/ErrorHandler.h =================================================================== --- lld/trunk/include/lld/Common/ErrorHandler.h +++ lld/trunk/include/lld/Common/ErrorHandler.h @@ -82,74 +82,74 @@ class ErrorHandler { public: - uint64_t ErrorCount = 0; - uint64_t ErrorLimit = 20; - StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now"; - StringRef LogName = "lld"; - llvm::raw_ostream *ErrorOS = &llvm::errs(); - bool ColorDiagnostics = llvm::errs().has_colors(); - bool ExitEarly = true; - bool FatalWarnings = false; - bool Verbose = false; - - void error(const Twine &Msg); - LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); - void log(const Twine &Msg); - void message(const Twine &Msg); - void warn(const Twine &Msg); + uint64_t errorCount = 0; + uint64_t errorLimit = 20; + StringRef errorLimitExceededMsg = "too many errors emitted, stopping now"; + StringRef logName = "lld"; + llvm::raw_ostream *errorOS = &llvm::errs(); + bool colorDiagnostics = llvm::errs().has_colors(); + bool exitEarly = true; + bool fatalWarnings = false; + bool verbose = false; + + void error(const Twine &msg); + LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg); + void log(const Twine &msg); + void message(const Twine &msg); + void warn(const Twine &msg); - std::unique_ptr OutputBuffer; + std::unique_ptr outputBuffer; private: - void print(StringRef S, raw_ostream::Colors C); + void print(StringRef s, raw_ostream::Colors c); }; /// Returns the default error handler. ErrorHandler &errorHandler(); -inline void error(const Twine &Msg) { errorHandler().error(Msg); } -inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) { - errorHandler().fatal(Msg); -} -inline void log(const Twine &Msg) { errorHandler().log(Msg); } -inline void message(const Twine &Msg) { errorHandler().message(Msg); } -inline void warn(const Twine &Msg) { errorHandler().warn(Msg); } -inline uint64_t errorCount() { return errorHandler().ErrorCount; } +inline void error(const Twine &msg) { errorHandler().error(msg); } +inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg) { + errorHandler().fatal(msg); +} +inline void log(const Twine &msg) { errorHandler().log(msg); } +inline void message(const Twine &msg) { errorHandler().message(msg); } +inline void warn(const Twine &msg) { errorHandler().warn(msg); } +inline uint64_t errorCount() { return errorHandler().errorCount; } -LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); +LLVM_ATTRIBUTE_NORETURN void exitLld(int val); -void diagnosticHandler(const llvm::DiagnosticInfo &DI); -void checkError(Error E); +void diagnosticHandler(const llvm::DiagnosticInfo &di); +void checkError(Error e); // check functions are convenient functions to strip errors // from error-or-value objects. -template T check(ErrorOr E) { - if (auto EC = E.getError()) - fatal(EC.message()); - return std::move(*E); +template T check(ErrorOr e) { + if (auto ec = e.getError()) + fatal(ec.message()); + return std::move(*e); } -template T check(Expected E) { - if (!E) - fatal(llvm::toString(E.takeError())); - return std::move(*E); +template T check(Expected e) { + if (!e) + fatal(llvm::toString(e.takeError())); + return std::move(*e); } template -T check2(ErrorOr E, llvm::function_ref Prefix) { - if (auto EC = E.getError()) - fatal(Prefix() + ": " + EC.message()); - return std::move(*E); +T check2(ErrorOr e, llvm::function_ref prefix) { + if (auto ec = e.getError()) + fatal(prefix() + ": " + ec.message()); + return std::move(*e); } template -T check2(Expected E, llvm::function_ref Prefix) { - if (!E) - fatal(Prefix() + ": " + toString(E.takeError())); - return std::move(*E); +T check2(Expected e, llvm::function_ref prefix) { + if (!e) + fatal(prefix() + ": " + toString(e.takeError())); + return std::move(*e); } -inline std::string toString(const Twine &S) { return S.str(); } +inline std::string toString(const Twine &s) { return s.str(); } // To evaluate the second argument lazily, we use C macro. #define CHECK(E, S) check2((E), [&] { return toString(S); }) Index: lld/trunk/include/lld/Common/Filesystem.h =================================================================== --- lld/trunk/include/lld/Common/Filesystem.h +++ lld/trunk/include/lld/Common/Filesystem.h @@ -13,8 +13,8 @@ #include namespace lld { -void unlinkAsync(StringRef Path); -std::error_code tryCreateFile(StringRef Path); +void unlinkAsync(StringRef path); +std::error_code tryCreateFile(StringRef path); } // namespace lld #endif Index: lld/trunk/include/lld/Common/Memory.h =================================================================== --- lld/trunk/include/lld/Common/Memory.h +++ lld/trunk/include/lld/Common/Memory.h @@ -28,30 +28,30 @@ namespace lld { // Use this arena if your object doesn't have a destructor. -extern llvm::BumpPtrAllocator BAlloc; -extern llvm::StringSaver Saver; +extern llvm::BumpPtrAllocator bAlloc; +extern llvm::StringSaver saver; void freeArena(); // These two classes are hack to keep track of all // SpecificBumpPtrAllocator instances. struct SpecificAllocBase { - SpecificAllocBase() { Instances.push_back(this); } + SpecificAllocBase() { instances.push_back(this); } virtual ~SpecificAllocBase() = default; virtual void reset() = 0; - static std::vector Instances; + static std::vector instances; }; template struct SpecificAlloc : public SpecificAllocBase { - void reset() override { Alloc.DestroyAll(); } - llvm::SpecificBumpPtrAllocator Alloc; + void reset() override { alloc.DestroyAll(); } + llvm::SpecificBumpPtrAllocator alloc; }; // Use this arena if your object has a destructor. // Your destructor will be invoked from freeArena(). -template T *make(U &&... Args) { - static SpecificAlloc Alloc; - return new (Alloc.Alloc.Allocate()) T(std::forward(Args)...); +template T *make(U &&... args) { + static SpecificAlloc alloc; + return new (alloc.alloc.Allocate()) T(std::forward(args)...); } } // namespace lld Index: lld/trunk/include/lld/Common/Reproduce.h =================================================================== --- lld/trunk/include/lld/Common/Reproduce.h +++ lld/trunk/include/lld/Common/Reproduce.h @@ -22,13 +22,13 @@ // Makes a given pathname an absolute path first, and then remove // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", // assuming that the current directory is "/home/john/bar". -std::string relativeToRoot(StringRef Path); +std::string relativeToRoot(StringRef path); // Quote a given string if it contains a space character. -std::string quote(StringRef S); +std::string quote(StringRef s); // Returns the string form of the given argument. -std::string toString(const llvm::opt::Arg &Arg); +std::string toString(const llvm::opt::Arg &arg); } #endif Index: lld/trunk/include/lld/Common/Strings.h =================================================================== --- lld/trunk/include/lld/Common/Strings.h +++ lld/trunk/include/lld/Common/Strings.h @@ -19,25 +19,25 @@ namespace lld { // Returns a demangled C++ symbol name. If Name is not a mangled // name, it returns Optional::None. -llvm::Optional demangleItanium(llvm::StringRef Name); -llvm::Optional demangleMSVC(llvm::StringRef S); +llvm::Optional demangleItanium(llvm::StringRef name); +llvm::Optional demangleMSVC(llvm::StringRef s); -std::vector parseHex(llvm::StringRef S); -bool isValidCIdentifier(llvm::StringRef S); +std::vector parseHex(llvm::StringRef s); +bool isValidCIdentifier(llvm::StringRef s); // Write the contents of the a buffer to a file -void saveBuffer(llvm::StringRef Buffer, const llvm::Twine &Path); +void saveBuffer(llvm::StringRef buffer, const llvm::Twine &path); // This class represents multiple glob patterns. class StringMatcher { public: StringMatcher() = default; - explicit StringMatcher(llvm::ArrayRef Pat); + explicit StringMatcher(llvm::ArrayRef pat); - bool match(llvm::StringRef S) const; + bool match(llvm::StringRef s) const; private: - std::vector Patterns; + std::vector patterns; }; } // namespace lld Index: lld/trunk/include/lld/Common/Threads.h =================================================================== --- lld/trunk/include/lld/Common/Threads.h +++ lld/trunk/include/lld/Common/Threads.h @@ -63,28 +63,28 @@ namespace lld { -extern bool ThreadsEnabled; +extern bool threadsEnabled; -template void parallelForEach(R &&Range, FuncTy Fn) { - if (ThreadsEnabled) - for_each(llvm::parallel::par, std::begin(Range), std::end(Range), Fn); +template void parallelForEach(R &&range, FuncTy fn) { + if (threadsEnabled) + for_each(llvm::parallel::par, std::begin(range), std::end(range), fn); else - for_each(llvm::parallel::seq, std::begin(Range), std::end(Range), Fn); + for_each(llvm::parallel::seq, std::begin(range), std::end(range), fn); } -inline void parallelForEachN(size_t Begin, size_t End, - llvm::function_ref Fn) { - if (ThreadsEnabled) - for_each_n(llvm::parallel::par, Begin, End, Fn); +inline void parallelForEachN(size_t begin, size_t end, + llvm::function_ref fn) { + if (threadsEnabled) + for_each_n(llvm::parallel::par, begin, end, fn); else - for_each_n(llvm::parallel::seq, Begin, End, Fn); + for_each_n(llvm::parallel::seq, begin, end, fn); } -template void parallelSort(R &&Range, FuncTy Fn) { - if (ThreadsEnabled) - sort(llvm::parallel::par, std::begin(Range), std::end(Range), Fn); +template void parallelSort(R &&range, FuncTy fn) { + if (threadsEnabled) + sort(llvm::parallel::par, std::begin(range), std::end(range), fn); else - sort(llvm::parallel::seq, std::begin(Range), std::end(Range), Fn); + sort(llvm::parallel::seq, std::begin(range), std::end(range), fn); } } // namespace lld Index: lld/trunk/include/lld/Common/Timer.h =================================================================== --- lld/trunk/include/lld/Common/Timer.h +++ lld/trunk/include/lld/Common/Timer.h @@ -21,18 +21,18 @@ class Timer; struct ScopedTimer { - explicit ScopedTimer(Timer &T); + explicit ScopedTimer(Timer &t); ~ScopedTimer(); void stop(); - Timer *T = nullptr; + Timer *t = nullptr; }; class Timer { public: - Timer(llvm::StringRef Name, Timer &Parent); + Timer(llvm::StringRef name, Timer &parent); static Timer &root(); @@ -43,14 +43,14 @@ double millis() const; private: - explicit Timer(llvm::StringRef Name); - void print(int Depth, double TotalDuration, bool Recurse = true) const; + explicit Timer(llvm::StringRef name); + void print(int depth, double totalDuration, bool recurse = true) const; - std::chrono::time_point StartTime; - std::chrono::nanoseconds Total; - std::vector Children; - std::string Name; - Timer *Parent; + std::chrono::time_point startTime; + std::chrono::nanoseconds total; + std::vector children; + std::string name; + Timer *parent; }; } // namespace lld Index: lld/trunk/lib/Driver/DarwinLdDriver.cpp =================================================================== --- lld/trunk/lib/Driver/DarwinLdDriver.cpp +++ lld/trunk/lib/Driver/DarwinLdDriver.cpp @@ -333,8 +333,8 @@ Twine(unknownArg->getAsString(parsedArgs))); } - errorHandler().Verbose = parsedArgs.hasArg(OPT_v); - errorHandler().ErrorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20); + errorHandler().verbose = parsedArgs.hasArg(OPT_v); + errorHandler().errorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20); // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static ) llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE; @@ -637,7 +637,7 @@ // Now that we've constructed the final set of search paths, print out those // search paths in verbose mode. - if (errorHandler().Verbose) { + if (errorHandler().verbose) { message("Library search paths:"); for (auto path : ctx.searchDirs()) { message(" " + path); @@ -1145,13 +1145,13 @@ /// This is where the link is actually performed. bool link(llvm::ArrayRef args, bool CanExitEarly, raw_ostream &Error) { - errorHandler().LogName = args::getFilenameWithoutExe(args[0]); - errorHandler().ErrorLimitExceededMsg = + errorHandler().logName = args::getFilenameWithoutExe(args[0]); + errorHandler().errorLimitExceededMsg = "too many errors emitted, stopping now (use " "'-error-limit 0' to see all errors)"; - errorHandler().ErrorOS = &Error; - errorHandler().ExitEarly = CanExitEarly; - errorHandler().ColorDiagnostics = Error.has_colors(); + errorHandler().errorOS = &Error; + errorHandler().exitEarly = CanExitEarly; + errorHandler().colorDiagnostics = Error.has_colors(); MachOLinkingContext ctx; if (!parse(args, ctx)) @@ -1196,9 +1196,9 @@ if (auto ec = pm.runOnFile(*merged)) { // FIXME: This should be passed to logAllUnhandledErrors but it needs // to be passed a Twine instead of a string. - *errorHandler().ErrorOS << "Failed to run passes on file '" + *errorHandler().errorOS << "Failed to run passes on file '" << ctx.outputPath() << "': "; - logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS, + logAllUnhandledErrors(std::move(ec), *errorHandler().errorOS, std::string()); return false; } @@ -1210,9 +1210,9 @@ if (auto ec = ctx.writeFile(*merged)) { // FIXME: This should be passed to logAllUnhandledErrors but it needs // to be passed a Twine instead of a string. - *errorHandler().ErrorOS << "Failed to write file '" << ctx.outputPath() + *errorHandler().errorOS << "Failed to write file '" << ctx.outputPath() << "': "; - logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS, + logAllUnhandledErrors(std::move(ec), *errorHandler().errorOS, std::string()); return false; } Index: lld/trunk/tools/lld/lld.cpp =================================================================== --- lld/trunk/tools/lld/lld.cpp +++ lld/trunk/tools/lld/lld.cpp @@ -49,13 +49,13 @@ Wasm, // -flavor wasm }; -LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) { - errs() << S << "\n"; +LLVM_ATTRIBUTE_NORETURN static void die(const Twine &s) { + errs() << s << "\n"; exit(1); } -static Flavor getFlavor(StringRef S) { - return StringSwitch(S) +static Flavor getFlavor(StringRef s) { + return StringSwitch(s) .CasesLower("ld", "ld.lld", "gnu", Gnu) .CasesLower("wasm", "ld-wasm", Wasm) .CaseLower("link", WinLink) @@ -69,29 +69,29 @@ return cl::TokenizeGNUCommandLine; } -static bool isPETargetName(StringRef S) { - return S == "i386pe" || S == "i386pep" || S == "thumb2pe" || S == "arm64pe"; +static bool isPETargetName(StringRef s) { + return s == "i386pe" || s == "i386pep" || s == "thumb2pe" || s == "arm64pe"; } -static bool isPETarget(std::vector &V) { - for (auto It = V.begin(); It + 1 != V.end(); ++It) { - if (StringRef(*It) != "-m") +static bool isPETarget(std::vector &v) { + for (auto it = v.begin(); it + 1 != v.end(); ++it) { + if (StringRef(*it) != "-m") continue; - return isPETargetName(*(It + 1)); + return isPETargetName(*(it + 1)); } // Expand response files (arguments in the form of @) // to allow detecting the -m argument from arguments in them. - SmallVector ExpandedArgs(V.data(), V.data() + V.size()); - cl::ExpandResponseFiles(Saver, getDefaultQuotingStyle(), ExpandedArgs); - for (auto It = ExpandedArgs.begin(); It + 1 != ExpandedArgs.end(); ++It) { - if (StringRef(*It) != "-m") + SmallVector expandedArgs(v.data(), v.data() + v.size()); + cl::ExpandResponseFiles(saver, getDefaultQuotingStyle(), expandedArgs); + for (auto it = expandedArgs.begin(); it + 1 != expandedArgs.end(); ++it) { + if (StringRef(*it) != "-m") continue; - return isPETargetName(*(It + 1)); + return isPETargetName(*(it + 1)); } return false; } -static Flavor parseProgname(StringRef Progname) { +static Flavor parseProgname(StringRef progname) { #if __APPLE__ // Use Darwin driver for "ld" on Darwin. if (Progname == "ld") @@ -100,36 +100,36 @@ #if LLVM_ON_UNIX // Use GNU driver for "ld" on other Unix-like system. - if (Progname == "ld") + if (progname == "ld") return Gnu; #endif // Progname may be something like "lld-gnu". Parse it. - SmallVector V; - Progname.split(V, "-"); - for (StringRef S : V) - if (Flavor F = getFlavor(S)) - return F; + SmallVector v; + progname.split(v, "-"); + for (StringRef s : v) + if (Flavor f = getFlavor(s)) + return f; return Invalid; } -static Flavor parseFlavor(std::vector &V) { +static Flavor parseFlavor(std::vector &v) { // Parse -flavor option. - if (V.size() > 1 && V[1] == StringRef("-flavor")) { - if (V.size() <= 2) + if (v.size() > 1 && v[1] == StringRef("-flavor")) { + if (v.size() <= 2) die("missing arg value for '-flavor'"); - Flavor F = getFlavor(V[2]); - if (F == Invalid) - die("Unknown flavor: " + StringRef(V[2])); - V.erase(V.begin() + 1, V.begin() + 3); - return F; + Flavor f = getFlavor(v[2]); + if (f == Invalid) + die("Unknown flavor: " + StringRef(v[2])); + v.erase(v.begin() + 1, v.begin() + 3); + return f; } // Deduct the flavor from argv[0]. - StringRef Arg0 = path::filename(V[0]); - if (Arg0.endswith_lower(".exe")) - Arg0 = Arg0.drop_back(4); - return parseProgname(Arg0); + StringRef arg0 = path::filename(v[0]); + if (arg0.endswith_lower(".exe")) + arg0 = arg0.drop_back(4); + return parseProgname(arg0); } // If this function returns true, lld calls _exit() so that it quickly @@ -142,21 +142,21 @@ /// Universal linker main(). This linker emulates the gnu, darwin, or /// windows linker based on the argv[0] or -flavor option. -int main(int Argc, const char **Argv) { - InitLLVM X(Argc, Argv); +int main(int argc, const char **argv) { + InitLLVM x(argc, argv); - std::vector Args(Argv, Argv + Argc); - switch (parseFlavor(Args)) { + std::vector args(argv, argv + argc); + switch (parseFlavor(args)) { case Gnu: - if (isPETarget(Args)) - return !mingw::link(Args); - return !elf::link(Args, canExitEarly()); + if (isPETarget(args)) + return !mingw::link(args); + return !elf::link(args, canExitEarly()); case WinLink: - return !coff::link(Args, canExitEarly()); + return !coff::link(args, canExitEarly()); case Darwin: - return !mach_o::link(Args, canExitEarly()); + return !mach_o::link(args, canExitEarly()); case Wasm: - return !wasm::link(Args, canExitEarly()); + return !wasm::link(args, canExitEarly()); default: die("lld is a generic driver.\n" "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld" Index: lld/trunk/wasm/Config.h =================================================================== --- lld/trunk/wasm/Config.h +++ lld/trunk/wasm/Config.h @@ -22,58 +22,58 @@ // and such fields have the same name as the corresponding options. // Most fields are initialized by the driver. struct Configuration { - bool AllowUndefined; - bool CheckFeatures; - bool CompressRelocations; - bool Demangle; - bool DisableVerify; - bool EmitRelocs; - bool ExportAll; - bool ExportDynamic; - bool ExportTable; - bool GcSections; - bool ImportMemory; - bool SharedMemory; - bool PassiveSegments; - bool ImportTable; - bool MergeDataSegments; - bool Pie; - bool PrintGcSections; - bool Relocatable; - bool SaveTemps; - bool Shared; - bool StripAll; - bool StripDebug; - bool StackFirst; - bool Trace; - uint32_t GlobalBase; - uint32_t InitialMemory; - uint32_t MaxMemory; - uint32_t ZStackSize; - unsigned LTOPartitions; - unsigned LTOO; - unsigned Optimize; - unsigned ThinLTOJobs; - - llvm::StringRef Entry; - llvm::StringRef OutputFile; - llvm::StringRef ThinLTOCacheDir; - - llvm::StringSet<> AllowUndefinedSymbols; - llvm::StringSet<> ExportedSymbols; - std::vector SearchPaths; - llvm::CachePruningPolicy ThinLTOCachePolicy; - llvm::Optional> Features; + bool allowUndefined; + bool checkFeatures; + bool compressRelocations; + bool demangle; + bool disableVerify; + bool emitRelocs; + bool exportAll; + bool exportDynamic; + bool exportTable; + bool gcSections; + bool importMemory; + bool sharedMemory; + bool passiveSegments; + bool importTable; + bool mergeDataSegments; + bool pie; + bool printGcSections; + bool relocatable; + bool saveTemps; + bool shared; + bool stripAll; + bool stripDebug; + bool stackFirst; + bool trace; + uint32_t globalBase; + uint32_t initialMemory; + uint32_t maxMemory; + uint32_t zStackSize; + unsigned ltoPartitions; + unsigned ltoo; + unsigned optimize; + unsigned thinLTOJobs; + + llvm::StringRef entry; + llvm::StringRef outputFile; + llvm::StringRef thinLTOCacheDir; + + llvm::StringSet<> allowUndefinedSymbols; + llvm::StringSet<> exportedSymbols; + std::vector searchPaths; + llvm::CachePruningPolicy thinLTOCachePolicy; + llvm::Optional> features; // The following config options do not directly correspond to any // particualr command line options. // True if we are creating position-independent code. - bool Pic; + bool isPic; }; // The only instance of Configuration struct. -extern Configuration *Config; +extern Configuration *config; } // namespace wasm } // namespace lld Index: lld/trunk/wasm/Driver.cpp =================================================================== --- lld/trunk/wasm/Driver.cpp +++ lld/trunk/wasm/Driver.cpp @@ -40,7 +40,7 @@ using namespace lld; using namespace lld::wasm; -Configuration *lld::wasm::Config; +Configuration *lld::wasm::config; namespace { @@ -65,39 +65,39 @@ class LinkerDriver { public: - void link(ArrayRef ArgsArr); + void link(ArrayRef argsArr); private: - void createFiles(opt::InputArgList &Args); - void addFile(StringRef Path); - void addLibrary(StringRef Name); + void createFiles(opt::InputArgList &args); + void addFile(StringRef path); + void addLibrary(StringRef name); // True if we are in --whole-archive and --no-whole-archive. - bool InWholeArchive = false; + bool inWholeArchive = false; - std::vector Files; + std::vector files; }; } // anonymous namespace -bool lld::wasm::link(ArrayRef Args, bool CanExitEarly, - raw_ostream &Error) { - errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); - errorHandler().ErrorOS = &Error; - errorHandler().ColorDiagnostics = Error.has_colors(); - errorHandler().ErrorLimitExceededMsg = +bool lld::wasm::link(ArrayRef args, bool canExitEarly, + raw_ostream &error) { + errorHandler().logName = args::getFilenameWithoutExe(args[0]); + errorHandler().errorOS = &error; + errorHandler().colorDiagnostics = error.has_colors(); + errorHandler().errorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; - Config = make(); - Symtab = make(); + config = make(); + symtab = make(); initLLVM(); - LinkerDriver().link(Args); + LinkerDriver().link(args); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors // for all globally-allocated objects is not negligible. - if (CanExitEarly) + if (canExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); @@ -110,7 +110,7 @@ #undef PREFIX // Create table mapping all options defined in Options.td -static const opt::OptTable::Info OptInfo[] = { +static const opt::OptTable::Info optInfo[] = { #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, @@ -121,57 +121,57 @@ namespace { class WasmOptTable : public llvm::opt::OptTable { public: - WasmOptTable() : OptTable(OptInfo) {} - opt::InputArgList parse(ArrayRef Argv); + WasmOptTable() : OptTable(optInfo) {} + opt::InputArgList parse(ArrayRef argv); }; } // namespace // Set color diagnostics according to -color-diagnostics={auto,always,never} // or -no-color-diagnostics flags. -static void handleColorDiagnostics(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, +static void handleColorDiagnostics(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, OPT_no_color_diagnostics); - if (!Arg) + if (!arg) return; - if (Arg->getOption().getID() == OPT_color_diagnostics) { - errorHandler().ColorDiagnostics = true; - } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) { - errorHandler().ColorDiagnostics = false; + if (arg->getOption().getID() == OPT_color_diagnostics) { + errorHandler().colorDiagnostics = true; + } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { + errorHandler().colorDiagnostics = false; } else { - StringRef S = Arg->getValue(); - if (S == "always") - errorHandler().ColorDiagnostics = true; - else if (S == "never") - errorHandler().ColorDiagnostics = false; - else if (S != "auto") - error("unknown option: --color-diagnostics=" + S); + StringRef s = arg->getValue(); + if (s == "always") + errorHandler().colorDiagnostics = true; + else if (s == "never") + errorHandler().colorDiagnostics = false; + else if (s != "auto") + error("unknown option: --color-diagnostics=" + s); } } // Find a file by concatenating given paths. -static Optional findFile(StringRef Path1, const Twine &Path2) { - SmallString<128> S; - path::append(S, Path1, Path2); - if (fs::exists(S)) - return S.str().str(); +static Optional findFile(StringRef path1, const Twine &path2) { + SmallString<128> s; + path::append(s, path1, path2); + if (fs::exists(s)) + return s.str().str(); return None; } -opt::InputArgList WasmOptTable::parse(ArrayRef Argv) { - SmallVector Vec(Argv.data(), Argv.data() + Argv.size()); +opt::InputArgList WasmOptTable::parse(ArrayRef argv) { + SmallVector vec(argv.data(), argv.data() + argv.size()); - unsigned MissingIndex; - unsigned MissingCount; + unsigned missingIndex; + unsigned missingCount; // Expand response files (arguments in the form of @) - cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Vec); + cl::ExpandResponseFiles(saver, cl::TokenizeGNUCommandLine, vec); - opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); + opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); - handleColorDiagnostics(Args); - for (auto *Arg : Args.filtered(OPT_UNKNOWN)) - error("unknown argument: " + Arg->getAsString(Args)); - return Args; + handleColorDiagnostics(args); + for (auto *arg : args.filtered(OPT_UNKNOWN)) + error("unknown argument: " + arg->getAsString(args)); + return args; } // Currently we allow a ".imports" to live alongside a library. This can @@ -181,189 +181,189 @@ // In the long run this information would be better stored as a symbol // attribute/flag in the object file itself. // See: https://github.com/WebAssembly/tool-conventions/issues/35 -static void readImportFile(StringRef Filename) { - if (Optional Buf = readFile(Filename)) - for (StringRef Sym : args::getLines(*Buf)) - Config->AllowUndefinedSymbols.insert(Sym); +static void readImportFile(StringRef filename) { + if (Optional buf = readFile(filename)) + for (StringRef sym : args::getLines(*buf)) + config->allowUndefinedSymbols.insert(sym); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. -std::vector static getArchiveMembers(MemoryBufferRef MB) { - std::unique_ptr File = - CHECK(Archive::create(MB), - MB.getBufferIdentifier() + ": failed to parse archive"); - - std::vector V; - Error Err = Error::success(); - for (const ErrorOr &COrErr : File->children(Err)) { - Archive::Child C = - CHECK(COrErr, MB.getBufferIdentifier() + +std::vector static getArchiveMembers(MemoryBufferRef mb) { + std::unique_ptr file = + CHECK(Archive::create(mb), + mb.getBufferIdentifier() + ": failed to parse archive"); + + std::vector v; + Error err = Error::success(); + for (const ErrorOr &cOrErr : file->children(err)) { + Archive::Child c = + CHECK(cOrErr, mb.getBufferIdentifier() + ": could not get the child of the archive"); - MemoryBufferRef MBRef = - CHECK(C.getMemoryBufferRef(), - MB.getBufferIdentifier() + + MemoryBufferRef mbref = + CHECK(c.getMemoryBufferRef(), + mb.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); - V.push_back(MBRef); + v.push_back(mbref); } - if (Err) - fatal(MB.getBufferIdentifier() + - ": Archive::children failed: " + toString(std::move(Err))); + if (err) + fatal(mb.getBufferIdentifier() + + ": Archive::children failed: " + toString(std::move(err))); // Take ownership of memory buffers created for members of thin archives. - for (std::unique_ptr &MB : File->takeThinBuffers()) - make>(std::move(MB)); + for (std::unique_ptr &mb : file->takeThinBuffers()) + make>(std::move(mb)); - return V; + return v; } -void LinkerDriver::addFile(StringRef Path) { - Optional Buffer = readFile(Path); - if (!Buffer.hasValue()) +void LinkerDriver::addFile(StringRef path) { + Optional buffer = readFile(path); + if (!buffer.hasValue()) return; - MemoryBufferRef MBRef = *Buffer; + MemoryBufferRef mbref = *buffer; - switch (identify_magic(MBRef.getBuffer())) { + switch (identify_magic(mbref.getBuffer())) { case file_magic::archive: { - SmallString<128> ImportFile = Path; - path::replace_extension(ImportFile, ".imports"); - if (fs::exists(ImportFile)) - readImportFile(ImportFile.str()); + SmallString<128> importFile = path; + path::replace_extension(importFile, ".imports"); + if (fs::exists(importFile)) + readImportFile(importFile.str()); // Handle -whole-archive. - if (InWholeArchive) { - for (MemoryBufferRef &M : getArchiveMembers(MBRef)) - Files.push_back(createObjectFile(M, Path)); + if (inWholeArchive) { + for (MemoryBufferRef &m : getArchiveMembers(mbref)) + files.push_back(createObjectFile(m, path)); return; } - std::unique_ptr File = - CHECK(Archive::create(MBRef), Path + ": failed to parse archive"); + std::unique_ptr file = + CHECK(Archive::create(mbref), path + ": failed to parse archive"); - if (!File->isEmpty() && !File->hasSymbolTable()) { - error(MBRef.getBufferIdentifier() + + if (!file->isEmpty() && !file->hasSymbolTable()) { + error(mbref.getBufferIdentifier() + ": archive has no index; run ranlib to add one"); } - Files.push_back(make(MBRef)); + files.push_back(make(mbref)); return; } case file_magic::bitcode: case file_magic::wasm_object: - Files.push_back(createObjectFile(MBRef)); + files.push_back(createObjectFile(mbref)); break; default: - error("unknown file type: " + MBRef.getBufferIdentifier()); + error("unknown file type: " + mbref.getBufferIdentifier()); } } // Add a given library by searching it from input search paths. -void LinkerDriver::addLibrary(StringRef Name) { - for (StringRef Dir : Config->SearchPaths) { - if (Optional S = findFile(Dir, "lib" + Name + ".a")) { - addFile(*S); +void LinkerDriver::addLibrary(StringRef name) { + for (StringRef dir : config->searchPaths) { + if (Optional s = findFile(dir, "lib" + name + ".a")) { + addFile(*s); return; } } - error("unable to find library -l" + Name); + error("unable to find library -l" + name); } -void LinkerDriver::createFiles(opt::InputArgList &Args) { - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { +void LinkerDriver::createFiles(opt::InputArgList &args) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_l: - addLibrary(Arg->getValue()); + addLibrary(arg->getValue()); break; case OPT_INPUT: - addFile(Arg->getValue()); + addFile(arg->getValue()); break; case OPT_whole_archive: - InWholeArchive = true; + inWholeArchive = true; break; case OPT_no_whole_archive: - InWholeArchive = false; + inWholeArchive = false; break; } } } -static StringRef getEntry(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry); - if (!Arg) { - if (Args.hasArg(OPT_relocatable)) +static StringRef getEntry(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_entry, OPT_no_entry); + if (!arg) { + if (args.hasArg(OPT_relocatable)) return ""; - if (Args.hasArg(OPT_shared)) + if (args.hasArg(OPT_shared)) return "__wasm_call_ctors"; return "_start"; } - if (Arg->getOption().getID() == OPT_no_entry) + if (arg->getOption().getID() == OPT_no_entry) return ""; - return Arg->getValue(); + return arg->getValue(); } // Initializes Config members by the command line options. -static void readConfigs(opt::InputArgList &Args) { - Config->AllowUndefined = Args.hasArg(OPT_allow_undefined); - Config->CheckFeatures = - Args.hasFlag(OPT_check_features, OPT_no_check_features, true); - Config->CompressRelocations = Args.hasArg(OPT_compress_relocations); - Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); - Config->DisableVerify = Args.hasArg(OPT_disable_verify); - Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); - Config->Entry = getEntry(Args); - Config->ExportAll = Args.hasArg(OPT_export_all); - Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, +static void readConfigs(opt::InputArgList &args) { + config->allowUndefined = args.hasArg(OPT_allow_undefined); + config->checkFeatures = + args.hasFlag(OPT_check_features, OPT_no_check_features, true); + config->compressRelocations = args.hasArg(OPT_compress_relocations); + config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true); + config->disableVerify = args.hasArg(OPT_disable_verify); + config->emitRelocs = args.hasArg(OPT_emit_relocs); + config->entry = getEntry(args); + config->exportAll = args.hasArg(OPT_export_all); + config->exportDynamic = args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); - Config->ExportTable = Args.hasArg(OPT_export_table); - errorHandler().FatalWarnings = - Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); - Config->ImportMemory = Args.hasArg(OPT_import_memory); - Config->SharedMemory = Args.hasArg(OPT_shared_memory); + config->exportTable = args.hasArg(OPT_export_table); + errorHandler().fatalWarnings = + args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); + config->importMemory = args.hasArg(OPT_import_memory); + config->sharedMemory = args.hasArg(OPT_shared_memory); // TODO: Make passive segments the default with shared memory - Config->PassiveSegments = - Args.hasFlag(OPT_passive_segments, OPT_active_segments, false); - Config->ImportTable = Args.hasArg(OPT_import_table); - Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); - Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); - Config->Optimize = args::getInteger(Args, OPT_O, 0); - Config->OutputFile = Args.getLastArgValue(OPT_o); - Config->Relocatable = Args.hasArg(OPT_relocatable); - Config->GcSections = - Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable); - Config->MergeDataSegments = - Args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, - !Config->Relocatable); - Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false); - Config->PrintGcSections = - Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); - Config->SaveTemps = Args.hasArg(OPT_save_temps); - Config->SearchPaths = args::getStrings(Args, OPT_L); - Config->Shared = Args.hasArg(OPT_shared); - Config->StripAll = Args.hasArg(OPT_strip_all); - Config->StripDebug = Args.hasArg(OPT_strip_debug); - Config->StackFirst = Args.hasArg(OPT_stack_first); - Config->Trace = Args.hasArg(OPT_trace); - Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); - Config->ThinLTOCachePolicy = CHECK( - parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), + config->passiveSegments = + args.hasFlag(OPT_passive_segments, OPT_active_segments, false); + config->importTable = args.hasArg(OPT_import_table); + config->ltoo = args::getInteger(args, OPT_lto_O, 2); + config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); + config->optimize = args::getInteger(args, OPT_O, 0); + config->outputFile = args.getLastArgValue(OPT_o); + config->relocatable = args.hasArg(OPT_relocatable); + config->gcSections = + args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable); + config->mergeDataSegments = + args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, + !config->relocatable); + config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false); + config->printGcSections = + args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); + config->saveTemps = args.hasArg(OPT_save_temps); + config->searchPaths = args::getStrings(args, OPT_L); + config->shared = args.hasArg(OPT_shared); + config->stripAll = args.hasArg(OPT_strip_all); + config->stripDebug = args.hasArg(OPT_strip_debug); + config->stackFirst = args.hasArg(OPT_stack_first); + config->trace = args.hasArg(OPT_trace); + config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir); + config->thinLTOCachePolicy = CHECK( + parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); - Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); - errorHandler().Verbose = Args.hasArg(OPT_verbose); - LLVM_DEBUG(errorHandler().Verbose = true); - ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); - - Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0); - Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024); - Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); - Config->ZStackSize = - args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); + config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u); + errorHandler().verbose = args.hasArg(OPT_verbose); + LLVM_DEBUG(errorHandler().verbose = true); + threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); + + config->initialMemory = args::getInteger(args, OPT_initial_memory, 0); + config->globalBase = args::getInteger(args, OPT_global_base, 1024); + config->maxMemory = args::getInteger(args, OPT_max_memory, 0); + config->zStackSize = + args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize); - if (auto *Arg = Args.getLastArg(OPT_features)) { - Config->Features = + if (auto *arg = args.getLastArg(OPT_features)) { + config->features = llvm::Optional>(std::vector()); - for (StringRef S : Arg->getValues()) - Config->Features->push_back(S); + for (StringRef s : arg->getValues()) + config->features->push_back(s); } } @@ -372,183 +372,183 @@ // This function initialize such members. See Config.h for the details // of these values. static void setConfigs() { - Config->Pic = Config->Pie || Config->Shared; + config->isPic = config->pie || config->shared; - if (Config->Pic) { - if (Config->ExportTable) + if (config->isPic) { + if (config->exportTable) error("-shared/-pie is incompatible with --export-table"); - Config->ImportTable = true; + config->importTable = true; } - if (Config->Shared) { - Config->ImportMemory = true; - Config->ExportDynamic = true; - Config->AllowUndefined = true; + if (config->shared) { + config->importMemory = true; + config->exportDynamic = true; + config->allowUndefined = true; } } // Some command line options or some combinations of them are not allowed. // This function checks for such errors. -static void checkOptions(opt::InputArgList &Args) { - if (!Config->StripDebug && !Config->StripAll && Config->CompressRelocations) +static void checkOptions(opt::InputArgList &args) { + if (!config->stripDebug && !config->stripAll && config->compressRelocations) error("--compress-relocations is incompatible with output debug" " information. Please pass --strip-debug or --strip-all"); - if (Config->LTOO > 3) - error("invalid optimization level for LTO: " + Twine(Config->LTOO)); - if (Config->LTOPartitions == 0) + if (config->ltoo > 3) + error("invalid optimization level for LTO: " + Twine(config->ltoo)); + if (config->ltoPartitions == 0) error("--lto-partitions: number of threads must be > 0"); - if (Config->ThinLTOJobs == 0) + if (config->thinLTOJobs == 0) error("--thinlto-jobs: number of threads must be > 0"); - if (Config->Pie && Config->Shared) + if (config->pie && config->shared) error("-shared and -pie may not be used together"); - if (Config->OutputFile.empty()) + if (config->outputFile.empty()) error("no output file specified"); - if (Config->ImportTable && Config->ExportTable) + if (config->importTable && config->exportTable) error("--import-table and --export-table may not be used together"); - if (Config->Relocatable) { - if (!Config->Entry.empty()) + if (config->relocatable) { + if (!config->entry.empty()) error("entry point specified for relocatable output file"); - if (Config->GcSections) + if (config->gcSections) error("-r and --gc-sections may not be used together"); - if (Config->CompressRelocations) + if (config->compressRelocations) error("-r -and --compress-relocations may not be used together"); - if (Args.hasArg(OPT_undefined)) + if (args.hasArg(OPT_undefined)) error("-r -and --undefined may not be used together"); - if (Config->Pie) + if (config->pie) error("-r and -pie may not be used together"); } } // Force Sym to be entered in the output. Used for -u or equivalent. -static Symbol *handleUndefined(StringRef Name) { - Symbol *Sym = Symtab->find(Name); - if (!Sym) +static Symbol *handleUndefined(StringRef name) { + Symbol *sym = symtab->find(name); + if (!sym) return nullptr; // Since symbol S may not be used inside the program, LTO may // eliminate it. Mark the symbol as "used" to prevent it. - Sym->IsUsedInRegularObj = true; + sym->isUsedInRegularObj = true; - if (auto *LazySym = dyn_cast(Sym)) - LazySym->fetch(); + if (auto *lazySym = dyn_cast(sym)) + lazySym->fetch(); - return Sym; + return sym; } static UndefinedGlobal * -createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) { - auto *Sym = - cast(Symtab->addUndefinedGlobal(Name, Name, - DefaultModule, 0, - nullptr, Type)); - Config->AllowUndefinedSymbols.insert(Sym->getName()); - Sym->IsUsedInRegularObj = true; - return Sym; +createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) { + auto *sym = + cast(symtab->addUndefinedGlobal(name, name, + defaultModule, 0, + nullptr, type)); + config->allowUndefinedSymbols.insert(sym->getName()); + sym->isUsedInRegularObj = true; + return sym; } // Create ABI-defined synthetic symbols static void createSyntheticSymbols() { - static WasmSignature NullSignature = {{}, {}}; - static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false}; - static llvm::wasm::WasmGlobalType MutableGlobalTypeI32 = {WASM_TYPE_I32, + static WasmSignature nullSignature = {{}, {}}; + static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false}; + static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32, true}; - if (!Config->Relocatable) { - WasmSym::CallCtors = Symtab->addSyntheticFunction( + if (!config->relocatable) { + WasmSym::callCtors = symtab->addSyntheticFunction( "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, - make(NullSignature, "__wasm_call_ctors")); + make(nullSignature, "__wasm_call_ctors")); - if (Config->PassiveSegments) { + if (config->passiveSegments) { // Passive segments are used to avoid memory being reinitialized on each // thread's instantiation. These passive segments are initialized and // dropped in __wasm_init_memory, which is the first function called from // __wasm_call_ctors. - WasmSym::InitMemory = Symtab->addSyntheticFunction( + WasmSym::initMemory = symtab->addSyntheticFunction( "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN, - make(NullSignature, "__wasm_init_memory")); + make(nullSignature, "__wasm_init_memory")); } - if (Config->Pic) { + if (config->isPic) { // For PIC code we create a synthetic function __wasm_apply_relocs which // is called from __wasm_call_ctors before the user-level constructors. - WasmSym::ApplyRelocs = Symtab->addSyntheticFunction( + WasmSym::applyRelocs = symtab->addSyntheticFunction( "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN, - make(NullSignature, "__wasm_apply_relocs")); + make(nullSignature, "__wasm_apply_relocs")); } } // The __stack_pointer is imported in the shared library case, and exported // in the non-shared (executable) case. - if (Config->Shared) { - WasmSym::StackPointer = - createUndefinedGlobal("__stack_pointer", &MutableGlobalTypeI32); + if (config->shared) { + WasmSym::stackPointer = + createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32); } else { - llvm::wasm::WasmGlobal Global; - Global.Type = {WASM_TYPE_I32, true}; - Global.InitExpr.Value.Int32 = 0; - Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; - Global.SymbolName = "__stack_pointer"; - auto *StackPointer = make(Global, nullptr); - StackPointer->Live = true; + llvm::wasm::WasmGlobal global; + global.Type = {WASM_TYPE_I32, true}; + global.InitExpr.Value.Int32 = 0; + global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; + global.SymbolName = "__stack_pointer"; + auto *stackPointer = make(global, nullptr); + stackPointer->live = true; // For non-PIC code // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global // spec proposal is implemented in all major browsers. // See: https://github.com/WebAssembly/mutable-global - WasmSym::StackPointer = Symtab->addSyntheticGlobal( - "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer); - WasmSym::DataEnd = Symtab->addOptionalDataSymbol("__data_end"); - WasmSym::GlobalBase = Symtab->addOptionalDataSymbol("__global_base"); - WasmSym::HeapBase = Symtab->addOptionalDataSymbol("__heap_base"); + WasmSym::stackPointer = symtab->addSyntheticGlobal( + "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, stackPointer); + WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end"); + WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base"); + WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); } - if (Config->Pic) { + if (config->isPic) { // For PIC code, we import two global variables (__memory_base and // __table_base) from the environment and use these as the offset at // which to load our static data and function table. // See: // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md - WasmSym::MemoryBase = - createUndefinedGlobal("__memory_base", &GlobalTypeI32); - WasmSym::TableBase = createUndefinedGlobal("__table_base", &GlobalTypeI32); - WasmSym::MemoryBase->markLive(); - WasmSym::TableBase->markLive(); + WasmSym::memoryBase = + createUndefinedGlobal("__memory_base", &globalTypeI32); + WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32); + WasmSym::memoryBase->markLive(); + WasmSym::tableBase->markLive(); } - WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol( + WasmSym::dsoHandle = symtab->addSyntheticDataSymbol( "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN); } // Reconstructs command line arguments so that so that you can re-run // the same command with the same inputs. This is for --reproduce. -static std::string createResponseFile(const opt::InputArgList &Args) { - SmallString<0> Data; - raw_svector_ostream OS(Data); +static std::string createResponseFile(const opt::InputArgList &args) { + SmallString<0> data; + raw_svector_ostream os(data); // Copy the command line to the output while rewriting paths. - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_reproduce: break; case OPT_INPUT: - OS << quote(relativeToRoot(Arg->getValue())) << "\n"; + os << quote(relativeToRoot(arg->getValue())) << "\n"; break; case OPT_o: // If -o path contains directories, "lld @response.txt" will likely // fail because the archive we are creating doesn't contain empty // directories for the output path (-o doesn't create directories). // Strip directories to prevent the issue. - OS << "-o " << quote(sys::path::filename(Arg->getValue())) << "\n"; + os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n"; break; default: - OS << toString(*Arg) << "\n"; + os << toString(*arg) << "\n"; } } - return Data.str(); + return data.str(); } // The --wrap option is a feature to rename symbols so that you can write @@ -560,13 +560,13 @@ // // This data structure is instantiated for each -wrap option. struct WrappedSymbol { - Symbol *Sym; - Symbol *Real; - Symbol *Wrap; + Symbol *sym; + Symbol *real; + Symbol *wrap; }; -static Symbol *addUndefined(StringRef Name) { - return Symtab->addUndefinedFunction(Name, "", "", 0, nullptr, nullptr, false); +static Symbol *addUndefined(StringRef name) { + return symtab->addUndefinedFunction(name, "", "", 0, nullptr, nullptr, false); } // Handles -wrap option. @@ -574,34 +574,34 @@ // This function instantiates wrapper symbols. At this point, they seem // like they are not being used at all, so we explicitly set some flags so // that LTO won't eliminate them. -static std::vector addWrappedSymbols(opt::InputArgList &Args) { - std::vector V; - DenseSet Seen; - - for (auto *Arg : Args.filtered(OPT_wrap)) { - StringRef Name = Arg->getValue(); - if (!Seen.insert(Name).second) +static std::vector addWrappedSymbols(opt::InputArgList &args) { + std::vector v; + DenseSet seen; + + for (auto *arg : args.filtered(OPT_wrap)) { + StringRef name = arg->getValue(); + if (!seen.insert(name).second) continue; - Symbol *Sym = Symtab->find(Name); - if (!Sym) + Symbol *sym = symtab->find(name); + if (!sym) continue; - Symbol *Real = addUndefined(Saver.save("__real_" + Name)); - Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); - V.push_back({Sym, Real, Wrap}); + Symbol *real = addUndefined(saver.save("__real_" + name)); + Symbol *wrap = addUndefined(saver.save("__wrap_" + name)); + v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten // because LTO doesn't know the final symbol contents after renaming. - Real->CanInline = false; - Sym->CanInline = false; + real->canInline = false; + sym->canInline = false; // Tell LTO not to eliminate these symbols. - Sym->IsUsedInRegularObj = true; - Wrap->IsUsedInRegularObj = true; - Real->IsUsedInRegularObj = false; + sym->isUsedInRegularObj = true; + wrap->isUsedInRegularObj = true; + real->isUsedInRegularObj = false; } - return V; + return v; } // Do renaming for -wrap by updating pointers to symbols. @@ -609,158 +609,158 @@ // When this function is executed, only InputFiles and symbol table // contain pointers to symbol objects. We visit them to replace pointers, // so that wrapped symbols are swapped as instructed by the command line. -static void wrapSymbols(ArrayRef Wrapped) { - DenseMap Map; - for (const WrappedSymbol &W : Wrapped) { - Map[W.Sym] = W.Wrap; - Map[W.Real] = W.Sym; +static void wrapSymbols(ArrayRef wrapped) { + DenseMap map; + for (const WrappedSymbol &w : wrapped) { + map[w.sym] = w.wrap; + map[w.real] = w.sym; } // Update pointers in input files. - parallelForEach(Symtab->ObjectFiles, [&](InputFile *File) { - MutableArrayRef Syms = File->getMutableSymbols(); - for (size_t I = 0, E = Syms.size(); I != E; ++I) - if (Symbol *S = Map.lookup(Syms[I])) - Syms[I] = S; + parallelForEach(symtab->objectFiles, [&](InputFile *file) { + MutableArrayRef syms = file->getMutableSymbols(); + for (size_t i = 0, e = syms.size(); i != e; ++i) + if (Symbol *s = map.lookup(syms[i])) + syms[i] = s; }); // Update pointers in the symbol table. - for (const WrappedSymbol &W : Wrapped) - Symtab->wrap(W.Sym, W.Real, W.Wrap); + for (const WrappedSymbol &w : wrapped) + symtab->wrap(w.sym, w.real, w.wrap); } -void LinkerDriver::link(ArrayRef ArgsArr) { - WasmOptTable Parser; - opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); +void LinkerDriver::link(ArrayRef argsArr) { + WasmOptTable parser; + opt::InputArgList args = parser.parse(argsArr.slice(1)); // Handle --help - if (Args.hasArg(OPT_help)) { - Parser.PrintHelp(outs(), - (std::string(ArgsArr[0]) + " [options] file...").c_str(), + if (args.hasArg(OPT_help)) { + parser.PrintHelp(outs(), + (std::string(argsArr[0]) + " [options] file...").c_str(), "LLVM Linker", false); return; } // Handle --version - if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { + if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) { outs() << getLLDVersion() << "\n"; return; } // Handle --reproduce - if (auto *Arg = Args.getLastArg(OPT_reproduce)) { - StringRef Path = Arg->getValue(); - Expected> ErrOrWriter = - TarWriter::create(Path, path::stem(Path)); - if (ErrOrWriter) { - Tar = std::move(*ErrOrWriter); - Tar->append("response.txt", createResponseFile(Args)); - Tar->append("version.txt", getLLDVersion() + "\n"); + if (auto *arg = args.getLastArg(OPT_reproduce)) { + StringRef path = arg->getValue(); + Expected> errOrWriter = + TarWriter::create(path, path::stem(path)); + if (errOrWriter) { + tar = std::move(*errOrWriter); + tar->append("response.txt", createResponseFile(args)); + tar->append("version.txt", getLLDVersion() + "\n"); } else { - error("--reproduce: " + toString(ErrOrWriter.takeError())); + error("--reproduce: " + toString(errOrWriter.takeError())); } } // Parse and evaluate -mllvm options. - std::vector V; - V.push_back("wasm-ld (LLVM option parsing)"); - for (auto *Arg : Args.filtered(OPT_mllvm)) - V.push_back(Arg->getValue()); - cl::ParseCommandLineOptions(V.size(), V.data()); + std::vector v; + v.push_back("wasm-ld (LLVM option parsing)"); + for (auto *arg : args.filtered(OPT_mllvm)) + v.push_back(arg->getValue()); + cl::ParseCommandLineOptions(v.size(), v.data()); - errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); + errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20); - readConfigs(Args); + readConfigs(args); setConfigs(); - checkOptions(Args); + checkOptions(args); - if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) - readImportFile(Arg->getValue()); + if (auto *arg = args.getLastArg(OPT_allow_undefined_file)) + readImportFile(arg->getValue()); - if (!Args.hasArg(OPT_INPUT)) { + if (!args.hasArg(OPT_INPUT)) { error("no input files"); return; } // Handle --trace-symbol. - for (auto *Arg : Args.filtered(OPT_trace_symbol)) - Symtab->trace(Arg->getValue()); + for (auto *arg : args.filtered(OPT_trace_symbol)) + symtab->trace(arg->getValue()); - for (auto *Arg : Args.filtered(OPT_export)) - Config->ExportedSymbols.insert(Arg->getValue()); + for (auto *arg : args.filtered(OPT_export)) + config->exportedSymbols.insert(arg->getValue()); - if (!Config->Relocatable) + if (!config->relocatable) createSyntheticSymbols(); - createFiles(Args); + createFiles(args); if (errorCount()) return; // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. - for (InputFile *F : Files) - Symtab->addFile(F); + for (InputFile *f : files) + symtab->addFile(f); if (errorCount()) return; // Handle the `--undefined ` options. - for (auto *Arg : Args.filtered(OPT_undefined)) - handleUndefined(Arg->getValue()); + for (auto *arg : args.filtered(OPT_undefined)) + handleUndefined(arg->getValue()); // Handle the `--export ` options // This works like --undefined but also exports the symbol if its found - for (auto *Arg : Args.filtered(OPT_export)) - handleUndefined(Arg->getValue()); + for (auto *arg : args.filtered(OPT_export)) + handleUndefined(arg->getValue()); - Symbol *EntrySym = nullptr; - if (!Config->Relocatable && !Config->Entry.empty()) { - EntrySym = handleUndefined(Config->Entry); - if (EntrySym && EntrySym->isDefined()) - EntrySym->ForceExport = true; + Symbol *entrySym = nullptr; + if (!config->relocatable && !config->entry.empty()) { + entrySym = handleUndefined(config->entry); + if (entrySym && entrySym->isDefined()) + entrySym->forceExport = true; else error("entry symbol not defined (pass --no-entry to supress): " + - Config->Entry); + config->entry); } if (errorCount()) return; // Create wrapped symbols for -wrap option. - std::vector Wrapped = addWrappedSymbols(Args); + std::vector wrapped = addWrappedSymbols(args); // Do link-time optimization if given files are LLVM bitcode files. // This compiles bitcode files into real object files. - Symtab->addCombinedLTOObject(); + symtab->addCombinedLTOObject(); if (errorCount()) return; // Resolve any variant symbols that were created due to signature // mismatchs. - Symtab->handleSymbolVariants(); + symtab->handleSymbolVariants(); if (errorCount()) return; // Apply symbol renames for -wrap. - if (!Wrapped.empty()) - wrapSymbols(Wrapped); + if (!wrapped.empty()) + wrapSymbols(wrapped); - for (auto *Arg : Args.filtered(OPT_export)) { - Symbol *Sym = Symtab->find(Arg->getValue()); - if (Sym && Sym->isDefined()) - Sym->ForceExport = true; - else if (!Config->AllowUndefined) + for (auto *arg : args.filtered(OPT_export)) { + Symbol *sym = symtab->find(arg->getValue()); + if (sym && sym->isDefined()) + sym->forceExport = true; + else if (!config->allowUndefined) error(Twine("symbol exported via --export not found: ") + - Arg->getValue()); + arg->getValue()); } - if (!Config->Relocatable) { + if (!config->relocatable) { // Add synthetic dummies for weak undefined functions. Must happen // after LTO otherwise functions may not yet have signatures. - Symtab->handleWeakUndefines(); + symtab->handleWeakUndefines(); } - if (EntrySym) - EntrySym->setHidden(false); + if (entrySym) + entrySym->setHidden(false); if (errorCount()) return; Index: lld/trunk/wasm/InputChunks.h =================================================================== --- lld/trunk/wasm/InputChunks.h +++ lld/trunk/wasm/InputChunks.h @@ -37,15 +37,15 @@ public: enum Kind { DataSegment, Function, SyntheticFunction, Section }; - Kind kind() const { return SectionKind; } + Kind kind() const { return sectionKind; } virtual uint32_t getSize() const { return data().size(); } virtual uint32_t getInputSize() const { return getSize(); }; - virtual void writeTo(uint8_t *SectionStart) const; + virtual void writeTo(uint8_t *sectionStart) const; - ArrayRef getRelocations() const { return Relocations; } - void setRelocations(ArrayRef Rs) { Relocations = Rs; } + ArrayRef getRelocations() const { return relocations; } + void setRelocations(ArrayRef rs) { relocations = rs; } virtual StringRef getName() const = 0; virtual StringRef getDebugName() const = 0; @@ -53,23 +53,23 @@ StringRef getComdatName() const; virtual uint32_t getInputSectionOffset() const = 0; - size_t getNumRelocations() const { return Relocations.size(); } - void writeRelocations(llvm::raw_ostream &OS) const; + size_t getNumRelocations() const { return relocations.size(); } + void writeRelocations(llvm::raw_ostream &os) const; - ObjFile *File; - int32_t OutputOffset = 0; + ObjFile *file; + int32_t outputOffset = 0; // Signals that the section is part of the output. The garbage collector, // and COMDAT handling can set a sections' Live bit. // If GC is disabled, all sections start out as live by default. - unsigned Live : 1; + unsigned live : 1; // Signals the chunk was discarded by COMDAT handling. - unsigned Discarded : 1; + unsigned discarded : 1; protected: - InputChunk(ObjFile *F, Kind K) - : File(F), Live(!Config->GcSections), Discarded(false), SectionKind(K) {} + InputChunk(ObjFile *f, Kind k) + : file(f), live(!config->gcSections), discarded(false), sectionKind(k) {} virtual ~InputChunk() = default; virtual ArrayRef data() const = 0; @@ -77,8 +77,8 @@ // This is performed only debug builds as an extra sanity check. void verifyRelocTargets() const; - ArrayRef Relocations; - Kind SectionKind; + ArrayRef relocations; + Kind sectionKind; }; // Represents a WebAssembly data segment which can be included as part of @@ -91,65 +91,65 @@ // each global variable. class InputSegment : public InputChunk { public: - InputSegment(const WasmSegment &Seg, ObjFile *F) - : InputChunk(F, InputChunk::DataSegment), Segment(Seg) {} + InputSegment(const WasmSegment &seg, ObjFile *f) + : InputChunk(f, InputChunk::DataSegment), segment(seg) {} - static bool classof(const InputChunk *C) { return C->kind() == DataSegment; } + static bool classof(const InputChunk *c) { return c->kind() == DataSegment; } - void generateRelocationCode(raw_ostream &OS) const; + void generateRelocationCode(raw_ostream &os) const; - uint32_t getAlignment() const { return Segment.Data.Alignment; } - StringRef getName() const override { return Segment.Data.Name; } + uint32_t getAlignment() const { return segment.Data.Alignment; } + StringRef getName() const override { return segment.Data.Name; } StringRef getDebugName() const override { return StringRef(); } - uint32_t getComdat() const override { return Segment.Data.Comdat; } + uint32_t getComdat() const override { return segment.Data.Comdat; } uint32_t getInputSectionOffset() const override { - return Segment.SectionOffset; + return segment.SectionOffset; } - const OutputSegment *OutputSeg = nullptr; - int32_t OutputSegmentOffset = 0; + const OutputSegment *outputSeg = nullptr; + int32_t outputSegmentOffset = 0; protected: - ArrayRef data() const override { return Segment.Data.Content; } + ArrayRef data() const override { return segment.Data.Content; } - const WasmSegment &Segment; + const WasmSegment &segment; }; // Represents a single wasm function within and input file. These are // combined to create the final output CODE section. class InputFunction : public InputChunk { public: - InputFunction(const WasmSignature &S, const WasmFunction *Func, ObjFile *F) - : InputChunk(F, InputChunk::Function), Signature(S), Function(Func) {} + InputFunction(const WasmSignature &s, const WasmFunction *func, ObjFile *f) + : InputChunk(f, InputChunk::Function), signature(s), function(func) {} - static bool classof(const InputChunk *C) { - return C->kind() == InputChunk::Function || - C->kind() == InputChunk::SyntheticFunction; + static bool classof(const InputChunk *c) { + return c->kind() == InputChunk::Function || + c->kind() == InputChunk::SyntheticFunction; } - void writeTo(uint8_t *SectionStart) const override; - StringRef getName() const override { return Function->SymbolName; } - StringRef getDebugName() const override { return Function->DebugName; } - uint32_t getComdat() const override { return Function->Comdat; } + void writeTo(uint8_t *sectionStart) const override; + StringRef getName() const override { return function->SymbolName; } + StringRef getDebugName() const override { return function->DebugName; } + uint32_t getComdat() const override { return function->Comdat; } uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); } - uint32_t getFunctionCodeOffset() const { return Function->CodeOffset; } + uint32_t getFunctionCodeOffset() const { return function->CodeOffset; } uint32_t getSize() const override { - if (Config->CompressRelocations && File) { - assert(CompressedSize); - return CompressedSize; + if (config->compressRelocations && file) { + assert(compressedSize); + return compressedSize; } return data().size(); } - uint32_t getInputSize() const override { return Function->Size; } - uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); } - bool hasFunctionIndex() const { return FunctionIndex.hasValue(); } - void setFunctionIndex(uint32_t Index); + uint32_t getInputSize() const override { return function->Size; } + uint32_t getFunctionIndex() const { return functionIndex.getValue(); } + bool hasFunctionIndex() const { return functionIndex.hasValue(); } + void setFunctionIndex(uint32_t index); uint32_t getInputSectionOffset() const override { - return Function->CodeSectionOffset; + return function->CodeSectionOffset; } - uint32_t getTableIndex() const { return TableIndex.getValue(); } - bool hasTableIndex() const { return TableIndex.hasValue(); } - void setTableIndex(uint32_t Index); + uint32_t getTableIndex() const { return tableIndex.getValue(); } + bool hasTableIndex() const { return tableIndex.hasValue(); } + void setTableIndex(uint32_t index); // The size of a given input function can depend on the values of the // LEB relocations within it. This finalizeContents method is called after @@ -157,76 +157,76 @@ // called. void calculateSize(); - const WasmSignature &Signature; + const WasmSignature &signature; protected: ArrayRef data() const override { - assert(!Config->CompressRelocations); - return File->CodeSection->Content.slice(getInputSectionOffset(), - Function->Size); + assert(!config->compressRelocations); + return file->codeSection->Content.slice(getInputSectionOffset(), + function->Size); } - const WasmFunction *Function; - llvm::Optional FunctionIndex; - llvm::Optional TableIndex; - uint32_t CompressedFuncSize = 0; - uint32_t CompressedSize = 0; + const WasmFunction *function; + llvm::Optional functionIndex; + llvm::Optional tableIndex; + uint32_t compressedFuncSize = 0; + uint32_t compressedSize = 0; }; class SyntheticFunction : public InputFunction { public: - SyntheticFunction(const WasmSignature &S, StringRef Name, - StringRef DebugName = {}) - : InputFunction(S, nullptr, nullptr), Name(Name), DebugName(DebugName) { - SectionKind = InputChunk::SyntheticFunction; + SyntheticFunction(const WasmSignature &s, StringRef name, + StringRef debugName = {}) + : InputFunction(s, nullptr, nullptr), name(name), debugName(debugName) { + sectionKind = InputChunk::SyntheticFunction; } - static bool classof(const InputChunk *C) { - return C->kind() == InputChunk::SyntheticFunction; + static bool classof(const InputChunk *c) { + return c->kind() == InputChunk::SyntheticFunction; } - StringRef getName() const override { return Name; } - StringRef getDebugName() const override { return DebugName; } + StringRef getName() const override { return name; } + StringRef getDebugName() const override { return debugName; } uint32_t getComdat() const override { return UINT32_MAX; } - void setBody(ArrayRef Body_) { Body = Body_; } + void setBody(ArrayRef body_) { body = body_; } protected: - ArrayRef data() const override { return Body; } + ArrayRef data() const override { return body; } - StringRef Name; - StringRef DebugName; - ArrayRef Body; + StringRef name; + StringRef debugName; + ArrayRef body; }; // Represents a single Wasm Section within an input file. class InputSection : public InputChunk { public: - InputSection(const WasmSection &S, ObjFile *F) - : InputChunk(F, InputChunk::Section), Section(S) { - assert(Section.Type == llvm::wasm::WASM_SEC_CUSTOM); + InputSection(const WasmSection &s, ObjFile *f) + : InputChunk(f, InputChunk::Section), section(s) { + assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM); } - StringRef getName() const override { return Section.Name; } + StringRef getName() const override { return section.Name; } StringRef getDebugName() const override { return StringRef(); } uint32_t getComdat() const override { return UINT32_MAX; } - OutputSection *OutputSec = nullptr; + OutputSection *outputSec = nullptr; protected: - ArrayRef data() const override { return Section.Content; } + ArrayRef data() const override { return section.Content; } // Offset within the input section. This is only zero since this chunk // type represents an entire input section, not part of one. uint32_t getInputSectionOffset() const override { return 0; } - const WasmSection &Section; + const WasmSection §ion; }; } // namespace wasm std::string toString(const wasm::InputChunk *); -StringRef relocTypeToString(uint8_t RelocType); +StringRef relocTypeToString(uint8_t relocType); } // namespace lld Index: lld/trunk/wasm/InputChunks.cpp =================================================================== --- lld/trunk/wasm/InputChunks.cpp +++ lld/trunk/wasm/InputChunks.cpp @@ -22,8 +22,8 @@ using namespace lld; using namespace lld::wasm; -StringRef lld::relocTypeToString(uint8_t RelocType) { - switch (RelocType) { +StringRef lld::relocTypeToString(uint8_t relocType) { + switch (relocType) { #define WASM_RELOC(NAME, REL) \ case REL: \ return #NAME; @@ -33,67 +33,67 @@ llvm_unreachable("unknown reloc type"); } -std::string lld::toString(const InputChunk *C) { - return (toString(C->File) + ":(" + C->getName() + ")").str(); +std::string lld::toString(const InputChunk *c) { + return (toString(c->file) + ":(" + c->getName() + ")").str(); } StringRef InputChunk::getComdatName() const { - uint32_t Index = getComdat(); - if (Index == UINT32_MAX) + uint32_t index = getComdat(); + if (index == UINT32_MAX) return StringRef(); - return File->getWasmObj()->linkingData().Comdats[Index]; + return file->getWasmObj()->linkingData().Comdats[index]; } void InputChunk::verifyRelocTargets() const { - for (const WasmRelocation &Rel : Relocations) { - uint32_t ExistingValue; - unsigned BytesRead = 0; - uint32_t Offset = Rel.Offset - getInputSectionOffset(); - const uint8_t *Loc = data().data() + Offset; - switch (Rel.Type) { + for (const WasmRelocation &rel : relocations) { + uint32_t existingValue; + unsigned bytesRead = 0; + uint32_t offset = rel.Offset - getInputSectionOffset(); + const uint8_t *loc = data().data() + offset; + switch (rel.Type) { case R_WASM_TYPE_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: case R_WASM_EVENT_INDEX_LEB: case R_WASM_MEMORY_ADDR_LEB: - ExistingValue = decodeULEB128(Loc, &BytesRead); + existingValue = decodeULEB128(loc, &bytesRead); break; case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_REL_SLEB: case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_REL_SLEB: - ExistingValue = static_cast(decodeSLEB128(Loc, &BytesRead)); + existingValue = static_cast(decodeSLEB128(loc, &bytesRead)); break; case R_WASM_TABLE_INDEX_I32: case R_WASM_MEMORY_ADDR_I32: case R_WASM_FUNCTION_OFFSET_I32: case R_WASM_SECTION_OFFSET_I32: - ExistingValue = static_cast(read32le(Loc)); + existingValue = static_cast(read32le(loc)); break; default: llvm_unreachable("unknown relocation type"); } - if (BytesRead && BytesRead != 5) + if (bytesRead && bytesRead != 5) warn("expected LEB at relocation site be 5-byte padded"); - if (Rel.Type != R_WASM_GLOBAL_INDEX_LEB) { - uint32_t ExpectedValue = File->calcExpectedValue(Rel); - if (ExpectedValue != ExistingValue) - warn("unexpected existing value for " + relocTypeToString(Rel.Type) + - ": existing=" + Twine(ExistingValue) + - " expected=" + Twine(ExpectedValue)); + if (rel.Type != R_WASM_GLOBAL_INDEX_LEB) { + uint32_t expectedValue = file->calcExpectedValue(rel); + if (expectedValue != existingValue) + warn("unexpected existing value for " + relocTypeToString(rel.Type) + + ": existing=" + Twine(existingValue) + + " expected=" + Twine(expectedValue)); } } } // Copy this input chunk to an mmap'ed output file and apply relocations. -void InputChunk::writeTo(uint8_t *Buf) const { +void InputChunk::writeTo(uint8_t *buf) const { // Copy contents - memcpy(Buf + OutputOffset, data().data(), data().size()); + memcpy(buf + outputOffset, data().data(), data().size()); // Apply relocations - if (Relocations.empty()) + if (relocations.empty()) return; #ifndef NDEBUG @@ -101,38 +101,38 @@ #endif LLVM_DEBUG(dbgs() << "applying relocations: " << getName() - << " count=" << Relocations.size() << "\n"); - int32_t Off = OutputOffset - getInputSectionOffset(); + << " count=" << relocations.size() << "\n"); + int32_t off = outputOffset - getInputSectionOffset(); - for (const WasmRelocation &Rel : Relocations) { - uint8_t *Loc = Buf + Rel.Offset + Off; - uint32_t Value = File->calcNewValue(Rel); - LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(Rel.Type)); - if (Rel.Type != R_WASM_TYPE_INDEX_LEB) - LLVM_DEBUG(dbgs() << " sym=" << File->getSymbols()[Rel.Index]->getName()); - LLVM_DEBUG(dbgs() << " addend=" << Rel.Addend << " index=" << Rel.Index - << " value=" << Value << " offset=" << Rel.Offset + for (const WasmRelocation &rel : relocations) { + uint8_t *loc = buf + rel.Offset + off; + uint32_t value = file->calcNewValue(rel); + LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(rel.Type)); + if (rel.Type != R_WASM_TYPE_INDEX_LEB) + LLVM_DEBUG(dbgs() << " sym=" << file->getSymbols()[rel.Index]->getName()); + LLVM_DEBUG(dbgs() << " addend=" << rel.Addend << " index=" << rel.Index + << " value=" << value << " offset=" << rel.Offset << "\n"); - switch (Rel.Type) { + switch (rel.Type) { case R_WASM_TYPE_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: case R_WASM_EVENT_INDEX_LEB: case R_WASM_MEMORY_ADDR_LEB: - encodeULEB128(Value, Loc, 5); + encodeULEB128(value, loc, 5); break; case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_REL_SLEB: case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_REL_SLEB: - encodeSLEB128(static_cast(Value), Loc, 5); + encodeSLEB128(static_cast(value), loc, 5); break; case R_WASM_TABLE_INDEX_I32: case R_WASM_MEMORY_ADDR_I32: case R_WASM_FUNCTION_OFFSET_I32: case R_WASM_SECTION_OFFSET_I32: - write32le(Loc, Value); + write32le(loc, value); break; default: llvm_unreachable("unknown relocation type"); @@ -143,59 +143,59 @@ // Copy relocation entries to a given output stream. // This function is used only when a user passes "-r". For a regular link, // we consume relocations instead of copying them to an output file. -void InputChunk::writeRelocations(raw_ostream &OS) const { - if (Relocations.empty()) +void InputChunk::writeRelocations(raw_ostream &os) const { + if (relocations.empty()) return; - int32_t Off = OutputOffset - getInputSectionOffset(); - LLVM_DEBUG(dbgs() << "writeRelocations: " << File->getName() - << " offset=" << Twine(Off) << "\n"); - - for (const WasmRelocation &Rel : Relocations) { - writeUleb128(OS, Rel.Type, "reloc type"); - writeUleb128(OS, Rel.Offset + Off, "reloc offset"); - writeUleb128(OS, File->calcNewIndex(Rel), "reloc index"); + int32_t off = outputOffset - getInputSectionOffset(); + LLVM_DEBUG(dbgs() << "writeRelocations: " << file->getName() + << " offset=" << Twine(off) << "\n"); + + for (const WasmRelocation &rel : relocations) { + writeUleb128(os, rel.Type, "reloc type"); + writeUleb128(os, rel.Offset + off, "reloc offset"); + writeUleb128(os, file->calcNewIndex(rel), "reloc index"); - if (relocTypeHasAddend(Rel.Type)) - writeSleb128(OS, File->calcNewAddend(Rel), "reloc addend"); + if (relocTypeHasAddend(rel.Type)) + writeSleb128(os, file->calcNewAddend(rel), "reloc addend"); } } -void InputFunction::setFunctionIndex(uint32_t Index) { +void InputFunction::setFunctionIndex(uint32_t index) { LLVM_DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName() - << " -> " << Index << "\n"); + << " -> " << index << "\n"); assert(!hasFunctionIndex()); - FunctionIndex = Index; + functionIndex = index; } -void InputFunction::setTableIndex(uint32_t Index) { +void InputFunction::setTableIndex(uint32_t index) { LLVM_DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> " - << Index << "\n"); + << index << "\n"); assert(!hasTableIndex()); - TableIndex = Index; + tableIndex = index; } // Write a relocation value without padding and return the number of bytes // witten. -static unsigned writeCompressedReloc(uint8_t *Buf, const WasmRelocation &Rel, - uint32_t Value) { - switch (Rel.Type) { +static unsigned writeCompressedReloc(uint8_t *buf, const WasmRelocation &rel, + uint32_t value) { + switch (rel.Type) { case R_WASM_TYPE_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: case R_WASM_EVENT_INDEX_LEB: case R_WASM_MEMORY_ADDR_LEB: - return encodeULEB128(Value, Buf); + return encodeULEB128(value, buf); case R_WASM_TABLE_INDEX_SLEB: case R_WASM_MEMORY_ADDR_SLEB: - return encodeSLEB128(static_cast(Value), Buf); + return encodeSLEB128(static_cast(value), buf); default: llvm_unreachable("unexpected relocation type"); } } -static unsigned getRelocWidthPadded(const WasmRelocation &Rel) { - switch (Rel.Type) { +static unsigned getRelocWidthPadded(const WasmRelocation &rel) { + switch (rel.Type) { case R_WASM_TYPE_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: @@ -209,9 +209,9 @@ } } -static unsigned getRelocWidth(const WasmRelocation &Rel, uint32_t Value) { - uint8_t Buf[5]; - return writeCompressedReloc(Buf, Rel, Value); +static unsigned getRelocWidth(const WasmRelocation &rel, uint32_t value) { + uint8_t buf[5]; + return writeCompressedReloc(buf, rel, value); } // Relocations of type LEB and SLEB in the code section are padded to 5 bytes @@ -225,124 +225,124 @@ // This function only computes the final output size. It must be called // before getSize() is used to calculate of layout of the code section. void InputFunction::calculateSize() { - if (!File || !Config->CompressRelocations) + if (!file || !config->compressRelocations) return; LLVM_DEBUG(dbgs() << "calculateSize: " << getName() << "\n"); - const uint8_t *SecStart = File->CodeSection->Content.data(); - const uint8_t *FuncStart = SecStart + getInputSectionOffset(); - uint32_t FunctionSizeLength; - decodeULEB128(FuncStart, &FunctionSizeLength); - - uint32_t Start = getInputSectionOffset(); - uint32_t End = Start + Function->Size; - - uint32_t LastRelocEnd = Start + FunctionSizeLength; - for (const WasmRelocation &Rel : Relocations) { - LLVM_DEBUG(dbgs() << " region: " << (Rel.Offset - LastRelocEnd) << "\n"); - CompressedFuncSize += Rel.Offset - LastRelocEnd; - CompressedFuncSize += getRelocWidth(Rel, File->calcNewValue(Rel)); - LastRelocEnd = Rel.Offset + getRelocWidthPadded(Rel); + const uint8_t *secStart = file->codeSection->Content.data(); + const uint8_t *funcStart = secStart + getInputSectionOffset(); + uint32_t functionSizeLength; + decodeULEB128(funcStart, &functionSizeLength); + + uint32_t start = getInputSectionOffset(); + uint32_t end = start + function->Size; + + uint32_t lastRelocEnd = start + functionSizeLength; + for (const WasmRelocation &rel : relocations) { + LLVM_DEBUG(dbgs() << " region: " << (rel.Offset - lastRelocEnd) << "\n"); + compressedFuncSize += rel.Offset - lastRelocEnd; + compressedFuncSize += getRelocWidth(rel, file->calcNewValue(rel)); + lastRelocEnd = rel.Offset + getRelocWidthPadded(rel); } - LLVM_DEBUG(dbgs() << " final region: " << (End - LastRelocEnd) << "\n"); - CompressedFuncSize += End - LastRelocEnd; + LLVM_DEBUG(dbgs() << " final region: " << (end - lastRelocEnd) << "\n"); + compressedFuncSize += end - lastRelocEnd; // Now we know how long the resulting function is we can add the encoding // of its length - uint8_t Buf[5]; - CompressedSize = CompressedFuncSize + encodeULEB128(CompressedFuncSize, Buf); + uint8_t buf[5]; + compressedSize = compressedFuncSize + encodeULEB128(compressedFuncSize, buf); - LLVM_DEBUG(dbgs() << " calculateSize orig: " << Function->Size << "\n"); - LLVM_DEBUG(dbgs() << " calculateSize new: " << CompressedSize << "\n"); + LLVM_DEBUG(dbgs() << " calculateSize orig: " << function->Size << "\n"); + LLVM_DEBUG(dbgs() << " calculateSize new: " << compressedSize << "\n"); } // Override the default writeTo method so that we can (optionally) write the // compressed version of the function. -void InputFunction::writeTo(uint8_t *Buf) const { - if (!File || !Config->CompressRelocations) - return InputChunk::writeTo(Buf); - - Buf += OutputOffset; - uint8_t *Orig = Buf; - (void)Orig; - - const uint8_t *SecStart = File->CodeSection->Content.data(); - const uint8_t *FuncStart = SecStart + getInputSectionOffset(); - const uint8_t *End = FuncStart + Function->Size; - uint32_t Count; - decodeULEB128(FuncStart, &Count); - FuncStart += Count; +void InputFunction::writeTo(uint8_t *buf) const { + if (!file || !config->compressRelocations) + return InputChunk::writeTo(buf); + + buf += outputOffset; + uint8_t *orig = buf; + (void)orig; + + const uint8_t *secStart = file->codeSection->Content.data(); + const uint8_t *funcStart = secStart + getInputSectionOffset(); + const uint8_t *end = funcStart + function->Size; + uint32_t count; + decodeULEB128(funcStart, &count); + funcStart += count; LLVM_DEBUG(dbgs() << "write func: " << getName() << "\n"); - Buf += encodeULEB128(CompressedFuncSize, Buf); - const uint8_t *LastRelocEnd = FuncStart; - for (const WasmRelocation &Rel : Relocations) { - unsigned ChunkSize = (SecStart + Rel.Offset) - LastRelocEnd; - LLVM_DEBUG(dbgs() << " write chunk: " << ChunkSize << "\n"); - memcpy(Buf, LastRelocEnd, ChunkSize); - Buf += ChunkSize; - Buf += writeCompressedReloc(Buf, Rel, File->calcNewValue(Rel)); - LastRelocEnd = SecStart + Rel.Offset + getRelocWidthPadded(Rel); + buf += encodeULEB128(compressedFuncSize, buf); + const uint8_t *lastRelocEnd = funcStart; + for (const WasmRelocation &rel : relocations) { + unsigned chunkSize = (secStart + rel.Offset) - lastRelocEnd; + LLVM_DEBUG(dbgs() << " write chunk: " << chunkSize << "\n"); + memcpy(buf, lastRelocEnd, chunkSize); + buf += chunkSize; + buf += writeCompressedReloc(buf, rel, file->calcNewValue(rel)); + lastRelocEnd = secStart + rel.Offset + getRelocWidthPadded(rel); } - unsigned ChunkSize = End - LastRelocEnd; - LLVM_DEBUG(dbgs() << " write final chunk: " << ChunkSize << "\n"); - memcpy(Buf, LastRelocEnd, ChunkSize); - LLVM_DEBUG(dbgs() << " total: " << (Buf + ChunkSize - Orig) << "\n"); + unsigned chunkSize = end - lastRelocEnd; + LLVM_DEBUG(dbgs() << " write final chunk: " << chunkSize << "\n"); + memcpy(buf, lastRelocEnd, chunkSize); + LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n"); } // Generate code to apply relocations to the data section at runtime. // This is only called when generating shared libaries (PIC) where address are // not known at static link time. -void InputSegment::generateRelocationCode(raw_ostream &OS) const { +void InputSegment::generateRelocationCode(raw_ostream &os) const { LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName() - << " count=" << Relocations.size() << "\n"); + << " count=" << relocations.size() << "\n"); // TODO(sbc): Encode the relocations in the data section and write a loop // here to apply them. - uint32_t SegmentVA = OutputSeg->StartVA + OutputSegmentOffset; - for (const WasmRelocation &Rel : Relocations) { - uint32_t Offset = Rel.Offset - getInputSectionOffset(); - uint32_t OutputOffset = SegmentVA + Offset; - - LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(Rel.Type) - << " addend=" << Rel.Addend << " index=" << Rel.Index - << " output offset=" << OutputOffset << "\n"); + uint32_t segmentVA = outputSeg->startVA + outputSegmentOffset; + for (const WasmRelocation &rel : relocations) { + uint32_t offset = rel.Offset - getInputSectionOffset(); + uint32_t outputOffset = segmentVA + offset; + + LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type) + << " addend=" << rel.Addend << " index=" << rel.Index + << " output offset=" << outputOffset << "\n"); // Get __memory_base - writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); - writeUleb128(OS, WasmSym::MemoryBase->getGlobalIndex(), "memory_base"); + writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); + writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base"); // Add the offset of the relocation - writeU8(OS, WASM_OPCODE_I32_CONST, "I32_CONST"); - writeSleb128(OS, OutputOffset, "offset"); - writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); + writeU8(os, WASM_OPCODE_I32_CONST, "I32_CONST"); + writeSleb128(os, outputOffset, "offset"); + writeU8(os, WASM_OPCODE_I32_ADD, "ADD"); - Symbol *Sym = File->getSymbol(Rel); + Symbol *sym = file->getSymbol(rel); // Now figure out what we want to store - if (Sym->hasGOTIndex()) { - writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); - writeUleb128(OS, Sym->getGOTIndex(), "global index"); - if (Rel.Addend) { - writeU8(OS, WASM_OPCODE_I32_CONST, "CONST"); - writeSleb128(OS, Rel.Addend, "addend"); - writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); + if (sym->hasGOTIndex()) { + writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); + writeUleb128(os, sym->getGOTIndex(), "global index"); + if (rel.Addend) { + writeU8(os, WASM_OPCODE_I32_CONST, "CONST"); + writeSleb128(os, rel.Addend, "addend"); + writeU8(os, WASM_OPCODE_I32_ADD, "ADD"); } } else { - const GlobalSymbol* BaseSymbol = WasmSym::MemoryBase; - if (Rel.Type == R_WASM_TABLE_INDEX_I32) - BaseSymbol = WasmSym::TableBase; - writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); - writeUleb128(OS, BaseSymbol->getGlobalIndex(), "base"); - writeU8(OS, WASM_OPCODE_I32_CONST, "CONST"); - writeSleb128(OS, File->calcNewValue(Rel), "offset"); - writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); + const GlobalSymbol* baseSymbol = WasmSym::memoryBase; + if (rel.Type == R_WASM_TABLE_INDEX_I32) + baseSymbol = WasmSym::tableBase; + writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); + writeUleb128(os, baseSymbol->getGlobalIndex(), "base"); + writeU8(os, WASM_OPCODE_I32_CONST, "CONST"); + writeSleb128(os, file->calcNewValue(rel), "offset"); + writeU8(os, WASM_OPCODE_I32_ADD, "ADD"); } // Store that value at the virtual address - writeU8(OS, WASM_OPCODE_I32_STORE, "I32_STORE"); - writeUleb128(OS, 2, "align"); - writeUleb128(OS, 0, "offset"); + writeU8(os, WASM_OPCODE_I32_STORE, "I32_STORE"); + writeUleb128(os, 2, "align"); + writeUleb128(os, 0, "offset"); } } Index: lld/trunk/wasm/InputEvent.h =================================================================== --- lld/trunk/wasm/InputEvent.h +++ lld/trunk/wasm/InputEvent.h @@ -28,33 +28,33 @@ // form the final EVENTS section. class InputEvent { public: - InputEvent(const WasmSignature &S, const WasmEvent &E, ObjFile *F) - : File(F), Event(E), Signature(S), Live(!Config->GcSections) {} + InputEvent(const WasmSignature &s, const WasmEvent &e, ObjFile *f) + : file(f), event(e), signature(s), live(!config->gcSections) {} - StringRef getName() const { return Event.SymbolName; } - const WasmEventType &getType() const { return Event.Type; } + StringRef getName() const { return event.SymbolName; } + const WasmEventType &getType() const { return event.Type; } - uint32_t getEventIndex() const { return EventIndex.getValue(); } - bool hasEventIndex() const { return EventIndex.hasValue(); } - void setEventIndex(uint32_t Index) { + uint32_t getEventIndex() const { return eventIndex.getValue(); } + bool hasEventIndex() const { return eventIndex.hasValue(); } + void setEventIndex(uint32_t index) { assert(!hasEventIndex()); - EventIndex = Index; + eventIndex = index; } - ObjFile *File; - WasmEvent Event; - const WasmSignature &Signature; + ObjFile *file; + WasmEvent event; + const WasmSignature &signature; - bool Live = false; + bool live = false; protected: - llvm::Optional EventIndex; + llvm::Optional eventIndex; }; } // namespace wasm -inline std::string toString(const wasm::InputEvent *E) { - return (toString(E->File) + ":(" + E->getName() + ")").str(); +inline std::string toString(const wasm::InputEvent *e) { + return (toString(e->file) + ":(" + e->getName() + ")").str(); } } // namespace lld Index: lld/trunk/wasm/InputFiles.h =================================================================== --- lld/trunk/wasm/InputFiles.h +++ lld/trunk/wasm/InputFiles.h @@ -35,7 +35,7 @@ // If --reproduce option is given, all input files are written // to this tar archive. -extern std::unique_ptr Tar; +extern std::unique_ptr tar; class InputFile { public: @@ -49,129 +49,129 @@ virtual ~InputFile() {} // Returns the filename. - StringRef getName() const { return MB.getBufferIdentifier(); } + StringRef getName() const { return mb.getBufferIdentifier(); } - Kind kind() const { return FileKind; } + Kind kind() const { return fileKind; } // An archive file name if this file is created from an archive. - StringRef ArchiveName; + StringRef archiveName; - ArrayRef getSymbols() const { return Symbols; } + ArrayRef getSymbols() const { return symbols; } - MutableArrayRef getMutableSymbols() { return Symbols; } + MutableArrayRef getMutableSymbols() { return symbols; } protected: - InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} - MemoryBufferRef MB; + InputFile(Kind k, MemoryBufferRef m) : mb(m), fileKind(k) {} + MemoryBufferRef mb; // List of all symbols referenced or defined by this file. - std::vector Symbols; + std::vector symbols; private: - const Kind FileKind; + const Kind fileKind; }; // .a file (ar archive) class ArchiveFile : public InputFile { public: - explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} - static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } + explicit ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {} + static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } - void addMember(const llvm::object::Archive::Symbol *Sym); + void addMember(const llvm::object::Archive::Symbol *sym); void parse(); private: - std::unique_ptr File; - llvm::DenseSet Seen; + std::unique_ptr file; + llvm::DenseSet seen; }; // .o file (wasm object file) class ObjFile : public InputFile { public: - explicit ObjFile(MemoryBufferRef M, StringRef ArchiveName) - : InputFile(ObjectKind, M) { - this->ArchiveName = ArchiveName; + explicit ObjFile(MemoryBufferRef m, StringRef archiveName) + : InputFile(ObjectKind, m) { + this->archiveName = archiveName; } - static bool classof(const InputFile *F) { return F->kind() == ObjectKind; } + static bool classof(const InputFile *f) { return f->kind() == ObjectKind; } - void parse(bool IgnoreComdats = false); + void parse(bool ignoreComdats = false); // Returns the underlying wasm file. - const WasmObjectFile *getWasmObj() const { return WasmObj.get(); } + const WasmObjectFile *getWasmObj() const { return wasmObj.get(); } void dumpInfo() const; - uint32_t calcNewIndex(const WasmRelocation &Reloc) const; - uint32_t calcNewValue(const WasmRelocation &Reloc) const; - uint32_t calcNewAddend(const WasmRelocation &Reloc) const; - uint32_t calcExpectedValue(const WasmRelocation &Reloc) const; - Symbol *getSymbol(const WasmRelocation &Reloc) const { - return Symbols[Reloc.Index]; + uint32_t calcNewIndex(const WasmRelocation &reloc) const; + uint32_t calcNewValue(const WasmRelocation &reloc) const; + uint32_t calcNewAddend(const WasmRelocation &reloc) const; + uint32_t calcExpectedValue(const WasmRelocation &reloc) const; + Symbol *getSymbol(const WasmRelocation &reloc) const { + return symbols[reloc.Index]; }; - const WasmSection *CodeSection = nullptr; - const WasmSection *DataSection = nullptr; + const WasmSection *codeSection = nullptr; + const WasmSection *dataSection = nullptr; // Maps input type indices to output type indices - std::vector TypeMap; - std::vector TypeIsUsed; + std::vector typeMap; + std::vector typeIsUsed; // Maps function indices to table indices - std::vector TableEntries; - std::vector KeptComdats; - std::vector Segments; - std::vector Functions; - std::vector Globals; - std::vector Events; - std::vector CustomSections; - llvm::DenseMap CustomSectionsByIndex; - - Symbol *getSymbol(uint32_t Index) const { return Symbols[Index]; } - FunctionSymbol *getFunctionSymbol(uint32_t Index) const; - DataSymbol *getDataSymbol(uint32_t Index) const; - GlobalSymbol *getGlobalSymbol(uint32_t Index) const; - SectionSymbol *getSectionSymbol(uint32_t Index) const; - EventSymbol *getEventSymbol(uint32_t Index) const; + std::vector tableEntries; + std::vector keptComdats; + std::vector segments; + std::vector functions; + std::vector globals; + std::vector events; + std::vector customSections; + llvm::DenseMap customSectionsByIndex; + + Symbol *getSymbol(uint32_t index) const { return symbols[index]; } + FunctionSymbol *getFunctionSymbol(uint32_t index) const; + DataSymbol *getDataSymbol(uint32_t index) const; + GlobalSymbol *getGlobalSymbol(uint32_t index) const; + SectionSymbol *getSectionSymbol(uint32_t index) const; + EventSymbol *getEventSymbol(uint32_t index) const; private: - Symbol *createDefined(const WasmSymbol &Sym); - Symbol *createUndefined(const WasmSymbol &Sym, bool IsCalledDirectly); + Symbol *createDefined(const WasmSymbol &sym); + Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly); - bool isExcludedByComdat(InputChunk *Chunk) const; + bool isExcludedByComdat(InputChunk *chunk) const; - std::unique_ptr WasmObj; + std::unique_ptr wasmObj; }; // .so file. class SharedFile : public InputFile { public: - explicit SharedFile(MemoryBufferRef M) : InputFile(SharedKind, M) {} - static bool classof(const InputFile *F) { return F->kind() == SharedKind; } + explicit SharedFile(MemoryBufferRef m) : InputFile(SharedKind, m) {} + static bool classof(const InputFile *f) { return f->kind() == SharedKind; } }; // .bc file class BitcodeFile : public InputFile { public: - explicit BitcodeFile(MemoryBufferRef M, StringRef ArchiveName) - : InputFile(BitcodeKind, M) { - this->ArchiveName = ArchiveName; + explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName) + : InputFile(BitcodeKind, m) { + this->archiveName = archiveName; } - static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } + static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } void parse(); - std::unique_ptr Obj; + std::unique_ptr obj; }; // Will report a fatal() error if the input buffer is not a valid bitcode // or wasm object file. -InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = ""); +InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = ""); // Opens a given file. -llvm::Optional readFile(StringRef Path); +llvm::Optional readFile(StringRef path); } // namespace wasm -std::string toString(const wasm::InputFile *File); +std::string toString(const wasm::InputFile *file); } // namespace lld Index: lld/trunk/wasm/InputFiles.cpp =================================================================== --- lld/trunk/wasm/InputFiles.cpp +++ lld/trunk/wasm/InputFiles.cpp @@ -29,77 +29,77 @@ using namespace llvm::object; using namespace llvm::wasm; -std::unique_ptr lld::wasm::Tar; +std::unique_ptr lld::wasm::tar; -Optional lld::wasm::readFile(StringRef Path) { - log("Loading: " + Path); +Optional lld::wasm::readFile(StringRef path) { + log("Loading: " + path); - auto MBOrErr = MemoryBuffer::getFile(Path); - if (auto EC = MBOrErr.getError()) { - error("cannot open " + Path + ": " + EC.message()); + auto mbOrErr = MemoryBuffer::getFile(path); + if (auto ec = mbOrErr.getError()) { + error("cannot open " + path + ": " + ec.message()); return None; } - std::unique_ptr &MB = *MBOrErr; - MemoryBufferRef MBRef = MB->getMemBufferRef(); - make>(std::move(MB)); // take MB ownership - - if (Tar) - Tar->append(relativeToRoot(Path), MBRef.getBuffer()); - return MBRef; -} - -InputFile *lld::wasm::createObjectFile(MemoryBufferRef MB, - StringRef ArchiveName) { - file_magic Magic = identify_magic(MB.getBuffer()); - if (Magic == file_magic::wasm_object) { - std::unique_ptr Bin = - CHECK(createBinary(MB), MB.getBufferIdentifier()); - auto *Obj = cast(Bin.get()); - if (Obj->isSharedObject()) - return make(MB); - return make(MB, ArchiveName); + std::unique_ptr &mb = *mbOrErr; + MemoryBufferRef mbref = mb->getMemBufferRef(); + make>(std::move(mb)); // take MB ownership + + if (tar) + tar->append(relativeToRoot(path), mbref.getBuffer()); + return mbref; +} + +InputFile *lld::wasm::createObjectFile(MemoryBufferRef mb, + StringRef archiveName) { + file_magic magic = identify_magic(mb.getBuffer()); + if (magic == file_magic::wasm_object) { + std::unique_ptr bin = + CHECK(createBinary(mb), mb.getBufferIdentifier()); + auto *obj = cast(bin.get()); + if (obj->isSharedObject()) + return make(mb); + return make(mb, archiveName); } - if (Magic == file_magic::bitcode) - return make(MB, ArchiveName); + if (magic == file_magic::bitcode) + return make(mb, archiveName); - fatal("unknown file type: " + MB.getBufferIdentifier()); + fatal("unknown file type: " + mb.getBufferIdentifier()); } void ObjFile::dumpInfo() const { log("info for: " + toString(this) + - "\n Symbols : " + Twine(Symbols.size()) + - "\n Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) + - "\n Global Imports : " + Twine(WasmObj->getNumImportedGlobals()) + - "\n Event Imports : " + Twine(WasmObj->getNumImportedEvents())); + "\n Symbols : " + Twine(symbols.size()) + + "\n Function Imports : " + Twine(wasmObj->getNumImportedFunctions()) + + "\n Global Imports : " + Twine(wasmObj->getNumImportedGlobals()) + + "\n Event Imports : " + Twine(wasmObj->getNumImportedEvents())); } // Relocations contain either symbol or type indices. This function takes a // relocation and returns relocated index (i.e. translates from the input // symbol/type space to the output symbol/type space). -uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const { - if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) { - assert(TypeIsUsed[Reloc.Index]); - return TypeMap[Reloc.Index]; - } - const Symbol *Sym = Symbols[Reloc.Index]; - if (auto *SS = dyn_cast(Sym)) - Sym = SS->getOutputSectionSymbol(); - return Sym->getOutputSymbolIndex(); +uint32_t ObjFile::calcNewIndex(const WasmRelocation &reloc) const { + if (reloc.Type == R_WASM_TYPE_INDEX_LEB) { + assert(typeIsUsed[reloc.Index]); + return typeMap[reloc.Index]; + } + const Symbol *sym = symbols[reloc.Index]; + if (auto *ss = dyn_cast(sym)) + sym = ss->getOutputSectionSymbol(); + return sym->getOutputSymbolIndex(); } // Relocations can contain addend for combined sections. This function takes a // relocation and returns updated addend by offset in the output section. -uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const { - switch (Reloc.Type) { +uint32_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const { + switch (reloc.Type) { case R_WASM_MEMORY_ADDR_LEB: case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_REL_SLEB: case R_WASM_MEMORY_ADDR_I32: case R_WASM_FUNCTION_OFFSET_I32: - return Reloc.Addend; + return reloc.Addend; case R_WASM_SECTION_OFFSET_I32: - return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend; + return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend; default: llvm_unreachable("unexpected relocation type"); } @@ -108,42 +108,42 @@ // Calculate the value we expect to find at the relocation location. // This is used as a sanity check before applying a relocation to a given // location. It is useful for catching bugs in the compiler and linker. -uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const { - switch (Reloc.Type) { +uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const { + switch (reloc.Type) { case R_WASM_TABLE_INDEX_I32: case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_REL_SLEB: { - const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; - return TableEntries[Sym.Info.ElementIndex]; + const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; + return tableEntries[sym.Info.ElementIndex]; } case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_I32: case R_WASM_MEMORY_ADDR_LEB: case R_WASM_MEMORY_ADDR_REL_SLEB: { - const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; - if (Sym.isUndefined()) + const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; + if (sym.isUndefined()) return 0; - const WasmSegment &Segment = - WasmObj->dataSegments()[Sym.Info.DataRef.Segment]; - return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset + - Reloc.Addend; + const WasmSegment &segment = + wasmObj->dataSegments()[sym.Info.DataRef.Segment]; + return segment.Data.Offset.Value.Int32 + sym.Info.DataRef.Offset + + reloc.Addend; } case R_WASM_FUNCTION_OFFSET_I32: { - const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; - InputFunction *F = - Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()]; - return F->getFunctionInputOffset() + F->getFunctionCodeOffset() + - Reloc.Addend; + const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; + InputFunction *f = + functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()]; + return f->getFunctionInputOffset() + f->getFunctionCodeOffset() + + reloc.Addend; } case R_WASM_SECTION_OFFSET_I32: - return Reloc.Addend; + return reloc.Addend; case R_WASM_TYPE_INDEX_LEB: - return Reloc.Index; + return reloc.Index; case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_GLOBAL_INDEX_LEB: case R_WASM_EVENT_INDEX_LEB: { - const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; - return Sym.Info.ElementIndex; + const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; + return sym.Info.ElementIndex; } default: llvm_unreachable("unknown relocation type"); @@ -151,115 +151,115 @@ } // Translate from the relocation's index into the final linked output value. -uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { - const Symbol* Sym = nullptr; - if (Reloc.Type != R_WASM_TYPE_INDEX_LEB) { - Sym = Symbols[Reloc.Index]; +uint32_t ObjFile::calcNewValue(const WasmRelocation &reloc) const { + const Symbol* sym = nullptr; + if (reloc.Type != R_WASM_TYPE_INDEX_LEB) { + sym = symbols[reloc.Index]; // We can end up with relocations against non-live symbols. For example // in debug sections. - if ((isa(Sym) || isa(Sym)) && !Sym->isLive()) + if ((isa(sym) || isa(sym)) && !sym->isLive()) return 0; } - switch (Reloc.Type) { + switch (reloc.Type) { case R_WASM_TABLE_INDEX_I32: case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_REL_SLEB: - if (Config->Pic && !getFunctionSymbol(Reloc.Index)->hasTableIndex()) + if (config->isPic && !getFunctionSymbol(reloc.Index)->hasTableIndex()) return 0; - return getFunctionSymbol(Reloc.Index)->getTableIndex(); + return getFunctionSymbol(reloc.Index)->getTableIndex(); case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_I32: case R_WASM_MEMORY_ADDR_LEB: case R_WASM_MEMORY_ADDR_REL_SLEB: - if (isa(Sym)) + if (isa(sym)) return 0; - return cast(Sym)->getVirtualAddress() + Reloc.Addend; + return cast(sym)->getVirtualAddress() + reloc.Addend; case R_WASM_TYPE_INDEX_LEB: - return TypeMap[Reloc.Index]; + return typeMap[reloc.Index]; case R_WASM_FUNCTION_INDEX_LEB: - return getFunctionSymbol(Reloc.Index)->getFunctionIndex(); + return getFunctionSymbol(reloc.Index)->getFunctionIndex(); case R_WASM_GLOBAL_INDEX_LEB: - if (auto GS = dyn_cast(Sym)) - return GS->getGlobalIndex(); - return Sym->getGOTIndex(); + if (auto gs = dyn_cast(sym)) + return gs->getGlobalIndex(); + return sym->getGOTIndex(); case R_WASM_EVENT_INDEX_LEB: - return getEventSymbol(Reloc.Index)->getEventIndex(); + return getEventSymbol(reloc.Index)->getEventIndex(); case R_WASM_FUNCTION_OFFSET_I32: { - auto *F = cast(Sym); - return F->Function->OutputOffset + F->Function->getFunctionCodeOffset() + - Reloc.Addend; + auto *f = cast(sym); + return f->function->outputOffset + f->function->getFunctionCodeOffset() + + reloc.Addend; } case R_WASM_SECTION_OFFSET_I32: - return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend; + return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend; default: llvm_unreachable("unknown relocation type"); } } template -static void setRelocs(const std::vector &Chunks, - const WasmSection *Section) { - if (!Section) +static void setRelocs(const std::vector &chunks, + const WasmSection *section) { + if (!section) return; - ArrayRef Relocs = Section->Relocations; - assert(std::is_sorted(Relocs.begin(), Relocs.end(), - [](const WasmRelocation &R1, const WasmRelocation &R2) { - return R1.Offset < R2.Offset; + ArrayRef relocs = section->Relocations; + assert(std::is_sorted(relocs.begin(), relocs.end(), + [](const WasmRelocation &r1, const WasmRelocation &r2) { + return r1.Offset < r2.Offset; })); assert(std::is_sorted( - Chunks.begin(), Chunks.end(), [](InputChunk *C1, InputChunk *C2) { - return C1->getInputSectionOffset() < C2->getInputSectionOffset(); + chunks.begin(), chunks.end(), [](InputChunk *c1, InputChunk *c2) { + return c1->getInputSectionOffset() < c2->getInputSectionOffset(); })); - auto RelocsNext = Relocs.begin(); - auto RelocsEnd = Relocs.end(); - auto RelocLess = [](const WasmRelocation &R, uint32_t Val) { - return R.Offset < Val; + auto relocsNext = relocs.begin(); + auto relocsEnd = relocs.end(); + auto relocLess = [](const WasmRelocation &r, uint32_t val) { + return r.Offset < val; }; - for (InputChunk *C : Chunks) { - auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd, - C->getInputSectionOffset(), RelocLess); - RelocsNext = std::lower_bound( - RelocsStart, RelocsEnd, C->getInputSectionOffset() + C->getInputSize(), - RelocLess); - C->setRelocations(ArrayRef(RelocsStart, RelocsNext)); + for (InputChunk *c : chunks) { + auto relocsStart = std::lower_bound(relocsNext, relocsEnd, + c->getInputSectionOffset(), relocLess); + relocsNext = std::lower_bound( + relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(), + relocLess); + c->setRelocations(ArrayRef(relocsStart, relocsNext)); } } -void ObjFile::parse(bool IgnoreComdats) { +void ObjFile::parse(bool ignoreComdats) { // Parse a memory buffer as a wasm file. LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n"); - std::unique_ptr Bin = CHECK(createBinary(MB), toString(this)); + std::unique_ptr bin = CHECK(createBinary(mb), toString(this)); - auto *Obj = dyn_cast(Bin.get()); - if (!Obj) + auto *obj = dyn_cast(bin.get()); + if (!obj) fatal(toString(this) + ": not a wasm file"); - if (!Obj->isRelocatableObject()) + if (!obj->isRelocatableObject()) fatal(toString(this) + ": not a relocatable wasm file"); - Bin.release(); - WasmObj.reset(Obj); + bin.release(); + wasmObj.reset(obj); // Build up a map of function indices to table indices for use when // verifying the existing table index relocations - uint32_t TotalFunctions = - WasmObj->getNumImportedFunctions() + WasmObj->functions().size(); - TableEntries.resize(TotalFunctions); - for (const WasmElemSegment &Seg : WasmObj->elements()) { - if (Seg.Offset.Opcode != WASM_OPCODE_I32_CONST) + uint32_t totalFunctions = + wasmObj->getNumImportedFunctions() + wasmObj->functions().size(); + tableEntries.resize(totalFunctions); + for (const WasmElemSegment &seg : wasmObj->elements()) { + if (seg.Offset.Opcode != WASM_OPCODE_I32_CONST) fatal(toString(this) + ": invalid table elements"); - uint32_t Offset = Seg.Offset.Value.Int32; - for (uint32_t Index = 0; Index < Seg.Functions.size(); Index++) { + uint32_t offset = seg.Offset.Value.Int32; + for (uint32_t index = 0; index < seg.Functions.size(); index++) { - uint32_t FunctionIndex = Seg.Functions[Index]; - TableEntries[FunctionIndex] = Offset + Index; + uint32_t functionIndex = seg.Functions[index]; + tableEntries[functionIndex] = offset + index; } } - uint32_t SectionIndex = 0; + uint32_t sectionIndex = 0; // Bool for each symbol, true if called directly. This allows us to implement // a weaker form of signature checking where undefined functions that are not @@ -267,185 +267,185 @@ // function's signature. We cannot do this for directly called functions // because those signatures are checked at validation times. // See https://bugs.llvm.org/show_bug.cgi?id=40412 - std::vector IsCalledDirectly(WasmObj->getNumberOfSymbols(), false); - for (const SectionRef &Sec : WasmObj->sections()) { - const WasmSection &Section = WasmObj->getWasmSection(Sec); + std::vector isCalledDirectly(wasmObj->getNumberOfSymbols(), false); + for (const SectionRef &sec : wasmObj->sections()) { + const WasmSection §ion = wasmObj->getWasmSection(sec); // Wasm objects can have at most one code and one data section. - if (Section.Type == WASM_SEC_CODE) { - assert(!CodeSection); - CodeSection = &Section; - } else if (Section.Type == WASM_SEC_DATA) { - assert(!DataSection); - DataSection = &Section; - } else if (Section.Type == WASM_SEC_CUSTOM) { - CustomSections.emplace_back(make(Section, this)); - CustomSections.back()->setRelocations(Section.Relocations); - CustomSectionsByIndex[SectionIndex] = CustomSections.back(); + if (section.Type == WASM_SEC_CODE) { + assert(!codeSection); + codeSection = §ion; + } else if (section.Type == WASM_SEC_DATA) { + assert(!dataSection); + dataSection = §ion; + } else if (section.Type == WASM_SEC_CUSTOM) { + customSections.emplace_back(make(section, this)); + customSections.back()->setRelocations(section.Relocations); + customSectionsByIndex[sectionIndex] = customSections.back(); } - SectionIndex++; + sectionIndex++; // Scans relocations to dermine determine if a function symbol is called // directly - for (const WasmRelocation &Reloc : Section.Relocations) - if (Reloc.Type == R_WASM_FUNCTION_INDEX_LEB) - IsCalledDirectly[Reloc.Index] = true; + for (const WasmRelocation &reloc : section.Relocations) + if (reloc.Type == R_WASM_FUNCTION_INDEX_LEB) + isCalledDirectly[reloc.Index] = true; } - TypeMap.resize(getWasmObj()->types().size()); - TypeIsUsed.resize(getWasmObj()->types().size(), false); - - ArrayRef Comdats = WasmObj->linkingData().Comdats; - for (StringRef Comdat : Comdats) { - bool IsNew = IgnoreComdats || Symtab->addComdat(Comdat); - KeptComdats.push_back(IsNew); + typeMap.resize(getWasmObj()->types().size()); + typeIsUsed.resize(getWasmObj()->types().size(), false); + + ArrayRef comdats = wasmObj->linkingData().Comdats; + for (StringRef comdat : comdats) { + bool isNew = ignoreComdats || symtab->addComdat(comdat); + keptComdats.push_back(isNew); } // Populate `Segments`. - for (const WasmSegment &S : WasmObj->dataSegments()) { - auto* Seg = make(S, this); - Seg->Discarded = isExcludedByComdat(Seg); - Segments.emplace_back(Seg); + for (const WasmSegment &s : wasmObj->dataSegments()) { + auto* seg = make(s, this); + seg->discarded = isExcludedByComdat(seg); + segments.emplace_back(seg); } - setRelocs(Segments, DataSection); + setRelocs(segments, dataSection); // Populate `Functions`. - ArrayRef Funcs = WasmObj->functions(); - ArrayRef FuncTypes = WasmObj->functionTypes(); - ArrayRef Types = WasmObj->types(); - Functions.reserve(Funcs.size()); - - for (size_t I = 0, E = Funcs.size(); I != E; ++I) { - auto* Func = make(Types[FuncTypes[I]], &Funcs[I], this); - Func->Discarded = isExcludedByComdat(Func); - Functions.emplace_back(Func); + ArrayRef funcs = wasmObj->functions(); + ArrayRef funcTypes = wasmObj->functionTypes(); + ArrayRef types = wasmObj->types(); + functions.reserve(funcs.size()); + + for (size_t i = 0, e = funcs.size(); i != e; ++i) { + auto* func = make(types[funcTypes[i]], &funcs[i], this); + func->discarded = isExcludedByComdat(func); + functions.emplace_back(func); } - setRelocs(Functions, CodeSection); + setRelocs(functions, codeSection); // Populate `Globals`. - for (const WasmGlobal &G : WasmObj->globals()) - Globals.emplace_back(make(G, this)); + for (const WasmGlobal &g : wasmObj->globals()) + globals.emplace_back(make(g, this)); // Populate `Events`. - for (const WasmEvent &E : WasmObj->events()) - Events.emplace_back(make(Types[E.Type.SigIndex], E, this)); + for (const WasmEvent &e : wasmObj->events()) + events.emplace_back(make(types[e.Type.SigIndex], e, this)); // Populate `Symbols` based on the WasmSymbols in the object. - Symbols.reserve(WasmObj->getNumberOfSymbols()); - for (const SymbolRef &Sym : WasmObj->symbols()) { - const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl()); - if (WasmSym.isDefined()) { + symbols.reserve(wasmObj->getNumberOfSymbols()); + for (const SymbolRef &sym : wasmObj->symbols()) { + const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(sym.getRawDataRefImpl()); + if (wasmSym.isDefined()) { // createDefined may fail if the symbol is comdat excluded in which case // we fall back to creating an undefined symbol - if (Symbol *D = createDefined(WasmSym)) { - Symbols.push_back(D); + if (Symbol *d = createDefined(wasmSym)) { + symbols.push_back(d); continue; } } - size_t Idx = Symbols.size(); - Symbols.push_back(createUndefined(WasmSym, IsCalledDirectly[Idx])); + size_t idx = symbols.size(); + symbols.push_back(createUndefined(wasmSym, isCalledDirectly[idx])); } } -bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const { - uint32_t C = Chunk->getComdat(); - if (C == UINT32_MAX) +bool ObjFile::isExcludedByComdat(InputChunk *chunk) const { + uint32_t c = chunk->getComdat(); + if (c == UINT32_MAX) return false; - return !KeptComdats[C]; + return !keptComdats[c]; } -FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const { - return cast(Symbols[Index]); +FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t index) const { + return cast(symbols[index]); } -GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const { - return cast(Symbols[Index]); +GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t index) const { + return cast(symbols[index]); } -EventSymbol *ObjFile::getEventSymbol(uint32_t Index) const { - return cast(Symbols[Index]); +EventSymbol *ObjFile::getEventSymbol(uint32_t index) const { + return cast(symbols[index]); } -SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const { - return cast(Symbols[Index]); +SectionSymbol *ObjFile::getSectionSymbol(uint32_t index) const { + return cast(symbols[index]); } -DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const { - return cast(Symbols[Index]); +DataSymbol *ObjFile::getDataSymbol(uint32_t index) const { + return cast(symbols[index]); } -Symbol *ObjFile::createDefined(const WasmSymbol &Sym) { - StringRef Name = Sym.Info.Name; - uint32_t Flags = Sym.Info.Flags; +Symbol *ObjFile::createDefined(const WasmSymbol &sym) { + StringRef name = sym.Info.Name; + uint32_t flags = sym.Info.Flags; - switch (Sym.Info.Kind) { + switch (sym.Info.Kind) { case WASM_SYMBOL_TYPE_FUNCTION: { - InputFunction *Func = - Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()]; - if (Func->Discarded) + InputFunction *func = + functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()]; + if (func->discarded) return nullptr; - if (Sym.isBindingLocal()) - return make(Name, Flags, this, Func); - return Symtab->addDefinedFunction(Name, Flags, this, Func); + if (sym.isBindingLocal()) + return make(name, flags, this, func); + return symtab->addDefinedFunction(name, flags, this, func); } case WASM_SYMBOL_TYPE_DATA: { - InputSegment *Seg = Segments[Sym.Info.DataRef.Segment]; - if (Seg->Discarded) + InputSegment *seg = segments[sym.Info.DataRef.Segment]; + if (seg->discarded) return nullptr; - uint32_t Offset = Sym.Info.DataRef.Offset; - uint32_t Size = Sym.Info.DataRef.Size; + uint32_t offset = sym.Info.DataRef.Offset; + uint32_t size = sym.Info.DataRef.Size; - if (Sym.isBindingLocal()) - return make(Name, Flags, this, Seg, Offset, Size); - return Symtab->addDefinedData(Name, Flags, this, Seg, Offset, Size); + if (sym.isBindingLocal()) + return make(name, flags, this, seg, offset, size); + return symtab->addDefinedData(name, flags, this, seg, offset, size); } case WASM_SYMBOL_TYPE_GLOBAL: { - InputGlobal *Global = - Globals[Sym.Info.ElementIndex - WasmObj->getNumImportedGlobals()]; - if (Sym.isBindingLocal()) - return make(Name, Flags, this, Global); - return Symtab->addDefinedGlobal(Name, Flags, this, Global); + InputGlobal *global = + globals[sym.Info.ElementIndex - wasmObj->getNumImportedGlobals()]; + if (sym.isBindingLocal()) + return make(name, flags, this, global); + return symtab->addDefinedGlobal(name, flags, this, global); } case WASM_SYMBOL_TYPE_SECTION: { - InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex]; - assert(Sym.isBindingLocal()); - return make(Flags, Section, this); + InputSection *section = customSectionsByIndex[sym.Info.ElementIndex]; + assert(sym.isBindingLocal()); + return make(flags, section, this); } case WASM_SYMBOL_TYPE_EVENT: { - InputEvent *Event = - Events[Sym.Info.ElementIndex - WasmObj->getNumImportedEvents()]; - if (Sym.isBindingLocal()) - return make(Name, Flags, this, Event); - return Symtab->addDefinedEvent(Name, Flags, this, Event); + InputEvent *event = + events[sym.Info.ElementIndex - wasmObj->getNumImportedEvents()]; + if (sym.isBindingLocal()) + return make(name, flags, this, event); + return symtab->addDefinedEvent(name, flags, this, event); } } llvm_unreachable("unknown symbol kind"); } -Symbol *ObjFile::createUndefined(const WasmSymbol &Sym, bool IsCalledDirectly) { - StringRef Name = Sym.Info.Name; - uint32_t Flags = Sym.Info.Flags; +Symbol *ObjFile::createUndefined(const WasmSymbol &sym, bool isCalledDirectly) { + StringRef name = sym.Info.Name; + uint32_t flags = sym.Info.Flags; - switch (Sym.Info.Kind) { + switch (sym.Info.Kind) { case WASM_SYMBOL_TYPE_FUNCTION: - if (Sym.isBindingLocal()) - return make(Name, Sym.Info.ImportName, - Sym.Info.ImportModule, Flags, this, - Sym.Signature, IsCalledDirectly); - return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName, - Sym.Info.ImportModule, Flags, this, - Sym.Signature, IsCalledDirectly); + if (sym.isBindingLocal()) + return make(name, sym.Info.ImportName, + sym.Info.ImportModule, flags, this, + sym.Signature, isCalledDirectly); + return symtab->addUndefinedFunction(name, sym.Info.ImportName, + sym.Info.ImportModule, flags, this, + sym.Signature, isCalledDirectly); case WASM_SYMBOL_TYPE_DATA: - if (Sym.isBindingLocal()) - return make(Name, Flags, this); - return Symtab->addUndefinedData(Name, Flags, this); + if (sym.isBindingLocal()) + return make(name, flags, this); + return symtab->addUndefinedData(name, flags, this); case WASM_SYMBOL_TYPE_GLOBAL: - if (Sym.isBindingLocal()) - return make(Name, Sym.Info.ImportName, - Sym.Info.ImportModule, Flags, this, - Sym.GlobalType); - return Symtab->addUndefinedGlobal(Name, Sym.Info.ImportName, - Sym.Info.ImportModule, Flags, this, - Sym.GlobalType); + if (sym.isBindingLocal()) + return make(name, sym.Info.ImportName, + sym.Info.ImportModule, flags, this, + sym.GlobalType); + return symtab->addUndefinedGlobal(name, sym.Info.ImportName, + sym.Info.ImportModule, flags, this, + sym.GlobalType); case WASM_SYMBOL_TYPE_SECTION: llvm_unreachable("section symbols cannot be undefined"); } @@ -455,41 +455,41 @@ void ArchiveFile::parse() { // Parse a MemoryBufferRef as an archive file. LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n"); - File = CHECK(Archive::create(MB), toString(this)); + file = CHECK(Archive::create(mb), toString(this)); // Read the symbol table to construct Lazy symbols. - int Count = 0; - for (const Archive::Symbol &Sym : File->symbols()) { - Symtab->addLazy(this, &Sym); - ++Count; - } - LLVM_DEBUG(dbgs() << "Read " << Count << " symbols\n"); + int count = 0; + for (const Archive::Symbol &sym : file->symbols()) { + symtab->addLazy(this, &sym); + ++count; + } + LLVM_DEBUG(dbgs() << "Read " << count << " symbols\n"); } -void ArchiveFile::addMember(const Archive::Symbol *Sym) { - const Archive::Child &C = - CHECK(Sym->getMember(), - "could not get the member for symbol " + Sym->getName()); +void ArchiveFile::addMember(const Archive::Symbol *sym) { + const Archive::Child &c = + CHECK(sym->getMember(), + "could not get the member for symbol " + sym->getName()); // Don't try to load the same member twice (this can happen when members // mutually reference each other). - if (!Seen.insert(C.getChildOffset()).second) + if (!seen.insert(c.getChildOffset()).second) return; - LLVM_DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n"); + LLVM_DEBUG(dbgs() << "loading lazy: " << sym->getName() << "\n"); LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n"); - MemoryBufferRef MB = - CHECK(C.getMemoryBufferRef(), + MemoryBufferRef mb = + CHECK(c.getMemoryBufferRef(), "could not get the buffer for the member defining symbol " + - Sym->getName()); + sym->getName()); - InputFile *Obj = createObjectFile(MB, getName()); - Symtab->addFile(Obj); + InputFile *obj = createObjectFile(mb, getName()); + symtab->addFile(obj); } -static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) { - switch (GvVisibility) { +static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) { + switch (gvVisibility) { case GlobalValue::DefaultVisibility: return WASM_SYMBOL_VISIBILITY_DEFAULT; case GlobalValue::HiddenVisibility: @@ -499,52 +499,52 @@ llvm_unreachable("unknown visibility"); } -static Symbol *createBitcodeSymbol(const std::vector &KeptComdats, - const lto::InputFile::Symbol &ObjSym, - BitcodeFile &F) { - StringRef Name = Saver.save(ObjSym.getName()); - - uint32_t Flags = ObjSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0; - Flags |= mapVisibility(ObjSym.getVisibility()); - - int C = ObjSym.getComdatIndex(); - bool ExcludedByComdat = C != -1 && !KeptComdats[C]; - - if (ObjSym.isUndefined() || ExcludedByComdat) { - if (ObjSym.isExecutable()) - return Symtab->addUndefinedFunction(Name, Name, DefaultModule, Flags, &F, +static Symbol *createBitcodeSymbol(const std::vector &keptComdats, + const lto::InputFile::Symbol &objSym, + BitcodeFile &f) { + StringRef name = saver.save(objSym.getName()); + + uint32_t flags = objSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0; + flags |= mapVisibility(objSym.getVisibility()); + + int c = objSym.getComdatIndex(); + bool excludedByComdat = c != -1 && !keptComdats[c]; + + if (objSym.isUndefined() || excludedByComdat) { + if (objSym.isExecutable()) + return symtab->addUndefinedFunction(name, name, defaultModule, flags, &f, nullptr, true); - return Symtab->addUndefinedData(Name, Flags, &F); + return symtab->addUndefinedData(name, flags, &f); } - if (ObjSym.isExecutable()) - return Symtab->addDefinedFunction(Name, Flags, &F, nullptr); - return Symtab->addDefinedData(Name, Flags, &F, nullptr, 0, 0); + if (objSym.isExecutable()) + return symtab->addDefinedFunction(name, flags, &f, nullptr); + return symtab->addDefinedData(name, flags, &f, nullptr, 0, 0); } void BitcodeFile::parse() { - Obj = check(lto::InputFile::create(MemoryBufferRef( - MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier())))); - Triple T(Obj->getTargetTriple()); - if (T.getArch() != Triple::wasm32) { - error(toString(MB.getBufferIdentifier()) + ": machine type must be wasm32"); + obj = check(lto::InputFile::create(MemoryBufferRef( + mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier())))); + Triple t(obj->getTargetTriple()); + if (t.getArch() != Triple::wasm32) { + error(toString(mb.getBufferIdentifier()) + ": machine type must be wasm32"); return; } - std::vector KeptComdats; - for (StringRef S : Obj->getComdatTable()) - KeptComdats.push_back(Symtab->addComdat(S)); + std::vector keptComdats; + for (StringRef s : obj->getComdatTable()) + keptComdats.push_back(symtab->addComdat(s)); - for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) - Symbols.push_back(createBitcodeSymbol(KeptComdats, ObjSym, *this)); + for (const lto::InputFile::Symbol &objSym : obj->symbols()) + symbols.push_back(createBitcodeSymbol(keptComdats, objSym, *this)); } // Returns a string in the format of "foo.o" or "foo.a(bar.o)". -std::string lld::toString(const wasm::InputFile *File) { - if (!File) +std::string lld::toString(const wasm::InputFile *file) { + if (!file) return ""; - if (File->ArchiveName.empty()) - return File->getName(); + if (file->archiveName.empty()) + return file->getName(); - return (File->ArchiveName + "(" + File->getName() + ")").str(); + return (file->archiveName + "(" + file->getName() + ")").str(); } Index: lld/trunk/wasm/InputGlobal.h =================================================================== --- lld/trunk/wasm/InputGlobal.h +++ lld/trunk/wasm/InputGlobal.h @@ -22,32 +22,32 @@ // combined to form the final GLOBALS section. class InputGlobal { public: - InputGlobal(const WasmGlobal &G, ObjFile *F) - : File(F), Global(G), Live(!Config->GcSections) {} + InputGlobal(const WasmGlobal &g, ObjFile *f) + : file(f), global(g), live(!config->gcSections) {} - StringRef getName() const { return Global.SymbolName; } - const WasmGlobalType &getType() const { return Global.Type; } + StringRef getName() const { return global.SymbolName; } + const WasmGlobalType &getType() const { return global.Type; } - uint32_t getGlobalIndex() const { return GlobalIndex.getValue(); } - bool hasGlobalIndex() const { return GlobalIndex.hasValue(); } - void setGlobalIndex(uint32_t Index) { + uint32_t getGlobalIndex() const { return globalIndex.getValue(); } + bool hasGlobalIndex() const { return globalIndex.hasValue(); } + void setGlobalIndex(uint32_t index) { assert(!hasGlobalIndex()); - GlobalIndex = Index; + globalIndex = index; } - ObjFile *File; - WasmGlobal Global; + ObjFile *file; + WasmGlobal global; - bool Live = false; + bool live = false; protected: - llvm::Optional GlobalIndex; + llvm::Optional globalIndex; }; } // namespace wasm -inline std::string toString(const wasm::InputGlobal *G) { - return (toString(G->File) + ":(" + G->getName() + ")").str(); +inline std::string toString(const wasm::InputGlobal *g) { + return (toString(g->file) + ":(" + g->getName() + ")").str(); } } // namespace lld Index: lld/trunk/wasm/LTO.h =================================================================== --- lld/trunk/wasm/LTO.h +++ lld/trunk/wasm/LTO.h @@ -43,13 +43,13 @@ BitcodeCompiler(); ~BitcodeCompiler(); - void add(BitcodeFile &F); + void add(BitcodeFile &f); std::vector compile(); private: - std::unique_ptr LTOObj; - std::vector> Buf; - std::vector> Files; + std::unique_ptr ltoObj; + std::vector> buf; + std::vector> files; }; } // namespace wasm } // namespace lld Index: lld/trunk/wasm/LTO.cpp =================================================================== --- lld/trunk/wasm/LTO.cpp +++ lld/trunk/wasm/LTO.cpp @@ -40,127 +40,127 @@ using namespace lld::wasm; static std::unique_ptr createLTO() { - lto::Config C; - C.Options = initTargetOptionsFromCodeGenFlags(); + lto::Config c; + c.Options = initTargetOptionsFromCodeGenFlags(); // Always emit a section per function/data with LTO. - C.Options.FunctionSections = true; - C.Options.DataSections = true; + c.Options.FunctionSections = true; + c.Options.DataSections = true; - C.DisableVerify = Config->DisableVerify; - C.DiagHandler = diagnosticHandler; - C.OptLevel = Config->LTOO; - C.MAttrs = getMAttrs(); - C.CGOptLevel = args::getCGOptLevel(Config->LTOO); - - if (Config->Relocatable) - C.RelocModel = None; - else if (Config->Pic) - C.RelocModel = Reloc::PIC_; + c.DisableVerify = config->disableVerify; + c.DiagHandler = diagnosticHandler; + c.OptLevel = config->ltoo; + c.MAttrs = getMAttrs(); + c.CGOptLevel = args::getCGOptLevel(config->ltoo); + + if (config->relocatable) + c.RelocModel = None; + else if (config->isPic) + c.RelocModel = Reloc::PIC_; else - C.RelocModel = Reloc::Static; + c.RelocModel = Reloc::Static; - if (Config->SaveTemps) - checkError(C.addSaveTemps(Config->OutputFile.str() + ".", + if (config->saveTemps) + checkError(c.addSaveTemps(config->outputFile.str() + ".", /*UseInputModulePath*/ true)); - lto::ThinBackend Backend; - if (Config->ThinLTOJobs != -1U) - Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs); - return llvm::make_unique(std::move(C), Backend, - Config->LTOPartitions); + lto::ThinBackend backend; + if (config->thinLTOJobs != -1U) + backend = lto::createInProcessThinBackend(config->thinLTOJobs); + return llvm::make_unique(std::move(c), backend, + config->ltoPartitions); } -BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} +BitcodeCompiler::BitcodeCompiler() : ltoObj(createLTO()) {} BitcodeCompiler::~BitcodeCompiler() = default; -static void undefine(Symbol *S) { - if (auto F = dyn_cast(S)) - replaceSymbol(F, F->getName(), F->getName(), - DefaultModule, 0, - F->getFile(), F->Signature); - else if (isa(S)) - replaceSymbol(S, S->getName(), 0, S->getFile()); +static void undefine(Symbol *s) { + if (auto f = dyn_cast(s)) + replaceSymbol(f, f->getName(), f->getName(), + defaultModule, 0, + f->getFile(), f->signature); + else if (isa(s)) + replaceSymbol(s, s->getName(), 0, s->getFile()); else llvm_unreachable("unexpected symbol kind"); } -void BitcodeCompiler::add(BitcodeFile &F) { - lto::InputFile &Obj = *F.Obj; - unsigned SymNum = 0; - ArrayRef Syms = F.getSymbols(); - std::vector Resols(Syms.size()); +void BitcodeCompiler::add(BitcodeFile &f) { + lto::InputFile &obj = *f.obj; + unsigned symNum = 0; + ArrayRef syms = f.getSymbols(); + std::vector resols(syms.size()); // Provide a resolution to the LTO API for each symbol. - for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { - Symbol *Sym = Syms[SymNum]; - lto::SymbolResolution &R = Resols[SymNum]; - ++SymNum; + for (const lto::InputFile::Symbol &objSym : obj.symbols()) { + Symbol *sym = syms[symNum]; + lto::SymbolResolution &r = resols[symNum]; + ++symNum; // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile // reports two symbols for module ASM defined. Without this check, lld // flags an undefined in IR with a definition in ASM as prevailing. // Once IRObjectFile is fixed to report only one symbol this hack can // be removed. - R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F; - R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj || - (R.Prevailing && Sym->isExported()); - if (R.Prevailing) - undefine(Sym); + r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f; + r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj || + (r.Prevailing && sym->isExported()); + if (r.Prevailing) + undefine(sym); // We tell LTO to not apply interprocedural optimization for wrapped // (with --wrap) symbols because otherwise LTO would inline them while // their values are still not final. - R.LinkerRedefined = !Sym->CanInline; + r.LinkerRedefined = !sym->canInline; } - checkError(LTOObj->add(std::move(F.Obj), Resols)); + checkError(ltoObj->add(std::move(f.obj), resols)); } // Merge all the bitcode files we have seen, codegen the result // and return the resulting objects. std::vector BitcodeCompiler::compile() { - unsigned MaxTasks = LTOObj->getMaxTasks(); - Buf.resize(MaxTasks); - Files.resize(MaxTasks); + unsigned maxTasks = ltoObj->getMaxTasks(); + buf.resize(maxTasks); + files.resize(maxTasks); // The --thinlto-cache-dir option specifies the path to a directory in which // to cache native object files for ThinLTO incremental builds. If a path was // specified, configure LTO to use it as the cache directory. - lto::NativeObjectCache Cache; - if (!Config->ThinLTOCacheDir.empty()) - Cache = check( - lto::localCache(Config->ThinLTOCacheDir, - [&](size_t Task, std::unique_ptr MB) { - Files[Task] = std::move(MB); + lto::NativeObjectCache cache; + if (!config->thinLTOCacheDir.empty()) + cache = check( + lto::localCache(config->thinLTOCacheDir, + [&](size_t task, std::unique_ptr mb) { + files[task] = std::move(mb); })); - checkError(LTOObj->run( - [&](size_t Task) { + checkError(ltoObj->run( + [&](size_t task) { return llvm::make_unique( - llvm::make_unique(Buf[Task])); + llvm::make_unique(buf[task])); }, - Cache)); + cache)); - if (!Config->ThinLTOCacheDir.empty()) - pruneCache(Config->ThinLTOCacheDir, Config->ThinLTOCachePolicy); + if (!config->thinLTOCacheDir.empty()) + pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy); - std::vector Ret; - for (unsigned I = 0; I != MaxTasks; ++I) { - if (Buf[I].empty()) + std::vector ret; + for (unsigned i = 0; i != maxTasks; ++i) { + if (buf[i].empty()) continue; - if (Config->SaveTemps) { - if (I == 0) - saveBuffer(Buf[I], Config->OutputFile + ".lto.o"); + if (config->saveTemps) { + if (i == 0) + saveBuffer(buf[i], config->outputFile + ".lto.o"); else - saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.o"); + saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o"); } - Ret.emplace_back(Buf[I].data(), Buf[I].size()); + ret.emplace_back(buf[i].data(), buf[i].size()); } - for (std::unique_ptr &File : Files) - if (File) - Ret.push_back(File->getBuffer()); + for (std::unique_ptr &file : files) + if (file) + ret.push_back(file->getBuffer()); - return Ret; + return ret; } Index: lld/trunk/wasm/MarkLive.cpp =================================================================== --- lld/trunk/wasm/MarkLive.cpp +++ lld/trunk/wasm/MarkLive.cpp @@ -32,68 +32,68 @@ using namespace llvm::wasm; void lld::wasm::markLive() { - if (!Config->GcSections) + if (!config->gcSections) return; LLVM_DEBUG(dbgs() << "markLive\n"); - SmallVector Q; + SmallVector q; - std::function Enqueue = [&](Symbol *Sym) { - if (!Sym || Sym->isLive()) + std::function enqueue = [&](Symbol *sym) { + if (!sym || sym->isLive()) return; - LLVM_DEBUG(dbgs() << "markLive: " << Sym->getName() << "\n"); - Sym->markLive(); - if (InputChunk *Chunk = Sym->getChunk()) - Q.push_back(Chunk); + LLVM_DEBUG(dbgs() << "markLive: " << sym->getName() << "\n"); + sym->markLive(); + if (InputChunk *chunk = sym->getChunk()) + q.push_back(chunk); // The ctor functions are all referenced by the synthetic CallCtors // function. However, this function does not contain relocations so we // have to manually mark the ctors as live if CallCtors itself is live. - if (Sym == WasmSym::CallCtors) { - if (Config->PassiveSegments) - Enqueue(WasmSym::InitMemory); - if (Config->Pic) - Enqueue(WasmSym::ApplyRelocs); - for (const ObjFile *Obj : Symtab->ObjectFiles) { - const WasmLinkingData &L = Obj->getWasmObj()->linkingData(); - for (const WasmInitFunc &F : L.InitFunctions) { - auto* InitSym = Obj->getFunctionSymbol(F.Symbol); - if (!InitSym->isDiscarded()) - Enqueue(InitSym); + if (sym == WasmSym::callCtors) { + if (config->passiveSegments) + enqueue(WasmSym::initMemory); + if (config->isPic) + enqueue(WasmSym::applyRelocs); + for (const ObjFile *obj : symtab->objectFiles) { + const WasmLinkingData &l = obj->getWasmObj()->linkingData(); + for (const WasmInitFunc &f : l.InitFunctions) { + auto* initSym = obj->getFunctionSymbol(f.Symbol); + if (!initSym->isDiscarded()) + enqueue(initSym); } } } }; // Add GC root symbols. - if (!Config->Entry.empty()) - Enqueue(Symtab->find(Config->Entry)); + if (!config->entry.empty()) + enqueue(symtab->find(config->entry)); // We need to preserve any exported symbol - for (Symbol *Sym : Symtab->getSymbols()) - if (Sym->isExported()) - Enqueue(Sym); + for (Symbol *sym : symtab->getSymbols()) + if (sym->isExported()) + enqueue(sym); // For relocatable output, we need to preserve all the ctor functions - if (Config->Relocatable) { - for (const ObjFile *Obj : Symtab->ObjectFiles) { - const WasmLinkingData &L = Obj->getWasmObj()->linkingData(); - for (const WasmInitFunc &F : L.InitFunctions) - Enqueue(Obj->getFunctionSymbol(F.Symbol)); + if (config->relocatable) { + for (const ObjFile *obj : symtab->objectFiles) { + const WasmLinkingData &l = obj->getWasmObj()->linkingData(); + for (const WasmInitFunc &f : l.InitFunctions) + enqueue(obj->getFunctionSymbol(f.Symbol)); } } - if (Config->Pic) - Enqueue(WasmSym::CallCtors); + if (config->isPic) + enqueue(WasmSym::callCtors); // Follow relocations to mark all reachable chunks. - while (!Q.empty()) { - InputChunk *C = Q.pop_back_val(); + while (!q.empty()) { + InputChunk *c = q.pop_back_val(); - for (const WasmRelocation Reloc : C->getRelocations()) { - if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) + for (const WasmRelocation reloc : c->getRelocations()) { + if (reloc.Type == R_WASM_TYPE_INDEX_LEB) continue; - Symbol *Sym = C->File->getSymbol(Reloc.Index); + Symbol *sym = c->file->getSymbol(reloc.Index); // If the function has been assigned the special index zero in the table, // the relocation doesn't pull in the function body, since the function @@ -102,38 +102,38 @@ // zero is only reachable via "call", not via "call_indirect". The stub // functions used for weak-undefined symbols have this behaviour (compare // equal to null pointer, only reachable via direct call). - if (Reloc.Type == R_WASM_TABLE_INDEX_SLEB || - Reloc.Type == R_WASM_TABLE_INDEX_I32) { - auto *FuncSym = cast(Sym); - if (FuncSym->hasTableIndex() && FuncSym->getTableIndex() == 0) + if (reloc.Type == R_WASM_TABLE_INDEX_SLEB || + reloc.Type == R_WASM_TABLE_INDEX_I32) { + auto *funcSym = cast(sym); + if (funcSym->hasTableIndex() && funcSym->getTableIndex() == 0) continue; } - Enqueue(Sym); + enqueue(sym); } } // Report garbage-collected sections. - if (Config->PrintGcSections) { - for (const ObjFile *Obj : Symtab->ObjectFiles) { - for (InputChunk *C : Obj->Functions) - if (!C->Live) - message("removing unused section " + toString(C)); - for (InputChunk *C : Obj->Segments) - if (!C->Live) - message("removing unused section " + toString(C)); - for (InputGlobal *G : Obj->Globals) - if (!G->Live) - message("removing unused section " + toString(G)); - for (InputEvent *E : Obj->Events) - if (!E->Live) - message("removing unused section " + toString(E)); + if (config->printGcSections) { + for (const ObjFile *obj : symtab->objectFiles) { + for (InputChunk *c : obj->functions) + if (!c->live) + message("removing unused section " + toString(c)); + for (InputChunk *c : obj->segments) + if (!c->live) + message("removing unused section " + toString(c)); + for (InputGlobal *g : obj->globals) + if (!g->live) + message("removing unused section " + toString(g)); + for (InputEvent *e : obj->events) + if (!e->live) + message("removing unused section " + toString(e)); } - for (InputChunk *C : Symtab->SyntheticFunctions) - if (!C->Live) - message("removing unused section " + toString(C)); - for (InputGlobal *G : Symtab->SyntheticGlobals) - if (!G->Live) - message("removing unused section " + toString(G)); + for (InputChunk *c : symtab->syntheticFunctions) + if (!c->live) + message("removing unused section " + toString(c)); + for (InputGlobal *g : symtab->syntheticGlobals) + if (!g->live) + message("removing unused section " + toString(g)); } } Index: lld/trunk/wasm/OutputSections.h =================================================================== --- lld/trunk/wasm/OutputSections.h +++ lld/trunk/wasm/OutputSections.h @@ -20,7 +20,7 @@ namespace wasm { class OutputSection; } -std::string toString(const wasm::OutputSection &Section); +std::string toString(const wasm::OutputSection §ion); namespace wasm { @@ -28,67 +28,67 @@ class OutputSection { public: - OutputSection(uint32_t Type, std::string Name = "") - : Type(Type), Name(Name) {} + OutputSection(uint32_t type, std::string name = "") + : type(type), name(name) {} virtual ~OutputSection() = default; StringRef getSectionName() const; - void setOffset(size_t NewOffset) { - log("setOffset: " + toString(*this) + ": " + Twine(NewOffset)); - Offset = NewOffset; + void setOffset(size_t newOffset) { + log("setOffset: " + toString(*this) + ": " + Twine(newOffset)); + offset = newOffset; } - void createHeader(size_t BodySize); + void createHeader(size_t bodySize); virtual bool isNeeded() const { return true; } virtual size_t getSize() const = 0; - virtual void writeTo(uint8_t *Buf) = 0; + virtual void writeTo(uint8_t *buf) = 0; virtual void finalizeContents() = 0; virtual uint32_t getNumRelocations() const { return 0; } - virtual void writeRelocations(raw_ostream &OS) const {} + virtual void writeRelocations(raw_ostream &os) const {} - std::string Header; - uint32_t Type; - uint32_t SectionIndex = UINT32_MAX; - std::string Name; - OutputSectionSymbol *SectionSym = nullptr; + std::string header; + uint32_t type; + uint32_t sectionIndex = UINT32_MAX; + std::string name; + OutputSectionSymbol *sectionSym = nullptr; protected: - size_t Offset = 0; + size_t offset = 0; }; class CodeSection : public OutputSection { public: - explicit CodeSection(ArrayRef Functions) - : OutputSection(llvm::wasm::WASM_SEC_CODE), Functions(Functions) {} + explicit CodeSection(ArrayRef functions) + : OutputSection(llvm::wasm::WASM_SEC_CODE), functions(functions) {} - size_t getSize() const override { return Header.size() + BodySize; } - void writeTo(uint8_t *Buf) override; + size_t getSize() const override { return header.size() + bodySize; } + void writeTo(uint8_t *buf) override; uint32_t getNumRelocations() const override; - void writeRelocations(raw_ostream &OS) const override; - bool isNeeded() const override { return Functions.size() > 0; } + void writeRelocations(raw_ostream &os) const override; + bool isNeeded() const override { return functions.size() > 0; } void finalizeContents() override; protected: - ArrayRef Functions; - std::string CodeSectionHeader; - size_t BodySize = 0; + ArrayRef functions; + std::string codeSectionHeader; + size_t bodySize = 0; }; class DataSection : public OutputSection { public: - explicit DataSection(ArrayRef Segments) - : OutputSection(llvm::wasm::WASM_SEC_DATA), Segments(Segments) {} + explicit DataSection(ArrayRef segments) + : OutputSection(llvm::wasm::WASM_SEC_DATA), segments(segments) {} - size_t getSize() const override { return Header.size() + BodySize; } - void writeTo(uint8_t *Buf) override; + size_t getSize() const override { return header.size() + bodySize; } + void writeTo(uint8_t *buf) override; uint32_t getNumRelocations() const override; - void writeRelocations(raw_ostream &OS) const override; - bool isNeeded() const override { return Segments.size() > 0; } + void writeRelocations(raw_ostream &os) const override; + bool isNeeded() const override { return segments.size() > 0; } void finalizeContents() override; protected: - ArrayRef Segments; - std::string DataSectionHeader; - size_t BodySize = 0; + ArrayRef segments; + std::string dataSectionHeader; + size_t bodySize = 0; }; // Represents a custom section in the output file. Wasm custom sections are @@ -100,21 +100,21 @@ // separately and are instead synthesized by the linker. class CustomSection : public OutputSection { public: - CustomSection(std::string Name, ArrayRef InputSections) - : OutputSection(llvm::wasm::WASM_SEC_CUSTOM, Name), - InputSections(InputSections) {} + CustomSection(std::string name, ArrayRef inputSections) + : OutputSection(llvm::wasm::WASM_SEC_CUSTOM, name), + inputSections(inputSections) {} size_t getSize() const override { - return Header.size() + NameData.size() + PayloadSize; + return header.size() + nameData.size() + payloadSize; } - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; uint32_t getNumRelocations() const override; - void writeRelocations(raw_ostream &OS) const override; + void writeRelocations(raw_ostream &os) const override; void finalizeContents() override; protected: - size_t PayloadSize = 0; - ArrayRef InputSections; - std::string NameData; + size_t payloadSize = 0; + ArrayRef inputSections; + std::string nameData; }; } // namespace wasm Index: lld/trunk/wasm/OutputSections.cpp =================================================================== --- lld/trunk/wasm/OutputSections.cpp +++ lld/trunk/wasm/OutputSections.cpp @@ -23,8 +23,8 @@ using namespace lld; using namespace lld::wasm; -static StringRef sectionTypeToString(uint32_t SectionType) { - switch (SectionType) { +static StringRef sectionTypeToString(uint32_t sectionType) { + switch (sectionType) { case WASM_SEC_CUSTOM: return "CUSTOM"; case WASM_SEC_TYPE: @@ -59,192 +59,192 @@ } // Returns a string, e.g. "FUNCTION(.text)". -std::string lld::toString(const OutputSection &Sec) { - if (!Sec.Name.empty()) - return (Sec.getSectionName() + "(" + Sec.Name + ")").str(); - return Sec.getSectionName(); +std::string lld::toString(const OutputSection &sec) { + if (!sec.name.empty()) + return (sec.getSectionName() + "(" + sec.name + ")").str(); + return sec.getSectionName(); } StringRef OutputSection::getSectionName() const { - return sectionTypeToString(Type); + return sectionTypeToString(type); } -void OutputSection::createHeader(size_t BodySize) { - raw_string_ostream OS(Header); - debugWrite(OS.tell(), "section type [" + getSectionName() + "]"); - encodeULEB128(Type, OS); - writeUleb128(OS, BodySize, "section size"); - OS.flush(); - log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) + +void OutputSection::createHeader(size_t bodySize) { + raw_string_ostream os(header); + debugWrite(os.tell(), "section type [" + getSectionName() + "]"); + encodeULEB128(type, os); + writeUleb128(os, bodySize, "section size"); + os.flush(); + log("createHeader: " + toString(*this) + " body=" + Twine(bodySize) + " total=" + Twine(getSize())); } void CodeSection::finalizeContents() { - raw_string_ostream OS(CodeSectionHeader); - writeUleb128(OS, Functions.size(), "function count"); - OS.flush(); - BodySize = CodeSectionHeader.size(); - - for (InputFunction *Func : Functions) { - Func->OutputOffset = BodySize; - Func->calculateSize(); - BodySize += Func->getSize(); + raw_string_ostream os(codeSectionHeader); + writeUleb128(os, functions.size(), "function count"); + os.flush(); + bodySize = codeSectionHeader.size(); + + for (InputFunction *func : functions) { + func->outputOffset = bodySize; + func->calculateSize(); + bodySize += func->getSize(); } - createHeader(BodySize); + createHeader(bodySize); } -void CodeSection::writeTo(uint8_t *Buf) { +void CodeSection::writeTo(uint8_t *buf) { log("writing " + toString(*this)); log(" size=" + Twine(getSize())); - log(" headersize=" + Twine(Header.size())); - log(" codeheadersize=" + Twine(CodeSectionHeader.size())); - Buf += Offset; + log(" headersize=" + Twine(header.size())); + log(" codeheadersize=" + Twine(codeSectionHeader.size())); + buf += offset; // Write section header - memcpy(Buf, Header.data(), Header.size()); - Buf += Header.size(); + memcpy(buf, header.data(), header.size()); + buf += header.size(); // Write code section headers - memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size()); + memcpy(buf, codeSectionHeader.data(), codeSectionHeader.size()); // Write code section bodies - for (const InputChunk *Chunk : Functions) - Chunk->writeTo(Buf); + for (const InputChunk *chunk : functions) + chunk->writeTo(buf); } uint32_t CodeSection::getNumRelocations() const { - uint32_t Count = 0; - for (const InputChunk *Func : Functions) - Count += Func->getNumRelocations(); - return Count; + uint32_t count = 0; + for (const InputChunk *func : functions) + count += func->getNumRelocations(); + return count; } -void CodeSection::writeRelocations(raw_ostream &OS) const { - for (const InputChunk *C : Functions) - C->writeRelocations(OS); +void CodeSection::writeRelocations(raw_ostream &os) const { + for (const InputChunk *c : functions) + c->writeRelocations(os); } void DataSection::finalizeContents() { - raw_string_ostream OS(DataSectionHeader); + raw_string_ostream os(dataSectionHeader); - writeUleb128(OS, Segments.size(), "data segment count"); - OS.flush(); - BodySize = DataSectionHeader.size(); + writeUleb128(os, segments.size(), "data segment count"); + os.flush(); + bodySize = dataSectionHeader.size(); - assert((!Config->Pic || Segments.size() <= 1) && + assert((!config->isPic || segments.size() <= 1) && "Currenly only a single data segment is supported in PIC mode"); - for (OutputSegment *Segment : Segments) { - raw_string_ostream OS(Segment->Header); - writeUleb128(OS, Segment->InitFlags, "init flags"); - if (Segment->InitFlags & WASM_SEGMENT_HAS_MEMINDEX) - writeUleb128(OS, 0, "memory index"); - if ((Segment->InitFlags & WASM_SEGMENT_IS_PASSIVE) == 0) { - WasmInitExpr InitExpr; - if (Config->Pic) { - InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET; - InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex(); + for (OutputSegment *segment : segments) { + raw_string_ostream os(segment->header); + writeUleb128(os, segment->initFlags, "init flags"); + if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX) + writeUleb128(os, 0, "memory index"); + if ((segment->initFlags & WASM_SEGMENT_IS_PASSIVE) == 0) { + WasmInitExpr initExpr; + if (config->isPic) { + initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; + initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex(); } else { - InitExpr.Opcode = WASM_OPCODE_I32_CONST; - InitExpr.Value.Int32 = Segment->StartVA; + initExpr.Opcode = WASM_OPCODE_I32_CONST; + initExpr.Value.Int32 = segment->startVA; } - writeInitExpr(OS, InitExpr); + writeInitExpr(os, initExpr); } - writeUleb128(OS, Segment->Size, "segment size"); - OS.flush(); + writeUleb128(os, segment->size, "segment size"); + os.flush(); - Segment->SectionOffset = BodySize; - BodySize += Segment->Header.size() + Segment->Size; - log("Data segment: size=" + Twine(Segment->Size) + ", startVA=" + - Twine::utohexstr(Segment->StartVA) + ", name=" + Segment->Name); - - for (InputSegment *InputSeg : Segment->InputSegments) - InputSeg->OutputOffset = Segment->SectionOffset + Segment->Header.size() + - InputSeg->OutputSegmentOffset; + segment->sectionOffset = bodySize; + bodySize += segment->header.size() + segment->size; + log("Data segment: size=" + Twine(segment->size) + ", startVA=" + + Twine::utohexstr(segment->startVA) + ", name=" + segment->name); + + for (InputSegment *inputSeg : segment->inputSegments) + inputSeg->outputOffset = segment->sectionOffset + segment->header.size() + + inputSeg->outputSegmentOffset; } - createHeader(BodySize); + createHeader(bodySize); } -void DataSection::writeTo(uint8_t *Buf) { +void DataSection::writeTo(uint8_t *buf) { log("writing " + toString(*this) + " size=" + Twine(getSize()) + - " body=" + Twine(BodySize)); - Buf += Offset; + " body=" + Twine(bodySize)); + buf += offset; // Write section header - memcpy(Buf, Header.data(), Header.size()); - Buf += Header.size(); + memcpy(buf, header.data(), header.size()); + buf += header.size(); // Write data section headers - memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size()); + memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size()); - for (const OutputSegment *Segment : Segments) { + for (const OutputSegment *segment : segments) { // Write data segment header - uint8_t *SegStart = Buf + Segment->SectionOffset; - memcpy(SegStart, Segment->Header.data(), Segment->Header.size()); + uint8_t *segStart = buf + segment->sectionOffset; + memcpy(segStart, segment->header.data(), segment->header.size()); // Write segment data payload - for (const InputChunk *Chunk : Segment->InputSegments) - Chunk->writeTo(Buf); + for (const InputChunk *chunk : segment->inputSegments) + chunk->writeTo(buf); } } uint32_t DataSection::getNumRelocations() const { - uint32_t Count = 0; - for (const OutputSegment *Seg : Segments) - for (const InputChunk *InputSeg : Seg->InputSegments) - Count += InputSeg->getNumRelocations(); - return Count; + uint32_t count = 0; + for (const OutputSegment *seg : segments) + for (const InputChunk *inputSeg : seg->inputSegments) + count += inputSeg->getNumRelocations(); + return count; } -void DataSection::writeRelocations(raw_ostream &OS) const { - for (const OutputSegment *Seg : Segments) - for (const InputChunk *C : Seg->InputSegments) - C->writeRelocations(OS); +void DataSection::writeRelocations(raw_ostream &os) const { + for (const OutputSegment *seg : segments) + for (const InputChunk *c : seg->inputSegments) + c->writeRelocations(os); } void CustomSection::finalizeContents() { - raw_string_ostream OS(NameData); - encodeULEB128(Name.size(), OS); - OS << Name; - OS.flush(); - - for (InputSection *Section : InputSections) { - Section->OutputOffset = PayloadSize; - Section->OutputSec = this; - PayloadSize += Section->getSize(); + raw_string_ostream os(nameData); + encodeULEB128(name.size(), os); + os << name; + os.flush(); + + for (InputSection *section : inputSections) { + section->outputOffset = payloadSize; + section->outputSec = this; + payloadSize += section->getSize(); } - createHeader(PayloadSize + NameData.size()); + createHeader(payloadSize + nameData.size()); } -void CustomSection::writeTo(uint8_t *Buf) { +void CustomSection::writeTo(uint8_t *buf) { log("writing " + toString(*this) + " size=" + Twine(getSize()) + - " chunks=" + Twine(InputSections.size())); + " chunks=" + Twine(inputSections.size())); - assert(Offset); - Buf += Offset; + assert(offset); + buf += offset; // Write section header - memcpy(Buf, Header.data(), Header.size()); - Buf += Header.size(); - memcpy(Buf, NameData.data(), NameData.size()); - Buf += NameData.size(); + memcpy(buf, header.data(), header.size()); + buf += header.size(); + memcpy(buf, nameData.data(), nameData.size()); + buf += nameData.size(); // Write custom sections payload - for (const InputSection *Section : InputSections) - Section->writeTo(Buf); + for (const InputSection *section : inputSections) + section->writeTo(buf); } uint32_t CustomSection::getNumRelocations() const { - uint32_t Count = 0; - for (const InputSection *InputSect : InputSections) - Count += InputSect->getNumRelocations(); - return Count; + uint32_t count = 0; + for (const InputSection *inputSect : inputSections) + count += inputSect->getNumRelocations(); + return count; } -void CustomSection::writeRelocations(raw_ostream &OS) const { - for (const InputSection *S : InputSections) - S->writeRelocations(OS); +void CustomSection::writeRelocations(raw_ostream &os) const { + for (const InputSection *s : inputSections) + s->writeRelocations(os); } Index: lld/trunk/wasm/OutputSegment.h =================================================================== --- lld/trunk/wasm/OutputSegment.h +++ lld/trunk/wasm/OutputSegment.h @@ -20,30 +20,30 @@ class OutputSegment { public: - OutputSegment(StringRef N, uint32_t Index) : Name(N), Index(Index) {} + OutputSegment(StringRef n, uint32_t index) : name(n), index(index) {} - void addInputSegment(InputSegment *InSeg) { - Alignment = std::max(Alignment, InSeg->getAlignment()); - InputSegments.push_back(InSeg); - Size = llvm::alignTo(Size, 1ULL << InSeg->getAlignment()); - InSeg->OutputSeg = this; - InSeg->OutputSegmentOffset = Size; - Size += InSeg->getSize(); + void addInputSegment(InputSegment *inSeg) { + alignment = std::max(alignment, inSeg->getAlignment()); + inputSegments.push_back(inSeg); + size = llvm::alignTo(size, 1ULL << inSeg->getAlignment()); + inSeg->outputSeg = this; + inSeg->outputSegmentOffset = size; + size += inSeg->getSize(); } - StringRef Name; - const uint32_t Index; - uint32_t InitFlags = 0; - uint32_t SectionOffset = 0; - uint32_t Alignment = 0; - uint32_t StartVA = 0; - std::vector InputSegments; + StringRef name; + const uint32_t index; + uint32_t initFlags = 0; + uint32_t sectionOffset = 0; + uint32_t alignment = 0; + uint32_t startVA = 0; + std::vector inputSegments; // Sum of the size of the all the input segments - uint32_t Size = 0; + uint32_t size = 0; // Segment header - std::string Header; + std::string header; }; } // namespace wasm Index: lld/trunk/wasm/Relocations.h =================================================================== --- lld/trunk/wasm/Relocations.h +++ lld/trunk/wasm/Relocations.h @@ -14,7 +14,7 @@ class InputChunk; -void scanRelocations(InputChunk *Chunk); +void scanRelocations(InputChunk *chunk); } // namespace wasm } // namespace lld Index: lld/trunk/wasm/Relocations.cpp =================================================================== --- lld/trunk/wasm/Relocations.cpp +++ lld/trunk/wasm/Relocations.cpp @@ -17,69 +17,69 @@ using namespace lld; using namespace lld::wasm; -static bool requiresGOTAccess(const Symbol *Sym) { - return Config->Pic && !Sym->isHidden() && !Sym->isLocal(); +static bool requiresGOTAccess(const Symbol *sym) { + return config->isPic && !sym->isHidden() && !sym->isLocal(); } -static bool allowUndefined(const Symbol* Sym) { +static bool allowUndefined(const Symbol* sym) { // Historically --allow-undefined doesn't work for data symbols since we don't // have any way to represent these as imports in the final binary. The idea // behind allowing undefined symbols is to allow importing these symbols from // the embedder and we can't do this for data symbols (at least not without // compiling with -fPIC) - if (isa(Sym)) + if (isa(sym)) return false; - return (Config->AllowUndefined || - Config->AllowUndefinedSymbols.count(Sym->getName()) != 0); + return (config->allowUndefined || + config->allowUndefinedSymbols.count(sym->getName()) != 0); } -static void reportUndefined(const Symbol* Sym) { - assert(Sym->isUndefined()); - assert(!Sym->isWeak()); - if (!allowUndefined(Sym)) - error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); +static void reportUndefined(const Symbol* sym) { + assert(sym->isUndefined()); + assert(!sym->isWeak()); + if (!allowUndefined(sym)) + error(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym)); } -void lld::wasm::scanRelocations(InputChunk *Chunk) { - if (!Chunk->Live) +void lld::wasm::scanRelocations(InputChunk *chunk) { + if (!chunk->live) return; - ObjFile *File = Chunk->File; - ArrayRef Types = File->getWasmObj()->types(); - for (const WasmRelocation &Reloc : Chunk->getRelocations()) { - if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) { + ObjFile *file = chunk->file; + ArrayRef types = file->getWasmObj()->types(); + for (const WasmRelocation &reloc : chunk->getRelocations()) { + if (reloc.Type == R_WASM_TYPE_INDEX_LEB) { // Mark target type as live - File->TypeMap[Reloc.Index] = - Out.TypeSec->registerType(Types[Reloc.Index]); - File->TypeIsUsed[Reloc.Index] = true; + file->typeMap[reloc.Index] = + out.typeSec->registerType(types[reloc.Index]); + file->typeIsUsed[reloc.Index] = true; continue; } // Other relocation types all have a corresponding symbol - Symbol *Sym = File->getSymbols()[Reloc.Index]; + Symbol *sym = file->getSymbols()[reloc.Index]; - switch (Reloc.Type) { + switch (reloc.Type) { case R_WASM_TABLE_INDEX_I32: case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_REL_SLEB: - if (requiresGOTAccess(Sym)) + if (requiresGOTAccess(sym)) break; - Out.ElemSec->addEntry(cast(Sym)); + out.elemSec->addEntry(cast(sym)); break; case R_WASM_GLOBAL_INDEX_LEB: - if (!isa(Sym)) - Out.ImportSec->addGOTEntry(Sym); + if (!isa(sym)) + out.importSec->addGOTEntry(sym); break; } - if (Config->Pic) { - switch (Reloc.Type) { + if (config->isPic) { + switch (reloc.Type) { case R_WASM_TABLE_INDEX_SLEB: case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_LEB: // Certain relocation types can't be used when building PIC output, // since they would require absolute symbol addresses at link time. - error(toString(File) + ": relocation " + relocTypeToString(Reloc.Type) + - " cannot be used against symbol " + toString(*Sym) + + error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) + + " cannot be used against symbol " + toString(*sym) + "; recompile with -fPIC"); break; case R_WASM_TABLE_INDEX_I32: @@ -87,14 +87,14 @@ // These relocation types are only present in the data section and // will be converted into code by `generateRelocationCode`. This code // requires the symbols to have GOT entires. - if (requiresGOTAccess(Sym)) - Out.ImportSec->addGOTEntry(Sym); + if (requiresGOTAccess(sym)) + out.importSec->addGOTEntry(sym); break; } } else { // Report undefined symbols - if (Sym->isUndefined() && !Config->Relocatable && !Sym->isWeak()) - reportUndefined(Sym); + if (sym->isUndefined() && !config->relocatable && !sym->isWeak()) + reportUndefined(sym); } } Index: lld/trunk/wasm/SymbolTable.h =================================================================== --- lld/trunk/wasm/SymbolTable.h +++ lld/trunk/wasm/SymbolTable.h @@ -35,89 +35,89 @@ // There is one add* function per symbol type. class SymbolTable { public: - void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap); + void wrap(Symbol *sym, Symbol *real, Symbol *wrap); - void addFile(InputFile *File); + void addFile(InputFile *file); void addCombinedLTOObject(); - ArrayRef getSymbols() const { return SymVector; } + ArrayRef getSymbols() const { return symVector; } - Symbol *find(StringRef Name); + Symbol *find(StringRef name); - void replace(StringRef Name, Symbol* Sym); + void replace(StringRef name, Symbol* sym); - void trace(StringRef Name); + void trace(StringRef name); - Symbol *addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, - InputFunction *Function); - Symbol *addDefinedData(StringRef Name, uint32_t Flags, InputFile *File, - InputSegment *Segment, uint32_t Address, - uint32_t Size); - Symbol *addDefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, - InputGlobal *G); - Symbol *addDefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, - InputEvent *E); - - Symbol *addUndefinedFunction(StringRef Name, StringRef ImportName, - StringRef ImportModule, uint32_t Flags, - InputFile *File, const WasmSignature *Signature, - bool IsCalledDirectly); - Symbol *addUndefinedData(StringRef Name, uint32_t Flags, InputFile *File); - Symbol *addUndefinedGlobal(StringRef Name, StringRef ImportName, - StringRef ImportModule, uint32_t Flags, - InputFile *File, const WasmGlobalType *Type); - - void addLazy(ArchiveFile *F, const llvm::object::Archive::Symbol *Sym); - - bool addComdat(StringRef Name); - - DefinedData *addSyntheticDataSymbol(StringRef Name, uint32_t Flags); - DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags, - InputGlobal *Global); - DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags, - InputFunction *Function); - DefinedData *addOptionalDataSymbol(StringRef Name, uint32_t Value = 0, - uint32_t Flags = 0); + Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file, + InputFunction *function); + Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file, + InputSegment *segment, uint32_t address, + uint32_t size); + Symbol *addDefinedGlobal(StringRef name, uint32_t flags, InputFile *file, + InputGlobal *g); + Symbol *addDefinedEvent(StringRef name, uint32_t flags, InputFile *file, + InputEvent *e); + + Symbol *addUndefinedFunction(StringRef name, StringRef importName, + StringRef importModule, uint32_t flags, + InputFile *file, const WasmSignature *signature, + bool isCalledDirectly); + Symbol *addUndefinedData(StringRef name, uint32_t flags, InputFile *file); + Symbol *addUndefinedGlobal(StringRef name, StringRef importName, + StringRef importModule, uint32_t flags, + InputFile *file, const WasmGlobalType *type); + + void addLazy(ArchiveFile *f, const llvm::object::Archive::Symbol *sym); + + bool addComdat(StringRef name); + + DefinedData *addSyntheticDataSymbol(StringRef name, uint32_t flags); + DefinedGlobal *addSyntheticGlobal(StringRef name, uint32_t flags, + InputGlobal *global); + DefinedFunction *addSyntheticFunction(StringRef name, uint32_t flags, + InputFunction *function); + DefinedData *addOptionalDataSymbol(StringRef name, uint32_t value = 0, + uint32_t flags = 0); void handleSymbolVariants(); void handleWeakUndefines(); - std::vector ObjectFiles; - std::vector SharedFiles; - std::vector BitcodeFiles; - std::vector SyntheticFunctions; - std::vector SyntheticGlobals; + std::vector objectFiles; + std::vector sharedFiles; + std::vector bitcodeFiles; + std::vector syntheticFunctions; + std::vector syntheticGlobals; private: - std::pair insert(StringRef Name, const InputFile *File); - std::pair insertName(StringRef Name); + std::pair insert(StringRef name, const InputFile *file); + std::pair insertName(StringRef name); - bool getFunctionVariant(Symbol* Sym, const WasmSignature *Sig, - const InputFile *File, Symbol **Out); - InputFunction *replaceWithUnreachable(Symbol *Sym, const WasmSignature &Sig, - StringRef DebugName); + bool getFunctionVariant(Symbol* sym, const WasmSignature *sig, + const InputFile *file, Symbol **out); + InputFunction *replaceWithUnreachable(Symbol *sym, const WasmSignature &sig, + StringRef debugName); // Maps symbol names to index into the SymVector. -1 means that symbols // is to not yet in the vector but it should have tracing enabled if it is // ever added. - llvm::DenseMap SymMap; - std::vector SymVector; + llvm::DenseMap symMap; + std::vector symVector; // For certain symbols types, e.g. function symbols, we allow for muliple // variants of the same symbol with different signatures. - llvm::DenseMap> SymVariants; + llvm::DenseMap> symVariants; // Comdat groups define "link once" sections. If two comdat groups have the // same name, only one of them is linked, and the other is ignored. This set // is used to uniquify them. - llvm::DenseSet ComdatGroups; + llvm::DenseSet comdatGroups; // For LTO. - std::unique_ptr LTO; + std::unique_ptr lto; }; -extern SymbolTable *Symtab; +extern SymbolTable *symtab; } // namespace wasm } // namespace lld Index: lld/trunk/wasm/SymbolTable.cpp =================================================================== --- lld/trunk/wasm/SymbolTable.cpp +++ lld/trunk/wasm/SymbolTable.cpp @@ -24,37 +24,37 @@ using namespace lld; using namespace lld::wasm; -SymbolTable *lld::wasm::Symtab; +SymbolTable *lld::wasm::symtab; -void SymbolTable::addFile(InputFile *File) { - log("Processing: " + toString(File)); +void SymbolTable::addFile(InputFile *file) { + log("Processing: " + toString(file)); // .a file - if (auto *F = dyn_cast(File)) { - F->parse(); + if (auto *f = dyn_cast(file)) { + f->parse(); return; } // .so file - if (auto *F = dyn_cast(File)) { - SharedFiles.push_back(F); + if (auto *f = dyn_cast(file)) { + sharedFiles.push_back(f); return; } - if (Config->Trace) - message(toString(File)); + if (config->trace) + message(toString(file)); // LLVM bitcode file - if (auto *F = dyn_cast(File)) { - F->parse(); - BitcodeFiles.push_back(F); + if (auto *f = dyn_cast(file)) { + f->parse(); + bitcodeFiles.push_back(f); return; } // Regular object file - auto *F = cast(File); - F->parse(false); - ObjectFiles.push_back(F); + auto *f = cast(file); + f->parse(false); + objectFiles.push_back(f); } // This function is where all the optimizations of link-time @@ -65,512 +65,512 @@ // Because all bitcode files that the program consists of are passed // to the compiler at once, it can do whole-program optimization. void SymbolTable::addCombinedLTOObject() { - if (BitcodeFiles.empty()) + if (bitcodeFiles.empty()) return; // Compile bitcode files and replace bitcode symbols. - LTO.reset(new BitcodeCompiler); - for (BitcodeFile *F : BitcodeFiles) - LTO->add(*F); + lto.reset(new BitcodeCompiler); + for (BitcodeFile *f : bitcodeFiles) + lto->add(*f); - for (StringRef Filename : LTO->compile()) { - auto *Obj = make(MemoryBufferRef(Filename, "lto.tmp"), ""); - Obj->parse(true); - ObjectFiles.push_back(Obj); + for (StringRef filename : lto->compile()) { + auto *obj = make(MemoryBufferRef(filename, "lto.tmp"), ""); + obj->parse(true); + objectFiles.push_back(obj); } } -Symbol *SymbolTable::find(StringRef Name) { - auto It = SymMap.find(CachedHashStringRef(Name)); - if (It == SymMap.end() || It->second == -1) +Symbol *SymbolTable::find(StringRef name) { + auto it = symMap.find(CachedHashStringRef(name)); + if (it == symMap.end() || it->second == -1) return nullptr; - return SymVector[It->second]; + return symVector[it->second]; } -void SymbolTable::replace(StringRef Name, Symbol* Sym) { - auto It = SymMap.find(CachedHashStringRef(Name)); - SymVector[It->second] = Sym; +void SymbolTable::replace(StringRef name, Symbol* sym) { + auto it = symMap.find(CachedHashStringRef(name)); + symVector[it->second] = sym; } -std::pair SymbolTable::insertName(StringRef Name) { - bool Trace = false; - auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); - int &SymIndex = P.first->second; - bool IsNew = P.second; - if (SymIndex == -1) { - SymIndex = SymVector.size(); - Trace = true; - IsNew = true; +std::pair SymbolTable::insertName(StringRef name) { + bool trace = false; + auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); + int &symIndex = p.first->second; + bool isNew = p.second; + if (symIndex == -1) { + symIndex = symVector.size(); + trace = true; + isNew = true; } - if (!IsNew) - return {SymVector[SymIndex], false}; + if (!isNew) + return {symVector[symIndex], false}; - Symbol *Sym = reinterpret_cast(make()); - Sym->IsUsedInRegularObj = false; - Sym->CanInline = true; - Sym->Traced = Trace; - SymVector.emplace_back(Sym); - return {Sym, true}; + Symbol *sym = reinterpret_cast(make()); + sym->isUsedInRegularObj = false; + sym->canInline = true; + sym->traced = trace; + symVector.emplace_back(sym); + return {sym, true}; } -std::pair SymbolTable::insert(StringRef Name, - const InputFile *File) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insertName(Name); +std::pair SymbolTable::insert(StringRef name, + const InputFile *file) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insertName(name); - if (!File || File->kind() == InputFile::ObjectKind) - S->IsUsedInRegularObj = true; + if (!file || file->kind() == InputFile::ObjectKind) + s->isUsedInRegularObj = true; - return {S, WasInserted}; + return {s, wasInserted}; } -static void reportTypeError(const Symbol *Existing, const InputFile *File, - llvm::wasm::WasmSymbolType Type) { - error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + - toString(Existing->getWasmType()) + " in " + - toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + - " in " + toString(File)); +static void reportTypeError(const Symbol *existing, const InputFile *file, + llvm::wasm::WasmSymbolType type) { + error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " + + toString(existing->getWasmType()) + " in " + + toString(existing->getFile()) + "\n>>> defined as " + toString(type) + + " in " + toString(file)); } // Check the type of new symbol matches that of the symbol is replacing. // Returns true if the function types match, false is there is a singature // mismatch. -static bool signatureMatches(FunctionSymbol *Existing, - const WasmSignature *NewSig) { - const WasmSignature *OldSig = Existing->Signature; +static bool signatureMatches(FunctionSymbol *existing, + const WasmSignature *newSig) { + const WasmSignature *oldSig = existing->signature; // If either function is missing a signature (this happend for bitcode // symbols) then assume they match. Any mismatch will be reported later // when the LTO objects are added. - if (!NewSig || !OldSig) + if (!newSig || !oldSig) return true; - return *NewSig == *OldSig; + return *newSig == *oldSig; } -static void checkGlobalType(const Symbol *Existing, const InputFile *File, - const WasmGlobalType *NewType) { - if (!isa(Existing)) { - reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); +static void checkGlobalType(const Symbol *existing, const InputFile *file, + const WasmGlobalType *newType) { + if (!isa(existing)) { + reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL); return; } - const WasmGlobalType *OldType = cast(Existing)->getGlobalType(); - if (*NewType != *OldType) { - error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + - toString(*OldType) + " in " + toString(Existing->getFile()) + - "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); + const WasmGlobalType *oldType = cast(existing)->getGlobalType(); + if (*newType != *oldType) { + error("Global type mismatch: " + existing->getName() + "\n>>> defined as " + + toString(*oldType) + " in " + toString(existing->getFile()) + + "\n>>> defined as " + toString(*newType) + " in " + toString(file)); } } -static void checkEventType(const Symbol *Existing, const InputFile *File, - const WasmEventType *NewType, - const WasmSignature *NewSig) { - auto ExistingEvent = dyn_cast(Existing); - if (!isa(Existing)) { - reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); +static void checkEventType(const Symbol *existing, const InputFile *file, + const WasmEventType *newType, + const WasmSignature *newSig) { + auto existingEvent = dyn_cast(existing); + if (!isa(existing)) { + reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT); return; } - const WasmEventType *OldType = cast(Existing)->getEventType(); - const WasmSignature *OldSig = ExistingEvent->Signature; - if (NewType->Attribute != OldType->Attribute) - error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + - toString(*OldType) + " in " + toString(Existing->getFile()) + - "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); - if (*NewSig != *OldSig) - warn("Event signature mismatch: " + Existing->getName() + - "\n>>> defined as " + toString(*OldSig) + " in " + - toString(Existing->getFile()) + "\n>>> defined as " + - toString(*NewSig) + " in " + toString(File)); -} - -static void checkDataType(const Symbol *Existing, const InputFile *File) { - if (!isa(Existing)) - reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); -} - -DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, - uint32_t Flags, - InputFunction *Function) { - LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); - assert(!find(Name)); - SyntheticFunctions.emplace_back(Function); - return replaceSymbol(insertName(Name).first, Name, - Flags, nullptr, Function); + const WasmEventType *oldType = cast(existing)->getEventType(); + const WasmSignature *oldSig = existingEvent->signature; + if (newType->Attribute != oldType->Attribute) + error("Event type mismatch: " + existing->getName() + "\n>>> defined as " + + toString(*oldType) + " in " + toString(existing->getFile()) + + "\n>>> defined as " + toString(*newType) + " in " + toString(file)); + if (*newSig != *oldSig) + warn("Event signature mismatch: " + existing->getName() + + "\n>>> defined as " + toString(*oldSig) + " in " + + toString(existing->getFile()) + "\n>>> defined as " + + toString(*newSig) + " in " + toString(file)); +} + +static void checkDataType(const Symbol *existing, const InputFile *file) { + if (!isa(existing)) + reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA); +} + +DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name, + uint32_t flags, + InputFunction *function) { + LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n"); + assert(!find(name)); + syntheticFunctions.emplace_back(function); + return replaceSymbol(insertName(name).first, name, + flags, nullptr, function); } // Adds an optional, linker generated, data symbols. The symbol will only be // added if there is an undefine reference to it, or if it is explictly exported // via the --export flag. Otherwise we don't add the symbol and return nullptr. -DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value, - uint32_t Flags) { - Symbol *S = find(Name); - if (!S && (Config->ExportAll || Config->ExportedSymbols.count(Name) != 0)) - S = insertName(Name).first; - else if (!S || S->isDefined()) +DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, uint32_t value, + uint32_t flags) { + Symbol *s = find(name); + if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0)) + s = insertName(name).first; + else if (!s || s->isDefined()) return nullptr; - LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n"); - auto *rtn = replaceSymbol(S, Name, Flags); - rtn->setVirtualAddress(Value); - rtn->Referenced = true; + LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n"); + auto *rtn = replaceSymbol(s, name, flags); + rtn->setVirtualAddress(value); + rtn->referenced = true; return rtn; } -DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, - uint32_t Flags) { - LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); - assert(!find(Name)); - return replaceSymbol(insertName(Name).first, Name, Flags); +DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name, + uint32_t flags) { + LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n"); + assert(!find(name)); + return replaceSymbol(insertName(name).first, name, flags); } -DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, - InputGlobal *Global) { - LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global +DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags, + InputGlobal *global) { + LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global << "\n"); - assert(!find(Name)); - SyntheticGlobals.emplace_back(Global); - return replaceSymbol(insertName(Name).first, Name, Flags, - nullptr, Global); + assert(!find(name)); + syntheticGlobals.emplace_back(global); + return replaceSymbol(insertName(name).first, name, flags, + nullptr, global); } -static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, - uint32_t NewFlags) { +static bool shouldReplace(const Symbol *existing, InputFile *newFile, + uint32_t newFlags) { // If existing symbol is undefined, replace it. - if (!Existing->isDefined()) { + if (!existing->isDefined()) { LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " - << Existing->getName() << "\n"); + << existing->getName() << "\n"); return true; } // Now we have two defined symbols. If the new one is weak, we can ignore it. - if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { + if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); return false; } // If the existing symbol is weak, we should replace it. - if (Existing->isWeak()) { + if (existing->isWeak()) { LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); return true; } // Neither symbol is week. They conflict. - error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + - toString(Existing->getFile()) + "\n>>> defined in " + - toString(NewFile)); + error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " + + toString(existing->getFile()) + "\n>>> defined in " + + toString(newFile)); return true; } -Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, - InputFile *File, - InputFunction *Function) { - LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" - << (Function ? toString(Function->Signature) : "none") +Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags, + InputFile *file, + InputFunction *function) { + LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " [" + << (function ? toString(function->signature) : "none") << "]\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&](Symbol *Sym) { + auto replaceSym = [&](Symbol *sym) { // If the new defined function doesn't have signture (i.e. bitcode // functions) but the old symbol does, then preserve the old signature - const WasmSignature *OldSig = S->getSignature(); - auto* NewSym = replaceSymbol(Sym, Name, Flags, File, Function); - if (!NewSym->Signature) - NewSym->Signature = OldSig; + const WasmSignature *oldSig = s->getSignature(); + auto* newSym = replaceSymbol(sym, name, flags, file, function); + if (!newSym->signature) + newSym->signature = oldSig; }; - if (WasInserted || S->isLazy()) { - ReplaceSym(S); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(s); + return s; } - auto ExistingFunction = dyn_cast(S); - if (!ExistingFunction) { - reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); - return S; + auto existingFunction = dyn_cast(s); + if (!existingFunction) { + reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); + return s; } - bool CheckSig = true; - if (auto UD = dyn_cast(ExistingFunction)) - CheckSig = UD->IsCalledDirectly; + bool checkSig = true; + if (auto ud = dyn_cast(existingFunction)) + checkSig = ud->isCalledDirectly; - if (CheckSig && Function && !signatureMatches(ExistingFunction, &Function->Signature)) { - Symbol* Variant; - if (getFunctionVariant(S, &Function->Signature, File, &Variant)) + if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) { + Symbol* variant; + if (getFunctionVariant(s, &function->signature, file, &variant)) // New variant, always replace - ReplaceSym(Variant); - else if (shouldReplace(S, File, Flags)) + replaceSym(variant); + else if (shouldReplace(s, file, flags)) // Variant already exists, replace it after checking shouldReplace - ReplaceSym(Variant); + replaceSym(variant); // This variant we found take the place in the symbol table as the primary // variant. - replace(Name, Variant); - return Variant; + replace(name, variant); + return variant; } // Existing function with matching signature. - if (shouldReplace(S, File, Flags)) - ReplaceSym(S); + if (shouldReplace(s, file, flags)) + replaceSym(s); - return S; + return s; } -Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, - InputFile *File, InputSegment *Segment, - uint32_t Address, uint32_t Size) { - LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address +Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags, + InputFile *file, InputSegment *segment, + uint32_t address, uint32_t size) { + LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&]() { - replaceSymbol(S, Name, Flags, File, Segment, Address, Size); + auto replaceSym = [&]() { + replaceSymbol(s, name, flags, file, segment, address, size); }; - if (WasInserted || S->isLazy()) { - ReplaceSym(); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(); + return s; } - checkDataType(S, File); + checkDataType(s, file); - if (shouldReplace(S, File, Flags)) - ReplaceSym(); - return S; + if (shouldReplace(s, file, flags)) + replaceSym(); + return s; } -Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, - InputFile *File, InputGlobal *Global) { - LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); +Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags, + InputFile *file, InputGlobal *global) { + LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&]() { - replaceSymbol(S, Name, Flags, File, Global); + auto replaceSym = [&]() { + replaceSymbol(s, name, flags, file, global); }; - if (WasInserted || S->isLazy()) { - ReplaceSym(); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(); + return s; } - checkGlobalType(S, File, &Global->getType()); + checkGlobalType(s, file, &global->getType()); - if (shouldReplace(S, File, Flags)) - ReplaceSym(); - return S; + if (shouldReplace(s, file, flags)) + replaceSym(); + return s; } -Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, - InputFile *File, InputEvent *Event) { - LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); +Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags, + InputFile *file, InputEvent *event) { + LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&]() { - replaceSymbol(S, Name, Flags, File, Event); + auto replaceSym = [&]() { + replaceSymbol(s, name, flags, file, event); }; - if (WasInserted || S->isLazy()) { - ReplaceSym(); - return S; - } - - checkEventType(S, File, &Event->getType(), &Event->Signature); - - if (shouldReplace(S, File, Flags)) - ReplaceSym(); - return S; -} - -Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, - StringRef ImportModule, - uint32_t Flags, InputFile *File, - const WasmSignature *Sig, - bool IsCalledDirectly) { - LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " [" - << (Sig ? toString(*Sig) : "none") - << "] IsCalledDirectly:" << IsCalledDirectly << "\n"); - - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); - if (S->Traced) - printTraceSymbolUndefined(Name, File); - - auto ReplaceSym = [&]() { - replaceSymbol(S, Name, ImportName, ImportModule, Flags, - File, Sig, IsCalledDirectly); + if (wasInserted || s->isLazy()) { + replaceSym(); + return s; + } + + checkEventType(s, file, &event->getType(), &event->signature); + + if (shouldReplace(s, file, flags)) + replaceSym(); + return s; +} + +Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName, + StringRef importModule, + uint32_t flags, InputFile *file, + const WasmSignature *sig, + bool isCalledDirectly) { + LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " [" + << (sig ? toString(*sig) : "none") + << "] IsCalledDirectly:" << isCalledDirectly << "\n"); + + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); + if (s->traced) + printTraceSymbolUndefined(name, file); + + auto replaceSym = [&]() { + replaceSymbol(s, name, importName, importModule, flags, + file, sig, isCalledDirectly); }; - if (WasInserted) - ReplaceSym(); - else if (auto *Lazy = dyn_cast(S)) - Lazy->fetch(); + if (wasInserted) + replaceSym(); + else if (auto *lazy = dyn_cast(s)) + lazy->fetch(); else { - auto ExistingFunction = dyn_cast(S); - if (!ExistingFunction) { - reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); - return S; + auto existingFunction = dyn_cast(s); + if (!existingFunction) { + reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); + return s; } - if (!ExistingFunction->Signature && Sig) - ExistingFunction->Signature = Sig; - if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig)) - if (getFunctionVariant(S, Sig, File, &S)) - ReplaceSym(); - } - - return S; -} - -Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, - InputFile *File) { - LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); - - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); - if (S->Traced) - printTraceSymbolUndefined(Name, File); - - if (WasInserted) - replaceSymbol(S, Name, Flags, File); - else if (auto *Lazy = dyn_cast(S)) - Lazy->fetch(); - else if (S->isDefined()) - checkDataType(S, File); - return S; -} - -Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, - StringRef ImportModule, uint32_t Flags, - InputFile *File, - const WasmGlobalType *Type) { - LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); - - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); - if (S->Traced) - printTraceSymbolUndefined(Name, File); - - if (WasInserted) - replaceSymbol(S, Name, ImportName, ImportModule, Flags, - File, Type); - else if (auto *Lazy = dyn_cast(S)) - Lazy->fetch(); - else if (S->isDefined()) - checkGlobalType(S, File, Type); - return S; -} - -void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { - LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); - StringRef Name = Sym->getName(); - - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insertName(Name); + if (!existingFunction->signature && sig) + existingFunction->signature = sig; + if (isCalledDirectly && !signatureMatches(existingFunction, sig)) + if (getFunctionVariant(s, sig, file, &s)) + replaceSym(); + } + + return s; +} + +Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags, + InputFile *file) { + LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n"); + + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); + if (s->traced) + printTraceSymbolUndefined(name, file); + + if (wasInserted) + replaceSymbol(s, name, flags, file); + else if (auto *lazy = dyn_cast(s)) + lazy->fetch(); + else if (s->isDefined()) + checkDataType(s, file); + return s; +} + +Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName, + StringRef importModule, uint32_t flags, + InputFile *file, + const WasmGlobalType *type) { + LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n"); + + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); + if (s->traced) + printTraceSymbolUndefined(name, file); + + if (wasInserted) + replaceSymbol(s, name, importName, importModule, flags, + file, type); + else if (auto *lazy = dyn_cast(s)) + lazy->fetch(); + else if (s->isDefined()) + checkGlobalType(s, file, type); + return s; +} + +void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) { + LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n"); + StringRef name = sym->getName(); + + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insertName(name); - if (WasInserted) { - replaceSymbol(S, Name, 0, File, *Sym); + if (wasInserted) { + replaceSymbol(s, name, 0, file, *sym); return; } - if (!S->isUndefined()) + if (!s->isUndefined()) return; // The existing symbol is undefined, load a new one from the archive, // unless the the existing symbol is weak in which case replace the undefined // symbols with a LazySymbol. - if (S->isWeak()) { - const WasmSignature *OldSig = nullptr; + if (s->isWeak()) { + const WasmSignature *oldSig = nullptr; // In the case of an UndefinedFunction we need to preserve the expected // signature. - if (auto *F = dyn_cast(S)) - OldSig = F->Signature; + if (auto *f = dyn_cast(s)) + oldSig = f->signature; LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); - auto NewSym = replaceSymbol(S, Name, WASM_SYMBOL_BINDING_WEAK, - File, *Sym); - NewSym->Signature = OldSig; + auto newSym = replaceSymbol(s, name, WASM_SYMBOL_BINDING_WEAK, + file, *sym); + newSym->signature = oldSig; return; } LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); - File->addMember(Sym); + file->addMember(sym); } -bool SymbolTable::addComdat(StringRef Name) { - return ComdatGroups.insert(CachedHashStringRef(Name)).second; +bool SymbolTable::addComdat(StringRef name) { + return comdatGroups.insert(CachedHashStringRef(name)).second; } // The new signature doesn't match. Create a variant to the symbol with the // signature encoded in the name and return that instead. These symbols are // then unified later in handleSymbolVariants. -bool SymbolTable::getFunctionVariant(Symbol* Sym, const WasmSignature *Sig, - const InputFile *File, Symbol **Out) { - LLVM_DEBUG(dbgs() << "getFunctionVariant: " << Sym->getName() << " -> " - << " " << toString(*Sig) << "\n"); - Symbol *Variant = nullptr; +bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig, + const InputFile *file, Symbol **out) { + LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> " + << " " << toString(*sig) << "\n"); + Symbol *variant = nullptr; // Linear search through symbol variants. Should never be more than two // or three entries here. - auto &Variants = SymVariants[CachedHashStringRef(Sym->getName())]; - if (Variants.empty()) - Variants.push_back(Sym); - - for (Symbol* V : Variants) { - if (*V->getSignature() == *Sig) { - Variant = V; + auto &variants = symVariants[CachedHashStringRef(sym->getName())]; + if (variants.empty()) + variants.push_back(sym); + + for (Symbol* v : variants) { + if (*v->getSignature() == *sig) { + variant = v; break; } } - bool WasAdded = !Variant; - if (WasAdded) { + bool wasAdded = !variant; + if (wasAdded) { // Create a new variant; LLVM_DEBUG(dbgs() << "added new variant\n"); - Variant = reinterpret_cast(make()); - Variants.push_back(Variant); + variant = reinterpret_cast(make()); + variants.push_back(variant); } else { - LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*Variant) << "\n"); - assert(*Variant->getSignature() == *Sig); + LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n"); + assert(*variant->getSignature() == *sig); } - *Out = Variant; - return WasAdded; + *out = variant; + return wasAdded; } // Set a flag for --trace-symbol so that we can print out a log message // if a new symbol with the same name is inserted into the symbol table. -void SymbolTable::trace(StringRef Name) { - SymMap.insert({CachedHashStringRef(Name), -1}); +void SymbolTable::trace(StringRef name) { + symMap.insert({CachedHashStringRef(name), -1}); } -void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { +void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { // Swap symbols as instructed by -wrap. - int &OrigIdx = SymMap[CachedHashStringRef(Sym->getName())]; - int &RealIdx= SymMap[CachedHashStringRef(Real->getName())]; - int &WrapIdx = SymMap[CachedHashStringRef(Wrap->getName())]; - LLVM_DEBUG(dbgs() << "wrap: " << Sym->getName() << "\n"); + int &origIdx = symMap[CachedHashStringRef(sym->getName())]; + int &realIdx= symMap[CachedHashStringRef(real->getName())]; + int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())]; + LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n"); // Anyone looking up __real symbols should get the original - RealIdx = OrigIdx; + realIdx = origIdx; // Anyone looking up the original should get the __wrap symbol - OrigIdx = WrapIdx; + origIdx = wrapIdx; } -static const uint8_t UnreachableFn[] = { +static const uint8_t unreachableFn[] = { 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 0x00 /* opcode unreachable */, 0x0b /* opcode end */ }; @@ -579,15 +579,15 @@ // This is used by handleWeakUndefines in order to generate a callable // equivalent of an undefined function and also handleSymbolVariants for // undefined functions that don't match the signature of the definition. -InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym, - const WasmSignature &Sig, - StringRef DebugName) { - auto *Func = make(Sig, Sym->getName(), DebugName); - Func->setBody(UnreachableFn); - SyntheticFunctions.emplace_back(Func); - replaceSymbol(Sym, Sym->getName(), Sym->getFlags(), nullptr, - Func); - return Func; +InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym, + const WasmSignature &sig, + StringRef debugName) { + auto *func = make(sig, sym->getName(), debugName); + func->setBody(unreachableFn); + syntheticFunctions.emplace_back(func); + replaceSymbol(sym, sym->getName(), sym->getFlags(), nullptr, + func); + return func; } // For weak undefined functions, there may be "call" instructions that reference @@ -595,41 +595,41 @@ // will abort at runtime, so that relocations can still provided an operand to // the call instruction that passes Wasm validation. void SymbolTable::handleWeakUndefines() { - for (Symbol *Sym : getSymbols()) { - if (!Sym->isUndefWeak()) + for (Symbol *sym : getSymbols()) { + if (!sym->isUndefWeak()) continue; - const WasmSignature *Sig = Sym->getSignature(); - if (!Sig) { + const WasmSignature *sig = sym->getSignature(); + if (!sig) { // It is possible for undefined functions not to have a signature (eg. if // added via "--undefined"), but weak undefined ones do have a signature. // Lazy symbols may not be functions and therefore Sig can still be null // in some circumstantce. - assert(!isa(Sym)); + assert(!isa(sym)); continue; } // Add a synthetic dummy for weak undefined functions. These dummies will // be GC'd if not used as the target of any "call" instructions. - StringRef DebugName = Saver.save("undefined:" + toString(*Sym)); - InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName); + StringRef debugName = saver.save("undefined:" + toString(*sym)); + InputFunction* func = replaceWithUnreachable(sym, *sig, debugName); // Ensure it compares equal to the null pointer, and so that table relocs // don't pull in the stub body (only call-operand relocs should do that). - Func->setTableIndex(0); + func->setTableIndex(0); // Hide our dummy to prevent export. - Sym->setHidden(true); + sym->setHidden(true); } } -static void reportFunctionSignatureMismatch(StringRef SymName, - FunctionSymbol *A, - FunctionSymbol *B, bool IsError) { - std::string msg = ("function signature mismatch: " + SymName + - "\n>>> defined as " + toString(*A->Signature) + " in " + - toString(A->getFile()) + "\n>>> defined as " + - toString(*B->Signature) + " in " + toString(B->getFile())) +static void reportFunctionSignatureMismatch(StringRef symName, + FunctionSymbol *a, + FunctionSymbol *b, bool isError) { + std::string msg = ("function signature mismatch: " + symName + + "\n>>> defined as " + toString(*a->signature) + " in " + + toString(a->getFile()) + "\n>>> defined as " + + toString(*b->signature) + " in " + toString(b->getFile())) .str(); - if (IsError) + if (isError) error(msg); else warn(msg); @@ -638,26 +638,26 @@ // Remove any variant symbols that were created due to function signature // mismatches. void SymbolTable::handleSymbolVariants() { - for (auto Pair : SymVariants) { + for (auto pair : symVariants) { // Push the initial symbol onto the list of variants. - StringRef SymName = Pair.first.val(); - std::vector &Variants = Pair.second; + StringRef symName = pair.first.val(); + std::vector &variants = pair.second; #ifndef NDEBUG - LLVM_DEBUG(dbgs() << "symbol with (" << Variants.size() - << ") variants: " << SymName << "\n"); - for (auto *S: Variants) { - auto *F = cast(S); - LLVM_DEBUG(dbgs() << " variant: " + F->getName() << " " - << toString(*F->Signature) << "\n"); + LLVM_DEBUG(dbgs() << "symbol with (" << variants.size() + << ") variants: " << symName << "\n"); + for (auto *s: variants) { + auto *f = cast(s); + LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " " + << toString(*f->signature) << "\n"); } #endif // Find the one definition. - DefinedFunction *Defined = nullptr; - for (auto *Symbol : Variants) { - if (auto F = dyn_cast(Symbol)) { - Defined = F; + DefinedFunction *defined = nullptr; + for (auto *symbol : variants) { + if (auto f = dyn_cast(symbol)) { + defined = f; break; } } @@ -665,19 +665,19 @@ // If there are no definitions, and the undefined symbols disagree on // the signature, there is not we can do since we don't know which one // to use as the signature on the import. - if (!Defined) { - reportFunctionSignatureMismatch(SymName, - cast(Variants[0]), - cast(Variants[1]), true); + if (!defined) { + reportFunctionSignatureMismatch(symName, + cast(variants[0]), + cast(variants[1]), true); return; } - for (auto *Symbol : Variants) { - if (Symbol != Defined) { - auto *F = cast(Symbol); - reportFunctionSignatureMismatch(SymName, F, Defined, false); - StringRef DebugName = Saver.save("unreachable:" + toString(*F)); - replaceWithUnreachable(F, *F->Signature, DebugName); + for (auto *symbol : variants) { + if (symbol != defined) { + auto *f = cast(symbol); + reportFunctionSignatureMismatch(symName, f, defined, false); + StringRef debugName = saver.save("unreachable:" + toString(*f)); + replaceWithUnreachable(f, *f->signature, debugName); } } } Index: lld/trunk/wasm/Symbols.h =================================================================== --- lld/trunk/wasm/Symbols.h +++ lld/trunk/wasm/Symbols.h @@ -20,10 +20,10 @@ // Shared string constants // The default module name to use for symbol imports. -extern const char *DefaultModule; +extern const char *defaultModule; // The name under which to import or export the wasm table. -extern const char *FunctionTableName; +extern const char *functionTableName; using llvm::wasm::WasmSymbolType; @@ -54,16 +54,16 @@ LazyKind, }; - Kind kind() const { return SymbolKind; } + Kind kind() const { return symbolKind; } bool isDefined() const { return !isLazy() && !isUndefined(); } bool isUndefined() const { - return SymbolKind == UndefinedFunctionKind || - SymbolKind == UndefinedDataKind || SymbolKind == UndefinedGlobalKind; + return symbolKind == UndefinedFunctionKind || + symbolKind == UndefinedDataKind || symbolKind == UndefinedGlobalKind; } - bool isLazy() const { return SymbolKind == LazyKind; } + bool isLazy() const { return symbolKind == LazyKind; } bool isLocal() const; bool isWeak() const; @@ -80,12 +80,12 @@ } // Returns the symbol name. - StringRef getName() const { return Name; } + StringRef getName() const { return name; } // Returns the file from which this symbol was created. - InputFile *getFile() const { return File; } + InputFile *getFile() const { return file; } - uint32_t getFlags() const { return Flags; } + uint32_t getFlags() const { return flags; } InputChunk *getChunk() const; @@ -97,120 +97,120 @@ // final image. void markLive(); - void setHidden(bool IsHidden); + void setHidden(bool isHidden); // Get/set the index in the output symbol table. This is only used for // relocatable output. uint32_t getOutputSymbolIndex() const; - void setOutputSymbolIndex(uint32_t Index); + void setOutputSymbolIndex(uint32_t index); WasmSymbolType getWasmType() const; bool isExported() const; const WasmSignature* getSignature() const; - bool isInGOT() const { return GOTIndex != INVALID_INDEX; } + bool isInGOT() const { return gotIndex != INVALID_INDEX; } uint32_t getGOTIndex() const { - assert(GOTIndex != INVALID_INDEX); - return GOTIndex; + assert(gotIndex != INVALID_INDEX); + return gotIndex; } - void setGOTIndex(uint32_t Index); - bool hasGOTIndex() const { return GOTIndex != INVALID_INDEX; } + void setGOTIndex(uint32_t index); + bool hasGOTIndex() const { return gotIndex != INVALID_INDEX; } protected: - Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F) - : Name(Name), File(F), Flags(Flags), SymbolKind(K), - Referenced(!Config->GcSections), IsUsedInRegularObj(false), - ForceExport(false), CanInline(false), Traced(false) {} - - StringRef Name; - InputFile *File; - uint32_t Flags; - uint32_t OutputSymbolIndex = INVALID_INDEX; - uint32_t GOTIndex = INVALID_INDEX; - Kind SymbolKind; + Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f) + : name(name), file(f), flags(flags), symbolKind(k), + referenced(!config->gcSections), isUsedInRegularObj(false), + forceExport(false), canInline(false), traced(false) {} + + StringRef name; + InputFile *file; + uint32_t flags; + uint32_t outputSymbolIndex = INVALID_INDEX; + uint32_t gotIndex = INVALID_INDEX; + Kind symbolKind; public: - bool Referenced : 1; + bool referenced : 1; // True if the symbol was used for linking and thus need to be added to the // output file's symbol table. This is true for all symbols except for // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that // are unreferenced except by other bitcode objects. - bool IsUsedInRegularObj : 1; + bool isUsedInRegularObj : 1; // True if ths symbol is explicity marked for export (i.e. via the -e/--export // command line flag) - bool ForceExport : 1; + bool forceExport : 1; // False if LTO shouldn't inline whatever this symbol points to. If a symbol // is overwritten after LTO, LTO shouldn't inline the symbol because it // doesn't know the final contents of the symbol. - bool CanInline : 1; + bool canInline : 1; // True if this symbol is specified by --trace-symbol option. - bool Traced : 1; + bool traced : 1; }; class FunctionSymbol : public Symbol { public: - static bool classof(const Symbol *S) { - return S->kind() == DefinedFunctionKind || - S->kind() == UndefinedFunctionKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedFunctionKind || + s->kind() == UndefinedFunctionKind; } // Get/set the table index - void setTableIndex(uint32_t Index); + void setTableIndex(uint32_t index); uint32_t getTableIndex() const; bool hasTableIndex() const; // Get/set the function index uint32_t getFunctionIndex() const; - void setFunctionIndex(uint32_t Index); + void setFunctionIndex(uint32_t index); bool hasFunctionIndex() const; - const WasmSignature *Signature; + const WasmSignature *signature; protected: - FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, - const WasmSignature *Sig) - : Symbol(Name, K, Flags, F), Signature(Sig) {} + FunctionSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f, + const WasmSignature *sig) + : Symbol(name, k, flags, f), signature(sig) {} - uint32_t TableIndex = INVALID_INDEX; - uint32_t FunctionIndex = INVALID_INDEX; + uint32_t tableIndex = INVALID_INDEX; + uint32_t functionIndex = INVALID_INDEX; }; class DefinedFunction : public FunctionSymbol { public: - DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, - InputFunction *Function); + DefinedFunction(StringRef name, uint32_t flags, InputFile *f, + InputFunction *function); - static bool classof(const Symbol *S) { - return S->kind() == DefinedFunctionKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedFunctionKind; } - InputFunction *Function; + InputFunction *function; }; class UndefinedFunction : public FunctionSymbol { public: - UndefinedFunction(StringRef Name, StringRef ImportName, - StringRef ImportModule, uint32_t Flags, - InputFile *File = nullptr, - const WasmSignature *Type = nullptr, - bool IsCalledDirectly = true) - : FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type), - ImportName(ImportName), ImportModule(ImportModule), IsCalledDirectly(IsCalledDirectly) {} - - static bool classof(const Symbol *S) { - return S->kind() == UndefinedFunctionKind; + UndefinedFunction(StringRef name, StringRef importName, + StringRef importModule, uint32_t flags, + InputFile *file = nullptr, + const WasmSignature *type = nullptr, + bool isCalledDirectly = true) + : FunctionSymbol(name, UndefinedFunctionKind, flags, file, type), + importName(importName), importModule(importModule), isCalledDirectly(isCalledDirectly) {} + + static bool classof(const Symbol *s) { + return s->kind() == UndefinedFunctionKind; } - StringRef ImportName; - StringRef ImportModule; - bool IsCalledDirectly; + StringRef importName; + StringRef importModule; + bool isCalledDirectly; }; // Section symbols for output sections are different from those for input @@ -218,128 +218,128 @@ // rather than an InputSection. class OutputSectionSymbol : public Symbol { public: - OutputSectionSymbol(const OutputSection *S) + OutputSectionSymbol(const OutputSection *s) : Symbol("", OutputSectionKind, llvm::wasm::WASM_SYMBOL_BINDING_LOCAL, nullptr), - Section(S) {} + section(s) {} - static bool classof(const Symbol *S) { - return S->kind() == OutputSectionKind; + static bool classof(const Symbol *s) { + return s->kind() == OutputSectionKind; } - const OutputSection *Section; + const OutputSection *section; }; class SectionSymbol : public Symbol { public: - SectionSymbol(uint32_t Flags, const InputSection *S, InputFile *F = nullptr) - : Symbol("", SectionKind, Flags, F), Section(S) {} + SectionSymbol(uint32_t flags, const InputSection *s, InputFile *f = nullptr) + : Symbol("", SectionKind, flags, f), section(s) {} - static bool classof(const Symbol *S) { return S->kind() == SectionKind; } + static bool classof(const Symbol *s) { return s->kind() == SectionKind; } const OutputSectionSymbol *getOutputSectionSymbol() const; - const InputSection *Section; + const InputSection *section; }; class DataSymbol : public Symbol { public: - static bool classof(const Symbol *S) { - return S->kind() == DefinedDataKind || S->kind() == UndefinedDataKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedDataKind || s->kind() == UndefinedDataKind; } protected: - DataSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F) - : Symbol(Name, K, Flags, F) {} + DataSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f) + : Symbol(name, k, flags, f) {} }; class DefinedData : public DataSymbol { public: // Constructor for regular data symbols originating from input files. - DefinedData(StringRef Name, uint32_t Flags, InputFile *F, - InputSegment *Segment, uint32_t Offset, uint32_t Size) - : DataSymbol(Name, DefinedDataKind, Flags, F), Segment(Segment), - Offset(Offset), Size(Size) {} + DefinedData(StringRef name, uint32_t flags, InputFile *f, + InputSegment *segment, uint32_t offset, uint32_t size) + : DataSymbol(name, DefinedDataKind, flags, f), segment(segment), + offset(offset), size(size) {} // Constructor for linker synthetic data symbols. - DefinedData(StringRef Name, uint32_t Flags) - : DataSymbol(Name, DefinedDataKind, Flags, nullptr) {} + DefinedData(StringRef name, uint32_t flags) + : DataSymbol(name, DefinedDataKind, flags, nullptr) {} - static bool classof(const Symbol *S) { return S->kind() == DefinedDataKind; } + static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; } // Returns the output virtual address of a defined data symbol. uint32_t getVirtualAddress() const; - void setVirtualAddress(uint32_t VA); + void setVirtualAddress(uint32_t va); // Returns the offset of a defined data symbol within its OutputSegment. uint32_t getOutputSegmentOffset() const; uint32_t getOutputSegmentIndex() const; - uint32_t getSize() const { return Size; } + uint32_t getSize() const { return size; } - InputSegment *Segment = nullptr; + InputSegment *segment = nullptr; protected: - uint32_t Offset = 0; - uint32_t Size = 0; + uint32_t offset = 0; + uint32_t size = 0; }; class UndefinedData : public DataSymbol { public: - UndefinedData(StringRef Name, uint32_t Flags, InputFile *File = nullptr) - : DataSymbol(Name, UndefinedDataKind, Flags, File) {} - static bool classof(const Symbol *S) { - return S->kind() == UndefinedDataKind; + UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr) + : DataSymbol(name, UndefinedDataKind, flags, file) {} + static bool classof(const Symbol *s) { + return s->kind() == UndefinedDataKind; } }; class GlobalSymbol : public Symbol { public: - static bool classof(const Symbol *S) { - return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedGlobalKind || s->kind() == UndefinedGlobalKind; } - const WasmGlobalType *getGlobalType() const { return GlobalType; } + const WasmGlobalType *getGlobalType() const { return globalType; } // Get/set the global index uint32_t getGlobalIndex() const; - void setGlobalIndex(uint32_t Index); + void setGlobalIndex(uint32_t index); bool hasGlobalIndex() const; protected: - GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, - const WasmGlobalType *GlobalType) - : Symbol(Name, K, Flags, F), GlobalType(GlobalType) {} + GlobalSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f, + const WasmGlobalType *globalType) + : Symbol(name, k, flags, f), globalType(globalType) {} - const WasmGlobalType *GlobalType; - uint32_t GlobalIndex = INVALID_INDEX; + const WasmGlobalType *globalType; + uint32_t globalIndex = INVALID_INDEX; }; class DefinedGlobal : public GlobalSymbol { public: - DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, - InputGlobal *Global); + DefinedGlobal(StringRef name, uint32_t flags, InputFile *file, + InputGlobal *global); - static bool classof(const Symbol *S) { - return S->kind() == DefinedGlobalKind; + static bool classof(const Symbol *s) { + return s->kind() == DefinedGlobalKind; } - InputGlobal *Global; + InputGlobal *global; }; class UndefinedGlobal : public GlobalSymbol { public: - UndefinedGlobal(StringRef Name, StringRef ImportName, StringRef ImportModule, - uint32_t Flags, InputFile *File = nullptr, - const WasmGlobalType *Type = nullptr) - : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type), - ImportName(ImportName), ImportModule(ImportModule) {} + UndefinedGlobal(StringRef name, StringRef importName, StringRef importModule, + uint32_t flags, InputFile *file = nullptr, + const WasmGlobalType *type = nullptr) + : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type), + importName(importName), importModule(importModule) {} - static bool classof(const Symbol *S) { - return S->kind() == UndefinedGlobalKind; + static bool classof(const Symbol *s) { + return s->kind() == UndefinedGlobalKind; } - StringRef ImportName; - StringRef ImportModule; + StringRef importName; + StringRef importModule; }; // Wasm events are features that suspend the current execution and transfer the @@ -356,34 +356,34 @@ // are used, and has name '__cpp_exception' for linking. class EventSymbol : public Symbol { public: - static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; } + static bool classof(const Symbol *s) { return s->kind() == DefinedEventKind; } - const WasmEventType *getEventType() const { return EventType; } + const WasmEventType *getEventType() const { return eventType; } // Get/set the event index uint32_t getEventIndex() const; - void setEventIndex(uint32_t Index); + void setEventIndex(uint32_t index); bool hasEventIndex() const; - const WasmSignature *Signature; + const WasmSignature *signature; protected: - EventSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, - const WasmEventType *EventType, const WasmSignature *Sig) - : Symbol(Name, K, Flags, F), Signature(Sig), EventType(EventType) {} + EventSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f, + const WasmEventType *eventType, const WasmSignature *sig) + : Symbol(name, k, flags, f), signature(sig), eventType(eventType) {} - const WasmEventType *EventType; - uint32_t EventIndex = INVALID_INDEX; + const WasmEventType *eventType; + uint32_t eventIndex = INVALID_INDEX; }; class DefinedEvent : public EventSymbol { public: - DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, - InputEvent *Event); + DefinedEvent(StringRef name, uint32_t flags, InputFile *file, + InputEvent *event); - static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; } + static bool classof(const Symbol *s) { return s->kind() == DefinedEventKind; } - InputEvent *Event; + InputEvent *event; }; // LazySymbol represents a symbol that is not yet in the link, but we know where @@ -397,11 +397,11 @@ // symbols into consideration. class LazySymbol : public Symbol { public: - LazySymbol(StringRef Name, uint32_t Flags, InputFile *File, - const llvm::object::Archive::Symbol &Sym) - : Symbol(Name, LazyKind, Flags, File), ArchiveSymbol(Sym) {} + LazySymbol(StringRef name, uint32_t flags, InputFile *file, + const llvm::object::Archive::Symbol &sym) + : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {} - static bool classof(const Symbol *S) { return S->kind() == LazyKind; } + static bool classof(const Symbol *s) { return s->kind() == LazyKind; } void fetch(); // Lazy symbols can have a signature because they can replace an @@ -409,71 +409,71 @@ // signture. // TODO(sbc): This repetition of the signature field is inelegant. Revisit // the use of class hierarchy to represent symbol taxonomy. - const WasmSignature *Signature = nullptr; + const WasmSignature *signature = nullptr; private: - llvm::object::Archive::Symbol ArchiveSymbol; + llvm::object::Archive::Symbol archiveSymbol; }; // linker-generated symbols struct WasmSym { // __global_base // Symbol marking the start of the global section. - static DefinedData *GlobalBase; + static DefinedData *globalBase; // __stack_pointer // Global that holds the address of the top of the explicit value stack in // linear memory. - static GlobalSymbol *StackPointer; + static GlobalSymbol *stackPointer; // __data_end // Symbol marking the end of the data and bss. - static DefinedData *DataEnd; + static DefinedData *dataEnd; // __heap_base // Symbol marking the end of the data, bss and explicit stack. Any linear // memory following this address is not used by the linked code and can // therefore be used as a backing store for brk()/malloc() implementations. - static DefinedData *HeapBase; + static DefinedData *heapBase; // __wasm_call_ctors // Function that directly calls all ctors in priority order. - static DefinedFunction *CallCtors; + static DefinedFunction *callCtors; // __wasm_init_memory // Function that initializes passive data segments post-instantiation. - static DefinedFunction *InitMemory; + static DefinedFunction *initMemory; // __wasm_apply_relocs // Function that applies relocations to data segment post-instantiation. - static DefinedFunction *ApplyRelocs; + static DefinedFunction *applyRelocs; // __dso_handle // Symbol used in calls to __cxa_atexit to determine current DLL - static DefinedData *DsoHandle; + static DefinedData *dsoHandle; // __table_base // Used in PIC code for offset of indirect function table - static UndefinedGlobal *TableBase; + static UndefinedGlobal *tableBase; // __memory_base // Used in PIC code for offset of global data - static UndefinedGlobal *MemoryBase; + static UndefinedGlobal *memoryBase; }; // A buffer class that is large enough to hold any Symbol-derived // object. We allocate memory using this class and instantiate a symbol // using the placement new. union SymbolUnion { - alignas(DefinedFunction) char A[sizeof(DefinedFunction)]; - alignas(DefinedData) char B[sizeof(DefinedData)]; - alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)]; - alignas(DefinedEvent) char D[sizeof(DefinedEvent)]; - alignas(LazySymbol) char E[sizeof(LazySymbol)]; - alignas(UndefinedFunction) char F[sizeof(UndefinedFunction)]; - alignas(UndefinedData) char G[sizeof(UndefinedData)]; - alignas(UndefinedGlobal) char H[sizeof(UndefinedGlobal)]; - alignas(SectionSymbol) char I[sizeof(SectionSymbol)]; + alignas(DefinedFunction) char a[sizeof(DefinedFunction)]; + alignas(DefinedData) char b[sizeof(DefinedData)]; + alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)]; + alignas(DefinedEvent) char d[sizeof(DefinedEvent)]; + alignas(LazySymbol) char e[sizeof(LazySymbol)]; + alignas(UndefinedFunction) char f[sizeof(UndefinedFunction)]; + alignas(UndefinedData) char g[sizeof(UndefinedData)]; + alignas(UndefinedGlobal) char h[sizeof(UndefinedGlobal)]; + alignas(SectionSymbol) char i[sizeof(SectionSymbol)]; }; // It is important to keep the size of SymbolUnion small for performance and @@ -481,11 +481,11 @@ // UndefinedFunction on a 64-bit system. static_assert(sizeof(SymbolUnion) <= 96, "SymbolUnion too large"); -void printTraceSymbol(Symbol *Sym); -void printTraceSymbolUndefined(StringRef Name, const InputFile* File); +void printTraceSymbol(Symbol *sym); +void printTraceSymbolUndefined(StringRef name, const InputFile* file); template -T *replaceSymbol(Symbol *S, ArgT &&... Arg) { +T *replaceSymbol(Symbol *s, ArgT &&... arg) { static_assert(std::is_trivially_destructible(), "Symbol types must be trivially destructible"); static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small"); @@ -494,28 +494,28 @@ assert(static_cast(static_cast(nullptr)) == nullptr && "Not a Symbol"); - Symbol SymCopy = *S; + Symbol symCopy = *s; - T *S2 = new (S) T(std::forward(Arg)...); - S2->IsUsedInRegularObj = SymCopy.IsUsedInRegularObj; - S2->ForceExport = SymCopy.ForceExport; - S2->CanInline = SymCopy.CanInline; - S2->Traced = SymCopy.Traced; + T *s2 = new (s) T(std::forward(arg)...); + s2->isUsedInRegularObj = symCopy.isUsedInRegularObj; + s2->forceExport = symCopy.forceExport; + s2->canInline = symCopy.canInline; + s2->traced = symCopy.traced; // Print out a log message if --trace-symbol was specified. // This is for debugging. - if (S2->Traced) - printTraceSymbol(S2); + if (s2->traced) + printTraceSymbol(s2); - return S2; + return s2; } } // namespace wasm // Returns a symbol name for an error message. -std::string toString(const wasm::Symbol &Sym); -std::string toString(wasm::Symbol::Kind Kind); -std::string maybeDemangleSymbol(StringRef Name); +std::string toString(const wasm::Symbol &sym); +std::string toString(wasm::Symbol::Kind kind); +std::string maybeDemangleSymbol(StringRef name); } // namespace lld Index: lld/trunk/wasm/Symbols.cpp =================================================================== --- lld/trunk/wasm/Symbols.cpp +++ lld/trunk/wasm/Symbols.cpp @@ -24,16 +24,16 @@ using namespace lld; using namespace lld::wasm; -DefinedFunction *WasmSym::CallCtors; -DefinedFunction *WasmSym::InitMemory; -DefinedFunction *WasmSym::ApplyRelocs; -DefinedData *WasmSym::DsoHandle; -DefinedData *WasmSym::DataEnd; -DefinedData *WasmSym::GlobalBase; -DefinedData *WasmSym::HeapBase; -GlobalSymbol *WasmSym::StackPointer; -UndefinedGlobal *WasmSym::TableBase; -UndefinedGlobal *WasmSym::MemoryBase; +DefinedFunction *WasmSym::callCtors; +DefinedFunction *WasmSym::initMemory; +DefinedFunction *WasmSym::applyRelocs; +DefinedData *WasmSym::dsoHandle; +DefinedData *WasmSym::dataEnd; +DefinedData *WasmSym::globalBase; +DefinedData *WasmSym::heapBase; +GlobalSymbol *WasmSym::stackPointer; +UndefinedGlobal *WasmSym::tableBase; +UndefinedGlobal *WasmSym::memoryBase; WasmSymbolType Symbol::getWasmType() const { if (isa(this)) @@ -50,248 +50,248 @@ } const WasmSignature *Symbol::getSignature() const { - if (auto* F = dyn_cast(this)) - return F->Signature; - if (auto *L = dyn_cast(this)) - return L->Signature; + if (auto* f = dyn_cast(this)) + return f->signature; + if (auto *l = dyn_cast(this)) + return l->signature; return nullptr; } InputChunk *Symbol::getChunk() const { - if (auto *F = dyn_cast(this)) - return F->Function; - if (auto *D = dyn_cast(this)) - return D->Segment; + if (auto *f = dyn_cast(this)) + return f->function; + if (auto *d = dyn_cast(this)) + return d->segment; return nullptr; } bool Symbol::isDiscarded() const { - if (InputChunk *C = getChunk()) - return C->Discarded; + if (InputChunk *c = getChunk()) + return c->discarded; return false; } bool Symbol::isLive() const { - if (auto *G = dyn_cast(this)) - return G->Global->Live; - if (auto *E = dyn_cast(this)) - return E->Event->Live; - if (InputChunk *C = getChunk()) - return C->Live; - return Referenced; + if (auto *g = dyn_cast(this)) + return g->global->live; + if (auto *e = dyn_cast(this)) + return e->event->live; + if (InputChunk *c = getChunk()) + return c->live; + return referenced; } void Symbol::markLive() { assert(!isDiscarded()); - if (auto *G = dyn_cast(this)) - G->Global->Live = true; - if (auto *E = dyn_cast(this)) - E->Event->Live = true; - if (InputChunk *C = getChunk()) - C->Live = true; - Referenced = true; + if (auto *g = dyn_cast(this)) + g->global->live = true; + if (auto *e = dyn_cast(this)) + e->event->live = true; + if (InputChunk *c = getChunk()) + c->live = true; + referenced = true; } uint32_t Symbol::getOutputSymbolIndex() const { - assert(OutputSymbolIndex != INVALID_INDEX); - return OutputSymbolIndex; + assert(outputSymbolIndex != INVALID_INDEX); + return outputSymbolIndex; } -void Symbol::setOutputSymbolIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index +void Symbol::setOutputSymbolIndex(uint32_t index) { + LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name << " -> " << index << "\n"); - assert(OutputSymbolIndex == INVALID_INDEX); - OutputSymbolIndex = Index; + assert(outputSymbolIndex == INVALID_INDEX); + outputSymbolIndex = index; } -void Symbol::setGOTIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "setGOTIndex " << Name << " -> " << Index << "\n"); - assert(GOTIndex == INVALID_INDEX); +void Symbol::setGOTIndex(uint32_t index) { + LLVM_DEBUG(dbgs() << "setGOTIndex " << name << " -> " << index << "\n"); + assert(gotIndex == INVALID_INDEX); // Any symbol that is assigned a GOT entry must be exported othewise the // dynamic linker won't be able create the entry that contains it. - ForceExport = true; - GOTIndex = Index; + forceExport = true; + gotIndex = index; } bool Symbol::isWeak() const { - return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; + return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; } bool Symbol::isLocal() const { - return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL; + return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL; } bool Symbol::isHidden() const { - return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN; + return (flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN; } -void Symbol::setHidden(bool IsHidden) { - LLVM_DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n"); - Flags &= ~WASM_SYMBOL_VISIBILITY_MASK; - if (IsHidden) - Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; +void Symbol::setHidden(bool isHidden) { + LLVM_DEBUG(dbgs() << "setHidden: " << name << " -> " << isHidden << "\n"); + flags &= ~WASM_SYMBOL_VISIBILITY_MASK; + if (isHidden) + flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; else - Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT; + flags |= WASM_SYMBOL_VISIBILITY_DEFAULT; } bool Symbol::isExported() const { if (!isDefined() || isLocal()) return false; - if (ForceExport || Config->ExportAll) + if (forceExport || config->exportAll) return true; - if (Config->ExportDynamic && !isHidden()) + if (config->exportDynamic && !isHidden()) return true; - return Flags & WASM_SYMBOL_EXPORTED; + return flags & WASM_SYMBOL_EXPORTED; } uint32_t FunctionSymbol::getFunctionIndex() const { - if (auto *F = dyn_cast(this)) - return F->Function->getFunctionIndex(); - assert(FunctionIndex != INVALID_INDEX); - return FunctionIndex; + if (auto *f = dyn_cast(this)) + return f->function->getFunctionIndex(); + assert(functionIndex != INVALID_INDEX); + return functionIndex; } -void FunctionSymbol::setFunctionIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n"); - assert(FunctionIndex == INVALID_INDEX); - FunctionIndex = Index; +void FunctionSymbol::setFunctionIndex(uint32_t index) { + LLVM_DEBUG(dbgs() << "setFunctionIndex " << name << " -> " << index << "\n"); + assert(functionIndex == INVALID_INDEX); + functionIndex = index; } bool FunctionSymbol::hasFunctionIndex() const { - if (auto *F = dyn_cast(this)) - return F->Function->hasFunctionIndex(); - return FunctionIndex != INVALID_INDEX; + if (auto *f = dyn_cast(this)) + return f->function->hasFunctionIndex(); + return functionIndex != INVALID_INDEX; } uint32_t FunctionSymbol::getTableIndex() const { - if (auto *F = dyn_cast(this)) - return F->Function->getTableIndex(); - assert(TableIndex != INVALID_INDEX); - return TableIndex; + if (auto *f = dyn_cast(this)) + return f->function->getTableIndex(); + assert(tableIndex != INVALID_INDEX); + return tableIndex; } bool FunctionSymbol::hasTableIndex() const { - if (auto *F = dyn_cast(this)) - return F->Function->hasTableIndex(); - return TableIndex != INVALID_INDEX; + if (auto *f = dyn_cast(this)) + return f->function->hasTableIndex(); + return tableIndex != INVALID_INDEX; } -void FunctionSymbol::setTableIndex(uint32_t Index) { +void FunctionSymbol::setTableIndex(uint32_t index) { // For imports, we set the table index here on the Symbol; for defined // functions we set the index on the InputFunction so that we don't export // the same thing twice (keeps the table size down). - if (auto *F = dyn_cast(this)) { - F->Function->setTableIndex(Index); + if (auto *f = dyn_cast(this)) { + f->function->setTableIndex(index); return; } - LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); - assert(TableIndex == INVALID_INDEX); - TableIndex = Index; + LLVM_DEBUG(dbgs() << "setTableIndex " << name << " -> " << index << "\n"); + assert(tableIndex == INVALID_INDEX); + tableIndex = index; } -DefinedFunction::DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, - InputFunction *Function) - : FunctionSymbol(Name, DefinedFunctionKind, Flags, F, - Function ? &Function->Signature : nullptr), - Function(Function) {} +DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f, + InputFunction *function) + : FunctionSymbol(name, DefinedFunctionKind, flags, f, + function ? &function->signature : nullptr), + function(function) {} uint32_t DefinedData::getVirtualAddress() const { LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); - if (Segment) - return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset; - return Offset; + if (segment) + return segment->outputSeg->startVA + segment->outputSegmentOffset + offset; + return offset; } -void DefinedData::setVirtualAddress(uint32_t Value) { - LLVM_DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); - assert(!Segment); - Offset = Value; +void DefinedData::setVirtualAddress(uint32_t value) { + LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n"); + assert(!segment); + offset = value; } uint32_t DefinedData::getOutputSegmentOffset() const { LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); - return Segment->OutputSegmentOffset + Offset; + return segment->outputSegmentOffset + offset; } uint32_t DefinedData::getOutputSegmentIndex() const { LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n"); - return Segment->OutputSeg->Index; + return segment->outputSeg->index; } uint32_t GlobalSymbol::getGlobalIndex() const { - if (auto *F = dyn_cast(this)) - return F->Global->getGlobalIndex(); - assert(GlobalIndex != INVALID_INDEX); - return GlobalIndex; + if (auto *f = dyn_cast(this)) + return f->global->getGlobalIndex(); + assert(globalIndex != INVALID_INDEX); + return globalIndex; } -void GlobalSymbol::setGlobalIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n"); - assert(GlobalIndex == INVALID_INDEX); - GlobalIndex = Index; +void GlobalSymbol::setGlobalIndex(uint32_t index) { + LLVM_DEBUG(dbgs() << "setGlobalIndex " << name << " -> " << index << "\n"); + assert(globalIndex == INVALID_INDEX); + globalIndex = index; } bool GlobalSymbol::hasGlobalIndex() const { - if (auto *F = dyn_cast(this)) - return F->Global->hasGlobalIndex(); - return GlobalIndex != INVALID_INDEX; + if (auto *f = dyn_cast(this)) + return f->global->hasGlobalIndex(); + return globalIndex != INVALID_INDEX; } -DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, - InputGlobal *Global) - : GlobalSymbol(Name, DefinedGlobalKind, Flags, File, - Global ? &Global->getType() : nullptr), - Global(Global) {} +DefinedGlobal::DefinedGlobal(StringRef name, uint32_t flags, InputFile *file, + InputGlobal *global) + : GlobalSymbol(name, DefinedGlobalKind, flags, file, + global ? &global->getType() : nullptr), + global(global) {} uint32_t EventSymbol::getEventIndex() const { - if (auto *F = dyn_cast(this)) - return F->Event->getEventIndex(); - assert(EventIndex != INVALID_INDEX); - return EventIndex; + if (auto *f = dyn_cast(this)) + return f->event->getEventIndex(); + assert(eventIndex != INVALID_INDEX); + return eventIndex; } -void EventSymbol::setEventIndex(uint32_t Index) { - LLVM_DEBUG(dbgs() << "setEventIndex " << Name << " -> " << Index << "\n"); - assert(EventIndex == INVALID_INDEX); - EventIndex = Index; +void EventSymbol::setEventIndex(uint32_t index) { + LLVM_DEBUG(dbgs() << "setEventIndex " << name << " -> " << index << "\n"); + assert(eventIndex == INVALID_INDEX); + eventIndex = index; } bool EventSymbol::hasEventIndex() const { - if (auto *F = dyn_cast(this)) - return F->Event->hasEventIndex(); - return EventIndex != INVALID_INDEX; + if (auto *f = dyn_cast(this)) + return f->event->hasEventIndex(); + return eventIndex != INVALID_INDEX; } -DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, - InputEvent *Event) - : EventSymbol(Name, DefinedEventKind, Flags, File, - Event ? &Event->getType() : nullptr, - Event ? &Event->Signature : nullptr), - Event(Event) {} +DefinedEvent::DefinedEvent(StringRef name, uint32_t flags, InputFile *file, + InputEvent *event) + : EventSymbol(name, DefinedEventKind, flags, file, + event ? &event->getType() : nullptr, + event ? &event->signature : nullptr), + event(event) {} const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const { - assert(Section->OutputSec && Section->OutputSec->SectionSym); - return Section->OutputSec->SectionSym; + assert(section->outputSec && section->outputSec->sectionSym); + return section->outputSec->sectionSym; } -void LazySymbol::fetch() { cast(File)->addMember(&ArchiveSymbol); } +void LazySymbol::fetch() { cast(file)->addMember(&archiveSymbol); } -std::string lld::toString(const wasm::Symbol &Sym) { - return lld::maybeDemangleSymbol(Sym.getName()); +std::string lld::toString(const wasm::Symbol &sym) { + return lld::maybeDemangleSymbol(sym.getName()); } -std::string lld::maybeDemangleSymbol(StringRef Name) { - if (Config->Demangle) - if (Optional S = demangleItanium(Name)) - return *S; - return Name; +std::string lld::maybeDemangleSymbol(StringRef name) { + if (config->demangle) + if (Optional s = demangleItanium(name)) + return *s; + return name; } -std::string lld::toString(wasm::Symbol::Kind Kind) { - switch (Kind) { +std::string lld::toString(wasm::Symbol::Kind kind) { + switch (kind) { case wasm::Symbol::DefinedFunctionKind: return "DefinedFunction"; case wasm::Symbol::DefinedDataKind: @@ -317,24 +317,24 @@ } -void lld::wasm::printTraceSymbolUndefined(StringRef Name, const InputFile* File) { - message(toString(File) + ": reference to " + Name); +void lld::wasm::printTraceSymbolUndefined(StringRef name, const InputFile* file) { + message(toString(file) + ": reference to " + name); } // Print out a log message for --trace-symbol. -void lld::wasm::printTraceSymbol(Symbol *Sym) { +void lld::wasm::printTraceSymbol(Symbol *sym) { // Undefined symbols are traced via printTraceSymbolUndefined - if (Sym->isUndefined()) + if (sym->isUndefined()) return; - std::string S; - if (Sym->isLazy()) - S = ": lazy definition of "; + std::string s; + if (sym->isLazy()) + s = ": lazy definition of "; else - S = ": definition of "; + s = ": definition of "; - message(toString(Sym->getFile()) + S + Sym->getName()); + message(toString(sym->getFile()) + s + sym->getName()); } -const char *lld::wasm::DefaultModule = "env"; -const char *lld::wasm::FunctionTableName = "__indirect_function_table"; +const char *lld::wasm::defaultModule = "env"; +const char *lld::wasm::functionTableName = "__indirect_function_table"; Index: lld/trunk/wasm/SyntheticSections.h =================================================================== --- lld/trunk/wasm/SyntheticSections.h +++ lld/trunk/wasm/SyntheticSections.h @@ -29,41 +29,41 @@ // An init entry to be written to either the synthetic init func or the // linking metadata. struct WasmInitEntry { - const FunctionSymbol *Sym; - uint32_t Priority; + 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"); + 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); + 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()); + 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(); } + size_t getSize() const override { return header.size() + body.size(); } virtual void writeBody() {} void finalizeContents() override { writeBody(); - BodyOutputStream.flush(); - createHeader(Body.size()); + bodyOutputStream.flush(); + createHeader(body.size()); } - raw_ostream &getStream() { return BodyOutputStream; } + raw_ostream &getStream() { return bodyOutputStream; } - std::string Body; + std::string body; protected: - llvm::raw_string_ostream BodyOutputStream; + llvm::raw_string_ostream bodyOutputStream; }; // Create the custom "dylink" section containing information for the dynamic @@ -73,25 +73,25 @@ class DylinkSection : public SyntheticSection { public: DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {} - bool isNeeded() const override { return Config->Pic; } + bool isNeeded() const override { return config->isPic; } void writeBody() override; - uint32_t MemAlign = 0; - uint32_t MemSize = 0; + 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; }; + bool isNeeded() const override { return types.size() > 0; }; void writeBody() override; - uint32_t registerType(const WasmSignature &Sig); - uint32_t lookupType(const WasmSignature &Sig); + uint32_t registerType(const WasmSignature &sig); + uint32_t lookupType(const WasmSignature &sig); protected: - std::vector Types; - llvm::DenseMap TypeIndices; + std::vector types; + llvm::DenseMap typeIndices; }; class ImportSection : public SyntheticSection { @@ -99,42 +99,42 @@ 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; } + void addImport(Symbol *sym); + void addGOTEntry(Symbol *sym); + void seal() { isSealed = true; } uint32_t getNumImports() const; uint32_t getNumImportedGlobals() const { - assert(IsSealed); - return NumImportedGlobals; + assert(isSealed); + return numImportedGlobals; } uint32_t getNumImportedFunctions() const { - assert(IsSealed); - return NumImportedFunctions; + assert(isSealed); + return numImportedFunctions; } uint32_t getNumImportedEvents() const { - assert(IsSealed); - return NumImportedEvents; + assert(isSealed); + return numImportedEvents; } - std::vector ImportedSymbols; + std::vector importedSymbols; protected: - bool IsSealed = false; - unsigned NumImportedGlobals = 0; - unsigned NumImportedFunctions = 0; - unsigned NumImportedEvents = 0; - std::vector GOTSymbols; + bool isSealed = false; + unsigned numImportedGlobals = 0; + unsigned numImportedFunctions = 0; + unsigned numImportedEvents = 0; + std::vector gotSymbols; }; class FunctionSection : public SyntheticSection { public: FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {} - bool isNeeded() const override { return InputFunctions.size() > 0; }; + bool isNeeded() const override { return inputFunctions.size() > 0; }; void writeBody() override; - void addFunction(InputFunction *Func); + void addFunction(InputFunction *func); - std::vector InputFunctions; + std::vector inputFunctions; protected: }; @@ -143,11 +143,11 @@ public: MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {} - bool isNeeded() const override { return !Config->ImportMemory; } + bool isNeeded() const override { return !config->importMemory; } void writeBody() override; - uint32_t NumMemoryPages = 0; - uint32_t MaxMemoryPages = 0; + uint32_t numMemoryPages = 0; + uint32_t maxMemoryPages = 0; }; class TableSection : public SyntheticSection { @@ -163,7 +163,7 @@ // no address-taken function will fail at validation time since it is // a validation error to include a call_indirect instruction if there // is not table. - return !Config->ImportTable; + return !config->importTable; } void writeBody() override; @@ -173,14 +173,14 @@ public: GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {} uint32_t numGlobals() const { - return InputGlobals.size() + DefinedFakeGlobals.size(); + return inputGlobals.size() + definedFakeGlobals.size(); } bool isNeeded() const override { return numGlobals() > 0; } void writeBody() override; - void addGlobal(InputGlobal *Global); + void addGlobal(InputGlobal *global); - std::vector DefinedFakeGlobals; - std::vector InputGlobals; + std::vector definedFakeGlobals; + std::vector inputGlobals; }; // The event section contains a list of declared wasm events associated with the @@ -197,66 +197,66 @@ public: EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {} void writeBody() override; - bool isNeeded() const override { return InputEvents.size() > 0; } - void addEvent(InputEvent *Event); + bool isNeeded() const override { return inputEvents.size() > 0; } + void addEvent(InputEvent *event); - std::vector InputEvents; + std::vector inputEvents; }; class ExportSection : public SyntheticSection { public: ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {} - bool isNeeded() const override { return Exports.size() > 0; } + bool isNeeded() const override { return exports.size() > 0; } void writeBody() override; - std::vector Exports; + std::vector exports; }; class ElemSection : public SyntheticSection { public: - ElemSection(uint32_t Offset) - : SyntheticSection(llvm::wasm::WASM_SEC_ELEM), ElemOffset(Offset) {} - bool isNeeded() const override { return IndirectFunctions.size() > 0; }; - void writeBody() override; - void addEntry(FunctionSymbol *Sym); - uint32_t numEntries() const { return IndirectFunctions.size(); } - uint32_t ElemOffset; + ElemSection(uint32_t offset) + : SyntheticSection(llvm::wasm::WASM_SEC_ELEM), elemOffset(offset) {} + bool isNeeded() const override { return indirectFunctions.size() > 0; }; + void writeBody() override; + void addEntry(FunctionSymbol *sym); + uint32_t numEntries() const { return indirectFunctions.size(); } + uint32_t elemOffset; protected: - std::vector IndirectFunctions; + std::vector indirectFunctions; }; class DataCountSection : public SyntheticSection { public: - DataCountSection(uint32_t NumSegments) + DataCountSection(uint32_t numSegments) : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT), - NumSegments(NumSegments) {} + numSegments(numSegments) {} bool isNeeded() const override; void writeBody() override; protected: - uint32_t NumSegments; + 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 &InitFunctions, - const std::vector &DataSegments) + LinkingSection(const std::vector &initFunctions, + const std::vector &dataSegments) : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"), - InitFunctions(InitFunctions), DataSegments(DataSegments) {} + initFunctions(initFunctions), dataSegments(dataSegments) {} bool isNeeded() const override { - return Config->Relocatable || Config->EmitRelocs; + return config->relocatable || config->emitRelocs; } void writeBody() override; - void addToSymtab(Symbol *Sym); + void addToSymtab(Symbol *sym); protected: - std::vector SymtabEntries; - llvm::StringMap SectionSymbolIndices; - const std::vector &InitFunctions; - const std::vector &DataSegments; + std::vector symtabEntries; + llvm::StringMap sectionSymbolIndices; + const std::vector &initFunctions; + const std::vector &dataSegments; }; // Create the custom "name" section containing debug symbol names. @@ -264,7 +264,7 @@ public: NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {} bool isNeeded() const override { - return !Config->StripDebug && !Config->StripAll && numNames() > 0; + return !config->stripDebug && !config->stripAll && numNames() > 0; } void writeBody() override; unsigned numNames() const; @@ -275,18 +275,18 @@ ProducersSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {} bool isNeeded() const override { - return !Config->StripAll && fieldCount() > 0; + return !config->stripAll && fieldCount() > 0; } void writeBody() override; - void addInfo(const llvm::wasm::WasmProducerInfo &Info); + void addInfo(const llvm::wasm::WasmProducerInfo &info); protected: int fieldCount() const { - return int(!Languages.empty()) + int(!Tools.empty()) + int(!SDKs.empty()); + return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty()); } - SmallVector, 8> Languages; - SmallVector, 8> Tools; - SmallVector, 8> SDKs; + SmallVector, 8> languages; + SmallVector, 8> tools; + SmallVector, 8> sDKs; }; class TargetFeaturesSection : public SyntheticSection { @@ -294,44 +294,44 @@ TargetFeaturesSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {} bool isNeeded() const override { - return !Config->StripAll && Features.size() > 0; + return !config->stripAll && features.size() > 0; } void writeBody() override; - llvm::SmallSet Features; + llvm::SmallSet features; }; class RelocSection : public SyntheticSection { public: - RelocSection(StringRef Name, OutputSection *Sec) - : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, Name), Sec(Sec) {} + RelocSection(StringRef name, OutputSection *sec) + : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, name), sec(sec) {} void writeBody() override; - bool isNeeded() const override { return Sec->getNumRelocations() > 0; }; + bool isNeeded() const override { return sec->getNumRelocations() > 0; }; protected: - OutputSection *Sec; + OutputSection *sec; }; // Linker generated output sections struct OutStruct { - DylinkSection *DylinkSec; - TypeSection *TypeSec; - FunctionSection *FunctionSec; - ImportSection *ImportSec; - TableSection *TableSec; - MemorySection *MemorySec; - GlobalSection *GlobalSec; - EventSection *EventSec; - ExportSection *ExportSec; - ElemSection *ElemSec; - DataCountSection *DataCountSec; - LinkingSection *LinkingSec; - NameSection *NameSec; - ProducersSection *ProducersSec; - TargetFeaturesSection *TargetFeaturesSec; + DylinkSection *dylinkSec; + TypeSection *typeSec; + FunctionSection *functionSec; + ImportSection *importSec; + TableSection *tableSec; + MemorySection *memorySec; + GlobalSection *globalSec; + EventSection *eventSec; + ExportSection *exportSec; + ElemSection *elemSec; + DataCountSection *dataCountSec; + LinkingSection *linkingSec; + NameSection *nameSec; + ProducersSection *producersSec; + TargetFeaturesSection *targetFeaturesSec; }; -extern OutStruct Out; +extern OutStruct out; } // namespace wasm } // namespace lld Index: lld/trunk/wasm/SyntheticSections.cpp =================================================================== --- lld/trunk/wasm/SyntheticSections.cpp +++ lld/trunk/wasm/SyntheticSections.cpp @@ -25,7 +25,7 @@ using namespace lld; using namespace lld::wasm; -OutStruct lld::wasm::Out; +OutStruct lld::wasm::out; namespace { @@ -36,512 +36,512 @@ // of the parent section. class SubSection { public: - explicit SubSection(uint32_t Type) : Type(Type) {} + explicit SubSection(uint32_t type) : type(type) {} - void writeTo(raw_ostream &To) { - OS.flush(); - writeUleb128(To, Type, "subsection type"); - writeUleb128(To, Body.size(), "subsection size"); - To.write(Body.data(), Body.size()); + void writeTo(raw_ostream &to) { + os.flush(); + writeUleb128(to, type, "subsection type"); + writeUleb128(to, body.size(), "subsection size"); + to.write(body.data(), body.size()); } private: - uint32_t Type; - std::string Body; + uint32_t type; + std::string body; public: - raw_string_ostream OS{Body}; + raw_string_ostream os{body}; }; } // namespace void DylinkSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, MemSize, "MemSize"); - writeUleb128(OS, MemAlign, "MemAlign"); - writeUleb128(OS, Out.ElemSec->numEntries(), "TableSize"); - writeUleb128(OS, 0, "TableAlign"); - writeUleb128(OS, Symtab->SharedFiles.size(), "Needed"); - for (auto *SO : Symtab->SharedFiles) - writeStr(OS, llvm::sys::path::filename(SO->getName()), "so name"); -} - -uint32_t TypeSection::registerType(const WasmSignature &Sig) { - auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size())); - if (Pair.second) { - LLVM_DEBUG(llvm::dbgs() << "type " << toString(Sig) << "\n"); - Types.push_back(&Sig); - } - return Pair.first->second; -} - -uint32_t TypeSection::lookupType(const WasmSignature &Sig) { - auto It = TypeIndices.find(Sig); - if (It == TypeIndices.end()) { - error("type not found: " + toString(Sig)); + writeUleb128(os, memSize, "MemSize"); + writeUleb128(os, memAlign, "MemAlign"); + writeUleb128(os, out.elemSec->numEntries(), "TableSize"); + writeUleb128(os, 0, "TableAlign"); + writeUleb128(os, symtab->sharedFiles.size(), "Needed"); + for (auto *so : symtab->sharedFiles) + writeStr(os, llvm::sys::path::filename(so->getName()), "so name"); +} + +uint32_t TypeSection::registerType(const WasmSignature &sig) { + auto pair = typeIndices.insert(std::make_pair(sig, types.size())); + if (pair.second) { + LLVM_DEBUG(llvm::dbgs() << "type " << toString(sig) << "\n"); + types.push_back(&sig); + } + return pair.first->second; +} + +uint32_t TypeSection::lookupType(const WasmSignature &sig) { + auto it = typeIndices.find(sig); + if (it == typeIndices.end()) { + error("type not found: " + toString(sig)); return 0; } - return It->second; + return it->second; } void TypeSection::writeBody() { - writeUleb128(BodyOutputStream, Types.size(), "type count"); - for (const WasmSignature *Sig : Types) - writeSig(BodyOutputStream, *Sig); + writeUleb128(bodyOutputStream, types.size(), "type count"); + for (const WasmSignature *sig : types) + writeSig(bodyOutputStream, *sig); } uint32_t ImportSection::getNumImports() const { - assert(IsSealed); - uint32_t NumImports = ImportedSymbols.size() + GOTSymbols.size(); - if (Config->ImportMemory) - ++NumImports; - if (Config->ImportTable) - ++NumImports; - return NumImports; + assert(isSealed); + uint32_t numImports = importedSymbols.size() + gotSymbols.size(); + if (config->importMemory) + ++numImports; + if (config->importTable) + ++numImports; + return numImports; } -void ImportSection::addGOTEntry(Symbol *Sym) { - assert(!IsSealed); - if (Sym->hasGOTIndex()) +void ImportSection::addGOTEntry(Symbol *sym) { + assert(!isSealed); + if (sym->hasGOTIndex()) return; - Sym->setGOTIndex(NumImportedGlobals++); - GOTSymbols.push_back(Sym); + sym->setGOTIndex(numImportedGlobals++); + gotSymbols.push_back(sym); } -void ImportSection::addImport(Symbol *Sym) { - assert(!IsSealed); - ImportedSymbols.emplace_back(Sym); - if (auto *F = dyn_cast(Sym)) - F->setFunctionIndex(NumImportedFunctions++); - else if (auto *G = dyn_cast(Sym)) - G->setGlobalIndex(NumImportedGlobals++); +void ImportSection::addImport(Symbol *sym) { + assert(!isSealed); + importedSymbols.emplace_back(sym); + if (auto *f = dyn_cast(sym)) + f->setFunctionIndex(numImportedFunctions++); + else if (auto *g = dyn_cast(sym)) + g->setGlobalIndex(numImportedGlobals++); else - cast(Sym)->setEventIndex(NumImportedEvents++); + cast(sym)->setEventIndex(numImportedEvents++); } void ImportSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, getNumImports(), "import count"); + writeUleb128(os, getNumImports(), "import count"); - if (Config->ImportMemory) { - WasmImport Import; - Import.Module = DefaultModule; - Import.Field = "memory"; - Import.Kind = WASM_EXTERNAL_MEMORY; - Import.Memory.Flags = 0; - Import.Memory.Initial = Out.MemorySec->NumMemoryPages; - if (Out.MemorySec->MaxMemoryPages != 0 || Config->SharedMemory) { - Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX; - Import.Memory.Maximum = Out.MemorySec->MaxMemoryPages; + if (config->importMemory) { + WasmImport import; + import.Module = defaultModule; + import.Field = "memory"; + import.Kind = WASM_EXTERNAL_MEMORY; + import.Memory.Flags = 0; + import.Memory.Initial = out.memorySec->numMemoryPages; + if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) { + import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX; + import.Memory.Maximum = out.memorySec->maxMemoryPages; } - if (Config->SharedMemory) - Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; - writeImport(OS, Import); - } - - if (Config->ImportTable) { - uint32_t TableSize = Out.ElemSec->ElemOffset + Out.ElemSec->numEntries(); - WasmImport Import; - Import.Module = DefaultModule; - Import.Field = FunctionTableName; - Import.Kind = WASM_EXTERNAL_TABLE; - Import.Table.ElemType = WASM_TYPE_FUNCREF; - Import.Table.Limits = {0, TableSize, 0}; - writeImport(OS, Import); - } - - for (const Symbol *Sym : ImportedSymbols) { - WasmImport Import; - if (auto *F = dyn_cast(Sym)) { - Import.Field = F->ImportName; - Import.Module = F->ImportModule; - } else if (auto *G = dyn_cast(Sym)) { - Import.Field = G->ImportName; - Import.Module = G->ImportModule; + if (config->sharedMemory) + import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; + writeImport(os, import); + } + + if (config->importTable) { + uint32_t tableSize = out.elemSec->elemOffset + out.elemSec->numEntries(); + WasmImport import; + import.Module = defaultModule; + import.Field = functionTableName; + import.Kind = WASM_EXTERNAL_TABLE; + import.Table.ElemType = WASM_TYPE_FUNCREF; + import.Table.Limits = {0, tableSize, 0}; + writeImport(os, import); + } + + for (const Symbol *sym : importedSymbols) { + WasmImport import; + if (auto *f = dyn_cast(sym)) { + import.Field = f->importName; + import.Module = f->importModule; + } else if (auto *g = dyn_cast(sym)) { + import.Field = g->importName; + import.Module = g->importModule; } else { - Import.Field = Sym->getName(); - Import.Module = DefaultModule; + import.Field = sym->getName(); + import.Module = defaultModule; } - if (auto *FunctionSym = dyn_cast(Sym)) { - Import.Kind = WASM_EXTERNAL_FUNCTION; - Import.SigIndex = Out.TypeSec->lookupType(*FunctionSym->Signature); - } else if (auto *GlobalSym = dyn_cast(Sym)) { - Import.Kind = WASM_EXTERNAL_GLOBAL; - Import.Global = *GlobalSym->getGlobalType(); + if (auto *functionSym = dyn_cast(sym)) { + import.Kind = WASM_EXTERNAL_FUNCTION; + import.SigIndex = out.typeSec->lookupType(*functionSym->signature); + } else if (auto *globalSym = dyn_cast(sym)) { + import.Kind = WASM_EXTERNAL_GLOBAL; + import.Global = *globalSym->getGlobalType(); } else { - auto *EventSym = cast(Sym); - Import.Kind = WASM_EXTERNAL_EVENT; - Import.Event.Attribute = EventSym->getEventType()->Attribute; - Import.Event.SigIndex = Out.TypeSec->lookupType(*EventSym->Signature); + auto *eventSym = cast(sym); + import.Kind = WASM_EXTERNAL_EVENT; + import.Event.Attribute = eventSym->getEventType()->Attribute; + import.Event.SigIndex = out.typeSec->lookupType(*eventSym->signature); } - writeImport(OS, Import); + writeImport(os, import); } - for (const Symbol *Sym : GOTSymbols) { - WasmImport Import; - Import.Kind = WASM_EXTERNAL_GLOBAL; - Import.Global = {WASM_TYPE_I32, true}; - if (isa(Sym)) - Import.Module = "GOT.mem"; + for (const Symbol *sym : gotSymbols) { + WasmImport import; + import.Kind = WASM_EXTERNAL_GLOBAL; + import.Global = {WASM_TYPE_I32, true}; + if (isa(sym)) + import.Module = "GOT.mem"; else - Import.Module = "GOT.func"; - Import.Field = Sym->getName(); - writeImport(OS, Import); + import.Module = "GOT.func"; + import.Field = sym->getName(); + writeImport(os, import); } } void FunctionSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, InputFunctions.size(), "function count"); - for (const InputFunction *Func : InputFunctions) - writeUleb128(OS, Out.TypeSec->lookupType(Func->Signature), "sig index"); + writeUleb128(os, inputFunctions.size(), "function count"); + for (const InputFunction *func : inputFunctions) + writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index"); } -void FunctionSection::addFunction(InputFunction *Func) { - if (!Func->Live) +void FunctionSection::addFunction(InputFunction *func) { + if (!func->live) return; - uint32_t FunctionIndex = - Out.ImportSec->getNumImportedFunctions() + InputFunctions.size(); - InputFunctions.emplace_back(Func); - Func->setFunctionIndex(FunctionIndex); + uint32_t functionIndex = + out.importSec->getNumImportedFunctions() + inputFunctions.size(); + inputFunctions.emplace_back(func); + func->setFunctionIndex(functionIndex); } void TableSection::writeBody() { - uint32_t TableSize = Out.ElemSec->ElemOffset + Out.ElemSec->numEntries(); + uint32_t tableSize = out.elemSec->elemOffset + out.elemSec->numEntries(); - raw_ostream &OS = BodyOutputStream; - writeUleb128(OS, 1, "table count"); - WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize}; - writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits}); + raw_ostream &os = bodyOutputStream; + writeUleb128(os, 1, "table count"); + WasmLimits limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize}; + writeTableType(os, WasmTable{WASM_TYPE_FUNCREF, limits}); } void MemorySection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - bool HasMax = MaxMemoryPages != 0 || Config->SharedMemory; - writeUleb128(OS, 1, "memory count"); - unsigned Flags = 0; - if (HasMax) - Flags |= WASM_LIMITS_FLAG_HAS_MAX; - if (Config->SharedMemory) - Flags |= WASM_LIMITS_FLAG_IS_SHARED; - writeUleb128(OS, Flags, "memory limits flags"); - writeUleb128(OS, NumMemoryPages, "initial pages"); - if (HasMax) - writeUleb128(OS, MaxMemoryPages, "max pages"); + bool hasMax = maxMemoryPages != 0 || config->sharedMemory; + writeUleb128(os, 1, "memory count"); + unsigned flags = 0; + if (hasMax) + flags |= WASM_LIMITS_FLAG_HAS_MAX; + if (config->sharedMemory) + flags |= WASM_LIMITS_FLAG_IS_SHARED; + writeUleb128(os, flags, "memory limits flags"); + writeUleb128(os, numMemoryPages, "initial pages"); + if (hasMax) + writeUleb128(os, maxMemoryPages, "max pages"); } void GlobalSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, numGlobals(), "global count"); - for (const InputGlobal *G : InputGlobals) - writeGlobal(OS, G->Global); - for (const DefinedData *Sym : DefinedFakeGlobals) { - WasmGlobal Global; - Global.Type = {WASM_TYPE_I32, false}; - Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; - Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); - writeGlobal(OS, Global); + writeUleb128(os, numGlobals(), "global count"); + for (const InputGlobal *g : inputGlobals) + writeGlobal(os, g->global); + for (const DefinedData *sym : definedFakeGlobals) { + WasmGlobal global; + global.Type = {WASM_TYPE_I32, false}; + global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; + global.InitExpr.Value.Int32 = sym->getVirtualAddress(); + writeGlobal(os, global); } } -void GlobalSection::addGlobal(InputGlobal *Global) { - if (!Global->Live) +void GlobalSection::addGlobal(InputGlobal *global) { + if (!global->live) return; - uint32_t GlobalIndex = - Out.ImportSec->getNumImportedGlobals() + InputGlobals.size(); - LLVM_DEBUG(dbgs() << "addGlobal: " << GlobalIndex << "\n"); - Global->setGlobalIndex(GlobalIndex); - Out.GlobalSec->InputGlobals.push_back(Global); + uint32_t globalIndex = + out.importSec->getNumImportedGlobals() + inputGlobals.size(); + LLVM_DEBUG(dbgs() << "addGlobal: " << globalIndex << "\n"); + global->setGlobalIndex(globalIndex); + out.globalSec->inputGlobals.push_back(global); } void EventSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, InputEvents.size(), "event count"); - for (InputEvent *E : InputEvents) { - E->Event.Type.SigIndex = Out.TypeSec->lookupType(E->Signature); - writeEvent(OS, E->Event); + writeUleb128(os, inputEvents.size(), "event count"); + for (InputEvent *e : inputEvents) { + e->event.Type.SigIndex = out.typeSec->lookupType(e->signature); + writeEvent(os, e->event); } } -void EventSection::addEvent(InputEvent *Event) { - if (!Event->Live) +void EventSection::addEvent(InputEvent *event) { + if (!event->live) return; - uint32_t EventIndex = - Out.ImportSec->getNumImportedEvents() + InputEvents.size(); - LLVM_DEBUG(dbgs() << "addEvent: " << EventIndex << "\n"); - Event->setEventIndex(EventIndex); - InputEvents.push_back(Event); + uint32_t eventIndex = + out.importSec->getNumImportedEvents() + inputEvents.size(); + LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n"); + event->setEventIndex(eventIndex); + inputEvents.push_back(event); } void ExportSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, Exports.size(), "export count"); - for (const WasmExport &Export : Exports) - writeExport(OS, Export); + writeUleb128(os, exports.size(), "export count"); + for (const WasmExport &export_ : exports) + writeExport(os, export_); } -void ElemSection::addEntry(FunctionSymbol *Sym) { - if (Sym->hasTableIndex()) +void ElemSection::addEntry(FunctionSymbol *sym) { + if (sym->hasTableIndex()) return; - Sym->setTableIndex(ElemOffset + IndirectFunctions.size()); - IndirectFunctions.emplace_back(Sym); + sym->setTableIndex(elemOffset + indirectFunctions.size()); + indirectFunctions.emplace_back(sym); } void ElemSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, 1, "segment count"); - writeUleb128(OS, 0, "table index"); - WasmInitExpr InitExpr; - if (Config->Pic) { - InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET; - InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex(); + writeUleb128(os, 1, "segment count"); + writeUleb128(os, 0, "table index"); + WasmInitExpr initExpr; + if (config->isPic) { + initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; + initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex(); } else { - InitExpr.Opcode = WASM_OPCODE_I32_CONST; - InitExpr.Value.Int32 = ElemOffset; + initExpr.Opcode = WASM_OPCODE_I32_CONST; + initExpr.Value.Int32 = elemOffset; } - writeInitExpr(OS, InitExpr); - writeUleb128(OS, IndirectFunctions.size(), "elem count"); + writeInitExpr(os, initExpr); + writeUleb128(os, indirectFunctions.size(), "elem count"); - uint32_t TableIndex = ElemOffset; - for (const FunctionSymbol *Sym : IndirectFunctions) { - assert(Sym->getTableIndex() == TableIndex); - writeUleb128(OS, Sym->getFunctionIndex(), "function index"); - ++TableIndex; + uint32_t tableIndex = elemOffset; + for (const FunctionSymbol *sym : indirectFunctions) { + assert(sym->getTableIndex() == tableIndex); + writeUleb128(os, sym->getFunctionIndex(), "function index"); + ++tableIndex; } } void DataCountSection::writeBody() { - writeUleb128(BodyOutputStream, NumSegments, "data count"); + writeUleb128(bodyOutputStream, numSegments, "data count"); } bool DataCountSection::isNeeded() const { - return NumSegments && Config->PassiveSegments; + return numSegments && config->passiveSegments; } -static uint32_t getWasmFlags(const Symbol *Sym) { - uint32_t Flags = 0; - if (Sym->isLocal()) - Flags |= WASM_SYMBOL_BINDING_LOCAL; - if (Sym->isWeak()) - Flags |= WASM_SYMBOL_BINDING_WEAK; - if (Sym->isHidden()) - Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; - if (Sym->isUndefined()) - Flags |= WASM_SYMBOL_UNDEFINED; - if (auto *F = dyn_cast(Sym)) { - if (F->getName() != F->ImportName) - Flags |= WASM_SYMBOL_EXPLICIT_NAME; - } else if (auto *G = dyn_cast(Sym)) { - if (G->getName() != G->ImportName) - Flags |= WASM_SYMBOL_EXPLICIT_NAME; +static uint32_t getWasmFlags(const Symbol *sym) { + uint32_t flags = 0; + if (sym->isLocal()) + flags |= WASM_SYMBOL_BINDING_LOCAL; + if (sym->isWeak()) + flags |= WASM_SYMBOL_BINDING_WEAK; + if (sym->isHidden()) + flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; + if (sym->isUndefined()) + flags |= WASM_SYMBOL_UNDEFINED; + if (auto *f = dyn_cast(sym)) { + if (f->getName() != f->importName) + flags |= WASM_SYMBOL_EXPLICIT_NAME; + } else if (auto *g = dyn_cast(sym)) { + if (g->getName() != g->importName) + flags |= WASM_SYMBOL_EXPLICIT_NAME; } - return Flags; + return flags; } void LinkingSection::writeBody() { - raw_ostream &OS = BodyOutputStream; + raw_ostream &os = bodyOutputStream; - writeUleb128(OS, WasmMetadataVersion, "Version"); + writeUleb128(os, WasmMetadataVersion, "Version"); - if (!SymtabEntries.empty()) { - SubSection Sub(WASM_SYMBOL_TABLE); - writeUleb128(Sub.OS, SymtabEntries.size(), "num symbols"); - - for (const Symbol *Sym : SymtabEntries) { - assert(Sym->isDefined() || Sym->isUndefined()); - WasmSymbolType Kind = Sym->getWasmType(); - uint32_t Flags = getWasmFlags(Sym); - - writeU8(Sub.OS, Kind, "sym kind"); - writeUleb128(Sub.OS, Flags, "sym flags"); - - if (auto *F = dyn_cast(Sym)) { - writeUleb128(Sub.OS, F->getFunctionIndex(), "index"); - if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) - writeStr(Sub.OS, Sym->getName(), "sym name"); - } else if (auto *G = dyn_cast(Sym)) { - writeUleb128(Sub.OS, G->getGlobalIndex(), "index"); - if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) - writeStr(Sub.OS, Sym->getName(), "sym name"); - } else if (auto *E = dyn_cast(Sym)) { - writeUleb128(Sub.OS, E->getEventIndex(), "index"); - if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) - writeStr(Sub.OS, Sym->getName(), "sym name"); - } else if (isa(Sym)) { - writeStr(Sub.OS, Sym->getName(), "sym name"); - if (auto *DataSym = dyn_cast(Sym)) { - writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index"); - writeUleb128(Sub.OS, DataSym->getOutputSegmentOffset(), + if (!symtabEntries.empty()) { + SubSection sub(WASM_SYMBOL_TABLE); + writeUleb128(sub.os, symtabEntries.size(), "num symbols"); + + for (const Symbol *sym : symtabEntries) { + assert(sym->isDefined() || sym->isUndefined()); + WasmSymbolType kind = sym->getWasmType(); + uint32_t flags = getWasmFlags(sym); + + writeU8(sub.os, kind, "sym kind"); + writeUleb128(sub.os, flags, "sym flags"); + + if (auto *f = dyn_cast(sym)) { + writeUleb128(sub.os, f->getFunctionIndex(), "index"); + if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) + writeStr(sub.os, sym->getName(), "sym name"); + } else if (auto *g = dyn_cast(sym)) { + writeUleb128(sub.os, g->getGlobalIndex(), "index"); + if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) + writeStr(sub.os, sym->getName(), "sym name"); + } else if (auto *e = dyn_cast(sym)) { + writeUleb128(sub.os, e->getEventIndex(), "index"); + if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) + writeStr(sub.os, sym->getName(), "sym name"); + } else if (isa(sym)) { + writeStr(sub.os, sym->getName(), "sym name"); + if (auto *dataSym = dyn_cast(sym)) { + writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index"); + writeUleb128(sub.os, dataSym->getOutputSegmentOffset(), "data offset"); - writeUleb128(Sub.OS, DataSym->getSize(), "data size"); + writeUleb128(sub.os, dataSym->getSize(), "data size"); } } else { - auto *S = cast(Sym); - writeUleb128(Sub.OS, S->Section->SectionIndex, "sym section index"); + auto *s = cast(sym); + writeUleb128(sub.os, s->section->sectionIndex, "sym section index"); } } - Sub.writeTo(OS); + sub.writeTo(os); } - if (DataSegments.size()) { - SubSection Sub(WASM_SEGMENT_INFO); - writeUleb128(Sub.OS, DataSegments.size(), "num data segments"); - for (const OutputSegment *S : DataSegments) { - writeStr(Sub.OS, S->Name, "segment name"); - writeUleb128(Sub.OS, S->Alignment, "alignment"); - writeUleb128(Sub.OS, 0, "flags"); + if (dataSegments.size()) { + SubSection sub(WASM_SEGMENT_INFO); + writeUleb128(sub.os, dataSegments.size(), "num data segments"); + for (const OutputSegment *s : dataSegments) { + writeStr(sub.os, s->name, "segment name"); + writeUleb128(sub.os, s->alignment, "alignment"); + writeUleb128(sub.os, 0, "flags"); } - Sub.writeTo(OS); + sub.writeTo(os); } - if (!InitFunctions.empty()) { - SubSection Sub(WASM_INIT_FUNCS); - writeUleb128(Sub.OS, InitFunctions.size(), "num init functions"); - for (const WasmInitEntry &F : InitFunctions) { - writeUleb128(Sub.OS, F.Priority, "priority"); - writeUleb128(Sub.OS, F.Sym->getOutputSymbolIndex(), "function index"); + if (!initFunctions.empty()) { + SubSection sub(WASM_INIT_FUNCS); + writeUleb128(sub.os, initFunctions.size(), "num init functions"); + for (const WasmInitEntry &f : initFunctions) { + writeUleb128(sub.os, f.priority, "priority"); + writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index"); } - Sub.writeTo(OS); + sub.writeTo(os); } struct ComdatEntry { - unsigned Kind; - uint32_t Index; + unsigned kind; + uint32_t index; }; - std::map> Comdats; + std::map> comdats; - for (const InputFunction *F : Out.FunctionSec->InputFunctions) { - StringRef Comdat = F->getComdatName(); - if (!Comdat.empty()) - Comdats[Comdat].emplace_back( - ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()}); - } - for (uint32_t I = 0; I < DataSegments.size(); ++I) { - const auto &InputSegments = DataSegments[I]->InputSegments; - if (InputSegments.empty()) + for (const InputFunction *f : out.functionSec->inputFunctions) { + StringRef comdat = f->getComdatName(); + if (!comdat.empty()) + comdats[comdat].emplace_back( + ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()}); + } + for (uint32_t i = 0; i < dataSegments.size(); ++i) { + const auto &inputSegments = dataSegments[i]->inputSegments; + if (inputSegments.empty()) continue; - StringRef Comdat = InputSegments[0]->getComdatName(); + StringRef comdat = inputSegments[0]->getComdatName(); #ifndef NDEBUG - for (const InputSegment *IS : InputSegments) - assert(IS->getComdatName() == Comdat); + for (const InputSegment *isec : inputSegments) + assert(isec->getComdatName() == comdat); #endif - if (!Comdat.empty()) - Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I}); + if (!comdat.empty()) + comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i}); } - if (!Comdats.empty()) { - SubSection Sub(WASM_COMDAT_INFO); - writeUleb128(Sub.OS, Comdats.size(), "num comdats"); - for (const auto &C : Comdats) { - writeStr(Sub.OS, C.first, "comdat name"); - writeUleb128(Sub.OS, 0, "comdat flags"); // flags for future use - writeUleb128(Sub.OS, C.second.size(), "num entries"); - for (const ComdatEntry &Entry : C.second) { - writeU8(Sub.OS, Entry.Kind, "entry kind"); - writeUleb128(Sub.OS, Entry.Index, "entry index"); + if (!comdats.empty()) { + SubSection sub(WASM_COMDAT_INFO); + writeUleb128(sub.os, comdats.size(), "num comdats"); + for (const auto &c : comdats) { + writeStr(sub.os, c.first, "comdat name"); + writeUleb128(sub.os, 0, "comdat flags"); // flags for future use + writeUleb128(sub.os, c.second.size(), "num entries"); + for (const ComdatEntry &entry : c.second) { + writeU8(sub.os, entry.kind, "entry kind"); + writeUleb128(sub.os, entry.index, "entry index"); } } - Sub.writeTo(OS); + sub.writeTo(os); } } -void LinkingSection::addToSymtab(Symbol *Sym) { - Sym->setOutputSymbolIndex(SymtabEntries.size()); - SymtabEntries.emplace_back(Sym); +void LinkingSection::addToSymtab(Symbol *sym) { + sym->setOutputSymbolIndex(symtabEntries.size()); + symtabEntries.emplace_back(sym); } unsigned NameSection::numNames() const { - unsigned NumNames = Out.ImportSec->getNumImportedFunctions(); - for (const InputFunction *F : Out.FunctionSec->InputFunctions) - if (!F->getName().empty() || !F->getDebugName().empty()) - ++NumNames; + unsigned numNames = out.importSec->getNumImportedFunctions(); + for (const InputFunction *f : out.functionSec->inputFunctions) + if (!f->getName().empty() || !f->getDebugName().empty()) + ++numNames; - return NumNames; + return numNames; } // Create the custom "name" section containing debug symbol names. void NameSection::writeBody() { - SubSection Sub(WASM_NAMES_FUNCTION); - writeUleb128(Sub.OS, numNames(), "name count"); + SubSection sub(WASM_NAMES_FUNCTION); + writeUleb128(sub.os, numNames(), "name count"); // Names must appear in function index order. As it happens ImportedSymbols // and InputFunctions are numbered in order with imported functions coming // first. - for (const Symbol *S : Out.ImportSec->ImportedSymbols) { - if (auto *F = dyn_cast(S)) { - writeUleb128(Sub.OS, F->getFunctionIndex(), "func index"); - writeStr(Sub.OS, toString(*S), "symbol name"); + for (const Symbol *s : out.importSec->importedSymbols) { + if (auto *f = dyn_cast(s)) { + writeUleb128(sub.os, f->getFunctionIndex(), "func index"); + writeStr(sub.os, toString(*s), "symbol name"); } } - for (const InputFunction *F : Out.FunctionSec->InputFunctions) { - if (!F->getName().empty()) { - writeUleb128(Sub.OS, F->getFunctionIndex(), "func index"); - if (!F->getDebugName().empty()) { - writeStr(Sub.OS, F->getDebugName(), "symbol name"); + for (const InputFunction *f : out.functionSec->inputFunctions) { + if (!f->getName().empty()) { + writeUleb128(sub.os, f->getFunctionIndex(), "func index"); + if (!f->getDebugName().empty()) { + writeStr(sub.os, f->getDebugName(), "symbol name"); } else { - writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name"); + writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name"); } } } - Sub.writeTo(BodyOutputStream); + sub.writeTo(bodyOutputStream); } -void ProducersSection::addInfo(const WasmProducerInfo &Info) { - for (auto &Producers : - {std::make_pair(&Info.Languages, &Languages), - std::make_pair(&Info.Tools, &Tools), std::make_pair(&Info.SDKs, &SDKs)}) - for (auto &Producer : *Producers.first) - if (Producers.second->end() == - llvm::find_if(*Producers.second, - [&](std::pair Seen) { - return Seen.first == Producer.first; +void ProducersSection::addInfo(const WasmProducerInfo &info) { + for (auto &producers : + {std::make_pair(&info.Languages, &languages), + std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)}) + for (auto &producer : *producers.first) + if (producers.second->end() == + llvm::find_if(*producers.second, + [&](std::pair seen) { + return seen.first == producer.first; })) - Producers.second->push_back(Producer); + producers.second->push_back(producer); } void ProducersSection::writeBody() { - auto &OS = BodyOutputStream; - writeUleb128(OS, fieldCount(), "field count"); - for (auto &Field : - {std::make_pair("language", Languages), - std::make_pair("processed-by", Tools), std::make_pair("sdk", SDKs)}) { - if (Field.second.empty()) + auto &os = bodyOutputStream; + writeUleb128(os, fieldCount(), "field count"); + for (auto &field : + {std::make_pair("language", languages), + std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) { + if (field.second.empty()) continue; - writeStr(OS, Field.first, "field name"); - writeUleb128(OS, Field.second.size(), "number of entries"); - for (auto &Entry : Field.second) { - writeStr(OS, Entry.first, "producer name"); - writeStr(OS, Entry.second, "producer version"); + writeStr(os, field.first, "field name"); + writeUleb128(os, field.second.size(), "number of entries"); + for (auto &entry : field.second) { + writeStr(os, entry.first, "producer name"); + writeStr(os, entry.second, "producer version"); } } } void TargetFeaturesSection::writeBody() { - SmallVector Emitted(Features.begin(), Features.end()); - llvm::sort(Emitted); - auto &OS = BodyOutputStream; - writeUleb128(OS, Emitted.size(), "feature count"); - for (auto &Feature : Emitted) { - writeU8(OS, WASM_FEATURE_PREFIX_USED, "feature used prefix"); - writeStr(OS, Feature, "feature name"); + SmallVector emitted(features.begin(), features.end()); + llvm::sort(emitted); + auto &os = bodyOutputStream; + writeUleb128(os, emitted.size(), "feature count"); + for (auto &feature : emitted) { + writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix"); + writeStr(os, feature, "feature name"); } } void RelocSection::writeBody() { - uint32_t Count = Sec->getNumRelocations(); - assert(Sec->SectionIndex != UINT32_MAX); - writeUleb128(BodyOutputStream, Sec->SectionIndex, "reloc section"); - writeUleb128(BodyOutputStream, Count, "reloc count"); - Sec->writeRelocations(BodyOutputStream); + uint32_t count = sec->getNumRelocations(); + assert(sec->sectionIndex != UINT32_MAX); + writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section"); + writeUleb128(bodyOutputStream, count, "reloc count"); + sec->writeRelocations(bodyOutputStream); } Index: lld/trunk/wasm/Writer.cpp =================================================================== --- lld/trunk/wasm/Writer.cpp +++ lld/trunk/wasm/Writer.cpp @@ -42,7 +42,7 @@ using namespace lld; using namespace lld::wasm; -static constexpr int StackAlignment = 16; +static constexpr int stackAlignment = 16; namespace { @@ -71,7 +71,7 @@ void layoutMemory(); void createHeader(); - void addSection(OutputSection *Sec); + void addSection(OutputSection *sec); void addSections(); @@ -85,56 +85,56 @@ void writeHeader(); void writeSections(); - uint64_t FileSize = 0; - uint32_t TableBase = 0; + uint64_t fileSize = 0; + uint32_t tableBase = 0; - std::vector InitFunctions; - llvm::StringMap> CustomSectionMapping; + std::vector initFunctions; + llvm::StringMap> customSectionMapping; // Elements that are used to construct the final output - std::string Header; - std::vector OutputSections; + std::string header; + std::vector outputSections; - std::unique_ptr Buffer; + std::unique_ptr buffer; - std::vector Segments; - llvm::SmallDenseMap SegmentMap; + std::vector segments; + llvm::SmallDenseMap segmentMap; }; } // anonymous namespace void Writer::calculateCustomSections() { log("calculateCustomSections"); - bool StripDebug = Config->StripDebug || Config->StripAll; - for (ObjFile *File : Symtab->ObjectFiles) { - for (InputSection *Section : File->CustomSections) { - StringRef Name = Section->getName(); + bool stripDebug = config->stripDebug || config->stripAll; + for (ObjFile *file : symtab->objectFiles) { + for (InputSection *section : file->customSections) { + StringRef name = section->getName(); // These custom sections are known the linker and synthesized rather than // blindly copied - if (Name == "linking" || Name == "name" || Name == "producers" || - Name == "target_features" || Name.startswith("reloc.")) + if (name == "linking" || name == "name" || name == "producers" || + name == "target_features" || name.startswith("reloc.")) continue; // .. or it is a debug section - if (StripDebug && Name.startswith(".debug_")) + if (stripDebug && name.startswith(".debug_")) continue; - CustomSectionMapping[Name].push_back(Section); + customSectionMapping[name].push_back(section); } } } void Writer::createCustomSections() { log("createCustomSections"); - for (auto &Pair : CustomSectionMapping) { - StringRef Name = Pair.first(); - LLVM_DEBUG(dbgs() << "createCustomSection: " << Name << "\n"); - - OutputSection *Sec = make(Name, Pair.second); - if (Config->Relocatable || Config->EmitRelocs) { - auto *Sym = make(Sec); - Out.LinkingSec->addToSymtab(Sym); - Sec->SectionSym = Sym; + for (auto &pair : customSectionMapping) { + StringRef name = pair.first(); + LLVM_DEBUG(dbgs() << "createCustomSection: " << name << "\n"); + + OutputSection *sec = make(name, pair.second); + if (config->relocatable || config->emitRelocs) { + auto *sym = make(sec); + out.linkingSec->addToSymtab(sym); + sec->sectionSym = sym; } - addSection(Sec); + addSection(sec); } } @@ -143,47 +143,47 @@ void Writer::createRelocSections() { log("createRelocSections"); // Don't use iterator here since we are adding to OutputSection - size_t OrigSize = OutputSections.size(); - for (size_t I = 0; I < OrigSize; I++) { - LLVM_DEBUG(dbgs() << "check section " << I << "\n"); - OutputSection *Sec = OutputSections[I]; + size_t origSize = outputSections.size(); + for (size_t i = 0; i < origSize; i++) { + LLVM_DEBUG(dbgs() << "check section " << i << "\n"); + OutputSection *sec = outputSections[i]; // Count the number of needed sections. - uint32_t Count = Sec->getNumRelocations(); - if (!Count) + uint32_t count = sec->getNumRelocations(); + if (!count) continue; - StringRef Name; - if (Sec->Type == WASM_SEC_DATA) - Name = "reloc.DATA"; - else if (Sec->Type == WASM_SEC_CODE) - Name = "reloc.CODE"; - else if (Sec->Type == WASM_SEC_CUSTOM) - Name = Saver.save("reloc." + Sec->Name); + StringRef name; + if (sec->type == WASM_SEC_DATA) + name = "reloc.DATA"; + else if (sec->type == WASM_SEC_CODE) + name = "reloc.CODE"; + else if (sec->type == WASM_SEC_CUSTOM) + name = saver.save("reloc." + sec->name); else llvm_unreachable( "relocations only supported for code, data, or custom sections"); - addSection(make(Name, Sec)); + addSection(make(name, sec)); } } void Writer::populateProducers() { - for (ObjFile *File : Symtab->ObjectFiles) { - const WasmProducerInfo &Info = File->getWasmObj()->getProducerInfo(); - Out.ProducersSec->addInfo(Info); + for (ObjFile *file : symtab->objectFiles) { + const WasmProducerInfo &info = file->getWasmObj()->getProducerInfo(); + out.producersSec->addInfo(info); } } void Writer::writeHeader() { - memcpy(Buffer->getBufferStart(), Header.data(), Header.size()); + memcpy(buffer->getBufferStart(), header.data(), header.size()); } void Writer::writeSections() { - uint8_t *Buf = Buffer->getBufferStart(); - parallelForEach(OutputSections, [Buf](OutputSection *S) { - assert(S->isNeeded()); - S->writeTo(Buf); + uint8_t *buf = buffer->getBufferStart(); + parallelForEach(outputSections, [buf](OutputSection *s) { + assert(s->isNeeded()); + s->writeTo(buf); }); } @@ -201,100 +201,100 @@ // rather than overwriting global data, but also increases code size since all // static data loads and stores requires larger offsets. void Writer::layoutMemory() { - uint32_t MemoryPtr = 0; + uint32_t memoryPtr = 0; - auto PlaceStack = [&]() { - if (Config->Relocatable || Config->Shared) + auto placeStack = [&]() { + if (config->relocatable || config->shared) return; - MemoryPtr = alignTo(MemoryPtr, StackAlignment); - if (Config->ZStackSize != alignTo(Config->ZStackSize, StackAlignment)) - error("stack size must be " + Twine(StackAlignment) + "-byte aligned"); - log("mem: stack size = " + Twine(Config->ZStackSize)); - log("mem: stack base = " + Twine(MemoryPtr)); - MemoryPtr += Config->ZStackSize; - auto *SP = cast(WasmSym::StackPointer); - SP->Global->Global.InitExpr.Value.Int32 = MemoryPtr; - log("mem: stack top = " + Twine(MemoryPtr)); + memoryPtr = alignTo(memoryPtr, stackAlignment); + if (config->zStackSize != alignTo(config->zStackSize, stackAlignment)) + error("stack size must be " + Twine(stackAlignment) + "-byte aligned"); + log("mem: stack size = " + Twine(config->zStackSize)); + log("mem: stack base = " + Twine(memoryPtr)); + memoryPtr += config->zStackSize; + auto *sp = cast(WasmSym::stackPointer); + sp->global->global.InitExpr.Value.Int32 = memoryPtr; + log("mem: stack top = " + Twine(memoryPtr)); }; - if (Config->StackFirst) { - PlaceStack(); + if (config->stackFirst) { + placeStack(); } else { - MemoryPtr = Config->GlobalBase; - log("mem: global base = " + Twine(Config->GlobalBase)); + memoryPtr = config->globalBase; + log("mem: global base = " + Twine(config->globalBase)); } - if (WasmSym::GlobalBase) - WasmSym::GlobalBase->setVirtualAddress(Config->GlobalBase); + if (WasmSym::globalBase) + WasmSym::globalBase->setVirtualAddress(config->globalBase); - uint32_t DataStart = MemoryPtr; + uint32_t dataStart = memoryPtr; // Arbitrarily set __dso_handle handle to point to the start of the data // segments. - if (WasmSym::DsoHandle) - WasmSym::DsoHandle->setVirtualAddress(DataStart); + if (WasmSym::dsoHandle) + WasmSym::dsoHandle->setVirtualAddress(dataStart); - Out.DylinkSec->MemAlign = 0; - for (OutputSegment *Seg : Segments) { - Out.DylinkSec->MemAlign = std::max(Out.DylinkSec->MemAlign, Seg->Alignment); - MemoryPtr = alignTo(MemoryPtr, 1ULL << Seg->Alignment); - Seg->StartVA = MemoryPtr; - log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name, - MemoryPtr, Seg->Size, Seg->Alignment)); - MemoryPtr += Seg->Size; + out.dylinkSec->memAlign = 0; + for (OutputSegment *seg : segments) { + out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment); + memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment); + seg->startVA = memoryPtr; + log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name, + memoryPtr, seg->size, seg->alignment)); + memoryPtr += seg->size; } // TODO: Add .bss space here. - if (WasmSym::DataEnd) - WasmSym::DataEnd->setVirtualAddress(MemoryPtr); + if (WasmSym::dataEnd) + WasmSym::dataEnd->setVirtualAddress(memoryPtr); - log("mem: static data = " + Twine(MemoryPtr - DataStart)); + log("mem: static data = " + Twine(memoryPtr - dataStart)); - if (Config->Shared) { - Out.DylinkSec->MemSize = MemoryPtr; + if (config->shared) { + out.dylinkSec->memSize = memoryPtr; return; } - if (!Config->StackFirst) - PlaceStack(); + if (!config->stackFirst) + placeStack(); // Set `__heap_base` to directly follow the end of the stack or global data. // The fact that this comes last means that a malloc/brk implementation // can grow the heap at runtime. - log("mem: heap base = " + Twine(MemoryPtr)); - if (WasmSym::HeapBase) - WasmSym::HeapBase->setVirtualAddress(MemoryPtr); + log("mem: heap base = " + Twine(memoryPtr)); + if (WasmSym::heapBase) + WasmSym::heapBase->setVirtualAddress(memoryPtr); - if (Config->InitialMemory != 0) { - if (Config->InitialMemory != alignTo(Config->InitialMemory, WasmPageSize)) + if (config->initialMemory != 0) { + if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize)) error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned"); - if (MemoryPtr > Config->InitialMemory) - error("initial memory too small, " + Twine(MemoryPtr) + " bytes needed"); + if (memoryPtr > config->initialMemory) + error("initial memory too small, " + Twine(memoryPtr) + " bytes needed"); else - MemoryPtr = Config->InitialMemory; + memoryPtr = config->initialMemory; } - Out.DylinkSec->MemSize = MemoryPtr; - Out.MemorySec->NumMemoryPages = - alignTo(MemoryPtr, WasmPageSize) / WasmPageSize; - log("mem: total pages = " + Twine(Out.MemorySec->NumMemoryPages)); + out.dylinkSec->memSize = memoryPtr; + out.memorySec->numMemoryPages = + alignTo(memoryPtr, WasmPageSize) / WasmPageSize; + log("mem: total pages = " + Twine(out.memorySec->numMemoryPages)); // Check max if explicitly supplied or required by shared memory - if (Config->MaxMemory != 0 || Config->SharedMemory) { - if (Config->MaxMemory != alignTo(Config->MaxMemory, WasmPageSize)) + if (config->maxMemory != 0 || config->sharedMemory) { + if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize)) error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); - if (MemoryPtr > Config->MaxMemory) - error("maximum memory too small, " + Twine(MemoryPtr) + " bytes needed"); - Out.MemorySec->MaxMemoryPages = Config->MaxMemory / WasmPageSize; - log("mem: max pages = " + Twine(Out.MemorySec->MaxMemoryPages)); + if (memoryPtr > config->maxMemory) + error("maximum memory too small, " + Twine(memoryPtr) + " bytes needed"); + out.memorySec->maxMemoryPages = config->maxMemory / WasmPageSize; + log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages)); } } -void Writer::addSection(OutputSection *Sec) { - if (!Sec->isNeeded()) +void Writer::addSection(OutputSection *sec) { + if (!sec->isNeeded()) return; - log("addSection: " + toString(*Sec)); - Sec->SectionIndex = OutputSections.size(); - OutputSections.push_back(Sec); + log("addSection: " + toString(*sec)); + sec->sectionIndex = outputSections.size(); + outputSections.push_back(sec); } // If a section name is valid as a C identifier (which is rare because of @@ -302,227 +302,227 @@ // __stop_ symbols. They are at beginning and end of the section, // respectively. This is not requested by the ELF standard, but GNU ld and // gold provide the feature, and used by many programs. -static void addStartStopSymbols(const OutputSegment *Seg) { - StringRef Name = Seg->Name; - if (!isValidCIdentifier(Name)) +static void addStartStopSymbols(const OutputSegment *seg) { + StringRef name = seg->name; + if (!isValidCIdentifier(name)) return; - LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << Name << "\n"); - uint32_t Start = Seg->StartVA; - uint32_t Stop = Start + Seg->Size; - Symtab->addOptionalDataSymbol(Saver.save("__start_" + Name), Start); - Symtab->addOptionalDataSymbol(Saver.save("__stop_" + Name), Stop); + LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n"); + uint32_t start = seg->startVA; + uint32_t stop = start + seg->size; + symtab->addOptionalDataSymbol(saver.save("__start_" + name), start); + symtab->addOptionalDataSymbol(saver.save("__stop_" + name), stop); } void Writer::addSections() { - addSection(Out.DylinkSec); - addSection(Out.TypeSec); - addSection(Out.ImportSec); - addSection(Out.FunctionSec); - addSection(Out.TableSec); - addSection(Out.MemorySec); - addSection(Out.GlobalSec); - addSection(Out.EventSec); - addSection(Out.ExportSec); - addSection(Out.ElemSec); - addSection(Out.DataCountSec); + addSection(out.dylinkSec); + addSection(out.typeSec); + addSection(out.importSec); + addSection(out.functionSec); + addSection(out.tableSec); + addSection(out.memorySec); + addSection(out.globalSec); + addSection(out.eventSec); + addSection(out.exportSec); + addSection(out.elemSec); + addSection(out.dataCountSec); - addSection(make(Out.FunctionSec->InputFunctions)); - addSection(make(Segments)); + addSection(make(out.functionSec->inputFunctions)); + addSection(make(segments)); createCustomSections(); - addSection(Out.LinkingSec); - if (Config->EmitRelocs || Config->Relocatable) { + addSection(out.linkingSec); + if (config->emitRelocs || config->relocatable) { createRelocSections(); } - addSection(Out.NameSec); - addSection(Out.ProducersSec); - addSection(Out.TargetFeaturesSec); + addSection(out.nameSec); + addSection(out.producersSec); + addSection(out.targetFeaturesSec); } void Writer::finalizeSections() { - for (OutputSection *S : OutputSections) { - S->setOffset(FileSize); - S->finalizeContents(); - FileSize += S->getSize(); + for (OutputSection *s : outputSections) { + s->setOffset(fileSize); + s->finalizeContents(); + fileSize += s->getSize(); } } void Writer::populateTargetFeatures() { - StringMap Used; - StringMap Required; - StringMap Disallowed; + StringMap used; + StringMap required; + StringMap disallowed; // Only infer used features if user did not specify features - bool InferFeatures = !Config->Features.hasValue(); + bool inferFeatures = !config->features.hasValue(); - if (!InferFeatures) { - for (auto &Feature : Config->Features.getValue()) - Out.TargetFeaturesSec->Features.insert(Feature); + if (!inferFeatures) { + for (auto &feature : config->features.getValue()) + out.targetFeaturesSec->features.insert(feature); // No need to read or check features - if (!Config->CheckFeatures) + if (!config->checkFeatures) return; } // Find the sets of used, required, and disallowed features - for (ObjFile *File : Symtab->ObjectFiles) { - StringRef FileName(File->getName()); - for (auto &Feature : File->getWasmObj()->getTargetFeatures()) { - switch (Feature.Prefix) { + for (ObjFile *file : symtab->objectFiles) { + StringRef fileName(file->getName()); + for (auto &feature : file->getWasmObj()->getTargetFeatures()) { + switch (feature.Prefix) { case WASM_FEATURE_PREFIX_USED: - Used.insert({Feature.Name, FileName}); + used.insert({feature.Name, fileName}); break; case WASM_FEATURE_PREFIX_REQUIRED: - Used.insert({Feature.Name, FileName}); - Required.insert({Feature.Name, FileName}); + used.insert({feature.Name, fileName}); + required.insert({feature.Name, fileName}); break; case WASM_FEATURE_PREFIX_DISALLOWED: - Disallowed.insert({Feature.Name, FileName}); + disallowed.insert({feature.Name, fileName}); break; default: error("Unrecognized feature policy prefix " + - std::to_string(Feature.Prefix)); + std::to_string(feature.Prefix)); } } } - if (InferFeatures) - Out.TargetFeaturesSec->Features.insert(Used.keys().begin(), - Used.keys().end()); - - if (Out.TargetFeaturesSec->Features.count("atomics") && - !Config->SharedMemory) { - if (InferFeatures) - error(Twine("'atomics' feature is used by ") + Used["atomics"] + + if (inferFeatures) + out.targetFeaturesSec->features.insert(used.keys().begin(), + used.keys().end()); + + if (out.targetFeaturesSec->features.count("atomics") && + !config->sharedMemory) { + if (inferFeatures) + error(Twine("'atomics' feature is used by ") + used["atomics"] + ", so --shared-memory must be used"); else error("'atomics' feature is used, so --shared-memory must be used"); } - if (!Config->CheckFeatures) + if (!config->checkFeatures) return; - if (Disallowed.count("atomics") && Config->SharedMemory) - error("'atomics' feature is disallowed by " + Disallowed["atomics"] + + if (disallowed.count("atomics") && config->sharedMemory) + error("'atomics' feature is disallowed by " + disallowed["atomics"] + ", so --shared-memory must not be used"); - if (!Used.count("bulk-memory") && Config->PassiveSegments) + if (!used.count("bulk-memory") && config->passiveSegments) error("'bulk-memory' feature must be used in order to emit passive " "segments"); // Validate that used features are allowed in output - if (!InferFeatures) { - for (auto &Feature : Used.keys()) { - if (!Out.TargetFeaturesSec->Features.count(Feature)) - error(Twine("Target feature '") + Feature + "' used by " + - Used[Feature] + " is not allowed."); + if (!inferFeatures) { + for (auto &feature : used.keys()) { + if (!out.targetFeaturesSec->features.count(feature)) + error(Twine("Target feature '") + feature + "' used by " + + used[feature] + " is not allowed."); } } // Validate the required and disallowed constraints for each file - for (ObjFile *File : Symtab->ObjectFiles) { - StringRef FileName(File->getName()); - SmallSet ObjectFeatures; - for (auto &Feature : File->getWasmObj()->getTargetFeatures()) { - if (Feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED) + for (ObjFile *file : symtab->objectFiles) { + StringRef fileName(file->getName()); + SmallSet objectFeatures; + for (auto &feature : file->getWasmObj()->getTargetFeatures()) { + if (feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED) continue; - ObjectFeatures.insert(Feature.Name); - if (Disallowed.count(Feature.Name)) - error(Twine("Target feature '") + Feature.Name + "' used in " + - FileName + " is disallowed by " + Disallowed[Feature.Name] + + objectFeatures.insert(feature.Name); + if (disallowed.count(feature.Name)) + error(Twine("Target feature '") + feature.Name + "' used in " + + fileName + " is disallowed by " + disallowed[feature.Name] + ". Use --no-check-features to suppress."); } - for (auto &Feature : Required.keys()) { - if (!ObjectFeatures.count(Feature)) - error(Twine("Missing target feature '") + Feature + "' in " + FileName + - ", required by " + Required[Feature] + + for (auto &feature : required.keys()) { + if (!objectFeatures.count(feature)) + error(Twine("Missing target feature '") + feature + "' in " + fileName + + ", required by " + required[feature] + ". Use --no-check-features to suppress."); } } } void Writer::calculateImports() { - for (Symbol *Sym : Symtab->getSymbols()) { - if (!Sym->isUndefined()) + for (Symbol *sym : symtab->getSymbols()) { + if (!sym->isUndefined()) continue; - if (Sym->isWeak() && !Config->Relocatable) + if (sym->isWeak() && !config->relocatable) continue; - if (!Sym->isLive()) + if (!sym->isLive()) continue; - if (!Sym->IsUsedInRegularObj) + if (!sym->isUsedInRegularObj) continue; // We don't generate imports for data symbols. They however can be imported // as GOT entries. - if (isa(Sym)) + if (isa(sym)) continue; - LLVM_DEBUG(dbgs() << "import: " << Sym->getName() << "\n"); - Out.ImportSec->addImport(Sym); + LLVM_DEBUG(dbgs() << "import: " << sym->getName() << "\n"); + out.importSec->addImport(sym); } } void Writer::calculateExports() { - if (Config->Relocatable) + if (config->relocatable) return; - if (!Config->Relocatable && !Config->ImportMemory) - Out.ExportSec->Exports.push_back( + if (!config->relocatable && !config->importMemory) + out.exportSec->exports.push_back( WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0}); - if (!Config->Relocatable && Config->ExportTable) - Out.ExportSec->Exports.push_back( - WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0}); + if (!config->relocatable && config->exportTable) + out.exportSec->exports.push_back( + WasmExport{functionTableName, WASM_EXTERNAL_TABLE, 0}); - unsigned FakeGlobalIndex = Out.ImportSec->getNumImportedGlobals() + - Out.GlobalSec->InputGlobals.size(); + unsigned fakeGlobalIndex = out.importSec->getNumImportedGlobals() + + out.globalSec->inputGlobals.size(); - for (Symbol *Sym : Symtab->getSymbols()) { - if (!Sym->isExported()) + for (Symbol *sym : symtab->getSymbols()) { + if (!sym->isExported()) continue; - if (!Sym->isLive()) + if (!sym->isLive()) continue; - StringRef Name = Sym->getName(); - WasmExport Export; - if (auto *F = dyn_cast(Sym)) { - Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()}; - } else if (auto *G = dyn_cast(Sym)) { + StringRef name = sym->getName(); + WasmExport export_; + if (auto *f = dyn_cast(sym)) { + export_ = {name, WASM_EXTERNAL_FUNCTION, f->getFunctionIndex()}; + } else if (auto *g = dyn_cast(sym)) { // TODO(sbc): Remove this check once to mutable global proposal is // implement in all major browsers. // See: https://github.com/WebAssembly/mutable-global - if (G->getGlobalType()->Mutable) { + if (g->getGlobalType()->Mutable) { // Only the __stack_pointer should ever be create as mutable. - assert(G == WasmSym::StackPointer); + assert(g == WasmSym::stackPointer); continue; } - Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()}; - } else if (auto *E = dyn_cast(Sym)) { - Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()}; + export_ = {name, WASM_EXTERNAL_GLOBAL, g->getGlobalIndex()}; + } else if (auto *e = dyn_cast(sym)) { + export_ = {name, WASM_EXTERNAL_EVENT, e->getEventIndex()}; } else { - auto *D = cast(Sym); - Out.GlobalSec->DefinedFakeGlobals.emplace_back(D); - Export = {Name, WASM_EXTERNAL_GLOBAL, FakeGlobalIndex++}; + auto *d = cast(sym); + out.globalSec->definedFakeGlobals.emplace_back(d); + export_ = {name, WASM_EXTERNAL_GLOBAL, fakeGlobalIndex++}; } - LLVM_DEBUG(dbgs() << "Export: " << Name << "\n"); - Out.ExportSec->Exports.push_back(Export); + LLVM_DEBUG(dbgs() << "Export: " << name << "\n"); + out.exportSec->exports.push_back(export_); } } void Writer::populateSymtab() { - if (!Config->Relocatable && !Config->EmitRelocs) + if (!config->relocatable && !config->emitRelocs) return; - for (Symbol *Sym : Symtab->getSymbols()) - if (Sym->IsUsedInRegularObj && Sym->isLive()) - Out.LinkingSec->addToSymtab(Sym); - - for (ObjFile *File : Symtab->ObjectFiles) { - LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n"); - for (Symbol *Sym : File->getSymbols()) - if (Sym->isLocal() && !isa(Sym) && Sym->isLive()) - Out.LinkingSec->addToSymtab(Sym); + for (Symbol *sym : symtab->getSymbols()) + if (sym->isUsedInRegularObj && sym->isLive()) + out.linkingSec->addToSymtab(sym); + + for (ObjFile *file : symtab->objectFiles) { + LLVM_DEBUG(dbgs() << "Local symtab entries: " << file->getName() << "\n"); + for (Symbol *sym : file->getSymbols()) + if (sym->isLocal() && !isa(sym) && sym->isLive()) + out.linkingSec->addToSymtab(sym); } } @@ -534,152 +534,152 @@ // 4. The signatures of all imported events // 5. The signatures of all defined events - for (ObjFile *File : Symtab->ObjectFiles) { - ArrayRef Types = File->getWasmObj()->types(); - for (uint32_t I = 0; I < Types.size(); I++) - if (File->TypeIsUsed[I]) - File->TypeMap[I] = Out.TypeSec->registerType(Types[I]); + for (ObjFile *file : symtab->objectFiles) { + ArrayRef types = file->getWasmObj()->types(); + for (uint32_t i = 0; i < types.size(); i++) + if (file->typeIsUsed[i]) + file->typeMap[i] = out.typeSec->registerType(types[i]); } - for (const Symbol *Sym : Out.ImportSec->ImportedSymbols) { - if (auto *F = dyn_cast(Sym)) - Out.TypeSec->registerType(*F->Signature); - else if (auto *E = dyn_cast(Sym)) - Out.TypeSec->registerType(*E->Signature); + for (const Symbol *sym : out.importSec->importedSymbols) { + if (auto *f = dyn_cast(sym)) + out.typeSec->registerType(*f->signature); + else if (auto *e = dyn_cast(sym)) + out.typeSec->registerType(*e->signature); } - for (const InputFunction *F : Out.FunctionSec->InputFunctions) - Out.TypeSec->registerType(F->Signature); + for (const InputFunction *f : out.functionSec->inputFunctions) + out.typeSec->registerType(f->signature); - for (const InputEvent *E : Out.EventSec->InputEvents) - Out.TypeSec->registerType(E->Signature); + for (const InputEvent *e : out.eventSec->inputEvents) + out.typeSec->registerType(e->signature); } static void scanRelocations() { - for (ObjFile *File : Symtab->ObjectFiles) { - LLVM_DEBUG(dbgs() << "scanRelocations: " << File->getName() << "\n"); - for (InputChunk *Chunk : File->Functions) - scanRelocations(Chunk); - for (InputChunk *Chunk : File->Segments) - scanRelocations(Chunk); - for (auto &P : File->CustomSections) - scanRelocations(P); + for (ObjFile *file : symtab->objectFiles) { + LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n"); + for (InputChunk *chunk : file->functions) + scanRelocations(chunk); + for (InputChunk *chunk : file->segments) + scanRelocations(chunk); + for (auto &p : file->customSections) + scanRelocations(p); } } void Writer::assignIndexes() { // Seal the import section, since other index spaces such as function and // global are effected by the number of imports. - Out.ImportSec->seal(); + out.importSec->seal(); - for (InputFunction *Func : Symtab->SyntheticFunctions) - Out.FunctionSec->addFunction(Func); + for (InputFunction *func : symtab->syntheticFunctions) + out.functionSec->addFunction(func); - for (ObjFile *File : Symtab->ObjectFiles) { - LLVM_DEBUG(dbgs() << "Functions: " << File->getName() << "\n"); - for (InputFunction *Func : File->Functions) - Out.FunctionSec->addFunction(Func); + for (ObjFile *file : symtab->objectFiles) { + LLVM_DEBUG(dbgs() << "Functions: " << file->getName() << "\n"); + for (InputFunction *func : file->functions) + out.functionSec->addFunction(func); } - for (InputGlobal *Global : Symtab->SyntheticGlobals) - Out.GlobalSec->addGlobal(Global); + for (InputGlobal *global : symtab->syntheticGlobals) + out.globalSec->addGlobal(global); - for (ObjFile *File : Symtab->ObjectFiles) { - LLVM_DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); - for (InputGlobal *Global : File->Globals) - Out.GlobalSec->addGlobal(Global); + for (ObjFile *file : symtab->objectFiles) { + LLVM_DEBUG(dbgs() << "Globals: " << file->getName() << "\n"); + for (InputGlobal *global : file->globals) + out.globalSec->addGlobal(global); } - for (ObjFile *File : Symtab->ObjectFiles) { - LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n"); - for (InputEvent *Event : File->Events) - Out.EventSec->addEvent(Event); + for (ObjFile *file : symtab->objectFiles) { + LLVM_DEBUG(dbgs() << "Events: " << file->getName() << "\n"); + for (InputEvent *event : file->events) + out.eventSec->addEvent(event); } } -static StringRef getOutputDataSegmentName(StringRef Name) { +static StringRef getOutputDataSegmentName(StringRef name) { // With PIC code we currently only support a single data segment since // we only have a single __memory_base to use as our base address. - if (Config->Pic) + if (config->isPic) return ".data"; - if (!Config->MergeDataSegments) - return Name; - if (Name.startswith(".text.")) + if (!config->mergeDataSegments) + return name; + if (name.startswith(".text.")) return ".text"; - if (Name.startswith(".data.")) + if (name.startswith(".data.")) return ".data"; - if (Name.startswith(".bss.")) + if (name.startswith(".bss.")) return ".bss"; - if (Name.startswith(".rodata.")) + if (name.startswith(".rodata.")) return ".rodata"; - return Name; + return name; } void Writer::createOutputSegments() { - for (ObjFile *File : Symtab->ObjectFiles) { - for (InputSegment *Segment : File->Segments) { - if (!Segment->Live) + for (ObjFile *file : symtab->objectFiles) { + for (InputSegment *segment : file->segments) { + if (!segment->live) continue; - StringRef Name = getOutputDataSegmentName(Segment->getName()); - OutputSegment *&S = SegmentMap[Name]; - if (S == nullptr) { - LLVM_DEBUG(dbgs() << "new segment: " << Name << "\n"); - S = make(Name, Segments.size()); - if (Config->PassiveSegments) - S->InitFlags = WASM_SEGMENT_IS_PASSIVE; - Segments.push_back(S); + StringRef name = getOutputDataSegmentName(segment->getName()); + OutputSegment *&s = segmentMap[name]; + if (s == nullptr) { + LLVM_DEBUG(dbgs() << "new segment: " << name << "\n"); + s = make(name, segments.size()); + if (config->passiveSegments) + s->initFlags = WASM_SEGMENT_IS_PASSIVE; + segments.push_back(s); } - S->addInputSegment(Segment); - LLVM_DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n"); + s->addInputSegment(segment); + LLVM_DEBUG(dbgs() << "added data: " << name << ": " << s->size << "\n"); } } } -static void createFunction(DefinedFunction *Func, StringRef BodyContent) { - std::string FunctionBody; +static void createFunction(DefinedFunction *func, StringRef bodyContent) { + std::string functionBody; { - raw_string_ostream OS(FunctionBody); - writeUleb128(OS, BodyContent.size(), "function size"); - OS << BodyContent; + raw_string_ostream os(functionBody); + writeUleb128(os, bodyContent.size(), "function size"); + os << bodyContent; } - ArrayRef Body = arrayRefFromStringRef(Saver.save(FunctionBody)); - cast(Func->Function)->setBody(Body); + ArrayRef body = arrayRefFromStringRef(saver.save(functionBody)); + cast(func->function)->setBody(body); } void Writer::createInitMemoryFunction() { LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n"); - std::string BodyContent; + std::string bodyContent; { - raw_string_ostream OS(BodyContent); - writeUleb128(OS, 0, "num locals"); + raw_string_ostream os(bodyContent); + writeUleb128(os, 0, "num locals"); // initialize passive data segments - for (const OutputSegment *S : Segments) { - if (S->InitFlags & WASM_SEGMENT_IS_PASSIVE) { + for (const OutputSegment *s : segments) { + if (s->initFlags & WASM_SEGMENT_IS_PASSIVE) { // destination address - writeU8(OS, WASM_OPCODE_I32_CONST, "i32.const"); - writeUleb128(OS, S->StartVA, "destination address"); + writeU8(os, WASM_OPCODE_I32_CONST, "i32.const"); + writeUleb128(os, s->startVA, "destination address"); // source segment offset - writeU8(OS, WASM_OPCODE_I32_CONST, "i32.const"); - writeUleb128(OS, 0, "segment offset"); + writeU8(os, WASM_OPCODE_I32_CONST, "i32.const"); + writeUleb128(os, 0, "segment offset"); // memory region size - writeU8(OS, WASM_OPCODE_I32_CONST, "i32.const"); - writeUleb128(OS, S->Size, "memory region size"); + writeU8(os, WASM_OPCODE_I32_CONST, "i32.const"); + writeUleb128(os, s->size, "memory region size"); // memory.init instruction - writeU8(OS, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); - writeUleb128(OS, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT"); - writeUleb128(OS, S->Index, "segment index immediate"); - writeU8(OS, 0, "memory index immediate"); + writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); + writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT"); + writeUleb128(os, s->index, "segment index immediate"); + writeU8(os, 0, "memory index immediate"); // data.drop instruction - writeU8(OS, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); - writeUleb128(OS, WASM_OPCODE_DATA_DROP, "DATA.DROP"); - writeUleb128(OS, S->Index, "segment index immediate"); + writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); + writeUleb128(os, WASM_OPCODE_DATA_DROP, "DATA.DROP"); + writeUleb128(os, s->index, "segment index immediate"); } } - writeU8(OS, WASM_OPCODE_END, "END"); + writeU8(os, WASM_OPCODE_END, "END"); } - createFunction(WasmSym::InitMemory, BodyContent); + createFunction(WasmSym::initMemory, bodyContent); } // For -shared (PIC) output, we create create a synthetic function which will @@ -689,109 +689,109 @@ void Writer::createApplyRelocationsFunction() { LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n"); // First write the body's contents to a string. - std::string BodyContent; + std::string bodyContent; { - raw_string_ostream OS(BodyContent); - writeUleb128(OS, 0, "num locals"); - for (const OutputSegment *Seg : Segments) - for (const InputSegment *InSeg : Seg->InputSegments) - InSeg->generateRelocationCode(OS); - writeU8(OS, WASM_OPCODE_END, "END"); + raw_string_ostream os(bodyContent); + writeUleb128(os, 0, "num locals"); + for (const OutputSegment *seg : segments) + for (const InputSegment *inSeg : seg->inputSegments) + inSeg->generateRelocationCode(os); + writeU8(os, WASM_OPCODE_END, "END"); } - createFunction(WasmSym::ApplyRelocs, BodyContent); + createFunction(WasmSym::applyRelocs, bodyContent); } // Create synthetic "__wasm_call_ctors" function based on ctor functions // in input object. void Writer::createCallCtorsFunction() { - if (!WasmSym::CallCtors->isLive()) + if (!WasmSym::callCtors->isLive()) return; // First write the body's contents to a string. - std::string BodyContent; + std::string bodyContent; { - raw_string_ostream OS(BodyContent); - writeUleb128(OS, 0, "num locals"); + raw_string_ostream os(bodyContent); + writeUleb128(os, 0, "num locals"); - if (Config->PassiveSegments) { - writeU8(OS, WASM_OPCODE_CALL, "CALL"); - writeUleb128(OS, WasmSym::InitMemory->getFunctionIndex(), + if (config->passiveSegments) { + writeU8(os, WASM_OPCODE_CALL, "CALL"); + writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index"); } - if (Config->Pic) { - writeU8(OS, WASM_OPCODE_CALL, "CALL"); - writeUleb128(OS, WasmSym::ApplyRelocs->getFunctionIndex(), + if (config->isPic) { + writeU8(os, WASM_OPCODE_CALL, "CALL"); + writeUleb128(os, WasmSym::applyRelocs->getFunctionIndex(), "function index"); } // Call constructors - for (const WasmInitEntry &F : InitFunctions) { - writeU8(OS, WASM_OPCODE_CALL, "CALL"); - writeUleb128(OS, F.Sym->getFunctionIndex(), "function index"); + for (const WasmInitEntry &f : initFunctions) { + writeU8(os, WASM_OPCODE_CALL, "CALL"); + writeUleb128(os, f.sym->getFunctionIndex(), "function index"); } - writeU8(OS, WASM_OPCODE_END, "END"); + writeU8(os, WASM_OPCODE_END, "END"); } - createFunction(WasmSym::CallCtors, BodyContent); + createFunction(WasmSym::callCtors, bodyContent); } // Populate InitFunctions vector with init functions from all input objects. // This is then used either when creating the output linking section or to // synthesize the "__wasm_call_ctors" function. void Writer::calculateInitFunctions() { - if (!Config->Relocatable && !WasmSym::CallCtors->isLive()) + if (!config->relocatable && !WasmSym::callCtors->isLive()) return; - for (ObjFile *File : Symtab->ObjectFiles) { - const WasmLinkingData &L = File->getWasmObj()->linkingData(); - for (const WasmInitFunc &F : L.InitFunctions) { - FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol); + for (ObjFile *file : symtab->objectFiles) { + const WasmLinkingData &l = file->getWasmObj()->linkingData(); + for (const WasmInitFunc &f : l.InitFunctions) { + FunctionSymbol *sym = file->getFunctionSymbol(f.Symbol); // comdat exclusions can cause init functions be discarded. - if (Sym->isDiscarded()) + if (sym->isDiscarded()) continue; - assert(Sym->isLive()); - if (*Sym->Signature != WasmSignature{{}, {}}) - error("invalid signature for init func: " + toString(*Sym)); - InitFunctions.emplace_back(WasmInitEntry{Sym, F.Priority}); + assert(sym->isLive()); + if (*sym->signature != WasmSignature{{}, {}}) + error("invalid signature for init func: " + toString(*sym)); + initFunctions.emplace_back(WasmInitEntry{sym, f.Priority}); } } // Sort in order of priority (lowest first) so that they are called // in the correct order. - llvm::stable_sort(InitFunctions, - [](const WasmInitEntry &L, const WasmInitEntry &R) { - return L.Priority < R.Priority; + llvm::stable_sort(initFunctions, + [](const WasmInitEntry &l, const WasmInitEntry &r) { + return l.priority < r.priority; }); } void Writer::createSyntheticSections() { - Out.DylinkSec = make(); - Out.TypeSec = make(); - Out.ImportSec = make(); - Out.FunctionSec = make(); - Out.TableSec = make(); - Out.MemorySec = make(); - Out.GlobalSec = make(); - Out.EventSec = make(); - Out.ExportSec = make(); - Out.ElemSec = make(TableBase); - Out.DataCountSec = make(Segments.size()); - Out.LinkingSec = make(InitFunctions, Segments); - Out.NameSec = make(); - Out.ProducersSec = make(); - Out.TargetFeaturesSec = make(); + out.dylinkSec = make(); + out.typeSec = make(); + out.importSec = make(); + out.functionSec = make(); + out.tableSec = make(); + out.memorySec = make(); + out.globalSec = make(); + out.eventSec = make(); + out.exportSec = make(); + out.elemSec = make(tableBase); + out.dataCountSec = make(segments.size()); + out.linkingSec = make(initFunctions, segments); + out.nameSec = make(); + out.producersSec = make(); + out.targetFeaturesSec = make(); } void Writer::run() { - if (Config->Relocatable || Config->Pic) - Config->GlobalBase = 0; + if (config->relocatable || config->isPic) + config->globalBase = 0; // For PIC code the table base is assigned dynamically by the loader. // For non-PIC, we start at 1 so that accessing table index 0 always traps. - if (!Config->Pic) - TableBase = 1; + if (!config->isPic) + tableBase = 1; log("-- createOutputSegments"); createOutputSegments(); @@ -806,11 +806,11 @@ log("-- layoutMemory"); layoutMemory(); - if (!Config->Relocatable) { + if (!config->relocatable) { // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols // This has to be done after memory layout is performed. - for (const OutputSegment *Seg : Segments) - addStartStopSymbols(Seg); + for (const OutputSegment *seg : segments) + addStartStopSymbols(seg); } log("-- scanRelocations"); @@ -820,11 +820,11 @@ log("-- calculateInitFunctions"); calculateInitFunctions(); - if (!Config->Relocatable) { + if (!config->relocatable) { // Create linker synthesized functions - if (Config->PassiveSegments) + if (config->passiveSegments) createInitMemoryFunction(); - if (Config->Pic) + if (config->isPic) createApplyRelocationsFunction(); createCallCtorsFunction(); } @@ -840,16 +840,16 @@ log("-- addSections"); addSections(); - if (errorHandler().Verbose) { - log("Defined Functions: " + Twine(Out.FunctionSec->InputFunctions.size())); - log("Defined Globals : " + Twine(Out.GlobalSec->InputGlobals.size())); - log("Defined Events : " + Twine(Out.EventSec->InputEvents.size())); + if (errorHandler().verbose) { + log("Defined Functions: " + Twine(out.functionSec->inputFunctions.size())); + log("Defined Globals : " + Twine(out.globalSec->inputGlobals.size())); + log("Defined Events : " + Twine(out.eventSec->inputEvents.size())); log("Function Imports : " + - Twine(Out.ImportSec->getNumImportedFunctions())); - log("Global Imports : " + Twine(Out.ImportSec->getNumImportedGlobals())); - log("Event Imports : " + Twine(Out.ImportSec->getNumImportedEvents())); - for (ObjFile *File : Symtab->ObjectFiles) - File->dumpInfo(); + Twine(out.importSec->getNumImportedFunctions())); + log("Global Imports : " + Twine(out.importSec->getNumImportedGlobals())); + log("Event Imports : " + Twine(out.importSec->getNumImportedEvents())); + for (ObjFile *file : symtab->objectFiles) + file->dumpInfo(); } createHeader(); @@ -868,31 +868,31 @@ if (errorCount()) return; - if (Error E = Buffer->commit()) - fatal("failed to write the output file: " + toString(std::move(E))); + if (Error e = buffer->commit()) + fatal("failed to write the output file: " + toString(std::move(e))); } // Open a result file. void Writer::openFile() { - log("writing: " + Config->OutputFile); + log("writing: " + config->outputFile); - Expected> BufferOrErr = - FileOutputBuffer::create(Config->OutputFile, FileSize, + Expected> bufferOrErr = + FileOutputBuffer::create(config->outputFile, fileSize, FileOutputBuffer::F_executable); - if (!BufferOrErr) - error("failed to open " + Config->OutputFile + ": " + - toString(BufferOrErr.takeError())); + if (!bufferOrErr) + error("failed to open " + config->outputFile + ": " + + toString(bufferOrErr.takeError())); else - Buffer = std::move(*BufferOrErr); + buffer = std::move(*bufferOrErr); } void Writer::createHeader() { - raw_string_ostream OS(Header); - writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic"); - writeU32(OS, WasmVersion, "wasm version"); - OS.flush(); - FileSize += Header.size(); + raw_string_ostream os(header); + writeBytes(os, WasmMagic, sizeof(WasmMagic), "wasm magic"); + writeU32(os, WasmVersion, "wasm version"); + os.flush(); + fileSize += header.size(); } void lld::wasm::writeResult() { Writer().run(); } Index: lld/trunk/wasm/WriterUtils.h =================================================================== --- lld/trunk/wasm/WriterUtils.h +++ lld/trunk/wasm/WriterUtils.h @@ -16,50 +16,50 @@ namespace lld { namespace wasm { -void debugWrite(uint64_t Offset, const Twine &Msg); +void debugWrite(uint64_t offset, const Twine &msg); -void writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg); +void writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg); -void writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg); +void writeSleb128(raw_ostream &os, int32_t number, const Twine &msg); -void writeBytes(raw_ostream &OS, const char *Bytes, size_t count, - const Twine &Msg); +void writeBytes(raw_ostream &os, const char *bytes, size_t count, + const Twine &msg); -void writeStr(raw_ostream &OS, StringRef String, const Twine &Msg); +void writeStr(raw_ostream &os, StringRef string, const Twine &msg); -void writeU8(raw_ostream &OS, uint8_t byte, const Twine &Msg); +void writeU8(raw_ostream &os, uint8_t byte, const Twine &msg); -void writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg); +void writeU32(raw_ostream &os, uint32_t number, const Twine &msg); -void writeValueType(raw_ostream &OS, llvm::wasm::ValType Type, - const Twine &Msg); +void writeValueType(raw_ostream &os, llvm::wasm::ValType type, + const Twine &msg); -void writeSig(raw_ostream &OS, const llvm::wasm::WasmSignature &Sig); +void writeSig(raw_ostream &os, const llvm::wasm::WasmSignature &sig); -void writeInitExpr(raw_ostream &OS, const llvm::wasm::WasmInitExpr &InitExpr); +void writeInitExpr(raw_ostream &os, const llvm::wasm::WasmInitExpr &initExpr); -void writeLimits(raw_ostream &OS, const llvm::wasm::WasmLimits &Limits); +void writeLimits(raw_ostream &os, const llvm::wasm::WasmLimits &limits); -void writeGlobalType(raw_ostream &OS, const llvm::wasm::WasmGlobalType &Type); +void writeGlobalType(raw_ostream &os, const llvm::wasm::WasmGlobalType &type); -void writeGlobal(raw_ostream &OS, const llvm::wasm::WasmGlobal &Global); +void writeGlobal(raw_ostream &os, const llvm::wasm::WasmGlobal &global); -void writeEventType(raw_ostream &OS, const llvm::wasm::WasmEventType &Type); +void writeEventType(raw_ostream &os, const llvm::wasm::WasmEventType &type); -void writeEvent(raw_ostream &OS, const llvm::wasm::WasmEvent &Event); +void writeEvent(raw_ostream &os, const llvm::wasm::WasmEvent &event); -void writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type); +void writeTableType(raw_ostream &os, const llvm::wasm::WasmTable &type); -void writeImport(raw_ostream &OS, const llvm::wasm::WasmImport &Import); +void writeImport(raw_ostream &os, const llvm::wasm::WasmImport &import); -void writeExport(raw_ostream &OS, const llvm::wasm::WasmExport &Export); +void writeExport(raw_ostream &os, const llvm::wasm::WasmExport &export_); } // namespace wasm -std::string toString(llvm::wasm::ValType Type); -std::string toString(const llvm::wasm::WasmSignature &Sig); -std::string toString(const llvm::wasm::WasmGlobalType &Type); -std::string toString(const llvm::wasm::WasmEventType &Type); +std::string toString(llvm::wasm::ValType type); +std::string toString(const llvm::wasm::WasmSignature &sig); +std::string toString(const llvm::wasm::WasmGlobalType &type); +std::string toString(const llvm::wasm::WasmEventType &type); } // namespace lld Index: lld/trunk/wasm/WriterUtils.cpp =================================================================== --- lld/trunk/wasm/WriterUtils.cpp +++ lld/trunk/wasm/WriterUtils.cpp @@ -19,159 +19,159 @@ namespace lld { -void wasm::debugWrite(uint64_t Offset, const Twine &Msg) { - LLVM_DEBUG(dbgs() << format(" | %08lld: ", Offset) << Msg << "\n"); +void wasm::debugWrite(uint64_t offset, const Twine &msg) { + LLVM_DEBUG(dbgs() << format(" | %08lld: ", offset) << msg << "\n"); } -void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg) { - debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]"); - encodeULEB128(Number, OS); +void wasm::writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg) { + debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]"); + encodeULEB128(number, os); } -void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg) { - debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]"); - encodeSLEB128(Number, OS); +void wasm::writeSleb128(raw_ostream &os, int32_t number, const Twine &msg) { + debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]"); + encodeSLEB128(number, os); } -void wasm::writeBytes(raw_ostream &OS, const char *Bytes, size_t Count, - const Twine &Msg) { - debugWrite(OS.tell(), Msg + " [data[" + Twine(Count) + "]]"); - OS.write(Bytes, Count); +void wasm::writeBytes(raw_ostream &os, const char *bytes, size_t count, + const Twine &msg) { + debugWrite(os.tell(), msg + " [data[" + Twine(count) + "]]"); + os.write(bytes, count); } -void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) { - debugWrite(OS.tell(), - Msg + " [str[" + Twine(String.size()) + "]: " + String + "]"); - encodeULEB128(String.size(), OS); - OS.write(String.data(), String.size()); +void wasm::writeStr(raw_ostream &os, StringRef string, const Twine &msg) { + debugWrite(os.tell(), + msg + " [str[" + Twine(string.size()) + "]: " + string + "]"); + encodeULEB128(string.size(), os); + os.write(string.data(), string.size()); } -void wasm::writeU8(raw_ostream &OS, uint8_t Byte, const Twine &Msg) { - debugWrite(OS.tell(), Msg + " [0x" + utohexstr(Byte) + "]"); - OS << Byte; +void wasm::writeU8(raw_ostream &os, uint8_t byte, const Twine &msg) { + debugWrite(os.tell(), msg + " [0x" + utohexstr(byte) + "]"); + os << byte; } -void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) { - debugWrite(OS.tell(), Msg + "[0x" + utohexstr(Number) + "]"); - support::endian::write(OS, Number, support::little); +void wasm::writeU32(raw_ostream &os, uint32_t number, const Twine &msg) { + debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]"); + support::endian::write(os, number, support::little); } -void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) { - writeU8(OS, static_cast(Type), - Msg + "[type: " + toString(Type) + "]"); +void wasm::writeValueType(raw_ostream &os, ValType type, const Twine &msg) { + writeU8(os, static_cast(type), + msg + "[type: " + toString(type) + "]"); } -void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) { - writeU8(OS, WASM_TYPE_FUNC, "signature type"); - writeUleb128(OS, Sig.Params.size(), "param Count"); - for (ValType ParamType : Sig.Params) { - writeValueType(OS, ParamType, "param type"); +void wasm::writeSig(raw_ostream &os, const WasmSignature &sig) { + writeU8(os, WASM_TYPE_FUNC, "signature type"); + writeUleb128(os, sig.Params.size(), "param Count"); + for (ValType paramType : sig.Params) { + writeValueType(os, paramType, "param type"); } - writeUleb128(OS, Sig.Returns.size(), "result Count"); - if (Sig.Returns.size()) { - writeValueType(OS, Sig.Returns[0], "result type"); + writeUleb128(os, sig.Returns.size(), "result Count"); + if (sig.Returns.size()) { + writeValueType(os, sig.Returns[0], "result type"); } } -void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) { - writeU8(OS, InitExpr.Opcode, "opcode"); - switch (InitExpr.Opcode) { +void wasm::writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) { + writeU8(os, initExpr.Opcode, "opcode"); + switch (initExpr.Opcode) { case WASM_OPCODE_I32_CONST: - writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)"); + writeSleb128(os, initExpr.Value.Int32, "literal (i32)"); break; case WASM_OPCODE_I64_CONST: - writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)"); + writeSleb128(os, initExpr.Value.Int64, "literal (i64)"); break; case WASM_OPCODE_GLOBAL_GET: - writeUleb128(OS, InitExpr.Value.Global, "literal (global index)"); + writeUleb128(os, initExpr.Value.Global, "literal (global index)"); break; default: - fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode)); + fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode)); } - writeU8(OS, WASM_OPCODE_END, "opcode:end"); + writeU8(os, WASM_OPCODE_END, "opcode:end"); } -void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) { - writeU8(OS, Limits.Flags, "limits flags"); - writeUleb128(OS, Limits.Initial, "limits initial"); - if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX) - writeUleb128(OS, Limits.Maximum, "limits max"); +void wasm::writeLimits(raw_ostream &os, const WasmLimits &limits) { + writeU8(os, limits.Flags, "limits flags"); + writeUleb128(os, limits.Initial, "limits initial"); + if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX) + writeUleb128(os, limits.Maximum, "limits max"); } -void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) { +void wasm::writeGlobalType(raw_ostream &os, const WasmGlobalType &type) { // TODO: Update WasmGlobalType to use ValType and remove this cast. - writeValueType(OS, ValType(Type.Type), "global type"); - writeU8(OS, Type.Mutable, "global mutable"); + writeValueType(os, ValType(type.Type), "global type"); + writeU8(os, type.Mutable, "global mutable"); } -void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) { - writeGlobalType(OS, Global.Type); - writeInitExpr(OS, Global.InitExpr); +void wasm::writeGlobal(raw_ostream &os, const WasmGlobal &global) { + writeGlobalType(os, global.Type); + writeInitExpr(os, global.InitExpr); } -void wasm::writeEventType(raw_ostream &OS, const WasmEventType &Type) { - writeUleb128(OS, Type.Attribute, "event attribute"); - writeUleb128(OS, Type.SigIndex, "sig index"); +void wasm::writeEventType(raw_ostream &os, const WasmEventType &type) { + writeUleb128(os, type.Attribute, "event attribute"); + writeUleb128(os, type.SigIndex, "sig index"); } -void wasm::writeEvent(raw_ostream &OS, const WasmEvent &Event) { - writeEventType(OS, Event.Type); +void wasm::writeEvent(raw_ostream &os, const WasmEvent &event) { + writeEventType(os, event.Type); } -void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) { - writeU8(OS, WASM_TYPE_FUNCREF, "table type"); - writeLimits(OS, Type.Limits); +void wasm::writeTableType(raw_ostream &os, const llvm::wasm::WasmTable &type) { + writeU8(os, WASM_TYPE_FUNCREF, "table type"); + writeLimits(os, type.Limits); } -void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) { - writeStr(OS, Import.Module, "import module name"); - writeStr(OS, Import.Field, "import field name"); - writeU8(OS, Import.Kind, "import kind"); - switch (Import.Kind) { +void wasm::writeImport(raw_ostream &os, const WasmImport &import) { + writeStr(os, import.Module, "import module name"); + writeStr(os, import.Field, "import field name"); + writeU8(os, import.Kind, "import kind"); + switch (import.Kind) { case WASM_EXTERNAL_FUNCTION: - writeUleb128(OS, Import.SigIndex, "import sig index"); + writeUleb128(os, import.SigIndex, "import sig index"); break; case WASM_EXTERNAL_GLOBAL: - writeGlobalType(OS, Import.Global); + writeGlobalType(os, import.Global); break; case WASM_EXTERNAL_EVENT: - writeEventType(OS, Import.Event); + writeEventType(os, import.Event); break; case WASM_EXTERNAL_MEMORY: - writeLimits(OS, Import.Memory); + writeLimits(os, import.Memory); break; case WASM_EXTERNAL_TABLE: - writeTableType(OS, Import.Table); + writeTableType(os, import.Table); break; default: - fatal("unsupported import type: " + Twine(Import.Kind)); + fatal("unsupported import type: " + Twine(import.Kind)); } } -void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) { - writeStr(OS, Export.Name, "export name"); - writeU8(OS, Export.Kind, "export kind"); - switch (Export.Kind) { +void wasm::writeExport(raw_ostream &os, const WasmExport &export_) { + writeStr(os, export_.Name, "export name"); + writeU8(os, export_.Kind, "export kind"); + switch (export_.Kind) { case WASM_EXTERNAL_FUNCTION: - writeUleb128(OS, Export.Index, "function index"); + writeUleb128(os, export_.Index, "function index"); break; case WASM_EXTERNAL_GLOBAL: - writeUleb128(OS, Export.Index, "global index"); + writeUleb128(os, export_.Index, "global index"); break; case WASM_EXTERNAL_MEMORY: - writeUleb128(OS, Export.Index, "memory index"); + writeUleb128(os, export_.Index, "memory index"); break; case WASM_EXTERNAL_TABLE: - writeUleb128(OS, Export.Index, "table index"); + writeUleb128(os, export_.Index, "table index"); break; default: - fatal("unsupported export type: " + Twine(Export.Kind)); + fatal("unsupported export type: " + Twine(export_.Kind)); } } } // namespace lld -std::string lld::toString(ValType Type) { - switch (Type) { +std::string lld::toString(ValType type) { + switch (type) { case ValType::I32: return "i32"; case ValType::I64: @@ -188,28 +188,28 @@ llvm_unreachable("Invalid wasm::ValType"); } -std::string lld::toString(const WasmSignature &Sig) { - SmallString<128> S("("); - for (ValType Type : Sig.Params) { - if (S.size() != 1) - S += ", "; - S += toString(Type); - } - S += ") -> "; - if (Sig.Returns.empty()) - S += "void"; +std::string lld::toString(const WasmSignature &sig) { + SmallString<128> s("("); + for (ValType type : sig.Params) { + if (s.size() != 1) + s += ", "; + s += toString(type); + } + s += ") -> "; + if (sig.Returns.empty()) + s += "void"; else - S += toString(Sig.Returns[0]); - return S.str(); + s += toString(sig.Returns[0]); + return s.str(); } -std::string lld::toString(const WasmGlobalType &Type) { - return (Type.Mutable ? "var " : "const ") + - toString(static_cast(Type.Type)); +std::string lld::toString(const WasmGlobalType &type) { + return (type.Mutable ? "var " : "const ") + + toString(static_cast(type.Type)); } -std::string lld::toString(const WasmEventType &Type) { - if (Type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION) +std::string lld::toString(const WasmEventType &type) { + if (type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION) return "exception"; return "unknown"; }