Skip to content

Commit

Permalink
[clang] Refactor target attribute mangling. (#81893)
Browse files Browse the repository at this point in the history
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 #80540 demonstrates a motivating
case.
  • Loading branch information
labrinea authored Feb 28, 2024
1 parent c6cbf81 commit b42b7c8
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 95 deletions.
52 changes: 52 additions & 0 deletions clang/lib/CodeGen/ABIInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,58 @@ ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
/*ByVal*/ false, Realign);
}

void ABIInfo::appendAttributeMangling(TargetAttr *Attr,
raw_ostream &Out) const {
if (Attr->isDefaultVersion())
return;
appendAttributeMangling(Attr->getFeaturesStr(), Out);
}

void ABIInfo::appendAttributeMangling(TargetVersionAttr *Attr,
raw_ostream &Out) const {
appendAttributeMangling(Attr->getNamesStr(), Out);
}

void ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
raw_ostream &Out) const {
appendAttributeMangling(Attr->getFeatureStr(Index), Out);
Out << '.' << Attr->getMangledIndex(Index);
}

void ABIInfo::appendAttributeMangling(StringRef AttrStr,
raw_ostream &Out) const {
if (AttrStr == "default") {
Out << ".default";
return;
}

Out << '.';
const TargetInfo &TI = CGT.getTarget();
ParsedTargetAttr Info = TI.parseTargetAttr(AttrStr);

llvm::sort(Info.Features, [&TI](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 TI.multiVersionSortPriority(LHS.substr(1)) >
TI.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);
}
}

// Pin the vtable to this file.
SwiftABIInfo::~SwiftABIInfo() = default;

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CodeGen/ABIInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
#define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H

#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/IR/CallingConv.h"
Expand Down Expand Up @@ -111,6 +112,15 @@ class ABIInfo {

CodeGen::ABIArgInfo getNaturalAlignIndirectInReg(QualType Ty,
bool Realign = false) const;

virtual void appendAttributeMangling(TargetAttr *Attr,
raw_ostream &Out) const;
virtual void appendAttributeMangling(TargetVersionAttr *Attr,
raw_ostream &Out) const;
virtual void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
raw_ostream &Out) const;
virtual void appendAttributeMangling(StringRef AttrStr,
raw_ostream &Out) const;
};

/// Target specific hooks for defining how a type should be passed or returned
Expand Down
111 changes: 16 additions & 95 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1727,59 +1727,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,
Expand All @@ -1789,41 +1736,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) {
Expand Down Expand Up @@ -1877,16 +1789,25 @@ 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>();
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
Info.appendAttributeMangling(Attr, Out);
break;
case MultiVersionKind::TargetVersion:
AppendTargetVersionMangling(CGM, FD->getAttr<TargetVersionAttr>(), Out);
}
case MultiVersionKind::TargetVersion: {
auto *Attr = FD->getAttr<TargetVersionAttr>();
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
Info.appendAttributeMangling(Attr, Out);
break;
case MultiVersionKind::TargetClones:
AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(),
GD.getMultiVersionIndex(), Out);
}
case MultiVersionKind::TargetClones: {
auto *Attr = FD->getAttr<TargetClonesAttr>();
unsigned Index = GD.getMultiVersionIndex();
const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
Info.appendAttributeMangling(Attr, Index, Out);
break;
}
case MultiVersionKind::None:
llvm_unreachable("None multiversion type isn't valid here");
}
Expand Down
40 changes: 40 additions & 0 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "ABIInfoImpl.h"
#include "TargetInfo.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "llvm/TargetParser/AArch64TargetParser.h"

using namespace clang;
using namespace clang::CodeGen;
Expand Down Expand Up @@ -75,6 +76,12 @@ class AArch64ABIInfo : public ABIInfo {
bool allowBFloatArgsAndRet() const override {
return getTarget().hasBFloat16Type();
}

using ABIInfo::appendAttributeMangling;
void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
raw_ostream &Out) const override;
void appendAttributeMangling(StringRef AttrStr,
raw_ostream &Out) const override;
};

class AArch64SwiftABIInfo : public SwiftABIInfo {
Expand Down Expand Up @@ -857,6 +864,39 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
<< Callee->getDeclName();
}

void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
unsigned Index,
raw_ostream &Out) const {
appendAttributeMangling(Attr->getFeatureStr(Index), Out);
}

void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
raw_ostream &Out) const {
if (AttrStr == "default") {
Out << ".default";
return;
}

Out << "._";
SmallVector<StringRef, 8> Features;
AttrStr.split(Features, "+");
for (auto &Feat : Features)
Feat = Feat.trim();

// FIXME: It was brought up in #79316 that sorting the features which are
// used for mangling based on their multiversion priority is not a good
// practice. Changing the feature priorities will break the ABI. Perhaps
// it would be preferable to perform a lexicographical sort instead.
const TargetInfo &TI = CGT.getTarget();
llvm::sort(Features, [&TI](const StringRef LHS, const StringRef RHS) {
return TI.multiVersionSortPriority(LHS) < TI.multiVersionSortPriority(RHS);
});

for (auto &Feat : Features)
if (auto Ext = llvm::AArch64::parseArchExtension(Feat))
Out << 'M' << Ext->Name;
}

std::unique_ptr<TargetCodeGenInfo>
CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM,
AArch64ABIKind Kind) {
Expand Down

0 comments on commit b42b7c8

Please sign in to comment.