From: Daniel Dunbar Date: Sat, 24 Apr 2010 17:56:46 +0000 (+0000) Subject: NeXT: Clean up dispatch method policy selection. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f643b9b338b797a824447207d7eab5f1187f4f34;p=clang NeXT: Clean up dispatch method policy selection. - Replace -cc1 level -fobjc-legacy-dispatch with -fobjc-dispatch-method={legacy,non-legacy,mixed}. - Lift "mixed" vs "non-mixed" policy choice up to driver level, instead of being buried in CGObjCMac.cpp. - No intended functionality change. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102255 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 51b9c57f2c..54d3ba03f3 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -28,6 +28,12 @@ public: OnlyAlwaysInlining // Only run the always inlining pass. }; + enum ObjCDispatchMethodKind { + Legacy = 0, + NonLegacy = 1, + Mixed = 2 + }; + unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors. unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker @@ -45,8 +51,7 @@ public: unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss - unsigned ObjCLegacyDispatch: 1; /// Use legacy Objective-C dispatch, even with - /// 2.0 runtime. + unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. unsigned OptimizeSize : 1; /// If -Os is specified. unsigned SoftFloat : 1; /// -soft-float. @@ -100,7 +105,7 @@ public: NoCommon = 0; NoImplicitFloat = 0; NoZeroInitializedInBSS = 0; - ObjCLegacyDispatch = 0; + ObjCDispatchMethod = Legacy; OptimizationLevel = 0; OptimizeSize = 0; SoftFloat = 0; @@ -113,6 +118,10 @@ public: Inlining = NoInlining; RelocationModel = "pic"; } + + ObjCDispatchMethodKind getObjCDispatchMethod() const { + return ObjCDispatchMethodKind(ObjCDispatchMethod); + } }; } // end namespace clang diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 9fd21e97a0..18b54ef5e0 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -391,8 +391,8 @@ def fobjc_gc : Flag<"-fobjc-gc">, HelpText<"Enable Objective-C garbage collection">; def fobjc_gc_only : Flag<"-fobjc-gc-only">, HelpText<"Use GC exclusively for Objective-C related memory management">; -def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, - HelpText<"Use legacy dispatch with the Objective-C non-fragile ABI">; +def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">, + HelpText<"Objective-C dispatch method to use">; def print_ivar_layout : Flag<"-print-ivar-layout">, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index b58205cc4d..1a8ae77491 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -103,6 +103,10 @@ public: /// ABI). virtual bool IsObjCLegacyDispatchDefault() const { return false; } + /// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the + /// mixed dispatch method be used? + virtual bool UseObjCMixedDispatch() const { return false; } + /// GetDefaultStackProtectorLevel - Get the default stack protector level for /// this tool chain (0=off, 1=on, 2=all). virtual unsigned GetDefaultStackProtectorLevel() const { return 0; } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index e000bd22aa..098a0f8221 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -4275,13 +4275,19 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { /// message dispatch call for all the rest. /// bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { - if (CGM.getCodeGenOpts().ObjCLegacyDispatch) + switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { + default: + assert(0 && "Invalid dispatch method!"); + case CodeGenOptions::Legacy: return true; - /* Leopard */ - if (CGM.getContext().Target.getTriple().getOS() == llvm::Triple::Darwin && - CGM.getContext().Target.getTriple().getDarwinMajorNumber() <= 9) + case CodeGenOptions::NonLegacy: return false; - + case CodeGenOptions::Mixed: + break; + } + + // If so, see whether this selector is in the white-list of things which must + // use the new dispatch convention. We lazily build a dense set for this. if (NonLegacyDispatchMethods.empty()) { NonLegacyDispatchMethods.insert(GetNullarySelector("alloc")); NonLegacyDispatchMethods.insert(GetNullarySelector("class")); @@ -4311,6 +4317,7 @@ bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { NonLegacyDispatchMethods.insert( CGM.getContext().Selectors.getSelector(3, KeyIdents)); } + return (NonLegacyDispatchMethods.count(Sel) == 0); } diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 9e61b8972f..a307b2bdac 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -168,6 +168,12 @@ public: return (getTriple().getArch() == llvm::Triple::arm || getTriple().getArch() == llvm::Triple::thumb); } + virtual bool UseObjCMixedDispatch() const { + // Mixed dispatch is only used on x86_64 for 10.6 and later. + return (!isTargetIPhoneOS() && + getTriple().getArch() == llvm::Triple::x86_64 && + !isMacosxVersionLT(10, 6)); + } virtual bool IsUnwindTablesDefault() const; virtual unsigned GetDefaultStackProtectorLevel() const { // Stack protectors default to on for 10.6 and beyond. diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 2e8db0062d..8ad04aa508 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1230,13 +1230,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fobjc_nonfragile_abi) || getToolChain().IsObjCNonFragileABIDefault()) { CmdArgs.push_back("-fobjc-nonfragile-abi"); - - // -fobjc-legacy-dispatch is only relevant with the nonfragile-abi, and - // defaults to off. - if (Args.hasFlag(options::OPT_fobjc_legacy_dispatch, - options::OPT_fno_objc_legacy_dispatch, - getToolChain().IsObjCLegacyDispatchDefault())) - CmdArgs.push_back("-fobjc-legacy-dispatch"); + + // -fobjc-dispatch-method is only relevant with the nonfragile-abi, and + // legacy is the default. + if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch, + options::OPT_fno_objc_legacy_dispatch, + getToolChain().IsObjCLegacyDispatchDefault())) { + if (getToolChain().UseObjCMixedDispatch()) + CmdArgs.push_back("-fobjc-dispatch-method=mixed"); + else + CmdArgs.push_back("-fobjc-dispatch-method=non-legacy"); + } } } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index db937bc4c7..68842a4015 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -178,8 +178,16 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, } if (Opts.NoZeroInitializedInBSS) Res.push_back("-mno-zero-initialized-bss"); - if (Opts.ObjCLegacyDispatch) - Res.push_back("-fobjc-legacy-dispatch"); + switch (Opts.getObjCDispatchMethod()) { + case CodeGenOptions::Legacy: + break; + case CodeGenOptions::Mixed: + Res.push_back("-fobjc-dispatch-method=mixed"); + break; + case CodeGenOptions::NonLegacy: + Res.push_back("-fobjc-dispatch-method=non-legacy"); + break; + } if (Opts.SoftFloat) Res.push_back("-msoft-float"); if (Opts.UnwindTables) @@ -820,7 +828,6 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.FloatABI = getLastArgValue(Args, OPT_mfloat_abi); Opts.LimitFloatPrecision = getLastArgValue(Args, OPT_mlimit_float_precision); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); - Opts.ObjCLegacyDispatch = Args.hasArg(OPT_fobjc_legacy_dispatch); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); Opts.RelocationModel = getLastArgValue(Args, OPT_mrelocation_model, "pic"); @@ -830,6 +837,19 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.MainFileName = getLastArgValue(Args, OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); + + if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) { + llvm::StringRef Name = A->getValue(Args); + unsigned Method = llvm::StringSwitch(Name) + .Case("legacy", CodeGenOptions::Legacy) + .Case("non-legacy", CodeGenOptions::NonLegacy) + .Case("mixed", CodeGenOptions::Mixed) + .Default(~0U); + if (Method == ~0U) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + else + Opts.ObjCDispatchMethod = Method; + } } static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, diff --git a/test/CodeGenObjC/legacy-api-leopard-test.m b/test/CodeGenObjC/legacy-api-leopard-test.m deleted file mode 100644 index 1a229c6bb7..0000000000 --- a/test/CodeGenObjC/legacy-api-leopard-test.m +++ /dev/null @@ -1,19 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s -// rdar: // 7866951 - -@interface NSObject -- (id)init; -@end - -@interface ClangTest : NSObject @end - -@implementation ClangTest -- (id)init -{ - [super init]; - return self; -} -@end - -// CHECK-LP64: objc_msgSendSuper2_fixup_init -// CHECK-LP64: objc_msgSendSuper2_fixup diff --git a/test/CodeGenObjC/metadata-symbols-64.m b/test/CodeGenObjC/metadata-symbols-64.m index 886d53a828..dbc06d76cd 100644 --- a/test/CodeGenObjC/metadata-symbols-64.m +++ b/test/CodeGenObjC/metadata-symbols-64.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm -o %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fobjc-dispatch-method=mixed -emit-llvm -o %t %s // RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && // RUN: grep '@"OBJC_CLASS_$_A" = global' %t diff --git a/test/CodeGenObjC/next-objc-dispatch.m b/test/CodeGenObjC/next-objc-dispatch.m new file mode 100644 index 0000000000..a3e8e19641 --- /dev/null +++ b/test/CodeGenObjC/next-objc-dispatch.m @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-dispatch-method=legacy | \ +// RUN: FileCheck -check-prefix CHECK-FRAGILE_LEGACY %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-nonfragile-abi -fobjc-dispatch-method=legacy | \ +// RUN: FileCheck -check-prefix CHECK-NONFRAGILE_LEGACY %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-nonfragile-abi -fobjc-dispatch-method=non-legacy | \ +// RUN: FileCheck -check-prefix CHECK-NONFRAGILE_NONLEGACY %s +// +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s \ +// RUN: -fobjc-nonfragile-abi -fobjc-dispatch-method=mixed | \ +// RUN: FileCheck -check-prefix CHECK-NONFRAGILE_MIXED %s +// +// + +// There are basically four ways that we end up doing message dispatch for the +// NeXT runtime. They are: +// (1) fragile ABI, legacy dispatch +// (2) non-fragile ABI, legacy dispatch +// (2) non-fragile ABI, non-legacy dispatch +// (2) non-fragile ABI, mixed dispatch +// +// Note that fragile ABI and non-fragile ABI legacy dispatch are not the same, +// they use some different API calls (objc_msgSendSuper vs objc_msgSendSuper2). + +// CHECK-FRAGILE_LEGACY: ModuleID +// CHECK-FRAGILE_LEGACY-NOT: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-FRAGILE_LEGACY-NOT: declare i8* @objc_msgSend_fixup( +// CHECK-FRAGILE_LEGACY: declare i8* @objc_msgSendSuper( +// CHECK-FRAGILE_LEGACY: declare i8* @objc_msgSend( + +// CHECK-NONFRAGILE_LEGACY: ModuleID +// CHECK-NONFRAGILE_LEGACY-NOT: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-NONFRAGILE_LEGACY-NOT: declare i8* @objc_msgSend_fixup( +// CHECK-NONFRAGILE_LEGACY: declare i8* @objc_msgSendSuper2( +// CHECK-NONFRAGILE_LEGACY: declare i8* @objc_msgSend( + +// CHECK-NONFRAGILE_NONLEGACY: ModuleID +// CHECK-NONFRAGILE_NONLEGACY: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-NONFRAGILE_NONLEGACY: declare i8* @objc_msgSend_fixup( + +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSendSuper2_fixup( +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSendSuper2( +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSend_fixup( +// CHECK-NONFRAGILE_MIXED: declare i8* @objc_msgSend( + +@interface NSObject ++ (id)alloc; +- (id)init; +@end + +@interface I0 : NSObject +-(void) im0; +@end + +@implementation I0 ++(id) alloc { + return [super alloc]; +} +-(id) init { + [super init]; + return self; +} +-(void) im0 {} +@end + +void f0(I0 *a) { + [I0 alloc]; + [a im0]; +} diff --git a/test/CodeGenObjC/objc2-legacy-dispatch.m b/test/CodeGenObjC/objc2-legacy-dispatch.m index 9f9a6aa9fe..7a99d15ba0 100644 --- a/test/CodeGenObjC/objc2-legacy-dispatch.m +++ b/test/CodeGenObjC/objc2-legacy-dispatch.m @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -fobjc-nonfragile-abi -triple i386-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK_NEW_DISPATCH %s +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-dispatch-method=mixed -triple i386-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK_NEW_DISPATCH %s // // CHECK_NEW_DISPATCH: define void @f0 // CHECK_NEW_DISPATCH: bitcast {{.*}}objc_msgSend_fixup_alloc // CHECK_NEW_DISPATCH: define void @f1 // CHECK_NEW_DISPATCH: load {{.*}}OBJC_SELECTOR_REFERENCES // -// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-legacy-dispatch -emit-llvm -o - %s | FileCheck -check-prefix=CHECK_OLD_DISPATCH %s +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-dispatch-method=legacy -emit-llvm -o - %s | FileCheck -check-prefix=CHECK_OLD_DISPATCH %s // // CHECK_OLD_DISPATCH: define void @f0 // CHECK_OLD_DISPATCH: load {{.*}}OBJC_SELECTOR_REFERENCES