Skip to content

ObjcRuntime.h: Add mips64, aarch64, and riscv64 to non-legacy dispatch #76694

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 9 commits into from
Jan 3, 2024

Conversation

hmelder
Copy link
Contributor

@hmelder hmelder commented Jan 2, 2024

This PR updates the list of architectures for which libobjc2 has fast-path objc_msgSend implementations.

Related to: gnustep/libobjc2#261

Copy link

github-actions bot commented Jan 2, 2024

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 2, 2024

@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-clang

Author: Hugo Melder (hmelder)

Changes

This PR updates the list of architectures for which libobjc2 has fast-path objc_msgSend implementations.

Related to: gnustep/libobjc2#261


Full diff: https://github.com/llvm/llvm-project/pull/76694.diff

1 Files Affected:

  • (modified) clang/include/clang/Basic/ObjCRuntime.h (+11-4)
diff --git a/clang/include/clang/Basic/ObjCRuntime.h b/clang/include/clang/Basic/ObjCRuntime.h
index 500b2462f00773..29392ad0a0f577 100644
--- a/clang/include/clang/Basic/ObjCRuntime.h
+++ b/clang/include/clang/Basic/ObjCRuntime.h
@@ -101,10 +101,17 @@ class ObjCRuntime {
     // The GNUstep runtime uses a newer dispatch method by default from
     // version 1.6 onwards
     if (getKind() == GNUstep && getVersion() >= VersionTuple(1, 6)) {
-      if (Arch == llvm::Triple::arm ||
-          Arch == llvm::Triple::x86 ||
-          Arch == llvm::Triple::x86_64)
-        return false;
+      switch (Arch) {
+        case llvm::Triple::arm:
+        case llvm::Triple::x86:
+        case llvm::Triple::x86_64:
+        case llvm::Triple::aarch64:
+        case llvm::Triple::mips64:
+        case llvm::Triple::riscv64:
+          return false;
+        default:
+          return true;
+      }
     }
     else if ((getKind() ==  MacOSX) && isNonFragile() &&
              (getVersion() >= VersionTuple(10, 0)) &&

Copy link

github-actions bot commented Jan 2, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

CC @davidchisnall

if (Arch == llvm::Triple::arm ||
Arch == llvm::Triple::x86 ||
Arch == llvm::Triple::x86_64)
switch (Arch) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version check above is not quite right for these.

AArch64 support is in 1.9.
RV64 in 2.2.

I think mips64 is correct (it looks like I added the code 9 years ago, which probably lines up with the 1.6 release).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version check above is not quite right for these.

This was my first approach, but it seems like GNUstep and libobjc2 unit tests are always emitting -fobjc-runtime=gnustep-2.0

So one would need to change this flag in the build configuration everytime libobjc2 gets updated.

Copy link
Contributor Author

@hmelder hmelder Jan 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do the version check and update the libobjc2 README to properly document this. I probably need to rewrite the detection in gnustep-make too -_-

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was my first approach, but it seems like GNUstep and libobjc2 unit tests are always emitting -fobjc-runtime=gnustep-2.0

That's fine. We should bump that in both places to the correct version. It's better than having the compiler emit things that are not supported when targeting a specific version of the runtime.

@davidchisnall
Copy link
Contributor

This should also come with a test to make sure that we’re generating objc_msgSend or the lookup functions with the runtime versions after / before the support for these architectures, respectively.

@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

This should also come with a test to make sure that we’re generating objc_msgSend or the lookup functions with the runtime versions after / before the support for these architectures, respectively.

Is libobjc2 included in the LLVM CI? I cannot find the place in the workflow where it is installed.

@davidchisnall
Copy link
Contributor

No, clang tests are not executable. This test is the right approximate shape:

// CHECK-GNU: call {{.*}} @objc_msg_lookup(

The RUN line invokes clang in a few different configurations (you want to invoke it with the -fobjc-runtime=gnustep-{version} flag and the correct triples and then check that we get either objc_msgSend or objc_msg_lookup, depending on whether objc_msgSend is expected to be supported in that configuration.

@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

It seems like isLegacyDispatchDefaultForArch is only called by the driver, and not when passing -cc1.

static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
ObjCRuntime &Runtime, bool InferCovariantReturns,
const InputInfo &Input, ArgStringList &CmdArgs) {
const llvm::Triple::ArchType Arch = TC.getArch();
// -fobjc-dispatch-method is only relevant with the nonfragile-abi, and legacy
// is the default. Except for deployment target of 10.5, next runtime is
// always legacy dispatch and -fno-objc-legacy-dispatch gets ignored silently.
if (Runtime.isNonFragile()) {
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
Runtime.isLegacyDispatchDefaultForArch(Arch))) {
if (TC.UseObjCMixedDispatch())
CmdArgs.push_back("-fobjc-dispatch-method=mixed");
else
CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
}
}

Using the driver instead of the frontend does not work as there are platform checks in Clang::AddObjCRuntimeArgs.

Example on macOS:

clang: error: GNUstep Objective-C runtime version 2 incompatible with target binary format

The result is that without specifying -fobjc-dispatch-method=mixed or -fobjc-dispatch-method=no-legacy, the frontend will always emit call ptr @objc_msg_lookup_sender.

Do you have an idea on how we can test this instead?

Tested with

#flags="-fobjc-dispatch-method=mixed"
flags=""
rt=gnustep-2.0
triple="x86_64-unknown-freebsd"

build-llvm/bin/clang -cc1\
		-triple ${triple} \
		-fobjc-runtime=${rt} ${flags} \
		-emit-llvm -o - gnustep2-message-dispatch.m | less
gnustep2-message-dispatch.m
// DEFINE: %{triple} =
// DEFINE: %{ver} =
// DEFINE: %{prefix} = CHECK-MSG-SEND
// DEFINE: %{check} = %clang_cc1 -triple %{triple} -fobjc-runtime=gnustep-%{ver} -emit-llvm -o - %s | FileCheck %s -check-prefix %{prefix}


// REDEFINE: %{ver} = 1.6
// REDEFINE: %{triple} = x86_64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = arm-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{prefix} = CHECK-MSG-LOOKUP
// REDEFINE: %{triple} = aarch64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = mips64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = riscv64-unknown-freebsd
// RUN: %{check}

// REDEFINE: %{ver} = 1.9
// REDEFINE: %{prefix} = CHECK-MSG-SEND
// REDEFINE: %{triple} = x86_64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = arm-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = aarch64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = mips64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{prefix} = CHECK-MSG-LOOKUP
// REDEFINE: %{triple} = riscv64-unknown-freebsd
// RUN: %{check}

// REDEFINE: %{ver} = 2.2
// REDEFINE: %{prefix} = CHECK-MSG-SEND
// REDEFINE: %{triple} = x86_64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = arm-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = aarch64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = mips64-unknown-freebsd
// RUN: %{check}
// REDEFINE: %{triple} = riscv64-unknown-freebsd
// RUN: %{check}

typedef struct {
  int x;
  int y;
  int z[10];
} MyPoint;

void f0(id a) {
  int i;
  MyPoint pt = { 1, 2};

  // CHECK-MSG-SEND: call {{.*}} @objc_msgSend
  // CHECK-MSG-LOOKUP: call {{.*}} @objc_msg_lookup(
  [a print0];

  // CHECK-MSG-SEND: call {{.*}} @objc_msgSend
  // CHECK-MSG-LOOKUP: call {{.*}} @objc_msg_lookup(
  [a print1: 10];

  // CHECK-MSG-SEND: call {{.*}} @objc_msgSend
  // CHECK-MSG-LOOKUP: call {{.*}} @objc_msg_lookup(
  [a print2: 10 and: "hello" and: 2.2];

  // CHECK-MSG-SEND: call {{.*}} @objc_msgSend
  // CHECK-MSG-LOOKUP: call {{.*}} @objc_msg_lookup(
  [a takeStruct: pt ];
}

@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

I assume we can split the test into two parts:

  1. Checking if the driver correctly sets -fobjc-dispatch-method
  2. Checking if frontend emits objc_msgSend

@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

Definition of -fobjc-dispatch-method:

def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">,
  HelpText<"Objective-C dispatch method to use">,
  Values<"legacy,non-legacy,mixed">,
  NormalizedValuesScope<"CodeGenOptions">, NormalizedValues<["Legacy", "NonLegacy", "Mixed"]>,
  MarshallingInfoEnum<CodeGenOpts<"ObjCDispatchMethod">, "Legacy">;

Which is used in CGObjCGNU::GenerateMessageSend

@llvmbot llvmbot added the clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' label Jan 2, 2024
@davidchisnall
Copy link
Contributor

I assume we can split the test into two parts:

  1. Checking if the driver correctly sets -fobjc-dispatch-method
  2. Checking if frontend emits objc_msgSend

Ah, I forgot that was how it propagated. I think we only need the driver tests, there should be existing checks for the dispatch-method thing.

@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

Should be ready now!

@davidchisnall
Copy link
Contributor

A lot of formatting changes seem to have crept into unrelated bits of the code, please can you revert them? You can use the clang-format-diff script to format only the bits that you’ve changed.

@hmelder hmelder requested a review from davidchisnall January 2, 2024 21:09
@hmelder
Copy link
Contributor Author

hmelder commented Jan 2, 2024

A lot of formatting changes seem to have crept into unrelated bits of the code, please can you revert them? You can use > the clang-format-diff script to format only the bits that you’ve changed.

Done. Sorry for the messy commit history.

@davidchisnall
Copy link
Contributor

LGTM. @rjmccall, do you want to take a look?

Copy link
Contributor

@rjmccall rjmccall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM if @davidchisnall's okay with it.

@davidchisnall davidchisnall merged commit 3f9f8ef into llvm:main Jan 3, 2024
triplef added a commit to gnustep/tools-android that referenced this pull request Feb 9, 2024
Forces Clang to use the fast path, which is not enabled by default on arm64 even though it's supported in the runtime.

Can be removed when Clang 18 containing this patch is available via the Android SDK:
llvm/llvm-project#76694
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category objective-c
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants