r348687 - Convert some ObjC msgSends to runtime calls.

Pete Cooper via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 7 21:13:51 PST 2018


Author: pete
Date: Fri Dec  7 21:13:50 2018
New Revision: 348687

URL: http://llvm.org/viewvc/llvm-project?rev=348687&view=rev
Log:
Convert some ObjC msgSends to runtime calls.

It is faster to directly call the ObjC runtime for methods such as alloc/allocWithZone instead of sending a message to those functions.

This patch adds support for converting messages to alloc/allocWithZone to their equivalent runtime calls.

Tests included for the positive case of applying this transformation, negative tests that we ensure we only convert "alloc" to objc_alloc, not "alloc2", and also a driver test to ensure we enable this only for supported runtime versions.

Reviewed By: rjmccall

https://reviews.llvm.org/D55349

Added:
    cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m
    cfe/trunk/test/Driver/objc-convert-messages-to-runtime-calls.m
Modified:
    cfe/trunk/include/clang/Basic/ObjCRuntime.h
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Frontend/CodeGenOptions.def
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/Driver/ToolChains/Clang.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp

Modified: cfe/trunk/include/clang/Basic/ObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ObjCRuntime.h?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/ObjCRuntime.h (original)
+++ cfe/trunk/include/clang/Basic/ObjCRuntime.h Fri Dec  7 21:13:50 2018
@@ -173,6 +173,43 @@ public:
     llvm_unreachable("bad kind");
   }
 
