switch MCSectionCOFF from a syntactic to semantic representation,
patch by Peter Housel!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103267 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 9f95993..b74ed56 100644
--- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -22,6 +22,7 @@
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/Target/Mangler.h"
 #include "llvm/Target/TargetData.h"
@@ -794,89 +795,147 @@
 //                                  COFF
 //===----------------------------------------------------------------------===//
 
-typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
-
-TargetLoweringObjectFileCOFF::~TargetLoweringObjectFileCOFF() {
-  delete (COFFUniqueMapTy*)UniquingMap;
-}
-
-
-const MCSection *TargetLoweringObjectFileCOFF::
-getCOFFSection(StringRef Name, bool isDirective, SectionKind Kind) const {
-  // Create the map if it doesn't already exist.
-  if (UniquingMap == 0)
-    UniquingMap = new COFFUniqueMapTy();
-  COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)UniquingMap;
-
-  // Do the lookup, if we have a hit, return it.
-  const MCSectionCOFF *&Entry = Map[Name];
-  if (Entry) return Entry;
-
-  return Entry = MCSectionCOFF::Create(Name, isDirective, Kind, getContext());
-}
-
 void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx,
                                               const TargetMachine &TM) {
-  if (UniquingMap != 0)
-    ((COFFUniqueMapTy*)UniquingMap)->clear();
   TargetLoweringObjectFile::Initialize(Ctx, TM);
-  TextSection = getCOFFSection("\t.text", true, SectionKind::getText());
-  DataSection = getCOFFSection("\t.data", true, SectionKind::getDataRel());
+  TextSection =
+    getContext().getCOFFSection(".text",
+                                MCSectionCOFF::IMAGE_SCN_CNT_CODE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_EXECUTE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getText());
+  DataSection =
+    getContext().getCOFFSection(".data",
+                                MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ |
+                                MCSectionCOFF::IMAGE_SCN_MEM_WRITE,
+                                SectionKind::getDataRel());
+  ReadOnlySection =
+    getContext().getCOFFSection(".rdata",
+                                MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getReadOnly());
   StaticCtorSection =
-    getCOFFSection(".ctors", false, SectionKind::getDataRel());
+    getContext().getCOFFSection(".ctors",
+                                MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ |
+                                MCSectionCOFF::IMAGE_SCN_MEM_WRITE,
+                                SectionKind::getDataRel());
   StaticDtorSection =
-    getCOFFSection(".dtors", false, SectionKind::getDataRel());
+    getContext().getCOFFSection(".dtors",
+                                MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ |
+                                MCSectionCOFF::IMAGE_SCN_MEM_WRITE,
+                                SectionKind::getDataRel());
 
   // FIXME: We're emitting LSDA info into a readonly section on COFF, even
   // though it contains relocatable pointers.  In PIC mode, this is probably a
   // big runtime hit for C++ apps.  Either the contents of the LSDA need to be
   // adjusted or this should be a data section.
   LSDASection =
-    getCOFFSection(".gcc_except_table", false, SectionKind::getReadOnly());
+    getContext().getCOFFSection(".gcc_except_table",
+                                MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getReadOnly());
   EHFrameSection =
-    getCOFFSection(".eh_frame", false, SectionKind::getDataRel());
+    getContext().getCOFFSection(".eh_frame",
+                                MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ |
+                                MCSectionCOFF::IMAGE_SCN_MEM_WRITE,
+                                SectionKind::getDataRel());
 
   // Debug info.
-  // FIXME: Don't use 'directive' mode here.
   DwarfAbbrevSection =
-    getCOFFSection("\t.section\t.debug_abbrev,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_abbrev",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfInfoSection =
-    getCOFFSection("\t.section\t.debug_info,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_info",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfLineSection =
-    getCOFFSection("\t.section\t.debug_line,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_line",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfFrameSection =
-    getCOFFSection("\t.section\t.debug_frame,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_frame",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfPubNamesSection =
-    getCOFFSection("\t.section\t.debug_pubnames,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_pubnames",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfPubTypesSection =
-    getCOFFSection("\t.section\t.debug_pubtypes,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_pubtypes",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfStrSection =
-    getCOFFSection("\t.section\t.debug_str,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_str",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfLocSection =
-    getCOFFSection("\t.section\t.debug_loc,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_loc",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfARangesSection =
-    getCOFFSection("\t.section\t.debug_aranges,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_aranges",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfRangesSection =
-    getCOFFSection("\t.section\t.debug_ranges,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_ranges",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
   DwarfMacroInfoSection =
-    getCOFFSection("\t.section\t.debug_macinfo,\"dr\"",
-                   true, SectionKind::getMetadata());
+    getContext().getCOFFSection(".debug_macinfo",
+                                MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE |
+                                MCSectionCOFF::IMAGE_SCN_MEM_READ,
+                                SectionKind::getMetadata());
+
+  DrectveSection =
+    getContext().getCOFFSection(".drectve",
+                                MCSectionCOFF::IMAGE_SCN_LNK_INFO,
+                                SectionKind::getMetadata());
+}
+
+static unsigned
+getCOFFSectionFlags(SectionKind K) {
+  unsigned Flags = 0;
+
+  if (!K.isMetadata())
+    Flags |= MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE;
+  else if (K.isText())
+    Flags |=
+      MCSectionCOFF::IMAGE_SCN_MEM_EXECUTE |
+      MCSectionCOFF::IMAGE_SCN_CNT_CODE;
+  else if (K.isReadOnly())
+    Flags |=
+      MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+      MCSectionCOFF::IMAGE_SCN_MEM_READ;
+  else if (K.isWriteable())
+    Flags |=
+      MCSectionCOFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+      MCSectionCOFF::IMAGE_SCN_MEM_READ |
+      MCSectionCOFF::IMAGE_SCN_MEM_WRITE;
+
+  return Flags;
 }
 
 const MCSection *TargetLoweringObjectFileCOFF::
 getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
                          Mangler *Mang, const TargetMachine &TM) const {
-  return getCOFFSection(GV->getSection(), false, Kind);
+  return getContext().getCOFFSection(GV->getSection(),
+                                     getCOFFSectionFlags(Kind),
+                                     Kind);
 }
 
 static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
@@ -900,7 +959,9 @@
     SmallString<128> Name(Prefix, Prefix+strlen(Prefix));
     MCSymbol *Sym = Mang->getSymbol(GV);
     Name.append(Sym->getName().begin(), Sym->getName().end());
-    return getCOFFSection(Name.str(), false, Kind);
+    return getContext().getCOFFSection(Name.str(),
+                                       getCOFFSectionFlags(Kind),
+                                       Kind);
   }
 
   if (Kind.isText())
diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp
index dc757bb..93388c0 100644
--- a/lib/MC/MCContext.cpp
+++ b/lib/MC/MCContext.cpp
@@ -11,6 +11,7 @@
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
@@ -18,11 +19,13 @@
 
 typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
 typedef StringMap<const MCSectionELF*> ELFUniqueMapTy;
+typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
 
 
 MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0) {
   MachOUniquingMap = 0;
   ELFUniquingMap = 0;
+  COFFUniquingMap = 0;
 }
 
 MCContext::~MCContext() {
@@ -32,6 +35,7 @@
   // If we have the MachO uniquing map, free it.
   delete (MachOUniqueMapTy*)MachOUniquingMap;
   delete (ELFUniqueMapTy*)ELFUniquingMap;
+  delete (COFFUniqueMapTy*)COFFUniquingMap;
 }
 
 //===----------------------------------------------------------------------===//
@@ -122,4 +126,19 @@
   return Result;
 }
 
-
+const MCSection *MCContext::
+getCOFFSection(StringRef Section, unsigned Flags, SectionKind Kind) {
+  if (COFFUniquingMap == 0)
+    COFFUniquingMap = new COFFUniqueMapTy();
+  COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap;
+  
+  // Do the lookup, if we have a hit, return it.
+  StringMapEntry<const MCSectionCOFF*> &Entry = Map.GetOrCreateValue(Section);
+  if (Entry.getValue()) return Entry.getValue();
+  
+  MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), Flags,
+                                                    Kind);
+  
+  Entry.setValue(Result);
+  return Result;
+}
diff --git a/lib/MC/MCSection.cpp b/lib/MC/MCSection.cpp
index f6e9636..a792d56 100644
--- a/lib/MC/MCSection.cpp
+++ b/lib/MC/MCSection.cpp
@@ -20,30 +20,3 @@
 MCSection::~MCSection() {
 }
 
-//===----------------------------------------------------------------------===//
-// MCSectionCOFF
-//===----------------------------------------------------------------------===//
-
-MCSectionCOFF *MCSectionCOFF::
-Create(StringRef Name, bool IsDirective, SectionKind K, MCContext &Ctx) {
-  char *NameCopy = static_cast<char*>(
-    Ctx.Allocate(Name.size(), /*Alignment=*/1));
-  memcpy(NameCopy, Name.data(), Name.size());
-  return new (Ctx) MCSectionCOFF(StringRef(NameCopy, Name.size()),
-                                 IsDirective, K);
-}
-
-void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI,
-                                         raw_ostream &OS) const {
-  
-  if (isDirective()) {
-    OS << getName() << '\n';
-    return;
-  }
-  OS << "\t.section\t" << getName() << ",\"";
-  if (getKind().isText())
-    OS << 'x';
-  if (getKind().isWriteable())
-    OS << 'w';
-  OS << "\"\n";
-}
diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp
new file mode 100644
index 0000000..f26768a
--- /dev/null
+++ b/lib/MC/MCSectionCOFF.cpp
@@ -0,0 +1,49 @@
+//===- lib/MC/MCSectionCOFF.cpp - COFF Code Section Representation --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+MCSectionCOFF::~MCSectionCOFF() {} // anchor.
+
+// ShouldOmitSectionDirective - Decides whether a '.section' directive
+// should be printed before the section name
+bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name,
+                                               const MCAsmInfo &MAI) const {
+  
+  // FIXME: Does .section .bss/.data/.text work everywhere??
+  if (Name == ".text" || Name == ".data" || Name == ".bss")
+    return true;
+
+  return false;
+}
+
+void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI,
+                                         raw_ostream &OS) const {
+  
+  if (ShouldOmitSectionDirective(SectionName, MAI)) {
+    OS << '\t' << getSectionName() << '\n';
+    return;
+  }
+
+  OS << "\t.section\t" << getSectionName() << ",\"";
+  if (getKind().isText())
+    OS << 'x';
+  if (getKind().isWriteable())
+    OS << 'w';
+  else
+    OS << 'r';
+  if (getFlags() & MCSectionCOFF::IMAGE_SCN_MEM_DISCARDABLE)
+    OS << 'n';
+  OS << "\"\n";
+}
diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
index 8b0ed1c..016a8c2 100644
--- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp
@@ -598,9 +598,7 @@
 
       // Output linker support code for dllexported globals on windows.
       if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) {
-        OutStreamer.SwitchSection(TLOFCOFF.getCOFFSection(".section .drectve",
-                                                          true,
-                                                   SectionKind::getMetadata()));
+        OutStreamer.SwitchSection(TLOFCOFF.getDrectveSection());
         for (unsigned i = 0, e = DLLExportedGlobals.size(); i != e; ++i)
           OutStreamer.EmitRawText("\t.ascii \" -export:" +
                                   Twine(DLLExportedGlobals[i]->getName()) +