Skip to content

[CodeGen][ARM64EC] Mangle EH personality handler names #121652

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 2, 2025
Merged

Conversation

bylaws
Copy link
Contributor

@bylaws bylaws commented Jan 4, 2025

Since the target isn't passed to llvm::classifyEHPersonality this currently demangles the handler name unconditionally when classifying, this shouldn't cause any issues but if preferred I can change that.

cc: @efriedma-quic @cjacek

@llvmbot
Copy link
Member

llvmbot commented Jan 4, 2025

@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-backend-aarch64

Author: Billy Laws (bylaws)

Changes

Since the target isn't passed to llvm::classifyEHPersonality this currently demangles the handler name unconditionally when classifying, this shouldn't cause any issues but if preferred I can change that.


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

3 Files Affected:

  • (modified) llvm/lib/IR/EHPersonalities.cpp (+7-1)
  • (modified) llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp (+10)
  • (added) llvm/test/CodeGen/AArch64/arm64ec-eh.ll (+65)
diff --git a/llvm/lib/IR/EHPersonalities.cpp b/llvm/lib/IR/EHPersonalities.cpp
index 7c32601b8a83ea..8320e738531937 100644
--- a/llvm/lib/IR/EHPersonalities.cpp
+++ b/llvm/lib/IR/EHPersonalities.cpp
@@ -12,6 +12,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
@@ -25,7 +26,12 @@ EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
       Pers ? dyn_cast<GlobalValue>(Pers->stripPointerCasts()) : nullptr;
   if (!F || !F->getValueType() || !F->getValueType()->isFunctionTy())
     return EHPersonality::Unknown;
-  return StringSwitch<EHPersonality>(F->getName())
+
+  std::string Name = F->getName().str();
+  if (auto DemangledName = getArm64ECDemangledFunctionName(Name))
+    Name = *DemangledName;
+
+  return StringSwitch<EHPersonality>(Name)
       .Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
       .Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
       .Case("__gxx_personality_seh0", EHPersonality::GNU_CXX)
diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
index 415edb189e60c4..f33cc5b6831ce3 100644
--- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
@@ -807,6 +807,16 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) {
   SetVector<GlobalAlias *> PatchableFns;
 
   for (Function &F : Mod) {
+    if (F.hasPersonalityFn()) {
+      GlobalValue *PersFn = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts());
+      if (PersFn->getValueType() && PersFn->getValueType()->isFunctionTy()) {
+        if (std::optional<std::string> MangledName =
+            getArm64ECMangledFunctionName(PersFn->getName().str())) {
+          PersFn->setName(MangledName.value());
+        }
+      }
+    }
+
     if (!F.hasFnAttribute(Attribute::HybridPatchable) || F.isDeclaration() ||
         F.hasLocalLinkage() || F.getName().ends_with("$hp_target"))
       continue;
diff --git a/llvm/test/CodeGen/AArch64/arm64ec-eh.ll b/llvm/test/CodeGen/AArch64/arm64ec-eh.ll
new file mode 100644
index 00000000000000..4b6bbb01c6c2dc
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/arm64ec-eh.ll
@@ -0,0 +1,65 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=arm64ec-pc-windows-msvc %s -o - | FileCheck %s
+
+define dso_local i32 @test() #0 personality ptr @__C_specific_handler {
+; CHECK-LABEL:  "#test"
+; CHECK:  .Lfunc_begin0:
+; CHECK-NEXT:  .seh_proc "#test"
+; CHECK-NEXT:    .seh_handler "#__C_specific_handler", @unwind, @except
+; CHECK-NEXT:  // %bb.0:
+; CHECK-NEXT:    sub sp, sp, #48
+; CHECK-NEXT:    .seh_stackalloc 48
+; CHECK-NEXT:    stp x29, x30, [sp, #16]             // 16-byte Folded Spill
+; CHECK-NEXT:    .seh_save_fplr 16
+; CHECK-NEXT:    add x29, sp, #16
+; CHECK-NEXT:    .seh_add_fp 16
+; CHECK-NEXT:    .seh_endprologue
+; CHECK-NEXT:    mov x0, #-2                         // =0xfffffffffffffffe
+; CHECK-NEXT:    mov w8, #-1                         // =0xffffffff
+; CHECK-NEXT:    stur x0, [x29, #16]
+; CHECK-NEXT:    stur w8, [x29, #-4]
+; CHECK-NEXT:  .Ltmp0:
+; CHECK-NEXT:    bl      "#ext"
+; CHECK-NEXT:  .Ltmp1:
+; CHECK-NEXT:  .LBB0_1:
+; CHECK-NEXT:  $ehgcr_0_1:
+; CHECK-NEXT:    stur    w0, [x29, #-4]
+; CHECK-NEXT:    .seh_startepilogue
+; CHECK-NEXT:    ldp     x29, x30, [sp, #16]             // 16-byte Folded Reload
+; CHECK-NEXT:    .seh_save_fplr  16
+; CHECK-NEXT:    add     sp, sp, #48
+; CHECK-NEXT:    .seh_stackalloc 48
+; CHECK-NEXT:    .seh_endepilogue
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    mov     w0, wzr
+; CHECK-NEXT:    b       .LBB0_1
+  %1 = alloca i32, align 4
+  %2 = alloca i32, align 4
+  store i32 -1, ptr %1, align 4
+  %3 = invoke i32 @ext() #3
+          to label %12 unwind label %4
+
+4:                                                ; preds = %0
+  %5 = catchswitch within none [label %6] unwind to caller
+
+6:                                                ; preds = %4
+  %7 = catchpad within %5 [ptr null]
+  catchret from %7 to label %8
+
+8:                                                ; preds = %6
+  store i32 0, ptr %1, align 4
+  br label %10
+
+10:                                               ; preds = %8, %12
+  %11 = load i32, ptr %1, align 4
+  ret i32 %11
+
+12:                                               ; preds = %0
+  store i32 %3, ptr %1, align 4
+  br label %10
+}
+
+declare dso_local i32 @ext() #1
+
+declare dso_local i32 @__C_specific_handler(...)

Copy link

github-actions bot commented Jan 4, 2025

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

Copy link
Collaborator

@efriedma-quic efriedma-quic left a comment

Choose a reason for hiding this comment

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

Not that it's really likely to matter, but I'd prefer to check the module triple is arm64ec before we try to do arm64ec-specific demangling.

@bylaws
Copy link
Contributor Author

bylaws commented Jan 7, 2025

Not that it's really likely to matter, but I'd prefer to check the module triple is arm64ec before we try to do arm64ec-specific demangling.

Right, jacek had suggested that this could be moved to target info to to allow that but doing so is quite a wide reaching change. It you think it makes sense to I will

@efriedma-quic
Copy link
Collaborator

Just checking Module::getTargetTriple() is probably good enough? We do that in a few different places already... it's not really a pattern I usually encourage, but sometimes there isn't a better solution.

@bylaws
Copy link
Contributor Author

bylaws commented Jan 7, 2025

Just checking Module::getTargetTriple() is probably good enough? We do that in a few different places already... it's not really a pattern I usually encourage, but sometimes there isn't a better solution.

Oh thanks, I hadn't realised there was a way to get the module from just the input value.

@bylaws bylaws force-pushed the eceh branch 2 times, most recently from b5425e5 to 5313cd4 Compare January 16, 2025 13:48
Copy link
Contributor

@cjacek cjacek left a comment

Choose a reason for hiding this comment

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

The change looks good to me overall.

Copy link
Contributor

@cjacek cjacek left a comment

Choose a reason for hiding this comment

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

LGTM

@cjacek cjacek merged commit 8eba022 into llvm:main Mar 2, 2025
11 checks passed
nikic added a commit to nikic/llvm-project that referenced this pull request Mar 5, 2025
The module currently stores the target triple as a string. This
means that any code that wants to actually use the triple first
has to instantiate a Triple, which is somewhat expensive. The
change in llvm#121652 caused a moderate compile-time regression due
to this. While it would be easy enough to work around, I think
that architecturally, it makes more sense to store the parsed
Triple in the module, so that it can always be directly queried.

For this change, I've opted not to add any magic conversions
between std::string and Triple for backwards-compatibilty purses,
and instead write out needed Triple()s or str()s explicitly. This
is because I think a decent number of them should be changed to
work on Triple as well, to avoid unnecessary conversions back and
forth.

The only interesting part in this patch is that the default triple
is Triple("") instead of Triple() to preserve existing behavior.
The former defaults to using the ELF object format instead of
unknown object format. We should fix that as well.
nikic added a commit that referenced this pull request Mar 6, 2025
The module currently stores the target triple as a string. This means
that any code that wants to actually use the triple first has to
instantiate a Triple, which is somewhat expensive. The change in #121652
caused a moderate compile-time regression due to this. While it would be
easy enough to work around, I think that architecturally, it makes more
sense to store the parsed Triple in the module, so that it can always be
directly queried.

For this change, I've opted not to add any magic conversions between
std::string and Triple for backwards-compatibilty purses, and instead
write out needed Triple()s or str()s explicitly. This is because I think
a decent number of them should be changed to work on Triple as well, to
avoid unnecessary conversions back and forth.

The only interesting part in this patch is that the default triple is
Triple("") instead of Triple() to preserve existing behavior. The former
defaults to using the ELF object format instead of unknown object
format. We should fix that as well.
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
The module currently stores the target triple as a string. This means
that any code that wants to actually use the triple first has to
instantiate a Triple, which is somewhat expensive. The change in llvm#121652
caused a moderate compile-time regression due to this. While it would be
easy enough to work around, I think that architecturally, it makes more
sense to store the parsed Triple in the module, so that it can always be
directly queried.

For this change, I've opted not to add any magic conversions between
std::string and Triple for backwards-compatibilty purses, and instead
write out needed Triple()s or str()s explicitly. This is because I think
a decent number of them should be changed to work on Triple as well, to
avoid unnecessary conversions back and forth.

The only interesting part in this patch is that the default triple is
Triple("") instead of Triple() to preserve existing behavior. The former
defaults to using the ELF object format instead of unknown object
format. We should fix that as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants