[PowerPC] Add function pointer alignment to DataLayout
authorDavid Tenty <daltenty@ibm.com>
Tue, 18 Apr 2023 15:36:10 +0000 (11:36 -0400)
committerDavid Tenty <daltenty@ibm.com>
Tue, 18 Apr 2023 17:00:27 +0000 (13:00 -0400)
The alignment of function pointers was added to the Datalayout by
D57335 but currently is unset for the Power target. This will cause us
to compute a conservative minimum alignment of one if places like
Value::getPointerAlignment.

This patch implements the function pointer alignment in the Datalayout
for the Power backend and Power targets in clang, so we can query the
value for a particular Power target.

We come up with the correct value one of two ways:

- If the target uses function descriptor objects (i.e. ELFv1 & AIX ABIs),
  then a function pointer points to the descriptor, so use the alignment
  we would emit the descriptor with.
- If the target doesn't use function descriptor objects (i.e. ELFv2), a
  function pointer points to the global entry point, so use the minimum
  alignment for code on Power (i.e. 4-bytes).

Reviewed By: nemanjai

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

clang/lib/Basic/Targets/OSTargets.h
clang/lib/Basic/Targets/PPC.h
clang/test/CodeGen/target-data.c
llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
llvm/test/CodeGen/PowerPC/pr45301.ll
llvm/test/ThinLTO/X86/builtin-nostrip-aix.ll

index ea21f7e..cb2a68f 100644 (file)
@@ -519,7 +519,7 @@ public:
     this->IntMaxType = TargetInfo::SignedLongLong;
     this->Int64Type = TargetInfo::SignedLongLong;
     this->SizeType = TargetInfo::UnsignedInt;
-    this->resetDataLayout("E-m:e-p:32:32-i64:64-n32:64");
+    this->resetDataLayout("E-m:e-p:32:32-Fi64-i64:64-n32:64");
   }
 };
 
