Skip to content

Commit b3a7b9f

Browse files
committed
[clang][RISCV] Emit RISCV function-signature-based CFI label in llvm::Function metadata
1 parent 02ed6d8 commit b3a7b9f

20 files changed

+573
-4
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
19521952
/// (struct/union/class/enum) decl.
19531953
QualType getTagDeclType(const TagDecl *Decl) const;
19541954

1955+
/// Return the type for "void *"
1956+
QualType getVoidPtrType() const { return VoidPtrTy; }
1957+
19551958
/// Return the unique type for "size_t" (C99 7.17), defined in
19561959
/// <stddef.h>.
19571960
///
@@ -1979,6 +1982,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
19791982
/// defined in <stddef.h> as defined by the target.
19801983
QualType getWideCharType() const { return WideCharTy; }
19811984

1985+
/// Return the type of wide characters in C context, no matter whether it's C
1986+
/// or C++ being compiled.
1987+
QualType getWCharTypeInC() const;
1988+
19821989
/// Return the type of "signed wchar_t".
19831990
///
19841991
/// Used when in C++, as a GCC extension.

clang/include/clang/AST/Mangle.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ class ItaniumMangleContext : public MangleContext {
215215

216216
virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 0;
217217

218+
virtual void mangleForRISCVZicfilpFuncSigLabel(const FunctionType &FT,
219+
const bool IsCXXInstanceMethod,
220+
const bool IsCXXVirtualMethod,
221+
raw_ostream &) = 0;
222+
218223
// This has to live here, otherwise the CXXNameMangler won't have access to
219224
// it.
220225
virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6712,6 +6712,12 @@ CanQualType ASTContext::getUIntMaxType() const {
67126712
return getFromTargetType(Target->getUIntMaxType());
67136713
}
67146714

6715+
/// Return the type of wide characters in C context, no matter whether it's C
6716+
/// or C++ being compiled.
6717+
QualType ASTContext::getWCharTypeInC() const {
6718+
return getFromTargetType(Target->getWCharType());
6719+
}
6720+
67156721
/// getSignedWCharType - Return the type of "signed wchar_t".
67166722
/// Used when in C++, as a GCC extension.
67176723
QualType ASTContext::getSignedWCharType() const {

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ using namespace clang;
4141

4242
namespace {
4343

44+
static bool mayBeCovariant(const Type &Ty) {
45+
if (auto *const PT = Ty.getAs<PointerType>())
46+
return PT->getPointeeType()->isStructureOrClassType();
47+
if (auto *const RT = Ty.getAs<ReferenceType>())
48+
return RT->getPointeeType()->isStructureOrClassType();
49+
return false;
50+
}
51+
4452
static bool isLocalContainerContext(const DeclContext *DC) {
4553
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
4654
}
@@ -134,6 +142,11 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
134142

135143
void mangleModuleInitializer(const Module *Module, raw_ostream &) override;
136144

145+
void mangleForRISCVZicfilpFuncSigLabel(const FunctionType &,
146+
const bool IsCXXInstanceMethod,
147+
const bool IsCXXVirtualMethod,
148+
raw_ostream &) override;
149+
137150
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
138151
// Lambda closure types are already numbered.
139152
if (isLambda(ND))
@@ -386,8 +399,10 @@ class CXXNameMangler {
386399
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
387400
llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions;
388401

402+
protected:
389403
ASTContext &getASTContext() const { return Context.getASTContext(); }
390404

405+
private:
391406
bool isCompatibleWith(LangOptions::ClangABI Ver) {
392407
return Context.getASTContext().getLangOpts().getClangABICompat() <= Ver;
393408
}
@@ -434,6 +449,8 @@ class CXXNameMangler {
434449
NullOut = true;
435450
}
436451

452+
virtual ~CXXNameMangler() = default;
453+
437454
struct WithTemplateDepthOffset { unsigned Offset; };
438455
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out,
439456
WithTemplateDepthOffset Offset)
@@ -552,9 +569,12 @@ class CXXNameMangler {
552569
StringRef Prefix = "");
553570
void mangleOperatorName(DeclarationName Name, unsigned Arity);
554571
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
572+
573+
protected:
555574
void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr);
556575
void mangleRefQualifier(RefQualifierKind RefQualifier);
557576

577+
private:
558578
void mangleObjCMethodName(const ObjCMethodDecl *MD);
559579

560580
// Declare manglers for every type class.
@@ -565,12 +585,25 @@ class CXXNameMangler {
565585

566586
void mangleType(const TagType*);
567587
void mangleType(TemplateName);
588+
589+
protected:
590+
// Use the `Impl` scheme instead of directly virtualizing `mangleType`s since
591+
// `mangleType`s are declared by tables
592+
virtual void mangleTypeImpl(const BuiltinType *T);
593+
virtual void mangleTypeImpl(const FunctionProtoType *T);
594+
virtual void mangleTypeImpl(const FunctionNoProtoType *T);
595+
596+
private:
568597
static StringRef getCallingConvQualifierName(CallingConv CC);
569598
void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info);
570599
void mangleExtFunctionInfo(const FunctionType *T);
571600
void mangleSMEAttrs(unsigned SMEAttrs);
601+
602+
protected:
572603
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
573604
const FunctionDecl *FD = nullptr);
605+
606+
private:
574607
void mangleNeonVectorType(const VectorType *T);
575608
void mangleNeonVectorType(const DependentVectorType *T);
576609
void mangleAArch64NeonVectorType(const VectorType *T);
@@ -3111,7 +3144,9 @@ void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record) {
31113144
addSubstitution(Record);
31123145
}
31133146

