MC-COFF: Add support for default-null weak externals.
authorMichael J. Spencer <bigcheesegs@gmail.com>
Sat, 16 Oct 2010 08:25:57 +0000 (08:25 +0000)
committerMichael J. Spencer <bigcheesegs@gmail.com>
Sat, 16 Oct 2010 08:25:57 +0000 (08:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116666 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/COFF.h
lib/MC/WinCOFFObjectWriter.cpp
lib/MC/WinCOFFStreamer.cpp
test/MC/COFF/weak.s [new file with mode: 0644]

index 2bba8d3c87e1e1d2305af71987272214df429e7b..46fe269a231d079df293fda18f9b35c06b52053b 100644 (file)
@@ -69,7 +69,7 @@ namespace COFF {
     SF_ClassMask = 0x00FF0000,
     SF_ClassShift = 16,
 
-    SF_WeakReference = 0x01000000
+    SF_WeakExternal = 0x01000000
   };
 
   enum SymbolSectionNumber {
index 285717e83e2a885a4cb1c4cbf8dbea99fef0c150..59cac2bc7a38458c226635594811f0011aa19ee2 100644 (file)
@@ -125,11 +125,8 @@ public:
   typedef std::vector<COFFSymbol*>  symbols;
   typedef std::vector<COFFSection*> sections;
 
-  typedef StringMap<COFFSymbol *>  name_symbol_map;
-  typedef StringMap<COFFSection *> name_section_map;
-
-  typedef DenseMap<MCSymbolData const *, COFFSymbol *>   symbol_map;
-  typedef DenseMap<MCSectionData const *, COFFSection *> section_map;
+  typedef DenseMap<MCSymbol  const *, COFFSymbol *>   symbol_map;
+  typedef DenseMap<MCSection const *, COFFSection *> section_map;
 
   // Root level file contents.
   bool Is64Bit;
@@ -145,8 +142,9 @@ public:
   WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
   ~WinCOFFObjectWriter();
 
-  COFFSymbol *createSymbol(llvm::StringRef Name);
-  COFFSection *createSection(llvm::StringRef Name);
+  COFFSymbol *createSymbol(StringRef Name);
+  COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol);
+  COFFSection *createSection(StringRef Name);
 
   template <typename object_t, typename list_t>
   object_t *createCOFFEntity(llvm::StringRef Name, list_t &List);
@@ -336,10 +334,20 @@ WinCOFFObjectWriter::~WinCOFFObjectWriter() {
     delete *I;
 }
 
-COFFSymbol *WinCOFFObjectWriter::createSymbol(llvm::StringRef Name) {
+COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
   return createCOFFEntity<COFFSymbol>(Name, Symbols);
 }
 
+COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){
+  symbol_map::iterator i = SymbolMap.find(Symbol);
+  if (i != SymbolMap.end())
+    return i->second;
+  COFFSymbol *RetSymbol
+    = createCOFFEntity<COFFSymbol>(Symbol->getName(), Symbols);
+  SymbolMap[Symbol] = RetSymbol;
+  return RetSymbol;
+}
+
 COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) {
   return createCOFFEntity<COFFSection>(Name, Sections);
 }
@@ -402,48 +410,43 @@ void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
 
   // Bind internal COFF section to MC section.
   coff_section->MCData = &SectionData;
-  SectionMap[&SectionData] = coff_section;
+  SectionMap[&SectionData.getSection()] = coff_section;
 }
 
 /// This function takes a section data object from the assembler
 /// and creates the associated COFF symbol staging object.
 void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
                                        MCAssembler &Assembler) {
-  assert(!SymbolData.getSymbol().isVariable()
-    && "Cannot define a symbol that is a variable!");
-  COFFSymbol *coff_symbol = createSymbol(SymbolData.getSymbol().getName());
+  COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&SymbolData.getSymbol());
 
   coff_symbol->Data.Type         = (SymbolData.getFlags() & 0x0000FFFF) >>  0;
   coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16;
 
