Hi majnemer, rnk,

They cannot be written to, so marking them const makes sense and may improve 
optimisation.

The actual motivation for doing this is to fix this kind of link error when 
compiling ATL:
warning LNK4254: section 'ATL' (C0000040) merged into '.rdata' (40000040) with 
different attributes

The warning comes from ATL headers putting variables in a special section which 
only has the "read" flag set. The flags to #pragma section don't actually 
affect the generated IR. However, if all variables in the section are const, 
the section becomes read-only.

I'm happy to break out the move of SectionFlags from Sema to ASTContext in a 
separate patch.

http://reviews.llvm.org/D5812

Files:
  include/clang/AST/ASTContext.h
  include/clang/Sema/Sema.h
  lib/CodeGen/CodeGenModule.cpp
  lib/Parse/ParsePragma.cpp
  lib/Sema/SemaAttr.cpp
  lib/Sema/SemaDecl.cpp
  test/CodeGen/sections.c
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -2328,6 +2328,31 @@
   std::unique_ptr<ParentMap> AllParents;
 
   std::unique_ptr<VTableContextBase> VTContext;
+
+public:
+  enum PragmaSectionFlag : unsigned {
+    PSF_None = 0,
+    PSF_Read = 0x1,
+    PSF_Write = 0x2,
+    PSF_Execute = 0x4,
+    PSF_Implicit = 0x8,
+    PSF_Invalid = 0x80000000U,
+  };
+
+  struct SectionInfo {
+    DeclaratorDecl *Decl;
+    SourceLocation PragmaSectionLocation;
+    int SectionFlags;
+    SectionInfo() {}
+    SectionInfo(DeclaratorDecl *Decl,
+                SourceLocation PragmaSectionLocation,
+                int SectionFlags)
+      : Decl(Decl),
+        PragmaSectionLocation(PragmaSectionLocation),
+        SectionFlags(SectionFlags) {}
+  };
+
+  llvm::StringMap<SectionInfo> SectionInfos;
 };
 
 /// \brief Utility function for constructing a nullary selector.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -7218,29 +7218,6 @@
     PSK_CodeSeg,
   };
 
-  enum PragmaSectionFlag : unsigned {
-    PSF_None = 0,
-    PSF_Read = 0x1,
-    PSF_Write = 0x2,
-    PSF_Execute = 0x4,
-    PSF_Implicit = 0x8,
-    PSF_Invalid = 0x80000000U,
-  };
-
-  struct SectionInfo {
-    DeclaratorDecl *Decl;
-    SourceLocation PragmaSectionLocation;
-    int SectionFlags;
-    SectionInfo() {}
-    SectionInfo(DeclaratorDecl *Decl,
-                SourceLocation PragmaSectionLocation,
-                int SectionFlags)
-      : Decl(Decl),
-        PragmaSectionLocation(PragmaSectionLocation),
-        SectionFlags(SectionFlags) {}
-  };
-
-  llvm::StringMap<SectionInfo> SectionInfos;
   bool UnifySection(StringRef SectionName,
                     int SectionFlags,
                     DeclaratorDecl *TheDecl);
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1931,6 +1931,13 @@
   GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
                   isTypeConstant(D->getType(), true));
 
+  // If it is in a read-only section, mark it 'constant'.
+  if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
+    const ASTContext::SectionInfo &SI = Context.SectionInfos[SA->getName()];
+    if ((SI.SectionFlags & ASTContext::PSF_Write) == 0)
+      GV->setConstant(true);
+  }
+
   GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
 
   // Set the llvm linkage type as appropriate.
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "RAIIObjectsForParser.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/ParseDiagnostic.h"
@@ -539,20 +540,20 @@
           << PragmaName;
       return false;
     }
-    Sema::PragmaSectionFlag Flag =
-      llvm::StringSwitch<Sema::PragmaSectionFlag>(
+    ASTContext::PragmaSectionFlag Flag =
+      llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
       Tok.getIdentifierInfo()->getName())
-      .Case("read", Sema::PSF_Read)
-      .Case("write", Sema::PSF_Write)
-      .Case("execute", Sema::PSF_Execute)
-      .Case("shared", Sema::PSF_Invalid)
-      .Case("nopage", Sema::PSF_Invalid)
-      .Case("nocache", Sema::PSF_Invalid)
-      .Case("discard", Sema::PSF_Invalid)
-      .Case("remove", Sema::PSF_Invalid)
-      .Default(Sema::PSF_None);
-    if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
-      PP.Diag(PragmaLocation, Flag == Sema::PSF_None
+      .Case("read", ASTContext::PSF_Read)
+      .Case("write", ASTContext::PSF_Write)
+      .Case("execute", ASTContext::PSF_Execute)
+      .Case("shared", ASTContext::PSF_Invalid)
+      .Case("nopage", ASTContext::PSF_Invalid)
+      .Case("nocache", ASTContext::PSF_Invalid)
+      .Case("discard", ASTContext::PSF_Invalid)
+      .Case("remove", ASTContext::PSF_Invalid)
+      .Default(ASTContext::PSF_None);
+    if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
+      PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
                                   ? diag::warn_pragma_invalid_specific_action
                                   : diag::warn_pragma_unsupported_action)
           << PragmaName << Tok.getIdentifierInfo()->getName();
