diff options
| author | Anders Carlsson <andersca@mac.com> | 2008-11-04 05:30:00 +0000 | 
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2008-11-04 05:30:00 +0000 | 
| commit | 13abd7e98bde4ea0e3ba1051c9920a9882045a8c (patch) | |
| tree | 2e0017cb58a19dfbd00543022bc0f0ae58474503 /clang/lib/CodeGen | |
| parent | 4961890c0723500bf0bf352873f6eb66ce738c9d (diff) | |
| download | bcm5719-llvm-13abd7e98bde4ea0e3ba1051c9920a9882045a8c.tar.gz bcm5719-llvm-13abd7e98bde4ea0e3ba1051c9920a9882045a8c.zip | |
Implement lowering of va_arg in clang directly. (This is 32-bit X86 only for now).
llvm-svn: 58681
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 6 | 
4 files changed, 55 insertions, 4 deletions
| diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 28fb9a338d0..e8ab1bbb7f3 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -256,10 +256,14 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {  void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {    llvm::Value *ArgValue = CGF.EmitLValue(VE->getSubExpr()).getAddress(); -  llvm::Value *V = Builder.CreateVAArg(ArgValue, CGF.ConvertType(VE->getType())); +  llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); + +  if (!ArgPtr) +    CGF.ErrorUnsupported(VE, "aggregate va_arg expression"); +      if (DestPtr)      // FIXME: volatility -    Builder.CreateStore(V, DestPtr); +    CGF.EmitAggregateCopy(DestPtr, ArgPtr, VE->getType());  }  void AggExprEmitter::EmitNonConstInit(InitListExpr *E) { diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 487cfcc57bf..a4c65c087f9 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1149,8 +1149,14 @@ Value *ScalarExprEmitter::VisitOverloadExpr(OverloadExpr *E) {  Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {    llvm::Value *ArgValue = EmitLValue(VE->getSubExpr()).getAddress(); -  llvm::Value *V = Builder.CreateVAArg(ArgValue, ConvertType(VE->getType()));   -  return V; +  llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); + +  // If EmitVAArg fails, we fall back to the LLVM instruction. +  if (!ArgPtr)  +    return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType())); + +  // FIXME: volatile? +  return Builder.CreateLoad(ArgPtr);  }  Value *ScalarExprEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index acce366ae93..c4a33245616 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -242,3 +242,38 @@ void CodeGenFunction::EmitIndirectSwitches() {      }    }           } + +llvm::Value *CodeGenFunction::EmitVAArg(llvm::Value *VAListAddr, QualType Ty) +{ +  // FIXME: This entire method is hardcoded for 32-bit X86. +   +  const char *TargetPrefix = getContext().Target.getTargetPrefix(); +   +  if (strcmp(TargetPrefix, "x86") != 0 || +      getContext().Target.getPointerWidth(0) != 32) +    return 0; +   +  const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); +  const llvm::Type *BPP = llvm::PointerType::getUnqual(BP); + +  llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,  +                                                       "ap"); +  llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur"); +  llvm::Value *AddrTyped =  +    Builder.CreateBitCast(Addr,  +                          llvm::PointerType::getUnqual(ConvertType(Ty))); +   +  uint64_t SizeInBytes = getContext().getTypeSize(Ty) / 8; +  const unsigned ArgumentSizeInBytes = 4; +  if (SizeInBytes < ArgumentSizeInBytes) +    SizeInBytes = ArgumentSizeInBytes; + +  llvm::Value *NextAddr =  +    Builder.CreateGEP(Addr,  +                      llvm::ConstantInt::get(llvm::Type::Int32Ty, SizeInBytes), +                      "ap.next"); +  Builder.CreateStore(NextAddr, VAListAddrAsBPP); + +  return AddrTyped; +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 797cbf42b25..ccc5008aee1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -281,6 +281,12 @@ public:    /// EmitMemSetToZero - Generate code to memset a value of the given type to 0;    void EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty); + +  // EmitVAArg - Generate code to get an argument from the passed in pointer +  // and update it accordingly. The return value is a pointer to the argument. +  // FIXME: We should be able to get rid of this method and use the va_arg +  // instruction in LLVM instead once it works well enough.   +  llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);    //===--------------------------------------------------------------------===//    //                            Declaration Emission | 