3114-
void CXXNameMangler::mangleType(const BuiltinType *T) {
3147+
void CXXNameMangler::mangleType(const BuiltinType *T) { mangleTypeImpl(T); }
3148+
3149+
void CXXNameMangler::mangleTypeImpl(const BuiltinType *T) {
31153150
// <type> ::= <builtin-type>
31163151
// <builtin-type> ::= v # void
31173152
// ::= w # wchar_t
@@ -3694,10 +3729,14 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
36943729
mangleVendorQualifier("noescape");
36953730
}
36963731

3732+
void CXXNameMangler::mangleType(const FunctionProtoType *T) {
3733+
return mangleTypeImpl(T);
3734+
}
3735+
36973736
// <type> ::= <function-type>
36983737
// <function-type> ::= [<CV-qualifiers>] F [Y]
36993738
// <bare-function-type> [<ref-qualifier>] E
3700-
void CXXNameMangler::mangleType(const FunctionProtoType *T) {
3739+
void CXXNameMangler::mangleTypeImpl(const FunctionProtoType *T) {
37013740
unsigned SMEAttrs = T->getAArch64SMEAttributes();
37023741

37033742
if (SMEAttrs)
@@ -3742,6 +3781,10 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
37423781
}
37433782

37443783
void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
3784+
return mangleTypeImpl(T);
3785+
}
3786+
3787+
void CXXNameMangler::mangleTypeImpl(const FunctionNoProtoType *T) {
37453788
// Function types without prototypes can arise when mangling a function type
37463789
// within an overloadable function in C. We mangle these as the absence of any
37473790
// parameter types (not even an empty parameter list).
@@ -7233,6 +7276,86 @@ bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C,
72337276
return TrackAbiTags.AbiTagsRoot.getUsedAbiTags().size();
72347277
}
72357278

7279+
namespace {
7280+
7281+
class RISCVZicfilpFuncSigLabelMangler : public CXXNameMangler {
7282+
bool IsTopLevelAndCXXVirtualMethod;
7283+
7284+
public:
7285+
RISCVZicfilpFuncSigLabelMangler(ItaniumMangleContextImpl &C, raw_ostream &Out,
7286+
const bool IsCXXVirtualMethod)
7287+
: CXXNameMangler(C, Out),
7288+
IsTopLevelAndCXXVirtualMethod(/*IsTopLevel=*/true &&
7289+
IsCXXVirtualMethod) {}
7290+
7291+
void mangleTypeImpl(const BuiltinType *T) override {
7292+
if (T->getKind() == BuiltinType::WChar_S ||
7293+
T->getKind() == BuiltinType::WChar_U) {
7294+
const Type *const OverrideT =
7295+
getASTContext().getWCharTypeInC().getTypePtr();
7296+
assert(isa<BuiltinType>(OverrideT) &&
7297+
"`wchar_t' in C is expected to be defined to a built-in type");
7298+
T = static_cast<const BuiltinType *>(OverrideT);
7299+
}
7300+
return CXXNameMangler::mangleTypeImpl(T);
7301+
}
7302+
7303+
// This <function-type> is the RISC-V psABI modified version
7304+
// <function-type> ::= [<CV-qualifiers>] [Dx] F <bare-function-type>
7305+
// [<ref-qualifier>] E
7306+
void mangleTypeImpl(const FunctionProtoType *T) override {
7307+
const bool WasTopLevelAndCXXVirtualMethod = IsTopLevelAndCXXVirtualMethod;
7308+
IsTopLevelAndCXXVirtualMethod = false; // Not top-level anymore
7309+
7310+
// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
7311+
// e.g. "const" in "int (A::*)() const".
7312+
mangleQualifiers(T->getMethodQuals());
7313+
7314+
getStream() << 'F';
7315+
7316+
bool MangleReturnType = true;
7317+
if (const Type &RetT = *T->getReturnType().getTypePtr();
7318+
WasTopLevelAndCXXVirtualMethod && mayBeCovariant(RetT)) {
7319+
// Possible covariant types mangle dummy cv-unqualified `class v` as its
7320+
// class type
7321+
if (RetT.isPointerType())
7322+
getStream() << "P1v";
7323+
else if (RetT.isLValueReferenceType())
7324+
getStream() << "R1v";
7325+
else {
7326+
assert(RetT.isRValueReferenceType() &&
7327+
"Expect an r-value ref for covariant return type that is not a "
7328+
"pointer or an l-value ref");
7329+
getStream() << "O1v";
7330+
}
7331+
MangleReturnType = false;
7332+
}
7333+
mangleBareFunctionType(T, MangleReturnType);
7334+
7335+
// Mangle the ref-qualifier, if present.
7336+
mangleRefQualifier(T->getRefQualifier());
7337+
7338+
getStream() << 'E';
7339+
}
7340+
7341+
void mangleTypeImpl(const FunctionNoProtoType *T) override {
7342+
return CXXNameMangler::mangleTypeImpl(toFunctionProtoType(T));
7343+
}
7344+
7345+
private:
7346+
const FunctionProtoType *
7347+
toFunctionProtoType(const FunctionNoProtoType *const T) {
7348+
FunctionProtoType::ExtProtoInfo EPI;
7349+
EPI.ExtInfo = T->getExtInfo();
7350+
const Type *const NewT = getASTContext()
7351+
.getFunctionType(T->getReturnType(), {}, EPI)
7352+
.getTypePtr();
7353+
return static_cast<const FunctionProtoType *>(NewT);
7354+
}
7355+
}; // class RISCVZicfilpFuncSigLabelMangler
7356+
7357+
} // anonymous namespace
7358+
72367359
//
72377360

72387361
/// Mangles the name of the declaration D and emits that name to the given
@@ -7571,6 +7694,17 @@ void ItaniumMangleContextImpl::mangleModuleInitializer(const Module *M,
75717694
}
75727695
}
75737696

7697+
void ItaniumMangleContextImpl::mangleForRISCVZicfilpFuncSigLabel(
7698+
const FunctionType &FT, const bool IsCXXInstanceMethod,
7699+
const bool IsCXXVirtualMethod, raw_ostream &Out) {
7700+
if (IsCXXInstanceMethod)
7701+
// member methods uses a dummy class named `v` in place of real classes
7702+
Out << "M1v";
7703+
7704+
RISCVZicfilpFuncSigLabelMangler Mangler(*this, Out, IsCXXVirtualMethod);
7705+
Mangler.mangleType(QualType(&FT, 0));
7706+
}
7707+
75747708
ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
75757709
DiagnosticsEngine &Diags,
75767710
bool IsAux) {

0 commit comments

Comments
 (0)