index 07a8a3a..8564fc0 100644 (file)
@@ -363,11 +363,11 @@ public:
   PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
       : PPCTargetInfo(Triple, Opts) {
     if (Triple.isOSAIX())
-      resetDataLayout("E-m:a-p:32:32-i64:64-n32");
+      resetDataLayout("E-m:a-p:32:32-Fi32-i64:64-n32");
     else if (Triple.getArch() == llvm::Triple::ppcle)
-      resetDataLayout("e-m:e-p:32:32-i64:64-n32");
+      resetDataLayout("e-m:e-p:32:32-Fn32-i64:64-n32");
     else
-      resetDataLayout("E-m:e-p:32:32-i64:64-n32");
+      resetDataLayout("E-m:e-p:32:32-Fn32-i64:64-n32");
 
     switch (getTriple().getOS()) {
     case llvm::Triple::Linux:
@@ -418,19 +418,23 @@ public:
 
     if (Triple.isOSAIX()) {
       // TODO: Set appropriate ABI for AIX platform.
-      DataLayout = "E-m:a-i64:64-n32:64";
+      DataLayout = "E-m:a-Fi64-i64:64-n32:64";
       LongDoubleWidth = 64;
       LongDoubleAlign = DoubleAlign = 32;
       LongDoubleFormat = &llvm::APFloat::IEEEdouble();
     } else if ((Triple.getArch() == llvm::Triple::ppc64le)) {
-      DataLayout = "e-m:e-i64:64-n32:64";
+      DataLayout = "e-m:e-Fn32-i64:64-n32:64";
       ABI = "elfv2";
     } else {
-      DataLayout = "E-m:e-i64:64-n32:64";
-      if (Triple.isPPC64ELFv2ABI())
+      DataLayout = "E-m:e";
+      if (Triple.isPPC64ELFv2ABI()) {
         ABI = "elfv2";
-      else
+        DataLayout += "-Fn32";
+      } else {
         ABI = "elfv1";
+        DataLayout += "-Fi64";
+      }
+      DataLayout += "-i64:64-n32:64";
     }
 
     if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) {
index e5ee17b..a7650c8 100644 (file)
@@ -88,7 +88,7 @@
 
 // RUN: %clang_cc1 -triple powerpc64-lv2 -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PS3
-// PS3: target datalayout = "E-m:e-p:32:32-i64:64-n32:64"
+// PS3: target datalayout = "E-m:e-p:32:32-Fi64-i64:64-n32:64"
 
 // RUN: %clang_cc1 -triple i686-nacl -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=I686-NACL
 
 // RUN: %clang_cc1 -triple powerpc-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC
-// PPC: target datalayout = "E-m:e-p:32:32-i64:64-n32"
+// PPC: target datalayout = "E-m:e-p:32:32-Fn32-i64:64-n32"
 
 // RUN: %clang_cc1 -triple powerpcle-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPCLE
-// PPCLE: target datalayout = "e-m:e-p:32:32-i64:64-n32"
+// PPCLE: target datalayout = "e-m:e-p:32:32-Fn32-i64:64-n32"
 
 // RUN: %clang_cc1 -triple powerpc64-freebsd -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64-FREEBSD
-// PPC64-FREEBSD: target datalayout = "E-m:e-i64:64-n32:64"
+// PPC64-FREEBSD: target datalayout = "E-m:e-Fn32-i64:64-n32:64"
 
 // RUN: %clang_cc1 -triple powerpc64le-freebsd -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64LE-FREEBSD
-// PPC64LE-FREEBSD: target datalayout = "e-m:e-i64:64-n32:64"
+// PPC64LE-FREEBSD: target datalayout = "e-m:e-Fn32-i64:64-n32:64"
 
 // RUN: %clang_cc1 -triple powerpc64-linux -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64-LINUX
-// PPC64-LINUX: target datalayout = "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+// PPC64-LINUX: target datalayout = "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64-linux -o - -emit-llvm -target-cpu future %s | \
 // RUN: FileCheck %s -check-prefix=PPC64-FUTURE
-// PPC64-FUTURE: target datalayout = "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+// PPC64-FUTURE: target datalayout = "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64-linux -o - -emit-llvm -target-cpu pwr10 %s | \
 // RUN: FileCheck %s -check-prefix=PPC64-P10
-// PPC64-P10: target datalayout = "E-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+// PPC64-P10: target datalayout = "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64le-linux -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=PPC64LE-LINUX
-// PPC64LE-LINUX: target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+// PPC64LE-LINUX: target datalayout = "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64le-linux -o - -emit-llvm -target-cpu future %s | \
 // RUN: FileCheck %s -check-prefix=PPC64LE-FUTURE
-// PPC64LE-FUTURE: target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+// PPC64LE-FUTURE: target datalayout = "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple powerpc64le-linux -o - -emit-llvm -target-cpu pwr10 %s | \
 // RUN: FileCheck %s -check-prefix=PPC64LE-P10
-// PPC64LE-P10: target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512"
+// PPC64LE-P10: target datalayout = "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
 
 // RUN: %clang_cc1 -triple nvptx-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=NVPTX
index 683a84e..3858d44 100644 (file)
@@ -161,6 +161,17 @@ static std::string getDataLayoutString(const Triple &T) {
   if (!is64Bit || T.getOS() == Triple::Lv2)
     Ret += "-p:32:32";
 
+  // If the target ABI uses function descriptors, then the alignment of function
+  // pointers depends on the alignment used to emit the descriptor. Otherwise,
+  // function pointers are aligned to 32 bits because the instructions must be.
+  if ((T.getArch() == Triple::ppc64 && !T.isPPC64ELFv2ABI())) {
+    Ret += "-Fi64";
+  } else if (T.isOSAIX()) {
+    Ret += is64Bit ? "-Fi64" : "-Fi32";
+  } else {
+    Ret += "-Fn32";
+  }
+
   // Note, the alignment values for f64 and i64 on ppc64 in Darwin
   // documentation are wrong; these are correct (i.e. "what gcc does").
   Ret += "-i64:64";
index fbd042f..bb6252e 100644 (file)
@@ -12,21 +12,21 @@ define dso_local void @g(ptr %agg.result) local_unnamed_addr #0 {
 ; CHECK-NEXT:    bl i
 ; CHECK-NEXT:    nop
 ; CHECK-NEXT:    addis r4, r2, g@toc@ha
-; CHECK-NEXT:    addi r4, r4, g@toc@l
-; CHECK-NEXT:    ld r5, 16(r4)
-; CHECK-NEXT:    std r5, 16(r3)
-; CHECK-NEXT:    ld r6, 0(r4)
-; CHECK-NEXT:    std r6, 0(r3)
-; CHECK-NEXT:    rldicl r6, r6, 32, 32
-; CHECK-NEXT:    ld r7, 8(r4)
+; CHECK-NEXT:    addi r5, r4, g@toc@l
+; CHECK-NEXT:    ld r6, 16(r5)
+; CHECK-NEXT:    std r6, 16(r3)
+; CHECK-NEXT:    ld r4, g@toc@l(r4)
+; CHECK-NEXT:    std r4, 0(r3)
+; CHECK-NEXT:    rldicl r4, r4, 32, 32
+; CHECK-NEXT:    ld r7, 8(r5)
 ; CHECK-NEXT:    std r7, 8(r3)
-; CHECK-NEXT:    ld r7, 24(r4)
+; CHECK-NEXT:    ld r7, 24(r5)
 ; CHECK-NEXT:    std r7, 24(r3)
-; CHECK-NEXT:    ld r4, 32(r4)
-; CHECK-NEXT:    std r4, 32(r3)
+; CHECK-NEXT:    ld r5, 32(r5)
+; CHECK-NEXT:    std r5, 32(r3)
+; CHECK-NEXT:    stwbrx r4, 0, r3
 ; CHECK-NEXT:    li r4, 20
-; CHECK-NEXT:    stwbrx r6, 0, r3
-; CHECK-NEXT:    stwbrx r5, r3, r4
+; CHECK-NEXT:    stwbrx r6, r3, r4
 ; CHECK-NEXT:    addi r1, r1, 112
 ; CHECK-NEXT:    ld r0, 16(r1)
 ; CHECK-NEXT:    mtlr r0
index 428a521..0f2a3c5 100644 (file)
@@ -30,7 +30,7 @@
 ; CHECK-NM: D __ssp_canary_word
 ; CHECK-NM: T __stack_chk_fail
 
-target datalayout = "E-m:a-p:32:32-i64:64-n32"
+target datalayout = "E-m:a-p:32:32-Fi32-i64:64-n32"
 target triple = "powerpc-ibm-aix-xcoff"
 
 define void @bar() {