]> granicus.if.org Git - clang/commitdiff
This patch addresses a 64-bit PowerPC ELF ABI compatibility issue with
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>
Fri, 26 Oct 2012 19:59:03 +0000 (19:59 +0000)
committerBill Schmidt <wschmidt@linux.vnet.ibm.com>
Fri, 26 Oct 2012 19:59:03 +0000 (19:59 +0000)
varargs parameter passing.

A strict reading of the ABI indicates that any argument with alignment greater
than 8 may require skipping doublewords in the parameter save area to align
the argument, and hence require skipping GPRs.  In practice, this is not done
by GCC.  The alignment restriction is used for internal alignment of a
structure, but a structure with 16-byte alignment, for example, is not
itself 16-byte aligned in the parameter save area.  Although this is messy,
it has become the de facto standard used in building existing libraries.

My initial varargs support followed the ABI language, but not the de facto
standard.  Running the GCC compatibility test suite exposed this issue, and
indeed showed that LLVM didn't pass parameters self-consistently with my
original logic.  Removing the additional alignment logic allows the affected
tests to now pass.

I modified the ppc64-varargs-struct.c test case to remove the existing test
for generation of alignment code, which is no longer appropriate.

Built and tested on powerpc64-unknown-linux-gnu with no new regressions.

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

lib/CodeGen/TargetInfo.cpp
test/CodeGen/ppc64-varargs-struct.c

index 0a6ebb897e985b6f89af0c3deab9f38cd46d5cc9..58cbf2e20684199c55ec3ac5442ae5072f7d1e6e 100644 (file)
@@ -2755,21 +2755,6 @@ llvm::Value *PPC64_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr,
   llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
   llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
 
-  // Handle address alignment for type alignment > 64 bits.  Although
-  // long double normally requires 16-byte alignment, this is not the
-  // case when it is passed as an argument; so handle that special case.
-  const BuiltinType *BT = Ty->getAs<BuiltinType>();
-  unsigned TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
-
-  if (TyAlign > 8 && (!BT || !BT->isFloatingPoint())) {
-    assert((TyAlign & (TyAlign - 1)) == 0 &&
-           "Alignment is not power of 2!");
-    llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int64Ty);
-    AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt64(TyAlign - 1));
-    AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt64(~(TyAlign - 1)));
-    Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
-  }
-
   // Update the va_list pointer.
   unsigned SizeInBytes = CGF.getContext().getTypeSize(Ty) / 8;
   unsigned Offset = llvm::RoundUpToAlignment(SizeInBytes, 8);
index 3c7e7cb6bc1092f89b3ae2efd2bc7b8f4bd568a5..e69332ead434235f281a6fd35c3c2b94d4a1929f 100644 (file)
@@ -18,12 +18,6 @@ void testva (int n, ...)
 // CHECK: bitcast %struct.x* %{{[0-9]+}} to i8*
 // CHECK: call void @llvm.memcpy
 
-  __int128_t u = va_arg (ap, __int128_t);
-// CHECK: ptrtoint i8* %{{[a-z.0-9]*}} to i64
-// CHECK: add i64 %{{[0-9]+}}, 15
-// CHECK: and i64 %{{[0-9]+}}, 4294967280
-// CHECK: inttoptr i64 %{{[0-9]+}} to i8*
-
   int v = va_arg (ap, int);
 // CHECK: ptrtoint i8* %{{[a-z.0-9]*}} to i64
 // CHECK: add i64 %{{[0-9]+}}, 4