Index: lld/trunk/COFF/Chunks.h =================================================================== --- lld/trunk/COFF/Chunks.h +++ lld/trunk/COFF/Chunks.h @@ -243,6 +243,7 @@ bool hasData() const override { return false; } uint32_t getPermissions() const override; StringRef getSectionName() const override { return ".bss"; } + void setAlign(uint32_t NewAlign); private: const COFFSymbolRef Sym; Index: lld/trunk/COFF/Chunks.cpp =================================================================== --- lld/trunk/COFF/Chunks.cpp +++ lld/trunk/COFF/Chunks.cpp @@ -377,6 +377,10 @@ Align = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue())); } +void CommonChunk::setAlign(uint32_t NewAlign) { + Align = std::max(Align, NewAlign); +} + uint32_t CommonChunk::getPermissions() const { return IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; Index: lld/trunk/COFF/Config.h =================================================================== --- lld/trunk/COFF/Config.h +++ lld/trunk/COFF/Config.h @@ -139,6 +139,9 @@ StringRef ManifestUIAccess = "'false'"; StringRef ManifestFile; + // Used for /aligncomm. + std::map AlignComm; + // Used for /failifmismatch. std::map MustMatch; Index: lld/trunk/COFF/Driver.h =================================================================== --- lld/trunk/COFF/Driver.h +++ lld/trunk/COFF/Driver.h @@ -145,6 +145,7 @@ void parseAlternateName(StringRef); void parseMerge(StringRef); void parseSection(StringRef); +void parseAligncomm(StringRef); // Parses a string in the form of "EMBED[,=]|NO". void parseManifest(StringRef Arg); Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -202,6 +202,9 @@ for (auto *Arg : Args) { switch (Arg->getOption().getUnaliasedOption().getID()) { + case OPT_aligncomm: + parseAligncomm(Arg->getValue()); + break; case OPT_alternatename: parseAlternateName(Arg->getValue()); break; @@ -899,6 +902,10 @@ for (auto *Arg : Args.filtered(OPT_section)) parseSection(Arg->getValue()); + // Handle /aligncomm + 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)) { @@ -1158,6 +1165,23 @@ assignExportOrdinals(); } + // Set extra alignment for .comm symbols + for (auto Pair : Config->AlignComm) { + StringRef Name = Pair.first; + int Align = Pair.second; + Symbol *Sym = Symtab.find(Name); + if (!Sym) { + warn("/aligncomm symbol " + Name + " not found"); + continue; + } + auto *DC = dyn_cast(Sym->body()); + if (!DC) { + warn("/aligncomm symbol " + Name + " of wrong kind"); + continue; + } + DC->getChunk()->setAlign(Align); + } + // Windows specific -- Create a side-by-side manifest file. if (Config->Manifest == Configuration::SideBySide) createSideBySideManifest(); Index: lld/trunk/COFF/DriverUtils.cpp =================================================================== --- lld/trunk/COFF/DriverUtils.cpp +++ lld/trunk/COFF/DriverUtils.cpp @@ -221,6 +221,22 @@ 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); + return; + } + int V; + if (Align.getAsInteger(0, V)) { + error("/aligncomm: invalid argument: " + S); + return; + } + Config->AlignComm[Name] = std::max(Config->AlignComm[Name], 1 << V); +} + // Parses a string in the form of "EMBED[,=]|NO". // Results are directly written to Config. void parseManifest(StringRef Arg) { Index: lld/trunk/COFF/Options.td =================================================================== --- lld/trunk/COFF/Options.td +++ lld/trunk/COFF/Options.td @@ -16,6 +16,7 @@ } def align : P<"align", "Section alignment">; +def aligncomm : P<"aligncomm", "Set common symbol alignment">; def alternatename : P<"alternatename", "Define weak alias">; def base : P<"base", "Base address of the program">; def defaultlib : P<"defaultlib", "Add the library to the list of input files">; Index: lld/trunk/COFF/Symbols.h =================================================================== --- lld/trunk/COFF/Symbols.h +++ lld/trunk/COFF/Symbols.h @@ -182,7 +182,7 @@ } uint64_t getRVA() { return Data->getRVA(); } - Chunk *getChunk() { return Data; } + CommonChunk *getChunk() { return Data; } private: friend SymbolTable; Index: lld/trunk/test/COFF/common-alignment.test =================================================================== --- lld/trunk/test/COFF/common-alignment.test +++ lld/trunk/test/COFF/common-alignment.test @@ -0,0 +1,78 @@ +# REQUIRES: x86 +# RUN: yaml2obj %s > %t.obj +# RUN: lld-link /out:%t.exe /entry:main %t.obj %t.obj +# RUN: llvm-objdump -d %t.exe | FileCheck %s + +# Operands of B8 (MOV EAX) are common symbols +# CHECK: 3000: b8 00 10 00 40 +# CHECK: 3005: b8 10 10 00 40 + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: b800000000b800000000 + Relocations: + - VirtualAddress: 1 + SymbolName: bssdata4 + Type: IMAGE_REL_AMD64_ADDR32 + - VirtualAddress: 6 + SymbolName: bssdata4_align16 + Type: IMAGE_REL_AMD64_ADDR32 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: 03000000 + - Name: .drectve + Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] + Alignment: 1 + SectionData: 202d616c69676e636f6d6d3a62737364617461345f616c69676e31362c340a # -aligncomm:bssdata4_align16,4 + +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 0 + NumberOfRelocations: 5 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .data + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bssdata4 + Value: 4 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bssdata4_align16 + Value: 4 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +...