From: Christian Pirker Date: Fri, 14 Mar 2014 11:51:06 +0000 (+0000) Subject: AArch64_be varargs processing for ARM ABI X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=85de826b581df571c85de8479125c1b2ab5e96f1;p=clang AArch64_be varargs processing for ARM ABI git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203917 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f013fcfb21..93b869bfda 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -4186,9 +4186,6 @@ llvm::Value *AArch64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // int __vr_offs; // }; - assert(!CGF.CGM.getDataLayout().isBigEndian() - && "va_arg not implemented for big-endian AArch64"); - int FreeIntRegs = 8, FreeVFPRegs = 8; Ty = CGF.getContext().getCanonicalType(Ty); ABIArgInfo AI = classifyGenericType(Ty, FreeIntRegs, FreeVFPRegs); @@ -4298,9 +4295,14 @@ llvm::Value *AArch64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, llvm::Type *BaseTy = CGF.ConvertType(QualType(Base, 0)); llvm::Type *HFATy = llvm::ArrayType::get(BaseTy, NumMembers); llvm::Value *Tmp = CGF.CreateTempAlloca(HFATy); + int Offset = 0; + if (CGF.CGM.getDataLayout().isBigEndian() && + getContext().getTypeSize(Base) < 128) + Offset = 16 - getContext().getTypeSize(Base)/8; for (unsigned i = 0; i < NumMembers; ++i) { - llvm::Value *BaseOffset = llvm::ConstantInt::get(CGF.Int32Ty, 16 * i); + llvm::Value *BaseOffset = llvm::ConstantInt::get(CGF.Int32Ty, + 16 * i + Offset); llvm::Value *LoadAddr = CGF.Builder.CreateGEP(BaseAddr, BaseOffset); LoadAddr = CGF.Builder.CreateBitCast(LoadAddr, llvm::PointerType::getUnqual(BaseTy)); @@ -4313,6 +4315,20 @@ llvm::Value *AArch64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, RegAddr = CGF.Builder.CreateBitCast(Tmp, MemTy); } else { // Otherwise the object is contiguous in memory + unsigned BeAlign = reg_top_index == 2 ? 16 : 8; + if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) && + getContext().getTypeSize(Ty) < (BeAlign * 8)) { + int Offset = BeAlign - getContext().getTypeSize(Ty)/8; + BaseAddr = CGF.Builder.CreatePtrToInt(BaseAddr, CGF.Int64Ty); + + BaseAddr = CGF.Builder.CreateAdd(BaseAddr, + llvm::ConstantInt::get(CGF.Int64Ty, + Offset), + "align_be"); + + BaseAddr = CGF.Builder.CreateIntToPtr(BaseAddr, CGF.Int8PtrTy); + } + RegAddr = CGF.Builder.CreateBitCast(BaseAddr, MemTy); } @@ -4360,6 +4376,19 @@ llvm::Value *AArch64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // Write the new value of __stack for the next call to va_arg CGF.Builder.CreateStore(NewStack, stack_p); + if (CGF.CGM.getDataLayout().isBigEndian() && !isAggregateTypeForABI(Ty) && + getContext().getTypeSize(Ty) < 64 ) { + int Offset = 8 - getContext().getTypeSize(Ty)/8; + OnStackAddr = CGF.Builder.CreatePtrToInt(OnStackAddr, CGF.Int64Ty); + + OnStackAddr = CGF.Builder.CreateAdd(OnStackAddr, + llvm::ConstantInt::get(CGF.Int64Ty, + Offset), + "align_be"); + + OnStackAddr = CGF.Builder.CreateIntToPtr(OnStackAddr, CGF.Int8PtrTy); + } + OnStackAddr = CGF.Builder.CreateBitCast(OnStackAddr, MemTy); CGF.EmitBranch(ContBlock); diff --git a/test/CodeGen/aarch64-varargs.c b/test/CodeGen/aarch64-varargs.c index 3d9cd866e8..11226855ca 100644 --- a/test/CodeGen/aarch64-varargs.c +++ b/test/CodeGen/aarch64-varargs.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple aarch64 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK --check-prefix=CHECK-LE %s +// RUN: %clang_cc1 -triple aarch64_be -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s + #include // Obviously there's more than one way to implement va_arg. This test should at @@ -22,6 +24,9 @@ int simple_int(void) { // CHECK: [[VAARG_IN_REG]] // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] +// CHECK-BE: [[REG_ADDR_VAL:%[0-9]+]] = ptrtoint i8* [[REG_ADDR]] to i64 +// CHECK-BE: [[REG_ADDR_VAL_ALIGNED:%align_be[0-9]*]] = add i64 [[REG_ADDR_VAL]], 4 +// CHECK-BE: [[REG_ADDR:%[0-9]+]] = inttoptr i64 [[REG_ADDR_VAL_ALIGNED]] to i8* // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i32* // CHECK: br label %[[VAARG_END:[a-z._0-9]+]] @@ -29,6 +34,9 @@ int simple_int(void) { // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) +// CHECK-BE: [[STACK_VAL:%[0-9]+]] = ptrtoint i8* {{%stack[0-9]*}} to i64 +// CHECK-BE: [[STACK_VAL_ALIGNED:%align_be[0-9]*]] = add i64 [[STACK_VAL]], 4 +// CHECK-BE: [[STACK:%[0-9]+]] = inttoptr i64 [[STACK_VAL_ALIGNED]] to i8* // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to i32* // CHECK: br label %[[VAARG_END]] @@ -165,6 +173,9 @@ double simple_double(void) { // CHECK: [[VAARG_IN_REG]] // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 2) // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[VR_OFFS]] +// CHECK-BE: [[REG_ADDR_VAL:%[0-9]+]] = ptrtoint i8* [[REG_ADDR]] to i64 +// CHECK-BE: [[REG_ADDR_VAL_ALIGNED:%align_be[0-9]*]] = add i64 [[REG_ADDR_VAL]], 8 +// CHECK-BE: [[REG_ADDR:%[0-9]+]] = inttoptr i64 [[REG_ADDR_VAL_ALIGNED]] to i8* // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to double* // CHECK: br label %[[VAARG_END]] @@ -201,12 +212,14 @@ struct hfa simple_hfa(void) { // CHECK: [[VAARG_IN_REG]] // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 2) // CHECK: [[FIRST_REG:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[VR_OFFS]] -// CHECK: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 0 +// CHECK-LE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 0 +// CHECK-BE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 12 // CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float* // CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float]* %[[TMP_HFA:[a-z_.0-9]+]], i32 0, i32 0 // CHECK: [[EL:%[a-z_0-9]+]] = load float* [[EL_TYPED]] // CHECK: store float [[EL]], float* [[EL_TMPADDR]] -// CHECK: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 16 +// CHECK-LE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 16 +// CHECK-BE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 28 // CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float* // CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float]* %[[TMP_HFA]], i32 0, i32 1 // CHECK: [[EL:%[a-z_0-9]+]] = load float* [[EL_TYPED]]