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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits