plotfi updated this revision to Diff 286141.
plotfi added a comment.

change for clang-tidy and clang-format.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGenObjC/objc-direct-wrapper.m

Index: clang/test/CodeGenObjC/objc-direct-wrapper.m
===================================================================
--- /dev/null
+++ clang/test/CodeGenObjC/objc-direct-wrapper.m
@@ -0,0 +1,43 @@
+// RUN: %clang -fobjc-arc -Wno-objc-root-class -ObjC -fobjc-runtime=ios -FFoundation \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN:   -fobjc-export-direct-method-wrappers -c -o - %s | \
+// RUN: llvm-nm - | FileCheck -check-prefix=CHECK-WRAPPER %s
+
+// RUN: %clang -fobjc-arc -Wno-objc-root-class \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN: -ObjC -fobjc-runtime=ios -FFoundation -c -o - %s | llvm-nm - | \
+// RUN: FileCheck -check-prefix=CHECK-DEFAULT %s
+
+// RUN: %clang -fobjc-arc -Wno-objc-root-class \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN: -ObjC -fobjc-runtime=ios -FFoundation \
+// RUN:   -fobjc-export-direct-method-wrappers -c -o - %s -S -emit-llvm | \
+// RUN: FileCheck -check-prefix=CHECK-WRAPPER-IR-DEFINE %s
+
+// RUN: %clang -fobjc-arc -Wno-objc-root-class -DNO_OBJC_IMPL \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN: -ObjC -fobjc-runtime=ios -FFoundation \
+// RUN:   -fobjc-export-direct-method-wrappers -c -o - %s -S -emit-llvm | \
+// RUN: FileCheck -check-prefix=CHECK-WRAPPER-IR-DECLARE %s
+
+// CHECK-WRAPPER: T ___objc_direct_wrapper-[C testMethod:bar:]
+// CHECK-DEFAULT-NOT: ___objc_direct_wrapper
+// CHECK-WRAPPER-IR-DEFINE: define {{(dso_local )?}}{{(dso_local )?}}void @"__objc_direct_wrapper-[C testMethod:bar:]"
+// CHECK-WRAPPER-IR-DECLARE: declare {{(dso_local )?}}void @"__objc_direct_wrapper-[C testMethod:bar:]"
+
+@interface C
+- (void)testMethod:(int)arg1 bar:(float)arg2 __attribute((objc_direct));
+@end
+
+#ifndef NO_OBJC_IMPL
+@implementation C
+- (void)testMethod:(int)arg1 bar:(float)arg2 __attribute((objc_direct)) {
+}
+@end
+#endif
+
+C *c;
+
+void f() {
+  [c testMethod:1 bar:1.0];
+}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -1283,6 +1283,8 @@
     }
   }
 
+  if (Args.hasArg(OPT_fobjc_export_direct_method_wrappers))
+    Opts.ObjCExportDirectMethodWrappers = 1;
 
   if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
     Opts.ObjCConvertMessagesToRuntimeCalls = 0;
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -3462,6 +3462,9 @@
       CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls");
   }
 
+  if (Args.hasArg(options::OPT_fobjc_export_direct_method_wrappers))
+    CmdArgs.push_back("-fobjc-export-direct-method-wrappers");
+
   // -fobjc-infer-related-result-type is the default, except in the Objective-C
   // rewriter.
   if (InferCovariantReturns)
Index: clang/lib/CodeGen/CGObjCMac.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -2143,6 +2143,36 @@
   return false;
 }
 
+/// Create or look up the declaration of an objc_direct method wrapper.
+llvm::Function *getObjCDirectWrapper(llvm::Function &F) {
+  std::string NewName = "__objc_direct_wrapper";
+  for (auto C : F.getName().str()) {
+    if (C == '\1')
+      continue;
+    NewName += C;
+  }
+
+  auto WI = llvm::find_if(*F.getParent(), [NewName](const llvm::Function &F) {
+    return F.getName() == NewName;
+  });
+
+  llvm::Function *Wrapper = nullptr;
+  if (WI == F.getParent()->end()) {
+    llvm::Module &M = *F.getParent();
+    llvm::FunctionType *FnTy = F.getFunctionType();
+    Wrapper = llvm::Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(),
+                                     NewName);
+    Wrapper->setLinkage(llvm::GlobalValue::ExternalLinkage);
+    Wrapper->addFnAttr(llvm::Attribute::AlwaysInline);
+    Wrapper->setVisibility(llvm::Function::DefaultVisibility);
+    M.getFunctionList().insert(F.getIterator(), Wrapper);
+  } else {
+    Wrapper = &*WI;
+  }
+
+  return Wrapper;
+}
+
 CodeGen::RValue
 CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
                                  ReturnValueSlot Return,
