pschuh created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

In swift, we want to be able to call c++ virtual methods by looking up in the 
virtual table. There appears to exist no way currently, via the standard APIs, 
to take a CXXMethodDecl and a llvm::Value representing a this-ptr and construct 
the llvm instructions necessary to extract the method from the virtual table as 
well as adjust the this-ptr.

For reference, this is used in https://github.com/apple/swift/pull/26658.


Repository:
  rC Clang

https://reviews.llvm.org/D66360

Files:
  include/clang/CodeGen/CodeGenABITypes.h
  include/clang/CodeGen/SwiftCallingConv.h
  lib/CodeGen/CodeGenABITypes.cpp
  lib/CodeGen/SwiftCallingConv.cpp

Index: lib/CodeGen/SwiftCallingConv.cpp
===================================================================
--- lib/CodeGen/SwiftCallingConv.cpp
+++ lib/CodeGen/SwiftCallingConv.cpp
@@ -11,9 +11,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/CodeGen/SwiftCallingConv.h"
-#include "clang/Basic/TargetInfo.h"
+#include "CGCXXABI.h"
+#include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
+#include "clang/Basic/TargetInfo.h"
 
 using namespace clang;
 using namespace CodeGen;
@@ -862,3 +864,25 @@
 bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) {
   return getSwiftABIInfo(CGM).isSwiftErrorInRegister();
 }
+
+llvm::Value *swiftcall::lowerCXXVirtualMethodDeclReference(
+    CodeGenModule &CGM, const CXXMethodDecl *MD, llvm::Value *&thisPtr,
+    CharUnits alignment, llvm::FunctionType *type,
+    llvm::IRBuilderBase *builder) {
+  assert(MD->isVirtual());
+
+  CodeGenFunction CGF(CGM, true);
+  CGF.Builder.SetInsertPoint(builder->GetInsertBlock(),
+                             builder->GetInsertPoint());
+  Address thisAddr(thisPtr, alignment);
+  auto callee = CGCallee::forVirtual(nullptr, MD, thisAddr, type);
+  const CGCallee &concreteCallee = callee.prepareConcreteCallee(CGF);
+  Address newThisAddr =
+      CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall(CGF, MD,
+                                                               thisAddr, true);
+  thisPtr = newThisAddr.getPointer();
+  auto *result = concreteCallee.getFunctionPointer();
+  builder->SetInsertPoint(CGF.Builder.GetInsertBlock(),
+                          CGF.Builder.GetInsertPoint());
+  return result;
+}
Index: lib/CodeGen/CodeGenABITypes.cpp
===================================================================
--- lib/CodeGen/CodeGenABITypes.cpp
+++ lib/CodeGen/CodeGenABITypes.cpp
@@ -52,6 +52,17 @@
   return CGM.getTypes().arrangeCXXMethodType(RD, FTP, MD);
 }
 
+const CGFunctionInfo &
+CodeGen::arrangeCXXMethodDeclaration(CodeGenModule &CGM,
+                                     const CXXMethodDecl *MD) {
+  return CGM.getTypes().arrangeCXXMethodDeclaration(MD);
+}
+
+llvm::FunctionType *CodeGen::getFunctionType(CodeGenModule &CGM,
+                                             const CGFunctionInfo &FI) {
+  return CGM.getTypes().GetFunctionType(FI);
+}
+
 const CGFunctionInfo &
 CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM,
                                  CanQualType returnType,
Index: include/clang/CodeGen/SwiftCallingConv.h
===================================================================
--- include/clang/CodeGen/SwiftCallingConv.h
+++ include/clang/CodeGen/SwiftCallingConv.h
@@ -22,14 +22,18 @@
 namespace llvm {
   class IntegerType;
   class Type;
+  class Value;
   class StructType;
   class VectorType;
+  class FunctionType;
+  class IRBuilderBase;
 }
 
 namespace clang {
 class Decl;
 class FieldDecl;
 class ASTRecordLayout;
+class CXXMethodDecl;
 
 namespace CodeGen {
 class ABIArgInfo;
@@ -177,6 +181,14 @@
 /// Is swifterror lowered to a register by the target ABI?
 bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);
 
+/// Lookup a virtual method `MD` from the vtable and adjusts the this ptr.
+llvm::Value *lowerCXXVirtualMethodDeclReference(CodeGenModule &CGM,
+                                                const CXXMethodDecl *MD,
+                                                llvm::Value *&thisPtr,
+                                                CharUnits alignment,
+                                                llvm::FunctionType *type,
+                                                llvm::IRBuilderBase *builder);
+
 } // end namespace swiftcall
 } // end namespace CodeGen
 } // end namespace clang
Index: include/clang/CodeGen/CodeGenABITypes.h
===================================================================
--- include/clang/CodeGen/CodeGenABITypes.h
+++ include/clang/CodeGen/CodeGenABITypes.h
@@ -65,6 +65,9 @@
                                            const FunctionProtoType *FTP,
                                            const CXXMethodDecl *MD);
 
+const CGFunctionInfo &arrangeCXXMethodDeclaration(CodeGenModule &CGM,
+                                                  const CXXMethodDecl *MD);
+
 const CGFunctionInfo &arrangeFreeFunctionCall(CodeGenModule &CGM,
                                               CanQualType returnType,
                                               ArrayRef<CanQualType> argTypes,
@@ -75,6 +78,9 @@
 llvm::FunctionType *convertFreeFunctionType(CodeGenModule &CGM,
                                             const FunctionDecl *FD);
 
+llvm::FunctionType *getFunctionType(CodeGenModule &CGM,
+                                    const CGFunctionInfo &FI);
+
 llvm::Type *convertTypeForMemory(CodeGenModule &CGM, QualType T);
 
 /// Given a non-bitfield struct field, return its index within the elements of
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to