[cfe-commits] r71467 - in /cfe/trunk: lib/CodeGen/CGObjCMac.cpp test/CodeGenObjC/metadata-symbols-64.m
Fariborz Jahanian
fjahanian at apple.com
Mon May 11 12:25:48 PDT 2009
Author: fjahanian
Date: Mon May 11 14:25:47 2009
New Revision: 71467
URL: http://llvm.org/viewvc/llvm-project?rev=71467&view=rev
Log:
Patch to allow Nonfragile ABI to use 32-bit style legacy
message dispage API for all but a few messages. This is
a runtime performance improvement and there is not meant
to be a functional change.
Modified:
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
cfe/trunk/test/CodeGenObjC/metadata-symbols-64.m
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=71467&r1=71466&r2=71467&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon May 11 14:25:47 2009
@@ -145,6 +145,100 @@
// metadata, string concatenation is lame.
class ObjCCommonTypesHelper {
+private:
+ llvm::Constant *getMessageSendFn() const {
+ // id objc_msgSend (id, SEL, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ "objc_msgSend");
+ }
+
+ llvm::Constant *getMessageSendStretFn() const {
+ // id objc_msgSend_stret (id, SEL, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
+ Params, true),
+ "objc_msgSend_stret");
+
+ }
+
+ llvm::Constant *getMessageSendFpretFn() const {
+ // FIXME: This should be long double on x86_64?
+ // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(ObjectPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return
+ CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::DoubleTy,
+ Params,
+ true),
+ "objc_msgSend_fpret");
+
+ }
+
+ llvm::Constant *getMessageSendSuperFn() const {
+ // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
+ const char *SuperName = "objc_msgSendSuper";
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ SuperName);
+ }
+
+ llvm::Constant *getMessageSendSuperFn2() const {
+ // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
+ const char *SuperName = "objc_msgSendSuper2";
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
+ Params, true),
+ SuperName);
+ }
+
+ llvm::Constant *getMessageSendSuperStretFn() const {
+ // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
+ // SEL op, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(Int8PtrTy);
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
+ Params, true),
+ "objc_msgSendSuper_stret");
+ }
+
+ llvm::Constant *getMessageSendSuperStretFn2() const {
+ // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
+ // SEL op, ...)
+ std::vector<const llvm::Type*> Params;
+ Params.push_back(Int8PtrTy);
+ Params.push_back(SuperPtrTy);
+ Params.push_back(SelectorPtrTy);
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
+ Params, true),
+ "objc_msgSendSuper2_stret");
+ }
+
+ llvm::Constant *getMessageSendSuperFpretFn() const {
+ // There is no objc_msgSendSuper_fpret? How can that work?
+ return getMessageSendSuperFn();
+ }
+
+ llvm::Constant *getMessageSendSuperFpretFn2() const {
+ // There is no objc_msgSendSuper_fpret? How can that work?
+ return getMessageSendSuperFn2();
+ }
+
protected:
CodeGen::CodeGenModule &CGM;
@@ -308,78 +402,37 @@
return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
}
- 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::Constant *getMessageSendFn() {
- // id objc_msgSend (id, SEL, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSend");
+ llvm::Constant *getSendFn(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
}
- llvm::Constant *getMessageSendStretFn() {
- // id objc_msgSend_stret (id, SEL, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
- Params, true),
- "objc_msgSend_stret");
-
+ llvm::Constant *getSendFn2(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
}
- llvm::Constant *getMessageSendFpretFn() {
- // FIXME: This should be long double on x86_64?
- // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::DoubleTy,
- Params,
- true),
- "objc_msgSend_fpret");
-
+ llvm::Constant *getSendStretFn(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
}
- llvm::Constant *getMessageSendSuperFn() {
- // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(SuperPtrTy);
- Params.push_back(SelectorPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendSuper");
+ llvm::Constant *getSendStretFn2(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
}
- llvm::Constant *getMessageSendSuperStretFn() {
- // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
- // SEL op, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(Int8PtrTy);
- Params.push_back(SuperPtrTy);
- Params.push_back(SelectorPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
- Params, true),
- "objc_msgSendSuper_stret");
+
+ llvm::Constant *getSendFpretFn(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
}
- llvm::Constant *getMessageSendSuperFpretFn() {
- // There is no objc_msgSendSuper_fpret? How can that work?
- return getMessageSendSuperFn();
+ llvm::Constant *getSendFpretFn2(bool IsSuper) const {
+ return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
}
+
+ ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
+ ~ObjCCommonTypesHelper(){}
+};
+/// ObjCTypesHelper - Helper class that encapsulates lazy
+/// construction of varies types used during ObjC generation.
+class ObjCTypesHelper : public ObjCCommonTypesHelper {
public:
/// SymtabTy - LLVM type for struct objc_symtab.
const llvm::StructType *SymtabTy;
@@ -488,19 +541,6 @@
public:
ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCTypesHelper() {}
-
-
- llvm::Constant *getSendFn(bool IsSuper) {
- return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
- }
-
- llvm::Constant *getSendStretFn(bool IsSuper) {
- return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
- }
-
- llvm::Constant *getSendFpretFn(bool IsSuper) {
- return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
- }
};
/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
@@ -871,6 +911,15 @@
/// ivars.
void GetNamedIvarList(const ObjCInterfaceDecl *OID,
llvm::SmallVector<ObjCIvarDecl*, 16> &Res) const;
+
+ CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
+ QualType ResultType,
+ llvm::Value *Sel,
+ llvm::Value *Arg0,
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs,
+ const ObjCCommonTypesHelper &ObjCTypes);
public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
@@ -1090,6 +1139,14 @@
/// EHTypeReferences - uniqued class ehtype references.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
+ /// NoneLegacyDispatchMethods - List of methods for which we do *not* generate
+ /// legacy messaging dispatch.
+ llvm::StringMap<bool> NoneLegacyDispatchMethods;
+
+ /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
+ /// NoneLegacyDispatchMethods; flase otherwise.
+ bool LegacyDispatchedSelector(Selector Sel);
+
/// FinishNonFragileABIModule - Write out global data structures at the end of
/// processing a translation unit.
void FinishNonFragileABIModule();
@@ -1387,10 +1444,10 @@
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
CGF.Builder.CreateStore(Target,
CGF.Builder.CreateStructGEP(ObjCSuper, 1));
-
- return EmitMessageSend(CGF, ResultType, Sel,
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs);
+ return EmitLegacyMessageSend(CGF, ResultType,
+ EmitSelector(CGF.Builder, Sel),
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs, ObjCTypes);
}
/// Generate code for a message send expression.
@@ -1401,42 +1458,56 @@
bool IsClassMessage,
const CallArgList &CallArgs,
const ObjCMethodDecl *Method) {
- return EmitMessageSend(CGF, ResultType, Sel,
- Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs);
+ return EmitLegacyMessageSend(CGF, ResultType,
+ EmitSelector(CGF.Builder, Sel),
+ Receiver, CGF.getContext().getObjCIdType(),
+ false, CallArgs, ObjCTypes);
}
-CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Arg0,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs) {
+CodeGen::RValue CGObjCCommonMac::EmitLegacyMessageSend(
+ CodeGen::CodeGenFunction &CGF,
+ QualType ResultType,
+ llvm::Value *Sel,
+ llvm::Value *Arg0,
+ QualType Arg0Ty,
+ bool IsSuper,
+ const CallArgList &CallArgs,
+ const ObjCCommonTypesHelper &ObjCTypes) {
CallArgList ActualArgs;
if (!IsSuper)
Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
- ActualArgs.push_back(std::make_pair(RValue::get(EmitSelector(CGF.Builder,
- Sel)),
+ ActualArgs.push_back(std::make_pair(RValue::get(Sel),
CGF.getContext().getObjCSelType()));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
-
+
CodeGenTypes &Types = CGM.getTypes();
const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
- // FIXME. vararg flag must be true when this API is used for 64bit code gen.
- const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo, false);
-
- llvm::Constant *Fn;
+ // In 64bit ABI, type must be assumed VARARG. It 32bit abi,
+ // it seems not to matter.
+ const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo, (ObjCABI == 2));
+
+ llvm::Constant *Fn = NULL;
if (CGM.ReturnTypeUsesSret(FnInfo)) {
- Fn = ObjCTypes.getSendStretFn(IsSuper);
+ Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
+ : ObjCTypes.getSendStretFn(IsSuper);
} else if (ResultType->isFloatingType()) {
// FIXME: Sadly, this is wrong. This actually depends on the
// architecture. This happens to be right for x86-32 though.
- Fn = ObjCTypes.getSendFpretFn(IsSuper);
+ if (ObjCABI == 2) {
+ if (const BuiltinType *BT = ResultType->getAsBuiltinType()) {
+ BuiltinType::Kind k = BT->getKind();
+ Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper)
+ : ObjCTypes.getSendFn2(IsSuper);
+ }
+ }
+ else
+ Fn = ObjCTypes.getSendFpretFn(IsSuper);
} else {
- Fn = ObjCTypes.getSendFn(IsSuper);
+ Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
+ : ObjCTypes.getSendFn(IsSuper);
}
+ assert(Fn && "EmitLegacyMessageSend - unknown API");
Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
return CGF.EmitCall(FnInfo, Fn, ActualArgs);
}
@@ -4054,6 +4125,41 @@
}
+/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
+/// NoneLegacyDispatchMethods; flase otherwise. What this means is that
+/// except for the 19 selectors in the list, we generate 32bit-style
+/// message dispatch call for all the rest.
+///
+bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
+ // FIXME! Lagcy API in Nonfragile ABI is for 10.6 on
+ if (NoneLegacyDispatchMethods.empty()) {
+ NoneLegacyDispatchMethods["allocWithZone:"] = true;
+ NoneLegacyDispatchMethods["alloc"] = true;
+ NoneLegacyDispatchMethods["class"] = true;
+ NoneLegacyDispatchMethods["self"] = true;
+ NoneLegacyDispatchMethods["isKindOfClass:"] = true;
+ NoneLegacyDispatchMethods["respondsToSelector:"] = true;
+ NoneLegacyDispatchMethods["isFlipped"] = true;
+ NoneLegacyDispatchMethods["length"] = true;
+ NoneLegacyDispatchMethods["objectForKey:"] = true;
+ NoneLegacyDispatchMethods["count"] = true;
+ NoneLegacyDispatchMethods["objectAtIndex:"] = true;
+ NoneLegacyDispatchMethods["isEqualToString:"] = true;
+ NoneLegacyDispatchMethods["isEqual:"] = true;
+ NoneLegacyDispatchMethods["retain"] = true;
+ NoneLegacyDispatchMethods["release"] = true;
+ NoneLegacyDispatchMethods["autorelease"] = true;
+ NoneLegacyDispatchMethods["hash"] = true;
+ NoneLegacyDispatchMethods["addObject:"] = true;
+ NoneLegacyDispatchMethods["countByEnumeratingWithState:objects:count:"]
+ = true;
+ }
+ const char *name = Sel.getAsString().c_str();
+ if (NoneLegacyDispatchMethods[name])
+ return false;
+ return true;
+}
+
// Metadata flags
enum MetaDataDlags {
CLS = 0x0,
@@ -5003,9 +5109,13 @@
bool IsClassMessage,
const CallArgList &CallArgs,
const ObjCMethodDecl *Method) {
- return EmitMessageSend(CGF, ResultType, Sel,
- Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs);
+ return LegacyDispatchedSelector(Sel)
+ ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel),
+ Receiver, CGF.getContext().getObjCIdType(),
+ false, CallArgs, ObjCTypes)
+ : EmitMessageSend(CGF, ResultType, Sel,
+ Receiver, CGF.getContext().getObjCIdType(),
+ false, CallArgs);
}
llvm::GlobalVariable *
@@ -5149,9 +5259,14 @@
CGF.Builder.CreateStore(Target,
CGF.Builder.CreateStructGEP(ObjCSuper, 1));
- return EmitMessageSend(CGF, ResultType, Sel,
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs);
+ return (LegacyDispatchedSelector(Sel))
+ ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel),
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs,
+ ObjCTypes)
+ : EmitMessageSend(CGF, ResultType, Sel,
+ ObjCSuper, ObjCTypes.SuperPtrCTy,
+ true, CallArgs);
}
llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
@@ -5167,7 +5282,7 @@
llvm::GlobalValue::InternalLinkage,
Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
&CGM.getModule());
- Entry->setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip");
+ Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
UsedGlobals.push_back(Entry);
}
Modified: cfe/trunk/test/CodeGenObjC/metadata-symbols-64.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/metadata-symbols-64.m?rev=71467&r1=71466&r2=71467&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/metadata-symbols-64.m (original)
+++ cfe/trunk/test/CodeGenObjC/metadata-symbols-64.m Mon May 11 14:25:47 2009
@@ -13,10 +13,7 @@
// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t &&
-
-// FIXME: clang is not currently using "optimized" message dispatch in 64-bit mode.
-// RUNX: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip", align 8' %t &&
-
+// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t &&
// RUN: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t &&
// RUN: grep '@"\\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t &&
// RUN: grep '@"\\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t &&
@@ -35,7 +32,7 @@
// RUN: grep '@_objc_empty_cache = external global' %t &&
// RUN: grep '@_objc_empty_vtable = external global' %t &&
// RUN: grep '@objc_msgSend_fixup(' %t &&
-// RUN: grep '@objc_msgSend_fpret_fixup(' %t &&
+// RUN: grep '@objc_msgSend_fpret(' %t &&
// RUN: true
More information about the cfe-commits
mailing list