Added testcase and removed triple check in favour of a TargetInfo query.

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D9297

Files:
  include/clang/Basic/TargetInfo.h
  lib/Basic/TargetInfo.cpp
  lib/Basic/Targets.cpp
  lib/CodeGen/CodeGenModule.cpp
  test/CodeGen/arm-bitfield-alignment.c

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -204,6 +204,11 @@
   /// not for language specific address spaces
   bool UseAddrSpaceMapMangling;
 
+  /// \brief Specify if globals of a struct type containing bitfields should
+  /// have their alignment explicitly specified so as to ensure that LLVM uses
+  /// the correct alignment
+  bool EnforceBitfieldContainerAlignment;
+
 public:
   IntType getSizeType() const { return SizeType; }
   IntType getIntMaxType() const { return IntMaxType; }
@@ -454,6 +459,11 @@
     return HasAlignMac68kSupport;
   }
 
+  /// \brief Check whether the alignment of bitfield struct should be enforced
+  bool enforceBitfieldContainerAlignment() const {
+    return EnforceBitfieldContainerAlignment;
+  }
+
   /// \brief Return the user string for the specified integer type enum.
   ///
   /// For example, SignedShort -> "short".
Index: lib/Basic/TargetInfo.cpp
===================================================================
--- lib/Basic/TargetInfo.cpp
+++ lib/Basic/TargetInfo.cpp
@@ -75,6 +75,7 @@
   RegParmMax = 0;
   SSERegParmMax = 0;
   HasAlignMac68kSupport = false;
+  EnforceBitfieldContainerAlignment = false;
 
   // Default to no types using fpret.
   RealTypeUsesObjCFPRet = 0;
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -3983,6 +3983,9 @@
 
     ZeroLengthBitfieldBoundary = 0;
 
+    // Enforce the alignment of bitfield structs
+    EnforceBitfieldContainerAlignment = true;
+
     // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
     // so set preferred for small types to 32.
     if (T.isOSBinFormatMachO()) {
@@ -4825,6 +4828,9 @@
     UseBitFieldTypeAlignment = true;
     UseZeroLengthBitfieldAlignment = true;
 
+    // Enforce the alignment of bitfield structs
+    EnforceBitfieldContainerAlignment = true;
+
     // AArch64 targets default to using the ARM C++ ABI.
     TheCXXABI.set(TargetCXXABI::GenericAArch64);
   }
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1799,6 +1799,24 @@
         D->getType().isConstant(Context) &&
         isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
       GV->setSection(".cp.rodata");
+
+    // The ARM/AArch64 ABI expects structs with bitfields to respect the proper
+    // container alignment, hence we have to enfore this in the IR so as to
+    // work around clang combining bitfields into one large type.
+    llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
+    if (getContext().getTargetInfo().enforceBitfieldContainerAlignment()) {
+      if (const auto *RT = D->getType()->getAs<RecordType>()) {
+        const RecordDecl *RD = RT->getDecl();
+
+        for (auto I = RD->field_begin(), End = RD->field_end(); I != End; ++I) {
+          if ((*I)->isBitField()) {
+            const ASTRecordLayout &Info = getContext().getASTRecordLayout(RD);
+            GV->setAlignment(Info.getAlignment().getQuantity());
+            break;
+          }
+        }
+      }
+    }
   }
 
   if (AddrSpace != Ty->getAddressSpace())
Index: test/CodeGen/arm-bitfield-alignment.c
===================================================================
--- /dev/null
+++ test/CodeGen/arm-bitfield-alignment.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple arm-none-eabi -ffreestanding -emit-llvm -o - -O3 %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64 -ffreestanding -emit-llvm -o - -O3 %s | FileCheck %s
+
+extern struct T {
+  int b0 : 8;
+  int b1 : 24;
+  int b2 : 1;
+} g;
+
+int func() {
+  return g.b1;
+}
+
+// CHECK: @g = external global %struct.T, align 4
+// CHECK: %{{.*}} = load i64, i64* bitcast (%struct.T* @g to i64*), align 4
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to