Hello. First-time contributor :)
This patch implements alignment for long long types in va_arg on ARM AAPCS.
Without alignment, sqlite breaks on ARM because it uses 64-bit types
extensively in vaarg calls (printf).
I also included a test if that is needed.
Thanks!
Jim
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp (revision 136604)
+++ lib/CodeGen/TargetInfo.cpp (working copy)
@@ -2579,7 +2579,6 @@
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);
@@ -2587,6 +2586,16 @@
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);
Index: test/CodeGen/arm-vaarg-align.c
===================================================================
--- test/CodeGen/arm-vaarg-align.c (revision 0)
+++ test/CodeGen/arm-vaarg-align.c (revision 0)
@@ -0,0 +1,18 @@
+// 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 requires 8-byte alignment under AAPCS
+ * however, it only requires 4-byte alignment under APCS
+ */
+long long t1(int i, ...) {
+ __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;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits