diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 34 | ||||
| -rw-r--r-- | clang/test/CodeGen/mips-vaarg.c | 29 |
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; -} |

