[clang] 21aa107 - Reland "Do not create LLVM IR `constant`s for objects with dynamic initialisation"

Momchil Velikov via cfe-commits cfe-commits at lists.llvm.org
Tue May 25 07:55:49 PDT 2021


Author: Momchil Velikov
Date: 2021-05-25T15:54:40+01:00
New Revision: 21aa107eb79f8ddc5e7ca4e8f3476338dfa90049

URL: https://github.com/llvm/llvm-project/commit/21aa107eb79f8ddc5e7ca4e8f3476338dfa90049
DIFF: https://github.com/llvm/llvm-project/commit/21aa107eb79f8ddc5e7ca4e8f3476338dfa90049.diff

LOG: Reland "Do not create LLVM IR `constant`s for objects with dynamic initialisation"

This relands commit 13dd65b3a1a3ac049b5f3a9712059f7c61649bea.

The original commit contained a test, which failed when compiled
for a MACH-O target.

This patch changes the test to run for x86_64-linux instead of
`%itanium_abi_triple`, to avoid having invalid syntax for MACH-O
sections. The patch itself does not care about section attribute
syntax and a x86 backend does not even need to be included in the
build.

Differential Revision: https://reviews.llvm.org/D102693

Added: 
    clang/test/CodeGenCXX/clang-sections-1.cpp
    clang/test/CodeGenCXX/const-dynamic-init.cpp

Modified: 
    clang/lib/Sema/SemaDecl.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 601f4f2502f0..e08e8d8346c0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13047,43 +13047,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
     }
   }
 
-  // Apply section attributes and pragmas to global variables.
-  bool GlobalStorage = var->hasGlobalStorage();
-  if (GlobalStorage && var->isThisDeclarationADefinition() &&
-      !inTemplateInstantiation()) {
-    PragmaStack<StringLiteral *> *Stack = nullptr;
-    int SectionFlags = ASTContext::PSF_Read;
-    if (var->getType().isConstQualified())
-      Stack = &ConstSegStack;
-    else if (!var->getInit()) {
-      Stack = &BSSSegStack;
-      SectionFlags |= ASTContext::PSF_Write;
-    } else {
-      Stack = &DataSegStack;
-      SectionFlags |= ASTContext::PSF_Write;
-    }
-    if (const SectionAttr *SA = var->getAttr<SectionAttr>()) {
-      if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec)
-        SectionFlags |= ASTContext::PSF_Implicit;
-      UnifySection(SA->getName(), SectionFlags, var);
-    } else if (Stack->CurrentValue) {
-      SectionFlags |= ASTContext::PSF_Implicit;
-      auto SectionName = Stack->CurrentValue->getString();
-      var->addAttr(SectionAttr::CreateImplicit(
-          Context, SectionName, Stack->CurrentPragmaLocation,
-          AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate));
-      if (UnifySection(SectionName, SectionFlags, var))
-        var->dropAttr<SectionAttr>();
-    }
-
-    // Apply the init_seg attribute if this has an initializer.  If the
-    // initializer turns out to not be dynamic, we'll end up ignoring this
-    // attribute.
-    if (CurInitSeg && var->getInit())
-      var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
-                                               CurInitSegLoc,
-                                               AttributeCommonInfo::AS_Pragma));
-  }
 
   if (!var->getType()->isStructureType() && var->hasInit() &&
       isa<InitListExpr>(var->getInit())) {
@@ -13133,14 +13096,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
       }
   }
 
-  // All the following checks are C++ only.
-  if (!getLangOpts().CPlusPlus) {
-    // If this variable must be emitted, add it as an initializer for the
-    // current module.
-    if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
-      Context.addModuleInitializer(ModuleScopes.back().Module, var);
-    return;
-  }
 
   QualType type = var->getType();
 
@@ -13148,11 +13103,14 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
     getCurFunction()->addByrefBlockVar(var);
 
   Expr *Init = var->getInit();
+  bool GlobalStorage = var->hasGlobalStorage();
   bool IsGlobal = GlobalStorage && !var->isStaticLocal();
   QualType baseType = Context.getBaseElementType(type);
+  bool HasConstInit = true;
 
   // Check whether the initializer is sufficiently constant.
