akhuang updated this revision to Diff 472447.
akhuang added a comment.

update


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136998/new/

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/inalloca-lambda.cpp

Index: clang/test/CodeGenCXX/inalloca-lambda.cpp
===================================================================
--- clang/test/CodeGenCXX/inalloca-lambda.cpp
+++ clang/test/CodeGenCXX/inalloca-lambda.cpp
@@ -1,7 +1,4 @@
-// RUN: not %clang_cc1 -triple i686-windows-msvc -emit-llvm -o /dev/null %s  2>&1 | FileCheck %s
-
-// PR28299
-// CHECK: error: cannot compile this forwarded non-trivially copyable parameter yet
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -o - %s  2>&1 | FileCheck %s
 
 class A {
   A(const A &);
@@ -9,3 +6,7 @@
 typedef void (*fptr_t)(A);
 fptr_t fn1() { return [](A) {}; }
 
+// CHECK: define internal x86_thiscallcc void @"?__invoke@<lambda_0>@?0??fn1@@YAP6AXVA@@@ZXZ@CA?A?<auto>@@0@Z"
+// CHECK-SAME: (ptr inalloca(<{ %class.A, [3 x i8] }>) %0)
+// CHECK: %1 = getelementptr inbounds <{ %class.A, [3 x i8] }>, ptr %0, i32 0, i32 0
+// CHECK: ret void
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3554,6 +3554,11 @@
     EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArgument(CGCXXABI &ABI, QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast<ValueDecl>(GD.getDecl());
 
@@ -3580,6 +3585,25 @@
       // This is necessary for the generation of certain thunks.
       if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
         ABI->emitCXXStructor(GD);
+      // Hack for lambda forwarding calls with inalloca parameters.
+      else if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker() &&
+          getTarget().getCXXABI().isMicrosoft() &&
+          llvm::any_of(cast<CXXMethodDecl>(FD)->parameters(), [&](ParmVarDecl *P) {
+            return isInAllocaArgument(getCXXABI(), P->getType());
+            })) {
+        // If the call op is not yet emitted, emit that.
+        const CXXRecordDecl *Lambda = cast<CXXMethodDecl>(FD)->getParent();
+        const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+        const CGFunctionInfo &CallOpFnInfo =
+          getTypes().arrangeCXXMethodDeclaration(CallOp);
+        llvm::Function *CallOpFn = cast<llvm::Function>(
+          GetAddrOfFunction(GlobalDecl(CallOp),
+                            getTypes().GetFunctionType(CallOpFnInfo)));
+        if (CallOpFn->isDeclaration())
+          EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+
+        CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(cast<CXXMethodDecl>(FD));
+      }
       else if (FD->isMultiVersion())
         EmitMultiVersionFunctionDefinition(GD, GV);
       else
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2223,6 +2223,8 @@
   void EmitLambdaBlockInvokeBody();
   void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
   void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
+  void EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD);
+
   void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
     EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
   }
Index: clang/lib/CodeGen/CGClass.cpp
===================================================================
--- clang/lib/CodeGen/CGClass.cpp
+++ clang/lib/CodeGen/CGClass.cpp
@@ -26,8 +26,10 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/SanitizerStats.h"
 
 using namespace clang;
@@ -3044,3 +3046,46 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  const CGFunctionInfo &InvokerFnInfo = CGM.getTypes().arrangeCXXMethodDeclaration(MD);
+  llvm::Type *InvokerTy = CGM.getTypes().GetFunctionType(InvokerFnInfo);
+  GlobalDecl GD = GlobalDecl(MD);
+  llvm::Function *InvokerFn = cast<llvm::Function>(CGM.GetAddrOfFunction(GD, InvokerTy));
+
+  const CXXRecordDecl *Lambda = MD->getParent();
+  const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
+  const CGFunctionInfo &CallOpFnInfo =
+    CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
+  llvm::Function *CallOpFn = cast<llvm::Function>(
+    CGM.GetAddrOfFunction(GlobalDecl(CallOp),
+                          CGM.getTypes().GetFunctionType(CallOpFnInfo)));
+
+  // Generate code for call op.
+  if (CallOpFn->isDeclaration()) {
+    CodeGenFunction(CGM).GenerateCode(GlobalDecl(CallOp), CallOpFn, CallOpFnInfo);
+  }
+
+  // Clone from call operator.
+  llvm::ValueToValueMapTy VMap;
+
+  // Don't copy the %this argument.
+  // Assume CallOp is going to have two parameters?: this and inalloca.
+  for (llvm::Argument &I : CallOpFn->args()) {
+    if (I.getName().equals("this")) {
+      VMap[&I] = llvm::PoisonValue::get(I.getType());
+    } else {
+      for (llvm::Argument &DestI : InvokerFn->args()) {
+        if (DestI.getType() == I.getType()) {
+          VMap[&I] = &DestI;
+          break;
+        }
+      }
+    }
+  }
+
+  InvokerFn->dropAllReferences(); // Erase function  body.
+  SmallVector<llvm::ReturnInst *, 8> Returns;
+  llvm::CloneFunctionInto(InvokerFn, CallOpFn, VMap, 
+      llvm::CloneFunctionChangeType::LocalChangesOnly, Returns, "", nullptr);
+}
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -3800,10 +3800,6 @@
 
   QualType type = param->getType();
 
-  if (isInAllocaArgument(CGM.getCXXABI(), type)) {
-    CGM.ErrorUnsupported(param, "forwarded non-trivially copyable parameter");
-  }
-
   // GetAddrOfLocalVar returns a pointer-to-pointer for references,
   // but the argument needs to be the original pointer.
   if (type->isReferenceType()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to