LiuChen3 updated this revision to Diff 220793.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60748/new/

https://reviews.llvm.org/D60748

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/x86_32-align-linux.c
  clang/test/CodeGen/x86_32-align-linux.cpp
  clang/test/CodeGen/x86_32-arguments-linux.c

Index: clang/test/CodeGen/x86_32-arguments-linux.c
===================================================================
--- clang/test/CodeGen/x86_32-arguments-linux.c
+++ clang/test/CodeGen/x86_32-arguments-linux.c
@@ -5,19 +5,19 @@
 // CHECK: i8 signext %a0, %struct.s56_0* byval(%struct.s56_0) align 4 %a1,
 // CHECK: i64 %a2.coerce, %struct.s56_1* byval(%struct.s56_1) align 4 %0,
 // CHECK: <1 x double> %a4, %struct.s56_2* byval(%struct.s56_2) align 4 %1,
-// CHECK: <4 x i32> %a6, %struct.s56_3* byval(%struct.s56_3) align 4 %2,
-// CHECK: <2 x double> %a8, %struct.s56_4* byval(%struct.s56_4) align 4 %3,
-// CHECK: <8 x i32> %a10, %struct.s56_5* byval(%struct.s56_5) align 4 %4,
-// CHECK: <4 x double> %a12, %struct.s56_6* byval(%struct.s56_6) align 4 %5)
+// CHECK: <4 x i32> %a6, %struct.s56_3* byval(%struct.s56_3) align 16 %a7,
+// CHECK: <2 x double> %a8, %struct.s56_4* byval(%struct.s56_4) align 16 %a9,
+// CHECK: <8 x i32> %a10, %struct.s56_5* byval(%struct.s56_5) align 32 %a11,
+// CHECK: <4 x double> %a12, %struct.s56_6* byval(%struct.s56_6) align 32 %a13)
 
 // CHECK: call void (i32, ...) @f56_0(i32 1,
 // CHECK: i32 %{{.*}}, %struct.s56_0* byval(%struct.s56_0) align 4 %{{[^ ]*}},
 // CHECK: i64 %{{[^ ]*}}, %struct.s56_1* byval(%struct.s56_1) align 4 %{{[^ ]*}},
 // CHECK: <1 x double> %{{[^ ]*}}, %struct.s56_2* byval(%struct.s56_2) align 4 %{{[^ ]*}},
-// CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval(%struct.s56_3) align 4 %{{[^ ]*}},
-// CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval(%struct.s56_4) align 4 %{{[^ ]*}},
-// CHECK: <8 x i32> %{{[^ ]*}}, %struct.s56_5* byval(%struct.s56_5) align 4 %{{[^ ]*}},
-// CHECK: <4 x double> %{{[^ ]*}}, %struct.s56_6* byval(%struct.s56_6) align 4 %{{[^ ]*}})
+// CHECK: <4 x i32> %{{[^ ]*}}, %struct.s56_3* byval(%struct.s56_3) align 16 %{{[^ ]*}},
+// CHECK: <2 x double> %{{[^ ]*}}, %struct.s56_4* byval(%struct.s56_4) align 16 %{{[^ ]*}},
+// CHECK: <8 x i32> %{{[^ ]*}}, %struct.s56_5* byval(%struct.s56_5) align 32 %{{[^ ]*}},
+// CHECK: <4 x double> %{{[^ ]*}}, %struct.s56_6* byval(%struct.s56_6) align 32 %{{[^ ]*}})
 // CHECK: }
 //
 // <rdar://problem/7964854> [i386] clang misaligns long double in structures