@@ -2214,7 +2244,13 @@
 
   llvm::FunctionCallee Fn = nullptr;
   if (Method && Method->isDirectMethod()) {
-    Fn = GenerateDirectMethod(Method, Method->getClassInterface());
+    if (CGM.getCodeGenOpts().ObjCExportDirectMethodWrappers) {
+      llvm::Function *FnDirect =
+          GenerateDirectMethod(Method, Method->getClassInterface());
+      Fn = getObjCDirectWrapper(*FnDirect);
+    } else {
+      Fn = GenerateDirectMethod(Method, Method->getClassInterface());
+    }
   } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
     if (ReceiverCanBeNull) RequiresNullCheck = true;
     Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
@@ -4006,6 +4042,9 @@
 
   if (OMD->isDirectMethod()) {
     Method = GenerateDirectMethod(OMD, CD);
+    if (CGM.getCodeGenOpts().ObjCExportDirectMethodWrappers) {
+      getObjCDirectWrapper(*Method);
+    }
   } else {
     SmallString<256> Name;
     GetNameForMethod(OMD, CD, Name);
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -673,6 +673,33 @@
 };
 }
 
+/// Populates the body of a objc_direct wrapper function.
+/// This should be done in the same TU that we are populating the definition of
+/// the objc_direct method it is wrapping.
+static void populateObjCDirectWrapperContent(llvm::Function &Wrapper,
+                                             llvm::Function &F) {
+  assert(Wrapper.isDeclaration() &&
+         "Expected empty objc_direct wrapper function.");
+  llvm::Module &M = *F.getParent();
+  llvm::LLVMContext &Ctx = M.getContext();
+  llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create(Ctx, "entry", &Wrapper);
+
+  llvm::SmallVector<llvm::Value *, 8> Args;
+  auto *FArgIt = F.arg_begin();
+  for (llvm::Argument &Arg : Wrapper.args()) {
+    Args.push_back(&Arg);
+    Arg.setName((FArgIt++)->getName());
+  }
+
+  llvm::CallInst *CI = llvm::CallInst::Create(&F, Args, "", EntryBB);
+  CI->setTailCall(true);
+  CI->addAttribute(llvm::AttributeList::FunctionIndex,
+                   llvm::Attribute::NoInline);
+  llvm::ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI,
+                           EntryBB);
+}
+llvm::Function *getObjCDirectWrapper(llvm::Function &F);
+
 /// StartObjCMethod - Begin emission of an ObjCMethod. This generates
 /// the LLVM function and sets the other context used by
 /// CodeGenFunction.
@@ -712,6 +739,10 @@
     //
     // TODO: possibly have several entry points to elide the check
     CGM.getObjCRuntime().GenerateDirectMethodPrologue(*this, Fn, OMD, CD);
+    if (CGM.getCodeGenOpts().ObjCExportDirectMethodWrappers) {
+      llvm::Function *Wrapper = getObjCDirectWrapper(*Fn);
+      populateObjCDirectWrapperContent(*Wrapper, *Fn);
+    }
   }
 
   // In ARC, certain methods get an extra cleanup.
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1622,6 +1622,8 @@
   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_export_direct_method_wrappers :
+  Flag<["-"], "fobjc-export-direct-method-wrappers">, 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>;
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -173,6 +173,8 @@
 ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
 /// Replace certain message sends with calls to ObjC runtime entrypoints
 CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
+/// Generate and export wrapper functions for objc_direct methods.
+CODEGENOPT(ObjCExportDirectMethodWrappers , 1, 0)
 
 VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
 VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to