]> granicus.if.org Git - clang/commitdiff
On PowerPC64, integer arguments and return values need to be sign- or
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 5 Nov 2012 19:13:42 +0000 (19:13 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 5 Nov 2012 19:13:42 +0000 (19:13 +0000)
zero-extended to 64 bits.  This information is currently provided to
the back end by setting "signext" or "zeroext" attributes.  However,
this is done only for integer types *smaller* than i32, not for i32
itself.  This causes clang to generate code violating the ABI, which
results in a failure of the tramp3d-v4 test case (due to calling a
system library routine without ABI-required extension).

This patch implements custom versions of classifyArgumentType and
classifyReturnType for PPC64_SVR4_ABIInfo, which are the same as the
default versions except that they also classify "int" and "unsigned int"
as types needing extending.  This fixed tramp3d-v4 on PowerPC64.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167393 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGen/ppc64-extend.c [new file with mode: 0644]

index 7aed35956f3f42c2abb2c2ea361e7363b2d6ef4c..f07e9548b159f845a8aa1fce0a9c206d41eeef4b 100644 (file)
@@ -2684,6 +2684,11 @@ class PPC64_SVR4_ABIInfo : public DefaultABIInfo {
 public:
   PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
 
+  bool isPromotableTypeForABI(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType Ty) const;
+
   // TODO: We can add more logic to computeInfo to improve performance.
   // Example: For aggregate arguments that fit in a register, we could
   // use getDirectInReg (as is done below for structs containing a single
@@ -2744,6 +2749,59 @@ public:
 
 }
 
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool
+PPC64_SVR4_ABIInfo::isPromotableTypeForABI(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+    Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (Ty->isPromotableIntegerType())
+    return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs<BuiltinType>())
+    switch (BT->getKind()) {
+    case BuiltinType::Int:
+    case BuiltinType::UInt:
+      return true;
+    default:
+      break;
+    }
+
+  return false;
+}
+
+ABIArgInfo
+PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
+  if (isAggregateTypeForABI(Ty)) {
+    // Records with non trivial destructors/constructors should not be passed
+    // by value.
+    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+      return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+
+    return ABIArgInfo::getIndirect(0);
+  }
+
+  return (isPromotableTypeForABI(Ty) ?
+          ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
+ABIArgInfo
+PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const {
+  if (RetTy->isVoidType())
+    return ABIArgInfo::getIgnore();
+
+  if (isAggregateTypeForABI(RetTy))
+    return ABIArgInfo::getIndirect(0);
+
+  return (isPromotableTypeForABI(RetTy) ?
+          ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+}
+
 // Based on ARMABIInfo::EmitVAArg, adjusted for 64-bit machine.
 llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
                                            QualType Ty,
diff --git a/test/CodeGen/ppc64-extend.c b/test/CodeGen/ppc64-extend.c
new file mode 100644 (file)
index 0000000..f4d6bf9
--- /dev/null
@@ -0,0 +1,15 @@
+// REQUIRES: ppc64-registered-target
+// RUN: %clang_cc1 -O0 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+void f1(int x) { return; }
+// CHECK: define void @f1(i32 signext %x) nounwind 
+
+void f2(unsigned int x) { return; }
+// CHECK: define void @f2(i32 zeroext %x) nounwind 
+
+int f3(void) { return 0; }
+// CHECK: define signext i32 @f3() nounwind
+
+unsigned int f4(void) { return 0; }
+// CHECK: define zeroext i32 @f4() nounwind
+