akhuang created this revision.
Herald added a subscriber: nlopes.
Herald added a project: All.
akhuang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  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 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/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/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1327,6 +1327,11 @@
   return ResTy;
 }
 
+static bool isInAllocaArgument(CGCXXABI &ABI, QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
 void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
                                    const CGFunctionInfo &FnInfo) {
   assert(Fn && "generating code for null Function");
@@ -1482,6 +1487,17 @@
   // a quick pass now to see if we can.
   if (!CurFn->doesNotThrow())
     TryMarkNoThrow(CurFn);
+
+  // If 32-bit Windows, and there's an inalloca parameter, don't use the
+  // emitted lambda static invoker function because we can't forward inalloca
+  // parameters. Instead copy the body from the call operator.
+  if (isa<CXXMethodDecl>(FD) && isLambdaCallOperator(cast<CXXMethodDecl>(FD)) && 
+      CGM.getTarget().getCXXABI().isMicrosoft() &&
+      llvm::any_of(cast<CXXMethodDecl>(FD)->parameters(), [&](ParmVarDecl *P) {
+        return isInAllocaArgument(CGM.getCXXABI(), P->getType());
+        })) {
+    EmitClonedLambdaStaticInvoke(cast<CXXMethodDecl>(FD));
+  }
 }
 
 /// ContainsLabel - Return true if the statement contains a label in it.  If
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,48 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeCXXMethodDeclaration(MD);
+  llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo);
+  llvm::Function *Fn = cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(MD), Ty));
+
+  // Loop through all the __invoke functions.
+  const CXXRecordDecl *Lambda = MD->getParent();
+
+  CallingConv CCs[] =
+    { CC_C, CC_X86StdCall, CC_X86FastCall, CC_X86ThisCall, CC_X86VectorCall };
+  for (CallingConv CC : CCs) {
+    const CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker(CC);
+    if (!Invoker)
+      continue;
+
+    const CGFunctionInfo &InvokerFnInfo =
+      CGM.getTypes().arrangeCXXMethodDeclaration(Invoker);
+    llvm::Function *InvokerFn = cast<llvm::Function>(
+      CGM.GetAddrOfFunction(GlobalDecl(Invoker),
+                            CGM.getTypes().GetFunctionType(InvokerFnInfo)));
+
+    if (InvokerFn->isDeclaration())
+      continue;
+
+    // Clone from call operator.
+    llvm::ValueToValueMapTy VMap;
+
+    // Don't copy the %this argument.
+    for (llvm::Argument &I : Fn->args()) {
+      if (I.getName().equals("this")) {
+        VMap[&I] = llvm::UndefValue::get(I.getType());
+      }
+    }
+
+    llvm::Function *NewFn = llvm::CloneFunction(Fn, VMap);
+    InvokerFn->replaceAllUsesWith(NewFn);
+    NewFn->takeName(InvokerFn);
+    NewFn->setCallingConv(InvokerFn->getCallingConv());
+    NewFn->setAttributes(InvokerFn->getAttributes());
+
+    InvokerFn->eraseFromParent();
+    InvokerFn = NewFn;
+  }
+}
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -3801,7 +3801,8 @@
   QualType type = param->getType();
 
   if (isInAllocaArgument(CGM.getCXXABI(), type)) {
-    CGM.ErrorUnsupported(param, "forwarded non-trivially copyable parameter");
+    // There should be an error here but instead we try to get rid of these
+    // calls later in codegen.
   }
 
   // GetAddrOfLocalVar returns a pointer-to-pointer for references,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to