-  // If no storage class was specified in the streamer, define it here.
-  if (coff_symbol->Data.StorageClass == 0) {
-    bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL);
-
-    coff_symbol->Data.StorageClass =
-      external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
-  }
-
-  if (SymbolData.getFlags() & COFF::SF_WeakReference) {
+  if (SymbolData.getFlags() & COFF::SF_WeakExternal) {
     coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
 
-    const MCExpr *Value = SymbolData.getSymbol().getVariableValue();
-
-    // FIXME: This assert message isn't very good.
-    assert(Value->getKind() == MCExpr::SymbolRef &&
-           "Value must be a SymbolRef!");
+    if (SymbolData.getSymbol().isVariable()) {
+      coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
+      const MCExpr *Value = SymbolData.getSymbol().getVariableValue();
 
-    const MCSymbolRefExpr *SymbolRef =
-      static_cast<const MCSymbolRefExpr *>(Value);
+      // FIXME: This assert message isn't very good.
+      assert(Value->getKind() == MCExpr::SymbolRef &&
+              "Value must be a SymbolRef!");
 
-    const MCSymbolData &OtherSymbolData =
-      Assembler.getSymbolData(SymbolRef->getSymbol());
-
-    // FIXME: This assert message isn't very good.
-    assert(SymbolMap.find(&OtherSymbolData) != SymbolMap.end() &&
-           "OtherSymbolData must be in the symbol map!");
-
-    coff_symbol->Other = SymbolMap[&OtherSymbolData];
+      const MCSymbolRefExpr *SymbolRef =
+        static_cast<const MCSymbolRefExpr *>(Value);
+      coff_symbol->Other = GetOrCreateCOFFSymbol(&SymbolRef->getSymbol());
+    } else {
+      std::string WeakName = std::string(".weak.")
+                           +  SymbolData.getSymbol().getName().str()
+                           + ".default";
+      COFFSymbol *WeakDefault = createSymbol(WeakName);
+      WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+      WeakDefault->Data.StorageClass  = COFF::IMAGE_SYM_CLASS_EXTERNAL;
+      WeakDefault->Data.Type          = 0;
+      WeakDefault->Data.Value         = 0;
+      coff_symbol->Other = WeakDefault;
+    }
 
     // Setup the Weak External auxiliary symbol.
     coff_symbol->Aux.resize(1);
@@ -451,15 +454,24 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
     coff_symbol->Aux[0].AuxType = ATWeakExternal;
     coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
     coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
-                                        COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
+      COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
+  }
+
+  // If no storage class was specified in the streamer, define it here.
+  if (coff_symbol->Data.StorageClass == 0) {
+    bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL);
+
+    coff_symbol->Data.StorageClass =
+      external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
   }
 
   if (SymbolData.Fragment != NULL)
-    coff_symbol->Section = SectionMap[SymbolData.Fragment->getParent()];
+    coff_symbol->Section =
+      SectionMap[&SymbolData.Fragment->getParent()->getSection()];
 
   // Bind internal COFF symbol to MC symbol.
   coff_symbol->MCData = &SymbolData;
-  SymbolMap[&SymbolData] = coff_symbol;
+  SymbolMap[&SymbolData.getSymbol()] = coff_symbol;
 }
 
 /// making a section real involves assigned it a number and putting
@@ -509,7 +521,7 @@ bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData,
 
   // For now, all non-variable symbols are exported,
   // the linker will sort the rest out for us.
-  return !SymbolData.getSymbol().isVariable();
+  return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable();
 }
 
 bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
@@ -632,13 +644,13 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
   MCSectionData const *SectionData = Fragment->getParent();
 
   // Mark this symbol as requiring an entry in the symbol table.
-  assert(SectionMap.find(SectionData) != SectionMap.end() &&
+  assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() &&
          "Section must already have been defined in ExecutePostLayoutBinding!");
-  assert(SymbolMap.find(&A_SD) != SymbolMap.end() &&
+  assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() &&
          "Symbol must already have been defined in ExecutePostLayoutBinding!");
 
