WinCOFF: Emit common symbols as specified in the COFF spec
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 8 Apr 2014 22:33:40 +0000 (22:33 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 8 Apr 2014 22:33:40 +0000 (22:33 +0000)
Summary:
Local common symbols were properly inserted into the .bss section.
However, putting external common symbols in the .bss section would give
them a strong definition.

Instead, encode them as undefined, external symbols who's symbol value
is equivalent to their size.

Reviewers: Bigcheese, rafael, rnk

CC: llvm-commits
Differential Revision: http://reviews.llvm.org/D3324

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205811 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetLoweringObjectFileImpl.cpp
lib/MC/MCObjectFileInfo.cpp
lib/MC/WinCOFFObjectWriter.cpp
lib/MC/WinCOFFStreamer.cpp
test/MC/COFF/comm.ll
test/MC/COFF/comm.s

index e41fbfc6d360e06fb4b242c59a0468ca1d3203d8..523d219daab464b1e234edf628ed857b8b02fd6f 100644 (file)
@@ -755,7 +755,7 @@ const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
 static const char *getCOFFSectionNameForUniqueGlobal(SectionKind Kind) {
   if (Kind.isText())
     return ".text";
-  if (Kind.isBSS ())
+  if (Kind.isBSS())
     return ".bss";
   if (Kind.isThreadLocal())
     return ".tls$";
@@ -781,7 +781,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
   // Section names depend on the name of the symbol which is not feasible if the
   // symbol has private linkage.
   if ((GV->isWeakForLinker() || EmitUniquedSection) &&
-      !GV->hasPrivateLinkage()) {
+      !GV->hasPrivateLinkage() && !Kind.isCommon()) {
     const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
     unsigned Characteristics = getCOFFSectionFlags(Kind);
 
@@ -802,7 +802,10 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
   if (Kind.isReadOnly())
     return ReadOnlySection;
 
-  if (Kind.isBSS())
+  // Note: we claim that common symbols are put in BSSSection, but they are
+  // really emitted with the magic .comm directive, which creates a symbol table
+  // entry but not a section.
+  if (Kind.isBSS() || Kind.isCommon())
     return BSSSection;
 
   return DataSection;
index 3b011c8bc5a222eb0f23b583533dc26931ff4330..75147bfb4899be3eb4d762782416bfad0beab2b4 100644 (file)
@@ -548,6 +548,10 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
 
 
 void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) {
+  // The object file format cannot represent common symbols with explicit
+  // alignments.
+  CommDirectiveSupportsAlignment = false;
+
   // COFF
   BSSSection =
     Ctx->getCOFFSection(".bss",
index 500acd8f14efa873b1fa2bde0bff83350b0b9b8c..f9426c61bdeccc4e951afd55668da40dd42cc663 100644 (file)
@@ -394,7 +394,7 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
   SectionMap[&SectionData.getSection()] = coff_section;
 }
 
-/// This function takes a section data object from the assembler
+/// This function takes a symbol data object from the assembler
 /// and creates the associated COFF symbol staging object.
 void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
                                        MCAssembler &Assembler,
@@ -443,6 +443,8 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
       int64_t Addr;
       if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout))
         coff_symbol->Data.Value = Addr;
+    } else if (SymbolData.isExternal() && SymbolData.isCommon()) {
+      coff_symbol->Data.Value = SymbolData.getCommonSize();
     }
 
     coff_symbol->Data.Type         = (ResSymData.getFlags() & 0x0000FFFF) >>  0;
index 5bd7b8f0c63cfc3551ff5698ea1d6845f21160f1..6981bb7982d001ea800ec6ef59bd79deff6c6769 100644 (file)
@@ -45,9 +45,6 @@ public:
                   MCCodeEmitter &CE,
                   raw_ostream &OS);
 
-  void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                       unsigned ByteAlignment, bool External);
-
   // MCStreamer interface
 
   void InitSections() override;
@@ -101,26 +98,6 @@ WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
                                  MCCodeEmitter &CE, raw_ostream &OS)
     : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(NULL) {}
 
-void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                                      unsigned ByteAlignment, bool External) {
-  assert(!Symbol->isInSection() && "Symbol must not already have a section!");
-
-  const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
-  MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
-  if (SectionData.getAlignment() < ByteAlignment)
-    SectionData.setAlignment(ByteAlignment);
-
-  MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol);
-  SymbolData.setExternal(External);
-
-  AssignSection(Symbol, Section);
-
-  if (ByteAlignment != 1)
-      new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData);
-
-  SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData));
-}
-
 // MCStreamer interface
 
 void WinCOFFStreamer::InitSections() {
@@ -244,15 +221,38 @@ void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
   assert((Symbol->isInSection()
          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
          : true) && "Got non-COFF section in the COFF backend!");
-  AddCommonSymbol(Symbol, Size, ByteAlignment, true);
+
+  if (ByteAlignment > 32)
+    report_fatal_error(
+        "The linker won't align common symbols beyond 32 bytes.");
+
+  AssignSection(Symbol, NULL);
+
+  MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+  SD.setExternal(true);
+  SD.setCommon(Size, ByteAlignment);
 }
 
 void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                             unsigned ByteAlignment) {
-  assert((Symbol->isInSection()
-         ? Symbol->getSection().getVariant() == MCSection::SV_COFF
-         : true) && "Got non-COFF section in the COFF backend!");
-  AddCommonSymbol(Symbol, Size, ByteAlignment, false);
+  assert(!Symbol->isInSection() && "Symbol must not already have a section!");
+
+  const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
+  MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
+  if (SectionData.getAlignment() < ByteAlignment)
+    SectionData.setAlignment(ByteAlignment);
+
+  MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+  SD.setExternal(false);
+
+  AssignSection(Symbol, Section);
+
+  if (ByteAlignment != 1)
+    new MCAlignFragment(ByteAlignment, /*_Value=*/0, /*_ValueSize=*/0,
+                        ByteAlignment, &SectionData);
+
+  SD.setFragment(
+      new MCFillFragment(/*_Value=*/0, /*_ValueSize=*/0, Size, &SectionData));
 }
 
 void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
index 74da557fb5cce2638d8fed77ae58d7f6e8a4477d..6fe122ef1d935b5be9e8eb26735a032c8ac9b6ac 100644 (file)
@@ -9,5 +9,5 @@
 ; CHECK: .lcomm        _a,1
 ; CHECK: .lcomm        _b,8,8
 ; .comm uses log2 alignment
-; CHECK: .comm _c,1,0
-; CHECK: .comm _d,8,3
+; CHECK: .comm _c,1
+; CHECK: .comm _d,8
index 21ae5d25ddaed8a24cd7edb1d1647b3ebdc320c6..37db75f9cc4a12e895f68757516fdec046dec182 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | llvm-readobj -t | FileCheck %s
 
 .lcomm _a,4,4
-.comm  _b, 4, 2
+.comm  _b, 4
 
 
 // CHECK:       Symbol {
@@ -17,7 +17,7 @@
 // CHECK:       Symbol {
 // CHECK:         Name: _b
 // CHECK-NEXT:    Value: 4
-// CHECK-NEXT:    Section: .bss
+// CHECK-NEXT:    Section:  (0)
 // CHECK-NEXT:    BaseType: Null
 // CHECK-NEXT:    ComplexType: Null
 // CHECK-NEXT:    StorageClass: External