diff options
| author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-06-05 03:00:18 +0000 |
|---|---|---|
| committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-06-05 03:00:18 +0000 |
| commit | 303caedd4b41f6dcfa994abfc7dc59d39e6cd346 (patch) | |
| tree | 850c3d970aed29491c914e924bbb74662b52d2c5 /clang/lib/CodeGen/TargetInfo.cpp | |
| parent | 36af2529ee81efc8fca98ad65a3a9fadc9e6e45e (diff) | |
| download | bcm5719-llvm-303caedd4b41f6dcfa994abfc7dc59d39e6cd346.tar.gz bcm5719-llvm-303caedd4b41f6dcfa994abfc7dc59d39e6cd346.zip | |
Implement SparcV9ABIInfo::EmitVAArg.
This could actually be implemented with the LLVM IR va_arg instruction,
but it doesn't seem to offer any advantages over accessing the va_list
pointer directly.
Using the va_list pointer directly makes it possible to perform type
coercion directly from the argument array, and the va_list updates are
exposed to the optimizers.
llvm-svn: 183292
Diffstat (limited to 'clang/lib/CodeGen/TargetInfo.cpp')
| -rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 6e5084a1492..c4ee7246a5b 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5332,8 +5332,52 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { llvm::Value *SparcV9ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { - // FIXME: Implement with va_arg. - return 0; + ABIArgInfo AI = classifyType(Ty, 16 * 8); + llvm::Type *ArgTy = CGT.ConvertType(Ty); + if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) + AI.setCoerceToType(ArgTy); + + 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"); + llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy); + llvm::Value *ArgAddr; + unsigned Stride; + + switch (AI.getKind()) { + case ABIArgInfo::Expand: + llvm_unreachable("Unsupported ABI kind for va_arg"); + + case ABIArgInfo::Extend: + Stride = 8; + ArgAddr = Builder + .CreateConstGEP1_32(Addr, 8 - getDataLayout().getTypeAllocSize(ArgTy), + "extend"); + break; + + case ABIArgInfo::Direct: + Stride = getDataLayout().getTypeAllocSize(AI.getCoerceToType()); + ArgAddr = Addr; + break; + + case ABIArgInfo::Indirect: + Stride = 8; + ArgAddr = Builder.CreateBitCast(Addr, + llvm::PointerType::getUnqual(ArgPtrTy), + "indirect"); + ArgAddr = Builder.CreateLoad(ArgAddr, "indirect.arg"); + break; + + case ABIArgInfo::Ignore: + return llvm::UndefValue::get(ArgPtrTy); + } + + // Update VAList. + Addr = Builder.CreateConstGEP1_32(Addr, Stride, "ap.next"); + Builder.CreateStore(Addr, VAListAddrAsBPP); + + return Builder.CreatePointerCast(ArgAddr, ArgPtrTy, "arg.addr"); } void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const { |

