summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp34
-rw-r--r--clang/test/CodeGen/mips-vaarg.c29
2 files changed, 33 insertions, 30 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 3870f72487d..ca99ba580a5 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -5560,7 +5560,39 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
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
diff --git a/clang/test/CodeGen/mips-vaarg.c b/clang/test/CodeGen/mips-vaarg.c
deleted file mode 100644
index f685ed8d997..00000000000
--- a/clang/test/CodeGen/mips-vaarg.c
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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;
-}
OpenPOWER on IntegriCloud