diff options
author | Daniel Sanders <daniel.sanders@imgtec.com> | 2014-08-01 13:26:28 +0000 |
---|---|---|
committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2014-08-01 13:26:28 +0000 |
commit | 2ef3cdd3d5495b2ae1faa4d575466728ecfcf0cf (patch) | |
tree | acbed54efb154ae80ec85e0f8fd49aedbb5467a9 /clang/lib/CodeGen/TargetInfo.cpp | |
parent | 41b10ac3b72d08d8d063eb94ff8264a7b061b1c7 (diff) | |
download | bcm5719-llvm-2ef3cdd3d5495b2ae1faa4d575466728ecfcf0cf.tar.gz bcm5719-llvm-2ef3cdd3d5495b2ae1faa4d575466728ecfcf0cf.zip |
Revert r214497: [mips] Defer va_arg expansion to the backend.
It appears that the backend does not handle all cases that were handled by clang.
In particular, it does not handle structs as used in
SingleSource/UnitTests/2003-05-07-VarArgs.
llvm-svn: 214512
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 34 |
1 files changed, 33 insertions, 1 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 |