зеркало из https://github.com/microsoft/clang.git
Implements alignment for long long and double types in va_arg on ARM AAPCS.
Patch by Jim (Ningjie) Chen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136734 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
cf565c5737
Коммит
e164c18052
|
@ -2575,7 +2575,6 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
|
|||
|
||||
llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
|
||||
CodeGenFunction &CGF) const {
|
||||
// FIXME: Need to handle alignment
|
||||
llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
|
||||
llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
|
||||
|
||||
|
@ -2583,6 +2582,16 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
|
|||
llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
|
||||
"ap");
|
||||
llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
|
||||
// Handle address alignment for type alignment > 32 bits
|
||||
uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
|
||||
if (TyAlign > 4) {
|
||||
assert((TyAlign & (TyAlign - 1)) == 0 &&
|
||||
"Alignment is not power of 2!");
|
||||
llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);
|
||||
AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));
|
||||
AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));
|
||||
Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
|
||||
}
|
||||
llvm::Type *PTy =
|
||||
llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
|
||||
llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// RUN: %clang_cc1 -triple arm -target-abi aapcs %s -emit-llvm -o - | FileCheck -check-prefix=AAPCS %s
|
||||
// RUN: %clang_cc1 -triple arm -target-abi apcs-gnu %s -emit-llvm -o - | FileCheck -check-prefix=APCS-GNU %s
|
||||
/*
|
||||
* Check that va_arg accesses stack according to ABI alignment
|
||||
* long long and double require 8-byte alignment under AAPCS
|
||||
* however, they only require 4-byte alignment under APCS
|
||||
*/
|
||||
long long t1(int i, ...) {
|
||||
// AAPCS: t1
|
||||
// APCS-GNU: t1
|
||||
__builtin_va_list ap;
|
||||
__builtin_va_start(ap, i);
|
||||
// AAPCS: add i32 %{{.*}} 7
|
||||
// AAPCS: and i32 %{{.*}} -8
|
||||
// APCS-GNU-NOT: add i32 %{{.*}} 7
|
||||
// APCS-GNU-NOT: and i32 %{{.*}} -8
|
||||
long long ll = __builtin_va_arg(ap, long long);
|
||||
__builtin_va_end(ap);
|
||||
return ll;
|
||||
}
|
||||
double t2(int i, ...) {
|
||||
// AAPCS: t2
|
||||
// APCS-GNU: t2
|
||||
__builtin_va_list ap;
|
||||
__builtin_va_start(ap, i);
|
||||
// AAPCS: add i32 %{{.*}} 7
|
||||
// AAPCS: and i32 %{{.*}} -8
|
||||
// APCS-GNU-NOT: add i32 %{{.*}} 7
|
||||
// APCS-GNU-NOT: and i32 %{{.*}} -8
|
||||
double ll = __builtin_va_arg(ap, double);
|
||||
__builtin_va_end(ap);
|
||||
return ll;
|
||||
}
|
Загрузка…
Ссылка в новой задаче