]> granicus.if.org Git - clang/commitdiff
Implement lowering of va_arg in clang directly. (This is 32-bit X86 only for now).
authorAnders Carlsson <andersca@mac.com>
Tue, 4 Nov 2008 05:30:00 +0000 (05:30 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 4 Nov 2008 05:30:00 +0000 (05:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58681 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h

index 28fb9a338d08f1de49ebfa35bf66cd8f6eb9b2a5..e8ab1bbb7f35d7e769d45cedac7bf499a0148fa4 100644 (file)
@@ -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) {
index 487cfcc57bfe590a03bd5158c88c7ce01e427512..a4c65c087f990b2384193c27566538fa3131cde3 100644 (file)
@@ -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) {
index acce366ae933dc06bd742d5adb4f4504980e8fec..c4a332456161301370e976d739c3be3c514f6858 100644 (file)
@@ -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;
+}
+
index 797cbf42b258c4c6f285ecb3426b9e4c53e0a920..ccc5008aee11f455e5da45462d0c874b05f8c701 100644 (file)
@@ -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