+  /// Does this runtime provide entrypoints that are likely to be faster
+  /// than an ordinary message send of the "alloc" selector?
+  ///
+  /// The "alloc" entrypoint is guaranteed to be equivalent to just sending the
+  /// corresponding message.  If the entrypoint is implemented naively as just a
+  /// message send, using it is a trade-off: it sacrifices a few cycles of
+  /// overhead to save a small amount of code.  However, it's possible for
+  /// runtimes to detect and special-case classes that use "standard"
+  /// alloc behavior; if that's dynamically a large proportion of all
+  /// objects, using the entrypoint will also be faster than using a message
+  /// send.
+  ///
+  /// When this method returns true, Clang will turn non-super message sends of
+  /// certain selectors into calls to the corresponding entrypoint:
+  ///   alloc => objc_alloc
+  ///   allocWithZone:nil => objc_allocWithZone
+  bool shouldUseRuntimeFunctionsForAlloc() const {
+    switch (getKind()) {
+    case FragileMacOSX:
+      return false;
+    case MacOSX:
+      return getVersion() >= VersionTuple(10, 10);
+    case iOS:
+      return getVersion() >= VersionTuple(8);
+    case WatchOS:
+      return true;
+
+    case GCC:
+      return false;
+    case GNUstep:
+      return false;
+    case ObjFW:
+      return false;
+    }
+    llvm_unreachable("bad kind");
+  }
+
   /// Does this runtime supports optimized setter entrypoints?
   bool hasOptimizedSetter() const {
     switch (getKind()) {

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Fri Dec  7 21:13:50 2018
@@ -1473,6 +1473,10 @@ def fno_zero_initialized_in_bss : Flag<[
 def fobjc_arc : Flag<["-"], "fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Synthesize retain and release calls for Objective-C pointers">;
 def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group<f_Group>;
+def fobjc_convert_messages_to_runtime_calls :
+  Flag<["-"], "fobjc-convert-messages-to-runtime-calls">, Group<f_Group>;
+def fno_objc_convert_messages_to_runtime_calls :
+  Flag<["-"], "fno-objc-convert-messages-to-runtime-calls">, Group<f_Group>, Flags<[CC1Option]>;
 def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
 def fno_objc_arc_exceptions : Flag<["-"], "fno-objc-arc-exceptions">, Group<f_Group>;

Modified: cfe/trunk/include/clang/Frontend/CodeGenOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.def?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CodeGenOptions.def (original)
+++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def Fri Dec  7 21:13:50 2018
@@ -149,6 +149,8 @@ CODEGENOPT(UniformWGSize     , 1, 0) ///
 CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
 /// Method of Objective-C dispatch to use.
 ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
+/// Replace certain message sends with calls to ObjC runtime entrypoints
+CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
 CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
                                         ///< enabled.
 

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Dec  7 21:13:50 2018
@@ -352,6 +352,56 @@ static const Expr *findWeakLValue(const
   return nullptr;
 }
 
+/// The ObjC runtime may provide entrypoints that are likely to be faster
+/// than an ordinary message send of the appropriate selector.
+///
+/// The entrypoints are guaranteed to be equivalent to just sending the
+/// corresponding message.  If the entrypoint is implemented naively as just a
+/// message send, using it is a trade-off: it sacrifices a few cycles of
+/// overhead to save a small amount of code.  However, it's possible for
+/// runtimes to detect and special-case classes that use "standard"
+/// behavior; if that's dynamically a large proportion of all objects, using
+/// the entrypoint will also be faster than using a message send.
+///
+/// If the runtime does support a required entrypoint, then this method will
+/// generate a call and return the resulting value.  Otherwise it will return
+/// None and the caller can generate a msgSend instead.
+static Optional<llvm::Value *>
+tryGenerateSpecializedMessageSend(CodeGenFunction &CGF, QualType ResultType,
+                                  llvm::Value *Receiver,
+                                  const CallArgList& Args, Selector Sel,
+                                  const ObjCMethodDecl *method) {
+  auto &CGM = CGF.CGM;
+  if (!CGM.getCodeGenOpts().ObjCConvertMessagesToRuntimeCalls)
+    return None;
+
+  auto &Runtime = CGM.getLangOpts().ObjCRuntime;
+  switch (Sel.getMethodFamily()) {
+  case OMF_alloc:
+    if (Runtime.shouldUseRuntimeFunctionsForAlloc() &&
+        ResultType->isObjCObjectPointerType()) {
+        // [Foo alloc] -> objc_alloc(Foo)
+        if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "alloc")
+          return CGF.EmitObjCAlloc(Receiver, CGF.ConvertType(ResultType));
+        // [Foo allocWithZone:nil] -> objc_allocWithZone(Foo)
+        if (Sel.isKeywordSelector() && Sel.getNumArgs() == 1 &&
+            Args.size() == 1 && Args.front().getType()->isPointerType() &&
+            Sel.getNameForSlot(0) == "allocWithZone") {
+          const llvm::Value* arg = Args.front().getKnownRValue().getScalarVal();
+          if (isa<llvm::ConstantPointerNull>(arg))
+            return CGF.EmitObjCAllocWithZone(Receiver,
+                                             CGF.ConvertType(ResultType));
+          return None;
+        }
+    }
+    break;
+
+  default:
+    break;
+  }
+  return None;
+}
+
 RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
                                             ReturnValueSlot Return) {
   // Only the lookup mechanism and first two arguments of the method
@@ -474,10 +524,16 @@ RValue CodeGenFunction::EmitObjCMessageE
                                               Args,
                                               method);
   } else {
-    result = Runtime.GenerateMessageSend(*this, Return, ResultType,
-                                         E->getSelector(),
-                                         Receiver, Args, OID,
-                                         method);
+    // Call runtime methods directly if we can.
+    if (Optional<llvm::Value *> SpecializedResult =
+            tryGenerateSpecializedMessageSend(*this, ResultType, Receiver, Args,
+                                              E->getSelector(), method)) {
+      result = RValue::get(SpecializedResult.getValue());
+    } else {
+      result = Runtime.GenerateMessageSend(*this, Return, ResultType,
+                                           E->getSelector(), Receiver, Args,
+                                           OID, method);
+    }
   }
 
   // For delegate init calls in ARC, implicitly store the result of
@@ -1845,6 +1901,7 @@ static llvm::Constant *createARCRuntimeF
 /// where a null input causes a no-op and returns null.
 static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
                                           llvm::Value *value,
+                                          llvm::Type *returnType,
                                           llvm::Constant *&fn,
                                           StringRef fnName,
                                           bool isTailCall = false) {
@@ -1858,7 +1915,7 @@ static llvm::Value *emitARCValueOperatio
   }
 
   // Cast the argument to 'id'.
-  llvm::Type *origType = value->getType();
+  llvm::Type *origType = returnType ? returnType : value->getType();
   value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy);
 
   // Call the function.
