llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
- return nullptr;
+ llvm::Type *BP = CGF.Int8PtrTy;
+ llvm::Type *BPP = CGF.Int8PtrPtrTy;
+
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ int64_t TypeAlign = getContext().getTypeAlign(Ty) / 8;
+ llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ llvm::Value *AddrTyped;
+ unsigned PtrWidth = getTarget().getPointerWidth(0);
+ llvm::IntegerType *IntTy = (PtrWidth == 32) ? CGF.Int32Ty : CGF.Int64Ty;
+
+ if (TypeAlign > MinABIStackAlignInBytes) {
+ llvm::Value *AddrAsInt = CGF.Builder.CreatePtrToInt(Addr, IntTy);
+ llvm::Value *Inc = llvm::ConstantInt::get(IntTy, TypeAlign - 1);
+ llvm::Value *Mask = llvm::ConstantInt::get(IntTy, -TypeAlign);
+ llvm::Value *Add = CGF.Builder.CreateAdd(AddrAsInt, Inc);
+ llvm::Value *And = CGF.Builder.CreateAnd(Add, Mask);
+ AddrTyped = CGF.Builder.CreateIntToPtr(And, PTy);
+ }
+ else
+ AddrTyped = Builder.CreateBitCast(Addr, PTy);
+
+ llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP);
+ TypeAlign = std::max((unsigned)TypeAlign, MinABIStackAlignInBytes);
+ uint64_t Offset =
+ llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, TypeAlign);
+ llvm::Value *NextAddr =
+ Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(IntTy, Offset),
+ "ap.next");
+ Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+
+ return AddrTyped;
}
bool
+++ /dev/null
-// RUN: %clang -target mips-unknown-linux -S -o - -emit-llvm %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
-// RUN: %clang -target mipsel-unknown-linux -S -o - -emit-llvm %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
-// RUN: %clang -target mips64-unknown-linux -S -o - -emit-llvm %s -mabi=n32 | FileCheck --check-prefix=ALL --check-prefix=N32 %s
-// RUN: %clang -target mips64el-unknown-linux -S -o - -emit-llvm %s -mabi=n32 | FileCheck --check-prefix=ALL --check-prefix=N32 %s
-// RUN: %clang -target mips64-unknown-linux -S -o - -emit-llvm %s -mabi=64 | FileCheck --check-prefix=ALL --check-prefix=N64 %s
-// RUN: %clang -target mips64el-unknown-linux -S -o - -emit-llvm %s -mabi=64 | FileCheck --check-prefix=ALL --check-prefix=N64 %s
-
-int foo (int a, ...)
-{
- // ALL-LABEL: define i32 @foo(i32 %a, ...)
-
- __builtin_va_list va;
- // O32: %va = alloca i8*, align 4
- // N32: %va = alloca i8*, align 4
- // N64: %va = alloca i8*, align 8
-
- __builtin_va_start (va, a);
- // ALL: %va1 = bitcast i8** %va to i8*
- // ALL: call void @llvm.va_start(i8* %va1)
-
- int n = __builtin_va_arg (va, int);
- // ALL: %{{[0-9]+}} = va_arg i8** %va, i32
-
- __builtin_va_end (va);
- // ALL: %va2 = bitcast i8** %va to i8*
- // ALL: call void @llvm.va_end(i8* %va2)
-
- return n;
-}