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

Fix calling convention of cloned function.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136998

Files:
  clang/lib/CodeGen/CGClass.cpp
  clang/lib/CodeGen/CGVTables.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 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,18 @@
     EmitGlobalFunctionDefinition(GD, GV);
 }
 
+static bool isInAllocaArg(CGCXXABI &ABI, QualType T) {
+  const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+  return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
+}
+
+static bool hasInAllocaArg(const TargetInfo &TI, CGCXXABI &CGABI, const CXXMethodDecl *MD) {
+  return TI.getCXXABI().isMicrosoft() && 
+    llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) {
+        return isInAllocaArg(CGABI, P->getType());
+      });
+}
+
 void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
   const auto *D = cast<ValueDecl>(GD.getDecl());
 
@@ -3580,6 +3592,14 @@
       // This is necessary for the generation of certain thunks.
       if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
         ABI->emitCXXStructor(GD);
+      // Special path for emitting lambda static invokers with inalloca parameters.
+      else if (Method->isLambdaStaticInvoker() && 
+               hasInAllocaArg(getTarget(), getCXXABI(), Method)) {
+        // Emit the call operator definition before emitting a static invoker.
+        const CXXMethodDecl *CallOp = Method->getParent()->getLambdaCallOperator();
+        EmitGlobalFunctionDefinition(GlobalDecl(CallOp), nullptr);
+        CodeGenFunction(*this).EmitClonedLambdaStaticInvoke(Method);
+      }
       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);
   }
@@ -2255,6 +2257,8 @@
                      GlobalDecl GD, const ThunkInfo &Thunk,
                      bool IsUnprototyped);
 
+  void CreateClonedFunction(llvm::Function *Fn, llvm::Function *BaseFn,
+                            llvm::ValueToValueMapTy &VMap);
   llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
                                        const CGFunctionInfo &FnInfo,
                                        GlobalDecl GD, const ThunkInfo &Thunk);
Index: clang/lib/CodeGen/CGVTables.cpp
===================================================================
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -139,6 +139,21 @@
   }
 }
 
+void CodeGenFunction::CreateClonedFunction(
+    llvm::Function *Fn, llvm::Function *BaseFn, llvm::ValueToValueMapTy &VMap) {
+  // We are cloning a function while some Metadata nodes are still unresolved.
+  // Ensure that the value mapper does not encounter any of them.
+  resolveTopLevelMetadata(BaseFn, VMap);
+  llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
+  Fn->replaceAllUsesWith(NewFn);
+  NewFn->takeName(Fn);
+  Fn->eraseFromParent();
+  Fn = NewFn;
+
+  // "Initialize" CGF (minimally).
+  CurFn = Fn;
+}
+
 // This function does roughly the same thing as GenerateThunk, but in a
 // very different way, so that va_start and va_end work correctly.
 // FIXME: This function assumes "this" is the first non-sret LLVM argument of
@@ -181,17 +196,7 @@
   // Clone to thunk.
   llvm::ValueToValueMapTy VMap;
 
-  // We are cloning a function while some Metadata nodes are still unresolved.
-  // Ensure that the value mapper does not encounter any of them.
-  resolveTopLevelMetadata(BaseFn, VMap);
-  llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
-  Fn->replaceAllUsesWith(NewFn);
-  NewFn->takeName(Fn);
-  Fn->eraseFromParent();
-  Fn = NewFn;
-
-  // "Initialize" CGF (minimally).
-  CurFn = Fn;
+  CreateClonedFunction(Fn, BaseFn, VMap);
 
   // Get the "this" value
   llvm::Function::arg_iterator AI = Fn->arg_begin();
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,22 @@
 
   EmitLambdaDelegatingInvokeBody(MD);
 }
+
+void CodeGenFunction::EmitClonedLambdaStaticInvoke(const CXXMethodDecl *MD) {
+  llvm::Function *Fn =
+    cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(MD)));
+
+  const CXXMethodDecl *CallOp = MD->getParent()->getLambdaCallOperator();
+  llvm::Function *CallOpFn =
+    cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));
+
+  // Clone from call operator, which we've made sure is already emitted.
+  llvm::ValueToValueMapTy VMap;
+
+  // Don't copy the %this argument, which is the first argument.
+  llvm::Argument &A = *CallOpFn->arg_begin();
+  VMap[&A] = llvm::Constant::getNullValue(A.getType());
+
+  CreateClonedFunction(Fn, CallOpFn, VMap);
+  CurFn->setCallingConv(Fn->getCallingConv());
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to