@@ -1964,7 +2021,7 @@ llvm::Value *CodeGenFunction::EmitARCRet
 /// Retain the given object, with normal retain semantics.
 ///   call i8* \@objc_retain(i8* %value)
 llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) {
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
                                CGM.getObjCEntrypoints().objc_retain,
                                "objc_retain");
 }
@@ -1978,7 +2035,7 @@ llvm::Value *CodeGenFunction::EmitARCRet
 llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value,
                                                  bool mandatory) {
   llvm::Value *result
-    = emitARCValueOperation(*this, value,
+    = emitARCValueOperation(*this, value, nullptr,
                             CGM.getObjCEntrypoints().objc_retainBlock,
                             "objc_retainBlock");
 
@@ -2048,7 +2105,7 @@ static void emitAutoreleasedReturnValueM
 llvm::Value *
 CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
   emitAutoreleasedReturnValueMarker(*this);
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
               CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
                                "objc_retainAutoreleasedReturnValue");
 }
@@ -2063,7 +2120,7 @@ CodeGenFunction::EmitARCRetainAutoreleas
 llvm::Value *
 CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) {
   emitAutoreleasedReturnValueMarker(*this);
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
               CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue,
                                "objc_unsafeClaimAutoreleasedReturnValue");
 }
@@ -2178,7 +2235,7 @@ llvm::Value *CodeGenFunction::EmitARCSto
 /// Autorelease the given object.
 ///   call i8* \@objc_autorelease(i8* %value)
 llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) {
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
                                CGM.getObjCEntrypoints().objc_autorelease,
                                "objc_autorelease");
 }
@@ -2187,7 +2244,7 @@ llvm::Value *CodeGenFunction::EmitARCAut
 ///   call i8* \@objc_autoreleaseReturnValue(i8* %value)
 llvm::Value *
 CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
                             CGM.getObjCEntrypoints().objc_autoreleaseReturnValue,
                                "objc_autoreleaseReturnValue",
                                /*isTailCall*/ true);
@@ -2197,7 +2254,7 @@ CodeGenFunction::EmitARCAutoreleaseRetur
 ///   call i8* \@objc_retainAutoreleaseReturnValue(i8* %value)
 llvm::Value *
 CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
                      CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue,
                                "objc_retainAutoreleaseReturnValue",
                                /*isTailCall*/ true);
@@ -2226,7 +2283,7 @@ llvm::Value *CodeGenFunction::EmitARCRet
 ///   call i8* \@objc_retainAutorelease(i8* %value)
 llvm::Value *
 CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) {
-  return emitARCValueOperation(*this, value,
+  return emitARCValueOperation(*this, value, nullptr,
                                CGM.getObjCEntrypoints().objc_retainAutorelease,
                                "objc_retainAutorelease");
 }
@@ -2385,6 +2442,24 @@ llvm::Value *CodeGenFunction::EmitObjCMR
   return InitRV.getScalarVal();
 }
 
+/// Allocate the given objc object.
+///   call i8* \@objc_alloc(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCAlloc(llvm::Value *value,
+                                            llvm::Type *resultType) {
+  return emitARCValueOperation(*this, value, resultType,
+                               CGM.getObjCEntrypoints().objc_alloc,
+                               "objc_alloc");
+}
+
+/// Allocate the given objc object.
+///   call i8* \@objc_allocWithZone(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCAllocWithZone(llvm::Value *value,
+                                                    llvm::Type *resultType) {
+  return emitARCValueOperation(*this, value, resultType,
+                               CGM.getObjCEntrypoints().objc_allocWithZone,
+                               "objc_allocWithZone");
+}
+
 /// Produce the code to do a primitive release.
 /// [tmp drain];
 void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Dec  7 21:13:50 2018
@@ -3805,6 +3805,10 @@ public:
   std::pair<LValue,llvm::Value*>
   EmitARCStoreUnsafeUnretained(const BinaryOperator *e, bool ignored);
 
+  llvm::Value *EmitObjCAlloc(llvm::Value *value,
+                             llvm::Type *returnType);
+  llvm::Value *EmitObjCAllocWithZone(llvm::Value *value,
+                                     llvm::Type *returnType);
   llvm::Value *EmitObjCThrowOperand(const Expr *expr);
   llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr);
   llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Dec  7 21:13:50 2018
