diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-03-31 18:27:22 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-03-31 18:27:22 +0000 |
commit | f8c4f5469d7db591eeacfc3381d91f773fb7af43 (patch) | |
tree | e61c98e9b63fb304d9919397e79e8d1658bb0549 /lib/CodeGen/CGObjCGNU.cpp | |
parent | 18191886554407b4260c40165bc294c3ea732033 (diff) |
Patch to fix proptocol reference ir-gen for GNU runtime.
Patch by David Chisnal.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68125 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index bc713bd8cc..d5aae03769 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -71,6 +71,7 @@ private: const llvm::SmallVectorImpl<Selector> &MethodSels, const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, bool isClassMethodList); + llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName); llvm::Constant *GenerateProtocolList( const llvm::SmallVectorImpl<std::string> &Protocols); llvm::Constant *GenerateClassStructure( @@ -554,8 +555,11 @@ llvm::Constant *CGObjCGNU::GenerateProtocolList( std::vector<llvm::Constant*> Elements; for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end(); iter != endIter ; iter++) { + llvm::Constant *protocol = ExistingProtocols[*iter]; + if (!protocol) + protocol = GenerateEmptyProtocol(*iter); llvm::Constant *Ptr = - llvm::ConstantExpr::getBitCast(ExistingProtocols[*iter], PtrToInt8Ty); + llvm::ConstantExpr::getBitCast(protocol, PtrToInt8Ty); Elements.push_back(Ptr); } llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, @@ -569,7 +573,40 @@ llvm::Constant *CGObjCGNU::GenerateProtocolList( llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD) { - return ExistingProtocols[PD->getNameAsString()]; + llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()]; + const llvm::Type *T = + CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType()); + return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T)); +} + +llvm::Constant *CGObjCGNU::GenerateEmptyProtocol( + const std::string &ProtocolName) { + llvm::SmallVector<std::string, 0> EmptyStringVector; + llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector; + + llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector); + llvm::Constant *InstanceMethodList = + GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector); + llvm::Constant *ClassMethodList = + GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector); + // Protocols are objects containing lists of the methods implemented and + // protocols adopted. + llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy, + PtrToInt8Ty, + ProtocolList->getType(), + InstanceMethodList->getType(), + ClassMethodList->getType(), + NULL); + std::vector<llvm::Constant*> Elements; + // The isa pointer must be set to a magic number so the runtime knows it's + // the correct layout. + Elements.push_back(llvm::ConstantExpr::getIntToPtr( + llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy)); + Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); + Elements.push_back(ProtocolList); + Elements.push_back(InstanceMethodList); + Elements.push_back(ClassMethodList); + return MakeGlobal(ProtocolTy, Elements, ".objc_protocol"); } void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { |