Skip to content

Commit b42b7c8

Browse files
authored
[clang] Refactor target attribute mangling. (llvm#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 ABIInfo and provided overrides for AArch64. This way we can resolve feature aliases without affecting the name mangling. The PR llvm#80540 demonstrates a motivating case.
1 parent c6cbf81 commit b42b7c8

File tree

4 files changed

+118
-95
lines changed

4 files changed

+118
-95
lines changed

clang/lib/CodeGen/ABIInfo.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,58 @@ ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
184184
/*ByVal*/ false, Realign);
185185
}
186186

187+
void ABIInfo::appendAttributeMangling(TargetAttr *Attr,
188+
raw_ostream &Out) const {
189+
if (Attr->isDefaultVersion())
190+
return;
191+
appendAttributeMangling(Attr->getFeaturesStr(), Out);
192+
}
193+
194+
void ABIInfo::appendAttributeMangling(TargetVersionAttr *Attr,
195+
raw_ostream &Out) const {
196+
appendAttributeMangling(Attr->getNamesStr(), Out);
197+
}
198+
199+
void ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
200+
raw_ostream &Out) const {
201+
appendAttributeMangling(Attr->getFeatureStr(Index), Out);
202+
Out << '.' << Attr->getMangledIndex(Index);
203+
}
204+
205+
void ABIInfo::appendAttributeMangling(StringRef AttrStr,
206+
raw_ostream &Out) const {
207+
if (AttrStr == "default") {
208+
Out << ".default";
209+
return;
210+
}
211+
212+
Out << '.';
213+
const TargetInfo &TI = CGT.getTarget();
214+
ParsedTargetAttr Info = TI.parseTargetAttr(AttrStr);
215+
216+
llvm::sort(Info.Features, [&TI](StringRef LHS, StringRef RHS) {
217+
// Multiversioning doesn't allow "no-${feature}", so we can
218+
// only have "+" prefixes here.
219+
assert(LHS.starts_with("+") && RHS.starts_with("+") &&
220+
"Features should always have a prefix.");
221+
return TI.multiVersionSortPriority(LHS.substr(1)) >
222+
TI.multiVersionSortPriority(RHS.substr(1));
223+
});
224+
225+
bool IsFirst = true;
226+
if (!Info.CPU.empty()) {
227+
IsFirst = false;
228+
Out << "arch_" << Info.CPU;
229+
}
230+
231+
for (StringRef Feat : Info.Features) {
232+
if (!IsFirst)
233+
Out << '_';
234+
IsFirst = false;
235+
Out << Feat.substr(1);
236+
}
237+
}
238+
187239
// Pin the vtable to this file.
188240
SwiftABIInfo::~SwiftABIInfo() = default;
189241

clang/lib/CodeGen/ABIInfo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
1010
#define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
1111

12+
#include "clang/AST/Attr.h"
1213
#include "clang/AST/CharUnits.h"
1314
#include "clang/AST/Type.h"
1415
#include "llvm/IR/CallingConv.h"
@@ -111,6 +112,15 @@ class ABIInfo {
111112

112113
CodeGen::ABIArgInfo getNaturalAlignIndirectInReg(QualType Ty,
113114
bool Realign = false) const;
115+
116+
virtual void appendAttributeMangling(TargetAttr *Attr,
117+
raw_ostream &Out) const;
118+
virtual void appendAttributeMangling(TargetVersionAttr *Attr,
119+
raw_ostream &Out) const;
120+
virtual void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
121+
raw_ostream &Out) const;
122+
virtual void appendAttributeMangling(StringRef AttrStr,
123+
raw_ostream &Out) const;
114124
};
115125

116126
/// Target specific hooks for defining how a type should be passed or returned

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 16 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,59 +1727,6 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
17271727
Out << ".resolver";
17281728
}
17291729

1730-
static void AppendTargetVersionMangling(const CodeGenModule &CGM,
1731-
const TargetVersionAttr *Attr,
1732-
raw_ostream &Out) {
1733-
if (Attr->isDefaultVersion()) {
1734-
Out << ".default";
1735-
return;
1736-
}
1737-
Out << "._";
1738-
const TargetInfo &TI = CGM.getTarget();
1739-
llvm::SmallVector<StringRef, 8> Feats;
1740-
Attr->getFeatures(Feats);
1741-
llvm::stable_sort(Feats, [&TI](const StringRef FeatL, const StringRef FeatR) {
1742-
return TI.multiVersionSortPriority(FeatL) <
1743-
TI.multiVersionSortPriority(FeatR);
1744-
});
1745-
for (const auto &Feat : Feats) {
1746-
Out << 'M';
1747-
Out << Feat;
1748-
}
1749-
}
1750-
1751-
static void AppendTargetMangling(const CodeGenModule &CGM,
1752-
const TargetAttr *Attr, raw_ostream &Out) {
1753-
if (Attr->isDefaultVersion())
1754-
return;
1755-
1756-
Out << '.';
1757-
const TargetInfo &Target = CGM.getTarget();
1758-
ParsedTargetAttr Info = Target.parseTargetAttr(Attr->getFeaturesStr());
1759-
llvm::sort(Info.Features, [&Target](StringRef LHS, StringRef RHS) {
1760-
// Multiversioning doesn't allow "no-${feature}", so we can
1761-
// only have "+" prefixes here.
1762-
assert(LHS.starts_with("+") && RHS.starts_with("+") &&
1763-
"Features should always have a prefix.");
1764-
return Target.multiVersionSortPriority(LHS.substr(1)) >
1765-
Target.multiVersionSortPriority(RHS.substr(1));
1766-
});
1767-
1768-
bool IsFirst = true;
1769-
1770-
if (!Info.CPU.empty()) {
1771-
IsFirst = false;
1772-
Out << "arch_" << Info.CPU;
1773-
}
1774-
1775-
for (StringRef Feat : Info.Features) {
1776-
if (!IsFirst)
1777-
Out << '_';
1778-
IsFirst = false;
1779-
Out << Feat.substr(1);
1780-
}
1781-
}
1782-
17831730
// Returns true if GD is a function decl with internal linkage and
17841731
// needs a unique suffix after the mangled name.
17851732
static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
@@ -1789,41 +1736,6 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
17891736
(CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
17901737
}
17911738