-  COFFSection *coff_section = SectionMap[SectionData];
-  COFFSymbol *coff_symbol = SymbolMap[&A_SD];
+  COFFSection *coff_section = SectionMap[&SectionData->getSection()];
+  COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()];
 
   if (Target.getSymB()) {
     if (&Target.getSymA()->getSymbol().getSection()
@@ -796,7 +808,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
   for (MCAssembler::const_iterator i = Asm.begin(),
                                    e = Asm.end();
                                    i != e; i++) {
-    COFFSection *Sec = SectionMap[i];
+    COFFSection *Sec = SectionMap[&i->getSection()];
 
     if (Sec->Number == -1)
       continue;
index 9fd80a4f63ce89c429f4f3f57790ae2c690999a9..b270648cfc8925be6e022bcfee79b53b8b416b5c 100644 (file)
@@ -245,9 +245,11 @@ void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
          : true) && "Got non COFF section in the COFF backend!");
   switch (Attribute) {
   case MCSA_WeakReference:
-    getAssembler().getOrCreateSymbolData(*Symbol).modifyFlags(
-      COFF::SF_WeakReference,
-      COFF::SF_WeakReference);
+  case MCSA_Weak: {
+      MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
+      SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal);
+      SD.setExternal(true);
+    }
     break;
 
   case MCSA_Global:
diff --git a/test/MC/COFF/weak.s b/test/MC/COFF/weak.s
new file mode 100644 (file)
index 0000000..d910059
--- /dev/null
@@ -0,0 +1,51 @@
+// This tests that default-null weak symbols (a GNU extension) are created\r
+// properly via the .weak directive.\r
+\r
+// RUN: llvm-mc -filetype=obj < %s | coff-dump.py | FileCheck %s\r
+\r
+    .def    _main;\r
+    .scl    2;\r
+    .type   32;\r
+    .endef\r
+    .text\r
+    .globl  _main\r
+    .align  16, 0x90\r
+_main:                                  # @main\r
+# BB#0:                                 # %entry\r
+    subl    $4, %esp\r
+    movl    $_test_weak, %eax\r
+    testl   %eax, %eax\r
+    je      LBB0_2\r
+# BB#1:                                 # %if.then\r
+    calll   _test_weak\r
+    movl    $1, %eax\r
+    addl    $4, %esp\r
+    ret\r
+LBB0_2:                                 # %return\r
+    xorl    %eax, %eax\r
+    addl    $4, %esp\r
+    ret\r
+\r
+    .weak   _test_weak\r
+\r
+// CHECK: Symbols = [\r
+\r
+// CHECK:      Name               = _test_weak\r
+// CHECK-NEXT: Value              = 0\r
+// CHECK-NEXT: SectionNumber      = 0\r
+// CHECK-NEXT: SimpleType         = IMAGE_SYM_TYPE_NULL (0)\r
+// CHECK-NEXT: ComplexType        = IMAGE_SYM_DTYPE_NULL (0)\r
+// CHECK-NEXT: StorageClass       = IMAGE_SYM_CLASS_WEAK_EXTERNAL (105)\r
+// CHECK-NEXT: NumberOfAuxSymbols = 1\r
+// CHECK-NEXT: AuxillaryData      =\r
+// CHECK-NEXT: 05 00 00 00 02 00 00 00 - 00 00 00 00 00 00 00 00 |................|\r
+// CHECK-NEXT: 00 00                                             |..|\r
+\r
+// CHECK:      Name               = .weak._test_weak.default\r
+// CHECK-NEXT: Value              = 0\r
+// CHECK-NEXT: SectionNumber      = 65535\r
+// CHECK-NEXT: SimpleType         = IMAGE_SYM_TYPE_NULL (0)\r
+// CHECK-NEXT: ComplexType        = IMAGE_SYM_DTYPE_NULL (0)\r
+// CHECK-NEXT: StorageClass       = IMAGE_SYM_CLASS_EXTERNAL (2)\r
+// CHECK-NEXT: NumberOfAuxSymbols = 0\r
+// CHECK-NEXT: AuxillaryData      =\r