Support @compatibility_alias at run time (GNUstep Runtime)

Patch by Niels Grewe!



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149401 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Chisnall 2012-01-31 18:59:20 +00:00
Родитель 2831092e80
Коммит 29254f4dd1
4 изменённых файлов: 63 добавлений и 2 удалений

Просмотреть файл

@ -18,7 +18,6 @@
#include "CodeGenModule.h"
#include "CodeGenFunction.h"
#include "CGCleanup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@ -288,6 +287,10 @@ private:
LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
WeakAssignFn, GlobalAssignFn;
typedef std::pair<std::string, std::string> ClassAliasPair;
/// All classes that have aliases set for them.
std::vector<ClassAliasPair> ClassAliases;
protected:
/// Function used for throwing Objective-C exceptions.
LazyRuntimeFunction ExceptionThrowFn;
@ -466,6 +469,7 @@ public:
const ObjCContainerDecl *CD);
virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD);
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);
virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
@ -1934,6 +1938,15 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI
".objc_property_list");
}
void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {
// Get the class declaration for which the alias is specified.
ObjCInterfaceDecl *ClassDecl =
const_cast<ObjCInterfaceDecl *>(OAD->getClassInterface());
std::string ClassName = ClassDecl->getNameAsString();
std::string AliasName = OAD->getNameAsString();
ClassAliases.push_back(ClassAliasPair(ClassName,AliasName));
}
void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
ASTContext &Context = CGM.getContext();
@ -2349,6 +2362,46 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
llvm::PointerType::getUnqual(ModuleTy), true);
llvm::Value *Register = CGM.CreateRuntimeFunction(FT, "__objc_exec_class");
Builder.CreateCall(Register, Module);
if (0 != ClassAliases.size()) {
llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
llvm::FunctionType *RegisterAliasTy =
llvm::FunctionType::get(Builder.getVoidTy(),
ArgTypes, false);
llvm::Function *RegisterAlias = llvm::Function::Create(
RegisterAliasTy,
llvm::GlobalValue::ExternalWeakLinkage, "class_registerAlias_np",
&TheModule);
llvm::BasicBlock *AliasBB =
llvm::BasicBlock::Create(VMContext, "alias", LoadFunction);
llvm::BasicBlock *NoAliasBB =
llvm::BasicBlock::Create(VMContext, "no_alias", LoadFunction);
// Branch based on whether the runtime provided class_registerAlias_np()
llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
llvm::Constant::getNullValue(RegisterAlias->getType()));
Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);
// The true branch (has alias registration fucntion):
Builder.SetInsertPoint(AliasBB);
// Emit alias registration calls:
for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
iter != ClassAliases.end(); ++iter) {
llvm::Constant *TheClass =
TheModule.getGlobalVariable(("_OBJC_CLASS_" + iter->first).c_str(),
true);
if (0 != TheClass) {
TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy);
Builder.CreateCall2(RegisterAlias, TheClass,
MakeConstantString(iter->second));
}
}
// Jump to end:
Builder.CreateBr(NoAliasBB);
// Missing alias registration function, just return from the function:
Builder.SetInsertPoint(NoAliasBB);
}
Builder.CreateRetVoid();
return LoadFunction;

Просмотреть файл

@ -1084,6 +1084,8 @@ public:
virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {};
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);
@ -1336,6 +1338,9 @@ public:
virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {};
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);

Просмотреть файл

@ -140,6 +140,9 @@ public:
/// Generate a class structure for this class.
virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0;
/// Register an class alias.
virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0;
/// Generate an Objective-C message send operation.
///
/// \param Method - The method being called, this may be null if synthesizing

Просмотреть файл

@ -2421,7 +2421,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
break;
}
case Decl::ObjCCompatibleAlias:
// compatibility-alias is a directive and has no code gen.
ObjCRuntime->RegisterAlias(cast<ObjCCompatibleAliasDecl>(D));
break;
case Decl::LinkageSpec: