-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[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
Conversation
@llvm/pr-subscribers-llvm-ir @llvm/pr-subscribers-backend-aarch64 Author: Billy Laws (bylaws) ChangesSince the target isn't passed to Full diff: https://github.com/llvm/llvm-project/pull/121652.diff 3 Files Affected:
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(...)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this 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.
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 |
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. |
b5425e5
to
5313cd4
Compare
There was a problem hiding this 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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.
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.
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.
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