[clang] [clang] Refactor target attribute mangling. (PR #81893)
Alexandros Lamprineas via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 15 10:17:57 PST 2024
https://github.com/labrinea created https://github.com/llvm/llvm-project/pull/81893
Before this patch all of the 'target', 'target_version' and 'target_clones' attributes were sharing a common mangling logic across different targets. However we would like to differenciate this logic, therefore I have moved the default path to TargetInfo and provided overrides for AArch64. This way we can resolve feature aliases without affecting the name mangling The PR #80540 demonstrates a motivating case.
>From 81ff9395020405dfb123ac6872839432583e067f Mon Sep 17 00:00:00 2001
From: Alexandros Lamprineas <alexandros.lamprineas at arm.com>
Date: Thu, 15 Feb 2024 15:53:51 +0000
Subject: [PATCH] [clang] Refactor target attribute mangling.
Before this patch all of the 'target', 'target_version' and 'target_clones'
attributes were sharing a common mangling logic across different targets.
However we would like to differenciate this logic, therefore I have moved
the default path to TargetInfo and provided overrides for AArch64. This
way we can resolve feature aliases without affecting the name mangling
The PR #80540 demonstrates a motivating case.
---
clang/include/clang/Basic/TargetInfo.h | 8 ++
clang/lib/Basic/TargetInfo.cpp | 51 ++++++++++++
clang/lib/Basic/Targets/AArch64.cpp | 27 +++++++
clang/lib/Basic/Targets/AArch64.h | 7 ++
clang/lib/CodeGen/CodeGenModule.cpp | 108 +++----------------------
5 files changed, 106 insertions(+), 95 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 2f80234c0dc7e3..7ea4e0c0197761 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
#define LLVM_CLANG_BASIC_TARGETINFO_H
+#include "clang/AST/Attr.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/BitmaskEnum.h"
#include "clang/Basic/CodeGenOptions.h"
@@ -1321,6 +1322,13 @@ class TargetInfo : public TransferrableTargetInfo,
return isValidCPUName(Name);
}
+ virtual std::string getManglingSuffixFromAttr(TargetAttr *Attr) const;
+ virtual std::string getManglingSuffixFromAttr(TargetVersionAttr *Attr) const;
+ virtual std::string getManglingSuffixFromAttr(TargetClonesAttr *Attr,
+ unsigned VersionIndex) const;
+
+ virtual std::string getManglingSuffixFromStr(StringRef AttrStr) const;
+
virtual ParsedTargetAttr parseTargetAttr(StringRef Str) const;
/// Determine whether this TargetInfo supports tune in target attribute.
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 08fb0f2bb1bad6..c17fd4949ef0cd 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -535,6 +535,57 @@ bool TargetInfo::initFeatureMap(
return true;
}
+std::string TargetInfo::getManglingSuffixFromAttr(TargetAttr *Attr) const {
+ if (Attr->isDefaultVersion())
+ return {};
+
+ return getManglingSuffixFromStr(Attr->getFeaturesStr());
+}
+
+std::string
+TargetInfo::getManglingSuffixFromAttr(TargetVersionAttr *Attr) const {
+ return getManglingSuffixFromStr(Attr->getNamesStr());
+}
+
+std::string TargetInfo::getManglingSuffixFromAttr(TargetClonesAttr *Attr,
+ unsigned Index) const {
+ std::string Suffix = getManglingSuffixFromStr(Attr->getFeatureStr(Index));
+ Suffix.append("." + Twine(Attr->getMangledIndex(Index)).str());
+ return Suffix;
+}
+
+std::string TargetInfo::getManglingSuffixFromStr(StringRef AttrStr) const {
+ if (AttrStr == "default")
+ return ".default";
+
+ std::string ManglingSuffix(".");
+ ParsedTargetAttr Info = parseTargetAttr(AttrStr);
+
+ llvm::sort(Info.Features, [this](StringRef LHS, StringRef RHS) {
+ // Multiversioning doesn't allow "no-${feature}", so we can
+ // only have "+" prefixes here.
+ assert(LHS.starts_with("+") && RHS.starts_with("+") &&
+ "Features should always have a prefix.");
+ return multiVersionSortPriority(LHS.substr(1)) >
+ multiVersionSortPriority(RHS.substr(1));
+ });
+
+ bool IsFirst = true;
+ if (!Info.CPU.empty()) {
+ IsFirst = false;
+ ManglingSuffix.append(Twine("arch_", Info.CPU).str());
+ }
+
+ for (StringRef Feat : Info.Features) {
+ if (!IsFirst)
+ ManglingSuffix.append("_");
+ IsFirst = false;
+ ManglingSuffix.append(Feat.substr(1).str());
+ }
+
+ return ManglingSuffix;
+}
+
ParsedTargetAttr TargetInfo::parseTargetAttr(StringRef Features) const {
ParsedTargetAttr Ret;
if (Features == "default")
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index c49461bd20eeec..d288c431a46207 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -1105,6 +1105,33 @@ bool AArch64TargetInfo::initFeatureMap(
return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
}
+std::string AArch64TargetInfo::getManglingSuffixFromAttr(TargetClonesAttr *Attr,
+ unsigned Index) const {
+ return getManglingSuffixFromStr(Attr->getFeatureStr(Index));
+}
+
+std::string AArch64TargetInfo::getManglingSuffixFromStr(StringRef Str) const {
+ if (Str == "default")
+ return ".default";
+
+ std::string ManglingSuffix("._");
+ SmallVector<StringRef, 8> Features;
+ Str.split(Features, "+");
+ for (auto &Feat : Features)
+ Feat = Feat.trim();
+
+ // TODO Lexicographical order won't break the ABI if priorities change.
+ llvm::sort(Features, [this](const StringRef LHS, const StringRef RHS) {
+ return multiVersionSortPriority(LHS) < multiVersionSortPriority(RHS);
+ });
+
+ for (auto &Feat : Features)
+ if (auto Ext = llvm::AArch64::parseArchExtension(Feat))
+ ManglingSuffix.append(Twine("M", Ext->Name).str());
+
+ return ManglingSuffix;
+}
+
// Parse AArch64 Target attributes, which are a comma separated list of:
// "arch=<arch>" - parsed to features as per -march=..
// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index f4ec3543f4082c..d5b09e064660e9 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -164,7 +164,14 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
bool Enabled) const override;
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
+
+ using TargetInfo::getManglingSuffixFromAttr;
+ std::string getManglingSuffixFromAttr(TargetClonesAttr *Attr,
+ unsigned VersionIndex) const override;
+ std::string getManglingSuffixFromStr(StringRef Str) const override;
+
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
+
bool supportsTargetAttributeTune() const override { return true; }
bool checkArithmeticFenceSupported() const override { return true; }
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 64836f8d174710..cc6e9f206f067f 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1724,59 +1724,6 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
Out << ".resolver";
}
-static void AppendTargetVersionMangling(const CodeGenModule &CGM,
- const TargetVersionAttr *Attr,
- raw_ostream &Out) {
- if (Attr->isDefaultVersion()) {
- Out << ".default";
- return;
- }
- Out << "._";
- const TargetInfo &TI = CGM.getTarget();
- llvm::SmallVector<StringRef, 8> Feats;
- Attr->getFeatures(Feats);
- llvm::stable_sort(Feats, [&TI](const StringRef FeatL, const StringRef FeatR) {
- return TI.multiVersionSortPriority(FeatL) <
- TI.multiVersionSortPriority(FeatR);
- });
- for (const auto &Feat : Feats) {
- Out << 'M';
- Out << Feat;
- }
-}
-
-static void AppendTargetMangling(const CodeGenModule &CGM,
- const TargetAttr *Attr, raw_ostream &Out) {
- if (Attr->isDefaultVersion())
- return;
-
- Out << '.';
- const TargetInfo &Target = CGM.getTarget();
- ParsedTargetAttr Info = Target.parseTargetAttr(Attr->getFeaturesStr());
- llvm::sort(Info.Features, [&Target](StringRef LHS, StringRef RHS) {
- // Multiversioning doesn't allow "no-${feature}", so we can
- // only have "+" prefixes here.
- assert(LHS.starts_with("+") && RHS.starts_with("+") &&
- "Features should always have a prefix.");
- return Target.multiVersionSortPriority(LHS.substr(1)) >
- Target.multiVersionSortPriority(RHS.substr(1));
- });
-
- bool IsFirst = true;
-
- if (!Info.CPU.empty()) {
- IsFirst = false;
- Out << "arch_" << Info.CPU;
- }
-
- for (StringRef Feat : Info.Features) {
- if (!IsFirst)
- Out << '_';
- IsFirst = false;
- Out << Feat.substr(1);
- }
-}
-
// Returns true if GD is a function decl with internal linkage and
// needs a unique suffix after the mangled name.
static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
@@ -1786,41 +1733,6 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
(CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
}
-static void AppendTargetClonesMangling(const CodeGenModule &CGM,
- const TargetClonesAttr *Attr,
- unsigned VersionIndex,
- raw_ostream &Out) {
- const TargetInfo &TI = CGM.getTarget();
- if (TI.getTriple().isAArch64()) {
- StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
- if (FeatureStr == "default") {
- Out << ".default";
- return;
- }
- Out << "._";
- SmallVector<StringRef, 8> Features;
- FeatureStr.split(Features, "+");
- llvm::stable_sort(Features,
- [&TI](const StringRef FeatL, const StringRef FeatR) {
- return TI.multiVersionSortPriority(FeatL) <
- TI.multiVersionSortPriority(FeatR);
- });
- for (auto &Feat : Features) {
- Out << 'M';
- Out << Feat;
- }
- } else {
- Out << '.';
- StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
- if (FeatureStr.starts_with("arch="))
- Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
- else
- Out << FeatureStr;
-
- Out << '.' << Attr->getMangledIndex(VersionIndex);
- }
-}
-
static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
const NamedDecl *ND,
bool OmitMultiVersionMangling = false) {
@@ -1874,16 +1786,22 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
FD->getAttr<CPUSpecificAttr>(),
GD.getMultiVersionIndex(), Out);
break;
- case MultiVersionKind::Target:
- AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
+ case MultiVersionKind::Target: {
+ auto *Attr = FD->getAttr<TargetAttr>();
+ Out << CGM.getTarget().getManglingSuffixFromAttr(Attr);
break;
- case MultiVersionKind::TargetVersion:
- AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out);
+ }
+ case MultiVersionKind::TargetVersion: {
+ auto *Attr = FD->getAttr<TargetVersionAttr>();
+ Out << CGM.getTarget().getManglingSuffixFromAttr(Attr);
break;
- case MultiVersionKind::TargetClones:
- AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
- GD.getMultiVersionIndex(), Out);
+ }
+ case MultiVersionKind::TargetClones: {
+ auto *Attr = FD->getAttr<TargetClonesAttr>();
+ unsigned VersionIndex = GD.getMultiVersionIndex();
+ Out << CGM.getTarget().getManglingSuffixFromAttr(Attr, VersionIndex);
break;
+ }
case MultiVersionKind::None:
llvm_unreachable("None multiversion type isn't valid here");
}
More information about the cfe-commits
mailing list