1792-
static void AppendTargetClonesMangling(const CodeGenModule &CGM,
1793-
const TargetClonesAttr *Attr,
1794-
unsigned VersionIndex,
1795-
raw_ostream &Out) {
1796-
const TargetInfo &TI = CGM.getTarget();
1797-
if (TI.getTriple().isAArch64()) {
1798-
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
1799-
if (FeatureStr == "default") {
1800-
Out << ".default";
1801-
return;
1802-
}
1803-
Out << "._";
1804-
SmallVector<StringRef, 8> Features;
1805-
FeatureStr.split(Features, "+");
1806-
llvm::stable_sort(Features,
1807-
[&TI](const StringRef FeatL, const StringRef FeatR) {
1808-
return TI.multiVersionSortPriority(FeatL) <
1809-
TI.multiVersionSortPriority(FeatR);
1810-
});
1811-
for (auto &Feat : Features) {
1812-
Out << 'M';
1813-
Out << Feat;
1814-
}
1815-
} else {
1816-
Out << '.';
1817-
StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
1818-
if (FeatureStr.starts_with("arch="))
1819-
Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
1820-
else
1821-
Out << FeatureStr;
1822-
1823-
Out << '.' << Attr->getMangledIndex(VersionIndex);
1824-
}
1825-
}
1826-
18271739
static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
18281740
const NamedDecl *ND,
18291741
bool OmitMultiVersionMangling = false) {
@@ -1877,16 +1789,25 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
18771789
FD->getAttr<CPUSpecificAttr>(),
18781790
GD.getMultiVersionIndex(), Out);
18791791
break;
1880-
case MultiVersionKind::Target:
1881-
AppendTargetMangling(CGM, FD->getAttr<TargetAttr>(), Out);
1792+
case MultiVersionKind::Target: {
1793+
auto *Attr = FD->getAttr<TargetAttr>();
1794+
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
1795+
Info.appendAttributeMangling(Attr, Out);
18821796
break;
1883-
case MultiVersionKind::TargetVersion:
1884-
AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out);
1797+
}
1798+
case MultiVersionKind::TargetVersion: {
1799+
auto *Attr = FD->getAttr<TargetVersionAttr>();
1800+
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
1801+
Info.appendAttributeMangling(Attr, Out);
18851802
break;
1886-
case MultiVersionKind::TargetClones:
1887-
AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
1888-
GD.getMultiVersionIndex(), Out);
1803+
}
1804+
case MultiVersionKind::TargetClones: {
1805+
auto *Attr = FD->getAttr<TargetClonesAttr>();
1806+
unsigned Index = GD.getMultiVersionIndex();
1807+
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
1808+
Info.appendAttributeMangling(Attr, Index, Out);
18891809
break;
1810+
}
18901811
case MultiVersionKind::None:
18911812
llvm_unreachable("None multiversion type isn't valid here");
18921813
}

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "ABIInfoImpl.h"
1010
#include "TargetInfo.h"
1111
#include "clang/Basic/DiagnosticFrontend.h"
12+
#include "llvm/TargetParser/AArch64TargetParser.h"
1213

1314
using namespace clang;
1415
using namespace clang::CodeGen;
@@ -75,6 +76,12 @@ class AArch64ABIInfo : public ABIInfo {
7576
bool allowBFloatArgsAndRet() const override {
7677
return getTarget().hasBFloat16Type();
7778
}
79+
80+
using ABIInfo::appendAttributeMangling;
81+
void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
82+
raw_ostream &Out) const override;
83+
void appendAttributeMangling(StringRef AttrStr,
84+
raw_ostream &Out) const override;
7885
};
7986

8087
class AArch64SwiftABIInfo : public SwiftABIInfo {
@@ -857,6 +864,39 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
857864
<< Callee->getDeclName();
858865
}
859866

867+
void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
868+
unsigned Index,
869+
raw_ostream &Out) const {
870+
appendAttributeMangling(Attr->getFeatureStr(Index), Out);
871+
}
872+
873+
void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
874+
raw_ostream &Out) const {
875+
if (AttrStr == "default") {
876+
Out << ".default";
877+
return;
878+
}
879+
880+
Out << "._";
881+
SmallVector<StringRef, 8> Features;
882+
AttrStr.split(Features, "+");
883+
for (auto &Feat : Features)
884+
Feat = Feat.trim();
885+
886+
// FIXME: It was brought up in #79316 that sorting the features which are
887+
// used for mangling based on their multiversion priority is not a good
888+
// practice. Changing the feature priorities will break the ABI. Perhaps
889+
// it would be preferable to perform a lexicographical sort instead.
890+
const TargetInfo &TI = CGT.getTarget();
891+
llvm::sort(Features, [&TI](const StringRef LHS, const StringRef RHS) {
892+
return TI.multiVersionSortPriority(LHS) < TI.multiVersionSortPriority(RHS);
893+
});
894+
895+
for (auto &Feat : Features)
896+
if (auto Ext = llvm::AArch64::parseArchExtension(Feat))
897+
Out << 'M' << Ext->Name;
898+
}
899+
860900
std::unique_ptr<TargetCodeGenInfo>
861901
CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM,
862902
AArch64ABIKind Kind) {

0 commit comments

Comments
 (0)