@@ -119,7 +119,13 @@ struct OrderGlobalInits {
 struct ObjCEntrypoints {
   ObjCEntrypoints() { memset(this, 0, sizeof(*this)); }
 
-    /// void objc_autoreleasePoolPop(void*);
+  /// void objc_alloc(id);
+  llvm::Constant *objc_alloc;
+
+  /// void objc_allocWithZone(id);
+  llvm::Constant *objc_allocWithZone;
+
+  /// void objc_autoreleasePoolPop(void*);
   llvm::Constant *objc_autoreleasePoolPop;
 
   /// void *objc_autoreleasePoolPush(void);

Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Clang.cpp?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Fri Dec  7 21:13:50 2018
@@ -2866,6 +2866,18 @@ static void RenderObjCOptions(const Tool
     Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
   }
 
+  // Allow the user to control whether messages can be converted to runtime
+  // functions.
+  if (types::isObjC(Input.getType())) {
+    auto *Arg = Args.getLastArg(
+        options::OPT_fobjc_convert_messages_to_runtime_calls,
+        options::OPT_fno_objc_convert_messages_to_runtime_calls);
+    if (Arg &&
+        Arg->getOption().matches(
+            options::OPT_fno_objc_convert_messages_to_runtime_calls))
+      CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls");
+  }
+
   // -fobjc-infer-related-result-type is the default, except in the Objective-C
   // rewriter.
   if (InferCovariantReturns)

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=348687&r1=348686&r2=348687&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Dec  7 21:13:50 2018
@@ -1155,6 +1155,10 @@ static bool ParseCodeGenArgs(CodeGenOpti
     }
   }
 
+
+  if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
+    Opts.ObjCConvertMessagesToRuntimeCalls = 0;
+
   if (Args.getLastArg(OPT_femulated_tls) ||
       Args.getLastArg(OPT_fno_emulated_tls)) {
     Opts.ExplicitEmulatedTLS = true;

Added: cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m?rev=348687&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m (added)
+++ cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m Fri Dec  7 21:13:50 2018
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
+// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+
+#define nil (id)0
+
+ at interface NSObject
++ (id)alloc;
++ (id)allocWithZone:(void*)zone;
++ (id)alloc2;
+ at end
+
+// CHECK-LABEL: define {{.*}}void @test1
+void test1(id x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS: {{call.*@objc_allocWithZone}}
+  [NSObject alloc];
+  [NSObject allocWithZone:nil];
+}
+
+// CHECK-LABEL: define {{.*}}void @test2
+void test2(void* x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  [NSObject alloc2];
+  [NSObject allocWithZone:(void*)-1];
+  [NSObject allocWithZone:x];
+}
+
+ at class A;
+ at interface B
++ (A*) alloc;
++ (A*)allocWithZone:(void*)zone;
+ at end
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_alloc_class_ptr() {
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B alloc];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_allocWithZone_class_ptr() {
+  // CALLS: {{call.*@objc_allocWithZone}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B allocWithZone:nil];
+}
+
+
+ at interface C
++ (id)allocWithZone:(int)intArg;
+ at end
+
+// Make sure we only accept pointer types
+// CHECK-LABEL: define {{.*}}void @test_allocWithZone_int
+C* test_allocWithZone_int() {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  return [C allocWithZone:3];
+}
+

Added: cfe/trunk/test/Driver/objc-convert-messages-to-runtime-calls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/objc-convert-messages-to-runtime-calls.m?rev=348687&view=auto
==============================================================================
--- cfe/trunk/test/Driver/objc-convert-messages-to-runtime-calls.m (added)
+++ cfe/trunk/test/Driver/objc-convert-messages-to-runtime-calls.m Fri Dec  7 21:13:50 2018
@@ -0,0 +1,7 @@
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fobjc-convert-messages-to-runtime-calls -fno-objc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=DISABLE
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fno-objc-convert-messages-to-runtime-calls -fobjc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=ENABLE
+
+// Check that we pass fobjc-convert-messages-to-runtime-calls only when supported, and not explicitly disabled.
+
+// DISABLE: "-fno-objc-convert-messages-to-runtime-calls"
+// ENABLE-NOT: "-fno-objc-convert-messages-to-runtime-calls"




More information about the cfe-commits mailing list