-  if (!type->isDependentType() && Init && !Init->isValueDependent() &&
+  if (getLangOpts().CPlusPlus && !type->isDependentType() && Init &&
+      !Init->isValueDependent() &&
       (GlobalStorage || var->isConstexpr() ||
        var->mightBeUsableInConstantExpressions(Context))) {
     // If this variable might have a constant initializer or might be usable in
@@ -13160,7 +13118,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
     // do this lazily, because the result might depend on things that change
     // later, such as which constexpr functions happen to be defined.
     SmallVector<PartialDiagnosticAt, 8> Notes;
-    bool HasConstInit;
     if (!getLangOpts().CPlusPlus11) {
       // Prior to C++11, in contexts where a constant initializer is required,
       // the set of valid constant initializers is described by syntactic rules
@@ -13225,6 +13182,57 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
     }
   }
 
+  // Apply section attributes and pragmas to global variables.
+  if (GlobalStorage && var->isThisDeclarationADefinition() &&
+      !inTemplateInstantiation()) {
+    PragmaStack<StringLiteral *> *Stack = nullptr;
+    int SectionFlags = ASTContext::PSF_Read;
+    if (var->getType().isConstQualified()) {
+      if (HasConstInit)
+        Stack = &ConstSegStack;
+      else {
+        Stack = &BSSSegStack;
+        SectionFlags |= ASTContext::PSF_Write;
+      }
+    } else if (var->hasInit() && HasConstInit) {
+      Stack = &DataSegStack;
+      SectionFlags |= ASTContext::PSF_Write;
+    } else {
+      Stack = &BSSSegStack;
+      SectionFlags |= ASTContext::PSF_Write;
+    }
+    if (const SectionAttr *SA = var->getAttr<SectionAttr>()) {
+      if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec)
+        SectionFlags |= ASTContext::PSF_Implicit;
+      UnifySection(SA->getName(), SectionFlags, var);
+    } else if (Stack->CurrentValue) {
+      SectionFlags |= ASTContext::PSF_Implicit;
+      auto SectionName = Stack->CurrentValue->getString();
+      var->addAttr(SectionAttr::CreateImplicit(
+          Context, SectionName, Stack->CurrentPragmaLocation,
+          AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate));
+      if (UnifySection(SectionName, SectionFlags, var))
+        var->dropAttr<SectionAttr>();
+    }
+
+    // Apply the init_seg attribute if this has an initializer.  If the
+    // initializer turns out to not be dynamic, we'll end up ignoring this
+    // attribute.
+    if (CurInitSeg && var->getInit())
+      var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
+                                               CurInitSegLoc,
+                                               AttributeCommonInfo::AS_Pragma));
+  }
+
+  // All the following checks are C++ only.
+  if (!getLangOpts().CPlusPlus) {
+    // If this variable must be emitted, add it as an initializer for the
+    // current module.
+    if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+      Context.addModuleInitializer(ModuleScopes.back().Module, var);
+    return;
+  }
+
   // Require the destructor.
   if (!type->isDependentType())
     if (const RecordType *recordType = baseType->getAs<RecordType>())

diff  --git a/clang/test/CodeGenCXX/clang-sections-1.cpp b/clang/test/CodeGenCXX/clang-sections-1.cpp
new file mode 100644
index 000000000000..5dbfb0afac22
--- /dev/null
+++ b/clang/test/CodeGenCXX/clang-sections-1.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-linux         -S -o - %s | FileCheck %s --check-prefix=ASM
+// Actually, any ELF target would do
+// REQUIRES: x86_64-linux
+
+#pragma clang section bss = "B$$" data = "d at t@" rodata = "r0d at t@"
+
+const int a = 1;
+const int *f() { return &a; }
+
+int init();
+const int b = init();
+
+int c = 2;
+
+int d = init();
+
+int e;
+
+// LLVM: @_ZL1a = internal constant i32 1, align 4 #[[#A:]]
+// LLVM: @_ZL1b = internal global i32 0, align 4 #[[#A]]
+// LLVM: @c = {{.*}}global i32 2, align 4 #[[#A]]
+// LLVM: @d = {{.*}}global i32 0, align 4 #[[#A]]
+// LLVM: @e = {{.*}}global i32 0, align 4 #[[#A]]
+
+// LLVM: attributes #[[#A]] = { "bss-section"="B$$" "data-section"="d at t@" "rodata-section"="r0d at t@" }
+
+// ASM:       .section "r0d at t@","a", at progbits
+// ASM-NOT:   .section
+// ASM-LABEL: _ZL1a:
+// ASM-NEXT:  .long 1
+
+// ASM:       .section "B$$","aw", at nobits
+// ASM-NOT:   .section
+// ASM-LABEL: _ZL1b:
+// ASM-NEXT: .long 0
+
+// ASM:       .section "d at t@","aw", at progbits
+// ASM-NOT:   .section
+// ASM-LABEL: c:
+// ASM:       .long 2
+
+// ASM:       .section "B$$","aw", at nobits
+// ASM-NOT:   .section
+// ASM-LABEL: d:
+// ASM:       .long 0
+
+// ASM-NOT:   .section
+// ASM-LABEL: e:
+// ASM        .long 0

diff  --git a/clang/test/CodeGenCXX/const-dynamic-init.cpp b/clang/test/CodeGenCXX/const-dynamic-init.cpp
new file mode 100644
index 000000000000..ec53daa9ea2a
--- /dev/null
+++ b/clang/test/CodeGenCXX/const-dynamic-init.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
+
+__attribute__((section("A")))
+const int a = 1;
+const int *f() { return &a; }
+// CHECK: @_ZL1a = internal constant i32 1, section "A"
+
+int init();
+__attribute__((section("B")))
+const int b = init();
+// Even if it's const-qualified, it must not be LLVM IR `constant` since it's
+// dynamically initialised.
+// CHECK: @_ZL1b = internal global i32 0, section "B"
+
+__attribute__((section("C")))
+int c = 2;
+// CHECK: @c = {{.*}}global i32 2, section "C"
+
+__attribute__((section("D")))
+int d = init();
+// CHECK: @d = {{.*}}global i32 0, section "D"
+
+__attribute__((section("E")))
+int e;
+// CHECK: @e = {{.*}}global i32 0, section "E", align 4


        


More information about the cfe-commits mailing list