]> granicus.if.org Git - clang/commitdiff
Correctly pass aggregates by reference when emitting thunks.
authorJohn McCall <rjmccall@apple.com>
Wed, 26 May 2010 22:34:26 +0000 (22:34 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 26 May 2010 22:34:26 +0000 (22:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104778 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
lib/CodeGen/CGClass.cpp
lib/CodeGen/CGVTables.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/thunks.cpp

index 0d6a70c64d4f7ad7a455cf7f0af541d8f4d4c9ea..73cee3c10d2e0fdf51578098233e3a094e630683 100644 (file)
@@ -862,6 +862,36 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
   }
 }
 
+RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
+  // StartFunction converted the ABI-lowered parameter(s) into a
+  // local alloca.  We need to turn that into an r-value suitable
+  // for EmitCall.
+  llvm::Value *Local = GetAddrOfLocalVar(Param);
+
+  QualType ArgType = Param->getType();
+  // For the most part, we just need to load the alloca, except:
+  // 1) aggregate r-values are actually pointers to temporaries, and
+  // 2) references to aggregates are pointers directly to the aggregate.
+  // I don't know why references to non-aggregates are different here.
+  if (const ReferenceType *RefType = ArgType->getAs<ReferenceType>()) {
+    if (hasAggregateLLVMType(RefType->getPointeeType()))
+      return RValue::getAggregate(Local);
+
+    // Locals which are references to scalars are represented
+    // with allocas holding the pointer.
+    return RValue::get(Builder.CreateLoad(Local));
+  }
+
+  if (ArgType->isAnyComplexType())
+    return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false));
+
+  if (hasAggregateLLVMType(ArgType))
+    return RValue::getAggregate(Local);
+
+  return RValue::get(EmitLoadOfScalar(Local, false, ArgType));
+}
+
 RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
   if (ArgType->isReferenceType())
     return EmitReferenceBindingToExpr(E);
index 587a68beb225ca2911beced3920865feeb80bfda..bebea549f965ad19f207b0b3ea961685aa68fb97 100644 (file)
@@ -1137,34 +1137,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
 
   // Explicit arguments.
   for (; I != E; ++I) {
-    
     const VarDecl *Param = I->first;
     QualType ArgType = Param->getType(); // because we're passing it to itself
-
-    // StartFunction converted the ABI-lowered parameter(s) into a
-    // local alloca.  We need to turn that into an r-value suitable
-    // for EmitCall.
-    llvm::Value *Local = GetAddrOfLocalVar(Param);
-    RValue Arg;
-    // For the most part, we just need to load the alloca, except:
-    // 1) aggregate r-values are actually pointers to temporaries, and
-    // 2) references to aggregates are pointers directly to the aggregate.
-    // I don't know why references to non-aggregates are different here.
-    if (ArgType->isReferenceType()) {
-      const ReferenceType *RefType = ArgType->getAs<ReferenceType>();
-      if (hasAggregateLLVMType(RefType->getPointeeType()))
-        Arg = RValue::getAggregate(Local);
-      else
-        // Locals which are references to scalars are represented
-        // with allocas holding the pointer.
-        Arg = RValue::get(Builder.CreateLoad(Local));
-    } else {
-      if (hasAggregateLLVMType(ArgType))
-        Arg = RValue::getAggregate(Local);
-      else
-        Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType));
-    }
+    RValue Arg = EmitDelegateCallArg(Param);
 
     DelegateArgs.push_back(std::make_pair(Arg, ArgType));
   }
index 8bdd4588d4a9bd7afe4601fc957a27bc9be523af..0f023e63ae54d4ae5d5c356bf3082254f0dd09a7 100644 (file)
@@ -2641,14 +2641,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
        E = MD->param_end(); I != E; ++I) {
     ParmVarDecl *Param = *I;
     QualType ArgType = Param->getType();
-    
-    // Load the argument corresponding to this parameter.
-    RValue Arg;
-    if (ArgType->isReferenceType() ||
-        (hasAggregateLLVMType(ArgType) && !ArgType->isAnyComplexType()))
-      Arg = RValue::get(Builder.CreateLoad(LocalDeclMap[Param]));
-    else
-      Arg = RValue::get(EmitLoadOfScalar(LocalDeclMap[Param], false, ArgType));
+    RValue Arg = EmitDelegateCallArg(Param);
     
     CallArgs.push_back(std::make_pair(Arg, ArgType));
   }
index 944aa48044264c47fc3756c38a7db5e533fce494..ece275e7629e894c68faa058ace763a01a6cf31e 100644 (file)
@@ -1302,6 +1302,11 @@ public:
   /// EmitCallArg - Emit a single call argument.
   RValue EmitCallArg(const Expr *E, QualType ArgType);
 
+  /// EmitDelegateCallArg - We are performing a delegate call; that
+  /// is, the current function is delegating to another one.  Produce
+  /// a r-value suitable for passing the given parameter.
+  RValue EmitDelegateCallArg(const VarDecl *Param);
+
 private:
 
   void EmitReturnOfRValue(RValue RV, QualType Ty);
index b6e18e6e01fe300102fa8eccb8db2af36abf41f2..79ca709f470da397833213df09f5c26b8a95bf76 100644 (file)
@@ -218,6 +218,24 @@ namespace Test7 {
   void testD() { D d; }
 }
 
+namespace Test8 {
+  struct NonPOD { ~NonPOD(); int x, y, z; };
+  struct A { virtual void foo(); };
+  struct B { virtual void bar(NonPOD); };
+  struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
+
+  // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
+  void C::helper(NonPOD var) {}
+
+  // CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
+  // CHECK-NOT: load [[NONPODTYPE]]*
+  // CHECK-NOT: memcpy
+  // CHECK: ret void
+  void C::bar(NonPOD var) {}
+}
+
+/**** The following has to go at the end of the file ****/
+
 // This is from Test5:
 // CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
 // CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(