Index: clang/test/CodeGen/x86_32-align-linux.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/x86_32-align-linux.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -w -fblocks -ffreestanding -triple i386-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: FileCheck < %t %s
+
+#include <immintrin.h>
+
+typedef __attribute__((aligned(16))) int alignedint16;
+typedef __attribute__((aligned(64))) int alignedint64;
+
+class __attribute__((aligned(64))) X1 {
+  class  __attribute__((aligned(32))) {
+   __m128 a1;
+  } a;
+  int b;
+};
+
+class __attribute__((aligned(64))) X2 {
+  class  __attribute__((aligned(32))) {
+    int a1;
+    alignedint16 a2;
+  } a;
+  int b;
+};
+
+class __attribute__((aligned(32))) X3 {
+  class __attribute__((aligned(64))) {
+    int a1;
+    alignedint16 a2;
+  } a;
+ int b;
+};
+
+class __attribute__((aligned(16))) X4 {
+  class  __attribute__((aligned(32))) {
+    int a1;
+    alignedint64 a2;
+  } a;
+  int b;
+};
+
+class __attribute__((aligned(64))) X5 {
+  int x;
+};
+
+class __attribute__((aligned(64))) X6 {
+  int x;
+  alignedint64 y;
+};
+
+extern void foo(int, ...);
+
+class X1 x1;
+class X2 x2;
+class X3 x3;
+class X4 x4;
+class X5 x5;
+class X6 x6;
+
+// CHECK-LABEL: define void @_Z4testv()
+// CHECK: entry:
+// CHECK: call void (i32, ...) @_Z3fooiz(i32 1, %class.X1* byval(%class.X1) align 64
+// CHECK: call void (i32, ...) @_Z3fooiz(i32 1, %class.X2* byval(%class.X2) align 64
+// CHECK: call void (i32, ...) @_Z3fooiz(i32 1, %class.X3* byval(%class.X3) align 64
+// CHECK: call void (i32, ...) @_Z3fooiz(i32 1, %class.X4* byval(%class.X4) align 64
+// CHECK: call void (i32, ...) @_Z3fooiz(i32 1, %class.X5* byval(%class.X5) align 4
+// CHECK: call void (i32, ...) @_Z3fooiz(i32 1, %class.X6* byval(%class.X6) align 64
+
+void test(void)
+{
+  foo(1, x1);
+  foo(1, x2);
+  foo(1, x3);
+  foo(1, x4);
+  foo(1, x5);
+  foo(1, x6);
+}
Index: clang/test/CodeGen/x86_32-align-linux.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/x86_32-align-linux.c
@@ -0,0 +1,96 @@
+// RUN: %clang_cc1 -w -fblocks -ffreestanding -triple i386-pc-linux-gnu -emit-llvm -o %t %s
+// RUN: FileCheck < %t %s
+
+#include <immintrin.h>
+
+typedef union {
+  int d[4];
+   __m128 m;
+} M128;
+
+typedef __attribute__((aligned(16))) int alignedint16;
+typedef __attribute__((aligned(64))) int alignedint64;
+
+struct __attribute__((aligned(64))) X1 {
+ struct  __attribute__((aligned(32))) {
+  int a1;
+ } a;
+ int b;
+};
+
+
+struct __attribute__((aligned(64))) X2 {
+ struct  __attribute__((aligned(32))) {
+  int a1;
+  alignedint16 a2;
+ } a;
+ int b;
+};
+
+struct __attribute__((aligned(32))) X3 {
+ struct __attribute__((aligned(64))) {
+  int a1;
+  alignedint16 a2;
+ } a;
+ int b;
+};
+
+struct __attribute__((aligned(16))) X4 {
+ struct  __attribute__((aligned(32))) {
+  int a1;
+  alignedint64 a2;
+ } a;
+ int b;
+};
+
+struct __attribute__((aligned(64))) X5 {
+  int x;
+};
+
+struct __attribute__((aligned(64))) X6 {
+ int x;
+ alignedint64 y;
+};
+
+union U1 {
+ struct __attribute__((aligned(32))) {
+  int i;
+  __m128 m;
+ };
+ int b;
+};
+
+extern void foo(int, ...);
+
+M128 a;
+struct X1 x1;
+struct X2 x2;
+struct X3 x3;
+struct X4 x4;
+struct X5 x5;
+struct X6 x6;
+union  U1 u1;
+
+// CHECK-LABEL: define void @test
+// CHECK: entry:
+// CHECK: call void (i32, ...) @foo(i32 1, %union.M128* byval(%union.M128) align 16
+// CHECK: call void (i32, ...) @foo(i32 1, <4 x float>
+// CHECK: call void (i32, ...) @foo(i32 1, %struct.X1* byval(%struct.X1) align 4
+// CHECK: call void (i32, ...) @foo(i32 1, %struct.X2* byval(%struct.X2) align 64
+// CHECK: call void (i32, ...) @foo(i32 1, %struct.X3* byval(%struct.X3) align 64
+// CHECK: call void (i32, ...) @foo(i32 1, %struct.X4* byval(%struct.X4) align 64
+// CHECK: call void (i32, ...) @foo(i32 1, %struct.X5* byval(%struct.X5) align 4
+// CHECK: call void (i32, ...) @foo(i32 1, %struct.X6* byval(%struct.X6) align 64
+// CHECK: call void (i32, ...) @foo(i32 1, %union.U1* byval(%union.U1) align 32
+void test(void)
+{
+  foo(1, a);
+  foo(1, a.m);
+  foo(1, x1);
+  foo(1, x2);
+  foo(1, x3);
+  foo(1, x4);
+  foo(1, x5);
+  foo(1, x6);
+  foo(1, u1);
+}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -1015,6 +1015,7 @@
   bool IsWin32StructABI;
   bool IsSoftFloatABI;
   bool IsMCUABI;
