[clang] [clang] Refactor target attribute mangling. (PR #81893)

via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 15 10:18:26 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64

@llvm/pr-subscribers-clang-codegen

Author: Alexandros Lamprineas (labrinea)

<details>
<summary>Changes</summary>

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.

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


5 Files Affected:

- (modified) clang/include/clang/Basic/TargetInfo.h (+8) 
- (modified) clang/lib/Basic/TargetInfo.cpp (+51) 
- (modified) clang/lib/Basic/Targets/AArch64.cpp (+27) 
- (modified) clang/lib/Basic/Targets/AArch64.h (+7) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+13-95) 


``````````diff
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");
       }

``````````

</details>


https://github.com/llvm/llvm-project/pull/81893


More information about the cfe-commits mailing list