[clang] CodeGen: Make getOrEmitProtocol public for Swift
Summary:
Swift would like to use clang's apis to emit protocol declarations.
This commits adds the public API:
```
emitObjCProtocolObject(CodeGenModule &CGM, const ObjCProtocolDecl *p);
```
rdar://60888524
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D77077
diff --git a/clang/include/clang/CodeGen/CodeGenABITypes.h b/clang/include/clang/CodeGen/CodeGenABITypes.h
index 31f0cea..5f4af7f 100644
--- a/clang/include/clang/CodeGen/CodeGenABITypes.h
+++ b/clang/include/clang/CodeGen/CodeGenABITypes.h
@@ -28,11 +28,12 @@
#include "clang/CodeGen/CGFunctionInfo.h"
namespace llvm {
- class DataLayout;
- class Module;
- class Function;
- class FunctionType;
- class Type;
+class Constant;
+class DataLayout;
+class Module;
+class Function;
+class FunctionType;
+class Type;
}
namespace clang {
@@ -44,6 +45,7 @@
class DiagnosticsEngine;
class HeaderSearchOptions;
class ObjCMethodDecl;
+class ObjCProtocolDecl;
class PreprocessorOptions;
namespace CodeGen {
@@ -137,6 +139,13 @@
CharUnits DstAlignment,
bool IsVolatile, QualType QT);
+/// Get a pointer to a protocol object for the given declaration, emitting it if
+/// it hasn't already been emitted in this translation unit. Note that the ABI
+/// for emitting a protocol reference in code (e.g. for a protocol expression)
+/// in most runtimes is not as simple as just materializing a pointer to this
+/// object.
+llvm::Constant *emitObjCProtocolObject(CodeGenModule &CGM,
+ const ObjCProtocolDecl *p);
} // end namespace CodeGen
} // end namespace clang
diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp
index db78309..35b9268 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -617,6 +617,13 @@
llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
const ObjCProtocolDecl *PD) override;
void GenerateProtocol(const ObjCProtocolDecl *PD) override;
+
+ virtual llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD);
+
+ llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override {
+ return GenerateProtocolRef(PD);
+ }
+
llvm::Function *ModuleInitFunction() override;
llvm::FunctionCallee GetPropertyGetFunction() override;
llvm::FunctionCallee GetPropertySetFunction() override;
@@ -1348,7 +1355,7 @@
void GenerateProtocol(const ObjCProtocolDecl *PD) override {
// Do nothing - we only emit referenced protocols.
}
- llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) {
+ llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) override {
std::string ProtocolName = PD->getNameAsString();
auto *&Protocol = ExistingProtocols[ProtocolName];
if (Protocol)
@@ -3039,13 +3046,18 @@
llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
const ObjCProtocolDecl *PD) {
+ auto protocol = GenerateProtocolRef(PD);
+ llvm::Type *T =
+ CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
+ return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
+}
+
+llvm::Constant *CGObjCGNU::GenerateProtocolRef(const ObjCProtocolDecl *PD) {
llvm::Constant *&protocol = ExistingProtocols[PD->getNameAsString()];
if (!protocol)
GenerateProtocol(PD);
assert(protocol && "Unknown protocol");
- llvm::Type *T =
- CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
- return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
+ return protocol;
}
llvm::Constant *
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 87fd51b..3986310 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -1107,11 +1107,6 @@
void GenerateProtocol(const ObjCProtocolDecl *PD) override;
- /// GetOrEmitProtocol - Get the protocol object for the given
- /// declaration, emitting it if necessary. The return value has type
- /// ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
-
/// GetOrEmitProtocolRef - Get a forward reference to the protocol
/// object for the given declaration, emitting it if needed. These
/// forward references will be filled in with empty bodies if no
diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp
index c34758c..39efe04 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -13,14 +13,15 @@
//===----------------------------------------------------------------------===//
#include "CGObjCRuntime.h"
-#include "CGCleanup.h"
#include "CGCXXABI.h"
+#include "CGCleanup.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtObjC.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/CodeGenABITypes.h"
#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
@@ -383,3 +384,9 @@
CGM.getTypes().GetFunctionType(argsInfo)->getPointerTo();
return MessageSendInfo(argsInfo, signatureType);
}
+
+llvm::Constant *
+clang::CodeGen::emitObjCProtocolObject(CodeGenModule &CGM,
+ const ObjCProtocolDecl *protocol) {
+ return CGM.getObjCRuntime().GetOrEmitProtocol(protocol);
+}
diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h
index f0b3525..a2c1895 100644
--- a/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/clang/lib/CodeGen/CGObjCRuntime.h
@@ -211,6 +211,11 @@
/// implementations.
virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0;
+ /// GetOrEmitProtocol - Get the protocol object for the given
+ /// declaration, emitting it if necessary. The return value has type
+ /// ProtocolPtrTy.
+ virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) = 0;
+
/// Generate a function preamble for a method with the specified
/// types.