Index: lib/Sema/SemaAttr.cpp
===================================================================
--- lib/Sema/SemaAttr.cpp
+++ lib/Sema/SemaAttr.cpp
@@ -363,15 +363,15 @@
 bool Sema::UnifySection(StringRef SectionName,
                         int SectionFlags,
                         DeclaratorDecl *Decl) {
-  auto Section = SectionInfos.find(SectionName);
-  if (Section == SectionInfos.end()) {
-    SectionInfos[SectionName] =
-        SectionInfo(Decl, SourceLocation(), SectionFlags);
+  auto Section = Context.SectionInfos.find(SectionName);
+  if (Section == Context.SectionInfos.end()) {
+    Context.SectionInfos[SectionName] =
+        ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
     return false;
   }
   // A pre-declared section takes precedence w/o diagnostic.
   if (Section->second.SectionFlags == SectionFlags ||
-      !(Section->second.SectionFlags & PSF_Implicit))
+      !(Section->second.SectionFlags & ASTContext::PSF_Implicit))
     return false;
   auto OtherDecl = Section->second.Decl;
   Diag(Decl->getLocation(), diag::err_section_conflict)
@@ -390,20 +390,20 @@
 bool Sema::UnifySection(StringRef SectionName,
                         int SectionFlags,
                         SourceLocation PragmaSectionLocation) {
-  auto Section = SectionInfos.find(SectionName);
-  if (Section != SectionInfos.end()) {
+  auto Section = Context.SectionInfos.find(SectionName);
+  if (Section != Context.SectionInfos.end()) {
     if (Section->second.SectionFlags == SectionFlags)
       return false;
-    if (!(Section->second.SectionFlags & PSF_Implicit)) {
+    if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
       Diag(PragmaSectionLocation, diag::err_section_conflict)
           << "this" << "a prior #pragma section";
       Diag(Section->second.PragmaSectionLocation,
            diag::note_pragma_entered_here);
       return true;
     }
   }
-  SectionInfos[SectionName] =
-      SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
+  Context.SectionInfos[SectionName] =
+      ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
   return false;
 }
 
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -7334,7 +7334,9 @@
                                     CodeSegStack.CurrentValue->getString(),
                                     CodeSegStack.CurrentPragmaLocation));
     if (UnifySection(CodeSegStack.CurrentValue->getString(),
-                     PSF_Implicit | PSF_Execute | PSF_Read, NewFD))
+                     ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
+                         ASTContext::PSF_Read,
+                     NewFD))
       NewFD->dropAttr<SectionAttr>();
   }
 
@@ -9403,15 +9405,15 @@
   if (var->isThisDeclarationADefinition() &&
       ActiveTemplateInstantiations.empty()) {
     PragmaStack<StringLiteral *> *Stack = nullptr;
-    int SectionFlags = PSF_Implicit | PSF_Read;
+    int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read;
     if (var->getType().isConstQualified())
       Stack = &ConstSegStack;
     else if (!var->getInit()) {
       Stack = &BSSSegStack;
-      SectionFlags |= PSF_Write;
+      SectionFlags |= ASTContext::PSF_Write;
     } else {
       Stack = &DataSegStack;
-      SectionFlags |= PSF_Write;
+      SectionFlags |= ASTContext::PSF_Write;
     }
     if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue)
       var->addAttr(
Index: test/CodeGen/sections.c
===================================================================
--- test/CodeGen/sections.c
+++ test/CodeGen/sections.c
@@ -31,6 +31,14 @@
 int TEST1;
 #pragma bss_seg(pop)
 int TEST2;
+
+#pragma section("read_flag_section", read)
+// Even though they are not declared const, these become constant since they are
+// in a read-only section.
+__declspec(allocate("read_flag_section")) int unreferenced = 0;
+extern __declspec(allocate("read_flag_section")) int referenced = 42;
+int *user() { return &referenced; }
+
 #ifdef __cplusplus
 }
 #endif
@@ -47,5 +55,7 @@
 //CHECK: @i = global i32 0
 //CHECK: @TEST1 = global i32 0
 //CHECK: @TEST2 = global i32 0, section ".bss1"
+//CHECK: @unreferenced = constant i32 0, section "read_flag_section"
+//CHECK: @referenced = constant i32 42, section "read_flag_section"
 //CHECK: define void @g()
 //CHECK: define void @h() {{.*}} section ".my_code"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to