Refactoring ObjC Next's runtime classes in preparation for

the new ObjC's abi.

llvm-svn: 62721
This commit is contained in:
Fariborz Jahanian 2009-01-21 22:04:16 +00:00
parent d776b6e51d
commit 279eda6275
5 changed files with 134 additions and 76 deletions

View File

@ -483,6 +483,9 @@ LaxVectorConversions("flax-vector-conversions",
static llvm::cl::opt<bool>
EnableBlocks("fblocks", llvm::cl::desc("enable the 'blocks' language feature"));
static llvm::cl::opt<bool>
ObjCModernABI("fobjc-modern-abi", llvm::cl::desc("enable objective-c's modern abi"));
// FIXME: This (and all GCC -f options) really come in -f... and
// -fno-... forms, and additionally support automagic behavior when
@ -614,6 +617,9 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
Options.NeXTRuntime = 1;
else if (GNURuntime)
Options.NeXTRuntime = 0;
if (ObjCModernABI)
Options.ObjCModernABI = 1;
}
static llvm::cl::opt<bool>

View File

@ -38,6 +38,7 @@ struct LangOptions {
unsigned ObjC1 : 1; // Objective-C 1 support enabled.
unsigned ObjC2 : 1; // Objective-C 2 support enabled.
unsigned ObjCModernABI : 1; // Objective-C modern abi enabled
unsigned PascalStrings : 1; // Allow Pascal strings
unsigned Boolean : 1; // Allow bool/true/false
@ -62,7 +63,7 @@ public:
Trigraphs = BCPLComment = DollarIdents = AsmPreprocessor = 0;
ImplicitInt = Digraphs = 0;
HexFloats = 0;
GC = ObjC1 = ObjC2 = 0;
GC = ObjC1 = ObjC2 = ObjCModernABI = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
LaxVectorConversions = Exceptions = NeXTRuntime = 0;

View File

@ -35,20 +35,14 @@ namespace {
// FIXME: We should find a nicer way to make the labels for
// metadata, string concatenation is lame.
/// ObjCTypesHelper - Helper class that encapsulates lazy
/// construction of varies types used during ObjC generation.
class ObjCTypesHelper {
private:
CodeGen::CodeGenModule &CGM;
class ObjCCommonTypesHelper {
protected:
CodeGen::CodeGenModule &CGM;
llvm::Function *MessageSendFn, *MessageSendStretFn, *MessageSendFpretFn;
llvm::Function *MessageSendSuperFn, *MessageSendSuperStretFn,
*MessageSendSuperFpretFn;
public:
const llvm::Type *ShortTy, *IntTy, *LongTy;
const llvm::Type *Int8PtrTy;
/// ObjectPtrTy - LLVM type for object handles (typeof(id))
const llvm::Type *ObjectPtrTy;
@ -60,17 +54,31 @@ public:
/// ProtocolPtrTy - LLVM type for external protocol handles
/// (typeof(Protocol))
const llvm::Type *ExternalProtocolPtrTy;
// SuperCTy - clang type for struct objc_super.
QualType SuperCTy;
// SuperPtrCTy - clang type for struct objc_super *.
QualType SuperPtrCTy;
/// SuperTy - LLVM type for struct objc_super.
const llvm::StructType *SuperTy;
/// SuperPtrTy - LLVM type for struct objc_super *.
const llvm::Type *SuperPtrTy;
ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCCommonTypesHelper(){}
};
/// ObjCTypesHelper - Helper class that encapsulates lazy
/// construction of varies types used during ObjC generation.
class ObjCTypesHelper : public ObjCCommonTypesHelper {
private:
llvm::Function *MessageSendFn, *MessageSendStretFn, *MessageSendFpretFn;
llvm::Function *MessageSendSuperFn, *MessageSendSuperStretFn,
*MessageSendSuperFpretFn;
public:
/// SymtabTy - LLVM type for struct objc_symtab.
const llvm::StructType *SymtabTy;
/// SymtabPtrTy - LLVM type for struct objc_symtab *.
@ -183,7 +191,7 @@ public:
public:
ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCTypesHelper();
~ObjCTypesHelper() {}
llvm::Function *getSendFn(bool IsSuper) {
@ -199,13 +207,20 @@ public:
}
};
class CGObjCMac : public CodeGen::CGObjCRuntime {
private:
CodeGen::CodeGenModule &CGM;
ObjCTypesHelper ObjCTypes;
/// ObjCABI - FIXME: Not sure yet.
/// ObjCModernTypesHelper - will have all types needed by objective-c's
/// modern abi
class ObjCModernTypesHelper : public ObjCCommonTypesHelper {
public:
ObjCModernTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCModernTypesHelper(){}
};
class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
protected:
CodeGen::CodeGenModule &CGM;
// FIXME! May not be needing this after all.
unsigned ObjCABI;
/// LazySymbols - Symbols to generate a lazy reference for. See
/// DefinedSymbols and FinishModule().
std::set<IdentifierInfo*> LazySymbols;
@ -215,49 +230,57 @@ private:
/// special linker symbols which ensure that Objective-C modules are
/// linked properly.
std::set<IdentifierInfo*> DefinedSymbols;
/// ClassNames - uniqued class names.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
/// MethodVarNames - uniqued method variable names.
llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
/// MethodVarTypes - uniqued method type signatures. We have to use
/// a StringMap here because have no other unique reference.
llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
/// MethodDefinitions - map of methods which have been defined in
/// this translation unit.
llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
/// PropertyNames - uniqued method variable names.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
/// ClassReferences - uniqued class references.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
/// SelectorReferences - uniqued selector references.
llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
/// Protocols - Protocols for which an objc_protocol structure has
/// been emitted. Forward declarations are handled by creating an
/// empty structure whose initializer is filled in when/if defined.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
/// DefinedProtocols - Protocols which have actually been
/// defined. We should not need this, see FIXME in GenerateProtocol.
llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
/// DefinedClasses - List of defined classes.
std::vector<llvm::GlobalValue*> DefinedClasses;
/// DefinedCategories - List of defined categories.
std::vector<llvm::GlobalValue*> DefinedCategories;
/// UsedGlobals - List of globals to pack into the llvm.used metadata
/// to prevent them from being clobbered.
std::vector<llvm::GlobalVariable*> UsedGlobals;
public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
{ }
};
class CGObjCMac : public CGObjCCommonMac {
private:
ObjCTypesHelper ObjCTypes;
/// EmitImageInfo - Emit the image info marker used to encode some module
/// level information.
void EmitImageInfo();
@ -467,6 +490,14 @@ public:
virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
};
class CGObjCModernMac : public CGObjCCommonMac {
private:
ObjCModernTypesHelper ObjCTypes;
public:
CGObjCModernMac(CodeGen::CodeGenModule &cgm);
};
} // end anonymous namespace
/* *** Helper Functions *** */
@ -484,15 +515,10 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C,
/* *** CGObjCMac Public Interface *** */
CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm)
: CGM(cgm),
ObjCTypes(cgm),
ObjCABI(1)
CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
ObjCTypes(cgm)
{
// FIXME: How does this get set in GCC? And what does it even mean?
if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy))
ObjCABI = 2;
ObjCABI = 1;
EmitImageInfo();
}
@ -2229,14 +2255,21 @@ void CGObjCMac::FinishModule() {
CGM.getModule().appendModuleInlineAsm(s.str());
}
CGObjCModernMac::CGObjCModernMac(CodeGen::CodeGenModule &cgm)
: CGObjCCommonMac(cgm),
ObjCTypes(cgm)
{
ObjCABI = 2;
}
/* *** */
ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
: CGM(cgm)
ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
: CGM(cgm)
{
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
ShortTy = Types.ConvertType(Ctx.ShortTy);
IntTy = Types.ConvertType(Ctx.IntTy);
LongTy = Types.ConvertType(Ctx.LongTy);
@ -2250,7 +2283,41 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
// that the IR comes out a bit cleaner.
const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
// I'm not sure I like this. The implicit coordination is a bit
// gross. We should solve this in a reasonable fashion because this
// is a pretty common task (match some runtime data structure with
// an LLVM data structure).
// FIXME: This is leaked.
// FIXME: Merge with rewriter code?
// struct _objc_super {
// id self;
// Class cls;
// }
RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
SourceLocation(),
&Ctx.Idents.get("_objc_super"));
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Ctx.getObjCIdType(), 0, false));
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Ctx.getObjCClassType(), 0, false));
RD->completeDefinition(Ctx);
SuperCTy = Ctx.getTagDeclType(RD);
SuperPtrCTy = Ctx.getPointerType(SuperCTy);
SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
}
ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
: ObjCCommonTypesHelper(cgm)
{
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
// struct _objc_method_description {
// SEL name;
// char *types;
@ -2326,10 +2393,11 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get();
llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
T = llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder),
LongTy,
llvm::ArrayType::get(ProtocolTyHolder, 0),
NULL);
const llvm::Type *T =
llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder),
LongTy,
llvm::ArrayType::get(ProtocolTyHolder, 0),
NULL);
cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
// struct _objc_protocol {
@ -2458,33 +2526,6 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
NULL);
CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
// I'm not sure I like this. The implicit coordination is a bit
// gross. We should solve this in a reasonable fashion because this
// is a pretty common task (match some runtime data structure with
// an LLVM data structure).
// FIXME: This is leaked.
// FIXME: Merge with rewriter code?
// struct _objc_super {
// id self;
// Class cls;
// }
RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
SourceLocation(),
&Ctx.Idents.get("_objc_super"));
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Ctx.getObjCIdType(), 0, false));
RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Ctx.getObjCClassType(), 0, false));
RD->completeDefinition(Ctx);
SuperCTy = Ctx.getTagDeclType(RD);
SuperPtrCTy = Ctx.getPointerType(SuperCTy);
SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
// Global metadata structures
// struct _objc_symtab {
@ -2711,7 +2752,9 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
}
ObjCTypesHelper::~ObjCTypesHelper() {
ObjCModernTypesHelper::ObjCModernTypesHelper(CodeGen::CodeGenModule &cgm)
: ObjCCommonTypesHelper(cgm)
{
}
/* *** */
@ -2720,3 +2763,9 @@ CodeGen::CGObjCRuntime *
CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
return new CGObjCMac(CGM);
}
CodeGen::CGObjCRuntime *
CodeGen::CreateMacModernObjCRuntime(CodeGen::CodeGenModule &CGM) {
return 0;
// return new CGObjCModernMac(CGM);
}

View File

@ -161,6 +161,7 @@ public:
//TODO: This should include some way of selecting which runtime to target.
CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM);
CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM);
CGObjCRuntime *CreateMacModernObjCRuntime(CodeGenModule &CGM);
}
}
#endif

View File

@ -39,7 +39,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
if (Features.ObjC1) {
if (Features.NeXTRuntime) {
Runtime = CreateMacObjCRuntime(*this);
Runtime = Features.ObjCModernABI ? CreateMacModernObjCRuntime(*this)
: CreateMacObjCRuntime(*this);
} else {
Runtime = CreateGNUObjCRuntime(*this);
}