+  bool IsLinuxABI;
   unsigned DefaultNumRegisterParameters;
 
   static bool isRegisterSize(unsigned Size) {
@@ -1081,6 +1082,7 @@
       IsWin32StructABI(Win32StructABI),
       IsSoftFloatABI(SoftFloatABI),
       IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()),
+      IsLinuxABI(CGT.getTarget().getTriple().isOSLinux()),
       DefaultNumRegisterParameters(NumRegisterParameters) {}
 
   bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
@@ -1497,8 +1499,42 @@
   if (Align <= MinABIStackAlignInBytes)
     return 0; // Use default alignment.
 
+  if (IsLinuxABI) {
+    // i386 System V ABI 2.1: Structures and unions assume the alignment of their
+    // most strictly aligned component.
+    //
+    // Exclude other System V OS (e.g Darwin, PS4 and FreeBSD) since we don't
+    // want to spend any effort dealing with the ramifications of ABI breaks.
+    //
+    // If the type is a struct/union/class type
+    if (const RecordType *RT = Ty->getAs<RecordType>()) {
+      unsigned MaxAlignment = 0;
+      const RecordDecl *RD = RT->getDecl();
+
+      for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+           i != e; ++i) {
+        QualType QT = i->getType();
+        unsigned TempAlignment = 0;
+        if (isAggregateTypeForABI(QT)) {
+          if (const auto *AT = QT->getAsArrayTypeUnsafe())
+            TempAlignment = getContext().getTypeAlign(AT->getElementType()) / 8;
+          else // recursively to get each type's alignment
+            TempAlignment = getTypeStackAlignInBytes(QT, getContext().getTypeAlign(QT) / 8);
+        } else
+          TempAlignment = getContext().getTypeAlign(QT) / 8;
+        MaxAlignment = std::max(MaxAlignment, TempAlignment);
+      }
+      if (MaxAlignment >= 16)
+        return std::max(MaxAlignment, Align);
+      else // return 4 when all the type alignments less than 16 bytes
+        return 4;
+    } else if (Align < 16)
+      return MinABIStackAlignInBytes;
+    else  // Otherwise
+      return Align;
+  }
   // On non-Darwin, the stack type alignment is always 4.
-  if (!IsDarwinVectorABI) {
+  else if (!IsDarwinVectorABI) {
     // Set explicit alignment, since we may need to realign the top.
     return MinABIStackAlignInBytes;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to