[cfe-commits] r145469 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/CodeGen/CGObjCMac.cpp
Bob Wilson
bob.wilson at apple.com
Tue Nov 29 17:57:58 PST 2011
Author: bwilson
Date: Tue Nov 29 19:57:58 2011
New Revision: 145469
URL: http://llvm.org/viewvc/llvm-project?rev=145469&view=rev
Log:
Add bigger method type encodings to protocol objects. <rdar://problem/10492418>
The new metadata are method @encode strings with additional data.
1. Each Objective-C object is marked with its class name and protocol names.
The same is done for property @encode already.
2. Each block object is marked with its function prototype's @encoding. For
example, a method parameter that is a block object that itself returns void
and takes an int would look like:
@?<v@?i>
These new method @encode strings are stored in a single array pointed to by structs protocol_t and objc_protocol_ext.
Patch provided by Greg Parker!
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=145469&r1=145468&r2=145469&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Nov 29 19:57:58 2011
@@ -1007,7 +1007,8 @@
///
/// \returns true if an error occurred (e.g., because one of the parameter
/// types is incomplete), false otherwise.
- bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S)
+ bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S,
+ bool Extended = false)
const;
/// getObjCEncodingForBlock - Return the encoded type for this block
@@ -1764,13 +1765,20 @@
const FieldDecl *Field,
bool OutermostType = false,
bool EncodingProperty = false,
- bool StructField = false) const;
+ bool StructField = false,
+ bool EncodeBlockParameters = false,
+ bool EncodeClassNames = false) const;
// Adds the encoding of the structure's members.
void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
const FieldDecl *Field,
bool includeVBases = true) const;
-
+
+ // Adds the encoding of a method parameter or return type.
+ void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
+ QualType T, std::string& S,
+ bool Extended) const;
+
const ASTRecordLayout &
getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl) const;
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=145469&r1=145468&r2=145469&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 29 19:57:58 2011
@@ -4080,15 +4080,32 @@
return false;
}
+/// getObjCEncodingForMethodParameter - Return the encoded type for a single
+/// method parameter or return type. If Extended, include class names and
+/// block object types.
+void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
+ QualType T, std::string& S,
+ bool Extended) const {
+ // Encode type qualifer, 'in', 'inout', etc. for the parameter.
+ getObjCEncodingForTypeQualifier(QT, S);
+ // Encode parameter type.
+ getObjCEncodingForTypeImpl(T, S, true, true, 0,
+ true /*OutermostType*/,
+ false /*EncodingProperty*/,
+ false /*StructField*/,
+ Extended /*EncodeBlockParameters*/,
+ Extended /*EncodeClassNames*/);
+}
+
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
- std::string& S) const {
+ std::string& S,
+ bool Extended) const {
// FIXME: This is not very efficient.
- // Encode type qualifer, 'in', 'inout', etc. for the return type.
- getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S);
- // Encode result type.
- getObjCEncodingForType(Decl->getResultType(), S);
+ // Encode return type.
+ getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(),
+ Decl->getResultType(), S, Extended);
// Compute size of all parameters.
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
@@ -4126,10 +4143,8 @@
PType = PVDecl->getType();
} else if (PType->isFunctionType())
PType = PVDecl->getType();
- // Process argument qualifiers for user supplied arguments; such as,
- // 'in', 'inout', etc.
- getObjCEncodingForTypeQualifier(PVDecl->getObjCDeclQualifier(), S);
- getObjCEncodingForType(PType, S);
+ getObjCEncodingForMethodParameter(PVDecl->getObjCDeclQualifier(),
+ PType, S, Extended);
S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
@@ -4355,7 +4370,9 @@
const FieldDecl *FD,
bool OutermostType,
bool EncodingProperty,
- bool StructField) const {
+ bool StructField,
+ bool EncodeBlockParameters,
+ bool EncodeClassNames) const {
if (T->getAs<BuiltinType>()) {
if (FD && FD->isBitField())
return EncodeBitField(this, S, T, FD);
@@ -4534,8 +4551,40 @@
return;
}
- if (T->isBlockPointerType()) {
+ if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
S += "@?"; // Unlike a pointer-to-function, which is "^?".
+ if (EncodeBlockParameters) {
+ const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
+
+ S += '<';
+ // Block return type
+ getObjCEncodingForTypeImpl(FT->getResultType(), S,
+ ExpandPointedToStructures, ExpandStructures,
+ FD,
+ false /* OutermostType */,
+ EncodingProperty,
+ false /* StructField */,
+ EncodeBlockParameters,
+ EncodeClassNames);
+ // Block self
+ S += "@?";
+ // Block parameters
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
+ for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),
+ E = FPT->arg_type_end(); I && (I != E); ++I) {
+ getObjCEncodingForTypeImpl(*I, S,
+ ExpandPointedToStructures,
+ ExpandStructures,
+ FD,
+ false /* OutermostType */,
+ EncodingProperty,
+ false /* StructField */,
+ EncodeBlockParameters,
+ EncodeClassNames);
+ }
+ }
+ S += '>';
+ }
return;
}
@@ -4581,7 +4630,7 @@
getObjCEncodingForTypeImpl(getObjCIdType(), S,
ExpandPointedToStructures,
ExpandStructures, FD);
- if (FD || EncodingProperty) {
+ if (FD || EncodingProperty || EncodeClassNames) {
// Note that we do extended encoding of protocol qualifer list
// Only when doing ivar or property encoding.
S += '"';
@@ -4610,7 +4659,8 @@
}
S += '@';
- if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) {
+ if (OPT->getInterfaceDecl() &&
+ (FD || EncodingProperty || EncodeClassNames)) {
S += '"';
S += OPT->getInterfaceDecl()->getIdentifier()->getName();
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=145469&r1=145468&r2=145469&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Nov 29 19:57:58 2011
@@ -175,7 +175,7 @@
public:
llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
- llvm::Type *Int8PtrTy;
+ llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
/// ObjectPtrTy - LLVM type for object handles (typeof(id))
llvm::Type *ObjectPtrTy;
@@ -766,10 +766,11 @@
llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
/// GetMethodVarType - Return a unique constant for the given
- /// selector's name. The return value has type char *.
+ /// method's type encoding string. The return value has type char *.
// FIXME: This is a horrible name.
- llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
+ llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
+ bool Extended = false);
llvm::Constant *GetMethodVarType(const FieldDecl *D);
/// GetPropertyName - Return a unique constant for the given
@@ -816,6 +817,12 @@
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes);
+ /// EmitProtocolMethodTypes - Generate the array of extended method type
+ /// strings. The return value has type Int8PtrPtrTy.
+ llvm::Constant *EmitProtocolMethodTypes(Twine Name,
+ const ConstantVector &MethodTypes,
+ const ObjCCommonTypesHelper &ObjCTypes);
+
/// PushProtocolProperties - Push protocol's property on the input stack.
void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
std::vector<llvm::Constant*> &Properties,
@@ -985,7 +992,8 @@
llvm::Constant *
EmitProtocolExtension(const ObjCProtocolDecl *PD,
const ConstantVector &OptInstanceMethods,
- const ConstantVector &OptClassMethods);
+ const ConstantVector &OptClassMethods,
+ const ConstantVector &MethodTypesExt);
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
@@ -1786,6 +1794,7 @@
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
+ std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
for (ObjCProtocolDecl::instmeth_iterator
i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
ObjCMethodDecl *MD = *i;
@@ -1795,8 +1804,10 @@
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptInstanceMethods.push_back(C);
+ OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
} else {
InstanceMethods.push_back(C);
+ MethodTypesExt.push_back(GetMethodVarType(MD, true));
}
}
@@ -1809,13 +1820,19 @@
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptClassMethods.push_back(C);
+ OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
} else {
ClassMethods.push_back(C);
+ MethodTypesExt.push_back(GetMethodVarType(MD, true));
}
}
+ MethodTypesExt.insert(MethodTypesExt.end(),
+ OptMethodTypesExt.begin(), OptMethodTypesExt.end());
+
llvm::Constant *Values[] = {
- EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods),
+ EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
+ MethodTypesExt),
GetClassName(PD->getIdentifier()),
EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
PD->protocol_begin(),
@@ -1875,12 +1892,14 @@
struct objc_method_description_list *optional_instance_methods;
struct objc_method_description_list *optional_class_methods;
struct objc_property_list *instance_properties;
+ const char ** extendedMethodTypes;
};
*/
llvm::Constant *
CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
const ConstantVector &OptInstanceMethods,
- const ConstantVector &OptClassMethods) {
+ const ConstantVector &OptClassMethods,
+ const ConstantVector &MethodTypesExt) {
uint64_t Size =
CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
llvm::Constant *Values[] = {
@@ -1893,12 +1912,14 @@
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
OptClassMethods),
EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
- ObjCTypes)
+ ObjCTypes),
+ EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
+ MethodTypesExt, ObjCTypes)
};
// Return null if no extension bits are used.
if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
- Values[3]->isNullValue())
+ Values[3]->isNullValue() && Values[4]->isNullValue())
return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
llvm::Constant *Init =
@@ -2037,6 +2058,25 @@
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
}
+llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
+ const ConstantVector &MethodTypes,
+ const ObjCCommonTypesHelper &ObjCTypes) {
+ // Return null for empty list.
+ if (MethodTypes.empty())
+ return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
+
+ llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
+ MethodTypes.size());
+ llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
+
+ llvm::GlobalVariable *GV =
+ CreateMetadataVar(Name, Init,
+ (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
+ (ObjCABI == 2) ? 8 : 4,
+ true);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
+}
+
/*
struct objc_method_description_list {
int count;
@@ -4024,11 +4064,12 @@
return getConstantGEP(VMContext, Entry, 0, 0);
}
-llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
+llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
+ bool Extended) {
std::string TypeStr;
if (CGM.getContext().getObjCEncodingForMethodDecl(
const_cast<ObjCMethodDecl*>(D),
- TypeStr))
+ TypeStr, Extended))
return 0;
llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
@@ -4152,6 +4193,7 @@
LongTy = Types.ConvertType(Ctx.LongTy);
LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+ Int8PtrPtrTy = llvm::PointerType::getUnqual(Int8PtrTy);
ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
@@ -4253,12 +4295,13 @@
// struct _objc_method_description_list *optional_instance_methods;
// struct _objc_method_description_list *optional_class_methods;
// struct _objc_property_list *instance_properties;
+ // const char ** extendedMethodTypes;
// }
ProtocolExtensionTy =
llvm::StructType::create("struct._objc_protocol_extension",
IntTy, MethodDescriptionListPtrTy,
MethodDescriptionListPtrTy, PropertyListPtrTy,
- NULL);
+ Int8PtrPtrTy, NULL);
// struct _objc_protocol_extension *
ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
@@ -4431,6 +4474,7 @@
// const struct _prop_list_t * properties;
// const uint32_t size; // sizeof(struct _protocol_t)
// const uint32_t flags; // = 0
+ // const char ** extendedMethodTypes;
// }
// Holder for struct _protocol_list_t *
@@ -4442,7 +4486,8 @@
llvm::PointerType::getUnqual(ProtocolListnfABITy),
MethodListnfABIPtrTy, MethodListnfABIPtrTy,
MethodListnfABIPtrTy, MethodListnfABIPtrTy,
- PropertyListPtrTy, IntTy, IntTy, NULL);
+ PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
+ NULL);
// struct _protocol_t*
ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
@@ -5353,6 +5398,7 @@
/// const struct _prop_list_t * properties;
/// const uint32_t size; // sizeof(struct _protocol_t)
/// const uint32_t flags; // = 0
+/// const char ** extendedMethodTypes;
/// }
/// @endcode
///
@@ -5368,6 +5414,7 @@
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
+ std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
for (ObjCProtocolDecl::instmeth_iterator
i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
ObjCMethodDecl *MD = *i;
@@ -5377,8 +5424,10 @@
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptInstanceMethods.push_back(C);
+ OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
} else {
InstanceMethods.push_back(C);
+ MethodTypesExt.push_back(GetMethodVarType(MD, true));
}
}
@@ -5391,12 +5440,17 @@
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptClassMethods.push_back(C);
+ OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
} else {
ClassMethods.push_back(C);
+ MethodTypesExt.push_back(GetMethodVarType(MD, true));
}
}
- llvm::Constant *Values[10];
+ MethodTypesExt.insert(MethodTypesExt.end(),
+ OptMethodTypesExt.begin(), OptMethodTypesExt.end());
+
+ llvm::Constant *Values[11];
// isa is NULL
Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Values[1] = GetClassName(PD->getIdentifier());
@@ -5426,6 +5480,9 @@
CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
+ Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
+ + PD->getName(),
+ MethodTypesExt, ObjCTypes);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Values);
More information about the cfe-commits
mailing list