Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][RISCV] Emit RISCV function-signature-based CFI label in llvm::Function metadata #111661

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// (struct/union/class/enum) decl.
QualType getTagDeclType(const TagDecl *Decl) const;

/// Return the type for "void *"
QualType getVoidPtrType() const { return VoidPtrTy; }

/// Return the unique type for "size_t" (C99 7.17), defined in
/// <stddef.h>.
///
Expand Down Expand Up @@ -1903,6 +1906,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// defined in <stddef.h> as defined by the target.
QualType getWideCharType() const { return WideCharTy; }

/// Return the type of wide characters in C context, no matter whether it's C
/// or C++ being compiled.
QualType getWCharTypeInC() const;

/// Return the type of "signed wchar_t".
///
/// Used when in C++, as a GCC extension.
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/Mangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ class ItaniumMangleContext : public MangleContext {

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

virtual void mangleForRISCVZicfilpFuncSigLabel(const FunctionType &FT,
const bool IsCXXInstanceMethod,
const bool IsCXXVirtualMethod,
raw_ostream &) = 0;

// This has to live here, otherwise the CXXNameMangler won't have access to
// it.
virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6442,6 +6442,12 @@ CanQualType ASTContext::getUIntMaxType() const {
return getFromTargetType(Target->getUIntMaxType());
}

/// Return the type of wide characters in C context, no matter whether it's C
/// or C++ being compiled.
QualType ASTContext::getWCharTypeInC() const {
return getFromTargetType(Target->getWCharType());
}

/// getSignedWCharType - Return the type of "signed wchar_t".
/// Used when in C++, as a GCC extension.
QualType ASTContext::getSignedWCharType() const {
Expand Down
138 changes: 136 additions & 2 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ using namespace clang;

namespace {

static bool mayBeCovariant(const Type &Ty) {
if (auto *const PT = Ty.getAs<PointerType>())
return PT->getPointeeType()->isStructureOrClassType();
if (auto *const RT = Ty.getAs<ReferenceType>())
return RT->getPointeeType()->isStructureOrClassType();
return false;
}

static bool isLocalContainerContext(const DeclContext *DC) {
return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
}
Expand Down Expand Up @@ -136,6 +144,11 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {

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

void mangleForRISCVZicfilpFuncSigLabel(const FunctionType &,
const bool IsCXXInstanceMethod,
const bool IsCXXVirtualMethod,
raw_ostream &) override;

bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
Expand Down Expand Up @@ -395,8 +408,10 @@ class CXXNameMangler {
llvm::DenseMap<uintptr_t, unsigned> Substitutions;
llvm::DenseMap<StringRef, unsigned> ModuleSubstitutions;

protected:
ASTContext &getASTContext() const { return Context.getASTContext(); }

private:
bool isCompatibleWith(LangOptions::ClangABI Ver) {
return Context.getASTContext().getLangOpts().getClangABICompat() <= Ver;
}
Expand Down Expand Up @@ -443,6 +458,8 @@ class CXXNameMangler {
NullOut = true;
}

virtual ~CXXNameMangler() = default;

struct WithTemplateDepthOffset { unsigned Offset; };
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out,
WithTemplateDepthOffset Offset)
Expand Down Expand Up @@ -559,9 +576,12 @@ class CXXNameMangler {
StringRef Prefix = "");
void mangleOperatorName(DeclarationName Name, unsigned Arity);
void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);

protected:
void mangleQualifiers(Qualifiers Quals, const DependentAddressSpaceType *DAST = nullptr);
void mangleRefQualifier(RefQualifierKind RefQualifier);

private:
void mangleObjCMethodName(const ObjCMethodDecl *MD);

// Declare manglers for every type class.
Expand All @@ -572,11 +592,24 @@ class CXXNameMangler {

void mangleType(const TagType*);
void mangleType(TemplateName);

protected:
// Use the `Impl` scheme instead of directly virtualizing `mangleType`s since
// `mangleType`s are declared by tables
virtual void mangleTypeImpl(const BuiltinType *T);
virtual void mangleTypeImpl(const FunctionProtoType *T);
virtual void mangleTypeImpl(const FunctionNoProtoType *T);

private:
static StringRef getCallingConvQualifierName(CallingConv CC);
void mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo info);
void mangleExtFunctionInfo(const FunctionType *T);

protected:
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
const FunctionDecl *FD = nullptr);

private:
void mangleNeonVectorType(const VectorType *T);
void mangleNeonVectorType(const DependentVectorType *T);
void mangleAArch64NeonVectorType(const VectorType *T);
Expand Down Expand Up @@ -3058,7 +3091,9 @@ void CXXNameMangler::mangleCXXRecordDecl(const CXXRecordDecl *Record) {
addSubstitution(Record);
}

void CXXNameMangler::mangleType(const BuiltinType *T) {
void CXXNameMangler::mangleType(const BuiltinType *T) { mangleTypeImpl(T); }

void CXXNameMangler::mangleTypeImpl(const BuiltinType *T) {
// <type> ::= <builtin-type>
// <builtin-type> ::= v # void
// ::= w # wchar_t
Expand Down Expand Up @@ -3563,10 +3598,14 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) {
mangleVendorQualifier("noescape");
}

void CXXNameMangler::mangleType(const FunctionProtoType *T) {
return mangleTypeImpl(T);
}

// <type> ::= <function-type>
// <function-type> ::= [<CV-qualifiers>] F [Y]
// <bare-function-type> [<ref-qualifier>] E
void CXXNameMangler::mangleType(const FunctionProtoType *T) {
void CXXNameMangler::mangleTypeImpl(const FunctionProtoType *T) {
mangleExtFunctionInfo(T);

// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
Expand Down Expand Up @@ -3604,6 +3643,10 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
}

void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
return mangleTypeImpl(T);
}

void CXXNameMangler::mangleTypeImpl(const FunctionNoProtoType *T) {
// Function types without prototypes can arise when mangling a function type
// within an overloadable function in C. We mangle these as the absence of any
// parameter types (not even an empty parameter list).
Expand Down Expand Up @@ -7074,6 +7117,86 @@ bool CXXNameMangler::shouldHaveAbiTags(ItaniumMangleContextImpl &C,
return TrackAbiTags.AbiTagsRoot.getUsedAbiTags().size();
}

namespace {

class RISCVZicfilpFuncSigLabelMangler : public CXXNameMangler {
bool IsTopLevelAndCXXVirtualMethod;

public:
RISCVZicfilpFuncSigLabelMangler(ItaniumMangleContextImpl &C, raw_ostream &Out,
const bool IsCXXVirtualMethod)
: CXXNameMangler(C, Out),
IsTopLevelAndCXXVirtualMethod(/*IsTopLevel=*/true &&
IsCXXVirtualMethod) {}

void mangleTypeImpl(const BuiltinType *T) override {
if (T->getKind() == BuiltinType::WChar_S ||
T->getKind() == BuiltinType::WChar_U) {
const Type *const OverrideT =
getASTContext().getWCharTypeInC().getTypePtr();
assert(isa<BuiltinType>(OverrideT) &&
"`wchar_t' in C is expected to be defined to a built-in type");
T = static_cast<const BuiltinType *>(OverrideT);
}
return CXXNameMangler::mangleTypeImpl(T);
}

// This <function-type> is the RISC-V psABI modified version
// <function-type> ::= [<CV-qualifiers>] [Dx] F <bare-function-type>
// [<ref-qualifier>] E
void mangleTypeImpl(const FunctionProtoType *T) override {
const bool WasTopLevelAndCXXVirtualMethod = IsTopLevelAndCXXVirtualMethod;
IsTopLevelAndCXXVirtualMethod = false; // Not top-level anymore

// Mangle CV-qualifiers, if present. These are 'this' qualifiers,
// e.g. "const" in "int (A::*)() const".
mangleQualifiers(T->getMethodQuals());

getStream() << 'F';

bool MangleReturnType = true;
if (const Type &RetT = *T->getReturnType().getTypePtr();
WasTopLevelAndCXXVirtualMethod && mayBeCovariant(RetT)) {
// Possible covariant types mangle dummy cv-unqualified `class v` as its
// class type
if (RetT.isPointerType())
getStream() << "P1v";
else if (RetT.isLValueReferenceType())
getStream() << "R1v";
else {
assert(RetT.isRValueReferenceType() &&
"Expect an r-value ref for covariant return type that is not a "
"pointer or an l-value ref");
getStream() << "O1v";
}
MangleReturnType = false;
}
mangleBareFunctionType(T, MangleReturnType);

// Mangle the ref-qualifier, if present.
mangleRefQualifier(T->getRefQualifier());

getStream() << 'E';
}

void mangleTypeImpl(const FunctionNoProtoType *T) override {
return CXXNameMangler::mangleTypeImpl(toFunctionProtoType(T));
}

private:
const FunctionProtoType *
toFunctionProtoType(const FunctionNoProtoType *const T) {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = T->getExtInfo();
const Type *const NewT = getASTContext()
.getFunctionType(T->getReturnType(), {}, EPI)
.getTypePtr();
return static_cast<const FunctionProtoType *>(NewT);
}
}; // class RISCVZicfilpFuncSigLabelMangler

} // anonymous namespace

//

/// Mangles the name of the declaration D and emits that name to the given
Expand Down Expand Up @@ -7412,6 +7535,17 @@ void ItaniumMangleContextImpl::mangleModuleInitializer(const Module *M,
}
}

void ItaniumMangleContextImpl::mangleForRISCVZicfilpFuncSigLabel(
const FunctionType &FT, const bool IsCXXInstanceMethod,
const bool IsCXXVirtualMethod, raw_ostream &Out) {
if (IsCXXInstanceMethod)
// member methods uses a dummy class named `v` in place of real classes
Out << "M1v";

RISCVZicfilpFuncSigLabelMangler Mangler(*this, Out, IsCXXVirtualMethod);
Mangler.mangleType(QualType(&FT, 0));
}

ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
DiagnosticsEngine &Diags,
bool IsAux) {
Expand Down
Loading
Loading