[clang] [RISCV][clang] Support XSfmm ABI attributes (PR #206260)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 27 08:55:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Brandon Wu (4vtomat)
<details>
<summary>Changes</summary>
This patch introduces a new attribute keyword to describe the architecture state for RISC-V, currently this is used by XSfmm matrix state, detail usage is described in SiFive documentation: https://www.sifive.com/document-file/xsfmm-matrix-extensions-specification
We add five new function type attributes:
1. __riscv_in("xsfmm"): function reads from matrix state
2. __riscv_out("xsfmm"): function writes to matrix state
3. __riscv_inout("xsfmm"): function reads and writes matrix state
4. __riscv_preserves("xsfmm"): function doesn't read or write state
5. __riscv_new("xsfmm"): function initiates new matrix state
TODO: Support __xsfmm_preserves statement attribute. We should allow non user-defined functions that are xsfmm unaware and is proved to not reading or writing the state, e.g. libc, libm, etc. One of the approach is providing statement attribute, e.g. __xsfmm_preserves printf("hello\n");, to make sema checking recognize and be aware of this call.
---
Patch is 33.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/206260.diff
10 Files Affected:
- (modified) clang/include/clang/AST/TypeBase.h (+95-7)
- (modified) clang/include/clang/Basic/Attr.td (+35)
- (modified) clang/include/clang/Basic/AttrDocs.td (+67)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+9)
- (modified) clang/lib/AST/ASTContext.cpp (+4-2)
- (modified) clang/lib/AST/Type.cpp (+18)
- (modified) clang/lib/AST/TypePrinter.cpp (+5)
- (modified) clang/lib/Sema/SemaChecking.cpp (+100)
- (modified) clang/lib/Sema/SemaType.cpp (+102)
- (added) clang/test/Sema/sifive-xsfmm-func-attr.c (+142)
``````````diff
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index c9658775f0470..9654bdf34a196 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -4816,14 +4816,17 @@ class FunctionType : public Type {
LLVM_PREFERRED_TYPE(bool)
unsigned HasArmTypeAttributes : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned HasRISCVTypeAttributes : 1;
+
LLVM_PREFERRED_TYPE(bool)
unsigned EffectsHaveConditions : 1;
unsigned NumFunctionEffects : 4;
FunctionTypeExtraBitfields()
: NumExceptionType(0), HasExtraAttributeInfo(false),
- HasArmTypeAttributes(false), EffectsHaveConditions(false),
- NumFunctionEffects(0) {}
+ HasArmTypeAttributes(false), HasRISCVTypeAttributes(false),
+ EffectsHaveConditions(false), NumFunctionEffects(0) {}
};
/// A holder for extra information from attributes which aren't part of an
@@ -4869,6 +4872,46 @@ class FunctionType : public Type {
ARM_InOut = 4,
};
+ /// RISC-V type attributes for states.
+ enum RISCVTypeAttributes : uint8_t {
+ RISCVNormalFunction = 0,
+
+ // Describes the value of the xsfmm tile state using RISCVStateValue.
+ // Each tile gets 3 bits to store its state.
+ RISCVXsfmmShift = 0,
+ RISCVXsfmmMask = 0b111 << RISCVXsfmmShift,
+
+ // Currently using 3 bits for xsfmm
+ RISCVAttributeMask = 0b111
+ };
+
+ enum RISCVStateValue : unsigned {
+ RISCVNone = 0,
+ RISCVIn = 1,
+ RISCVOut = 2,
+ RISCVInOut = 3,
+ RISCVPreserves = 4,
+ RISCVNew = 5,
+ };
+
+ static const char *ToRISCVStateString(RISCVStateValue St) {
+ switch (St) {
+ case RISCVNone:
+ return "none";
+ case RISCVIn:
+ return "__riscv_in";
+ case RISCVOut:
+ return "__riscv_out";
+ case RISCVInOut:
+ return "__riscv_inout";
+ case RISCVPreserves:
+ return "__riscv_preserves";
+ case RISCVNew:
+ return "__riscv_new";
+ }
+ llvm_unreachable("Invalid RISCV state value");
+ }
+
static ArmStateValue getArmZAState(unsigned AttrBits) {
return static_cast<ArmStateValue>((AttrBits & SME_ZAMask) >> SME_ZAShift);
}
@@ -4877,6 +4920,11 @@ class FunctionType : public Type {
return static_cast<ArmStateValue>((AttrBits & SME_ZT0Mask) >> SME_ZT0Shift);
}
+ static RISCVStateValue getRISCVXsfmmState(unsigned AttrBits) {
+ return static_cast<RISCVStateValue>((AttrBits & RISCVXsfmmMask) >>
+ RISCVXsfmmShift);
+ }
+
/// A holder for Arm type attributes as described in the Arm C/C++
/// Language extensions which are not particularly common to all
/// types and therefore accounted separately from FunctionTypeBitfields.
@@ -4889,6 +4937,13 @@ class FunctionType : public Type {
FunctionTypeArmAttributes() : AArch64SMEAttributes(SME_NormalFunction) {}
};
+ struct alignas(void *) FunctionTypeRISCVAttributes {
+ LLVM_PREFERRED_TYPE(RISCVTypeAttributes)
+ unsigned RISCVAttributes : 3;
+
+ FunctionTypeRISCVAttributes() : RISCVAttributes(RISCVNormalFunction) {}
+ };
+
protected:
FunctionType(TypeClass tc, QualType res, QualType Canonical,
TypeDependence Dependence, ExtInfo Info)
@@ -5366,9 +5421,11 @@ class FunctionProtoType final
FunctionProtoType, QualType, SourceLocation,
FunctionType::FunctionTypeExtraBitfields,
FunctionType::FunctionTypeExtraAttributeInfo,
- FunctionType::FunctionTypeArmAttributes, FunctionType::ExceptionType,
- Expr *, FunctionDecl *, FunctionType::ExtParameterInfo, Qualifiers,
- FunctionEffect, EffectConditionExpr> {
+ FunctionType::FunctionTypeArmAttributes,
+ FunctionType::FunctionTypeRISCVAttributes,
+ FunctionType::ExceptionType, Expr *, FunctionDecl *,
+ FunctionType::ExtParameterInfo, Qualifiers, FunctionEffect,
+ EffectConditionExpr> {
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;
@@ -5471,14 +5528,18 @@ class FunctionProtoType final
unsigned CFIUncheckedCallee : 1;
LLVM_PREFERRED_TYPE(AArch64SMETypeAttributes)
unsigned AArch64SMEAttributes : 9;
+ LLVM_PREFERRED_TYPE(RISCVTypeAttributes)
+ unsigned RISCVAttributes : 3;
ExtProtoInfo()
: Variadic(false), HasTrailingReturn(false), CFIUncheckedCallee(false),
- AArch64SMEAttributes(SME_NormalFunction) {}
+ AArch64SMEAttributes(SME_NormalFunction),
+ RISCVAttributes(RISCVNormalFunction) {}
ExtProtoInfo(CallingConv CC)
: ExtInfo(CC), Variadic(false), HasTrailingReturn(false),
- CFIUncheckedCallee(false), AArch64SMEAttributes(SME_NormalFunction) {}
+ CFIUncheckedCallee(false), AArch64SMEAttributes(SME_NormalFunction),
+ RISCVAttributes(RISCVNormalFunction) {}
ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &ESI) {
ExtProtoInfo Result(*this);
@@ -5495,6 +5556,7 @@ class FunctionProtoType final
bool requiresFunctionProtoTypeExtraBitfields() const {
return ExceptionSpec.Type == EST_Dynamic ||
requiresFunctionProtoTypeArmAttributes() ||
+ requiresFunctionProtoTypeRISCVAttributes() ||
requiresFunctionProtoTypeExtraAttributeInfo() ||
!FunctionEffects.empty();
}
@@ -5513,6 +5575,14 @@ class FunctionProtoType final
else
AArch64SMEAttributes &= ~Kind;
}
+
+ bool requiresFunctionProtoTypeRISCVAttributes() const {
+ return RISCVAttributes != RISCVNormalFunction;
+ }
+
+ void setRISCVAttribute(RISCVTypeAttributes Kind) {
+ RISCVAttributes |= Kind;
+ }
};
private:
@@ -5528,6 +5598,11 @@ class FunctionProtoType final
return hasArmTypeAttributes();
}
+ unsigned
+ numTrailingObjects(OverloadToken<FunctionTypeRISCVAttributes>) const {
+ return hasRISCVTypeAttributes();
+ }
+
unsigned numTrailingObjects(OverloadToken<FunctionTypeExtraBitfields>) const {
return hasExtraBitfields();
}
@@ -5641,6 +5716,12 @@ class FunctionProtoType final
->HasArmTypeAttributes;
}
+ bool hasRISCVTypeAttributes() const {
+ return FunctionTypeBits.HasExtraBitfields &&
+ getTrailingObjects<FunctionTypeExtraBitfields>()
+ ->HasRISCVTypeAttributes;
+ }
+
bool hasExtQualifiers() const {
return FunctionTypeBits.HasExtQuals;
}
@@ -5670,6 +5751,7 @@ class FunctionProtoType final
EPI.ExtParameterInfos = getExtParameterInfosOrNull();
EPI.ExtraAttributeInfo = getExtraAttributeInfo();
EPI.AArch64SMEAttributes = getAArch64SMEAttributes();
+ EPI.RISCVAttributes = getRISCVAttributes();
EPI.FunctionEffects = getFunctionEffects();
return EPI;
}
@@ -5872,6 +5954,12 @@ class FunctionProtoType final
->AArch64SMEAttributes;
}
+ unsigned getRISCVAttributes() const {
+ if (!hasRISCVTypeAttributes())
+ return RISCVNormalFunction;
+ return getTrailingObjects<FunctionTypeRISCVAttributes>()->RISCVAttributes;
+ }
+
ExtParameterInfo getExtParameterInfo(unsigned I) const {
assert(I < getNumParams() && "parameter index out of range");
if (hasExtParameterInfos())
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index a222092cd42cf..9e78094640b33 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3583,6 +3583,41 @@ def RISCVVLSCC: DeclOrTypeAttr, TargetSpecificAttr<TargetRISCV> {
let Documentation = [RISCVVLSCCDocs];
}
+def RISCVIn : TypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [RegularKeyword<"__riscv_in">];
+ let Args = [VariadicStringArgument<"InArgs">];
+ let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
+ let Documentation = [RISCVInDocs];
+}
+
+def RISCVOut : TypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [RegularKeyword<"__riscv_out">];
+ let Args = [VariadicStringArgument<"OutArgs">];
+ let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
+ let Documentation = [RISCVOutDocs];
+}
+
+def RISCVInOut : TypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [RegularKeyword<"__riscv_inout">];
+ let Args = [VariadicStringArgument<"InOutArgs">];
+ let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
+ let Documentation = [RISCVInOutDocs];
+}
+
+def RISCVPreserves : TypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [RegularKeyword<"__riscv_preserves">];
+ let Args = [VariadicStringArgument<"PreserveArgs">];
+ let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
+ let Documentation = [RISCVPreservesDocs];
+}
+
+def RISCVNew : TypeAttr, TargetSpecificAttr<TargetRISCV> {
+ let Spellings = [RegularKeyword<"__riscv_new">];
+ let Args = [VariadicStringArgument<"NewArgs">];
+ let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
+ let Documentation = [RISCVNewDocs];
+}
+
def Target : InheritableAttr {
let Spellings = [GCC<"target">];
let Args = [StringArgument<"featuresStr">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 04362de2d5be2..c86891c3c5cea 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6787,6 +6787,73 @@ the ABI. This variant aims to pass fixed-length vectors via vector registers,
if possible, rather than through general-purpose registers.}];
}
+def RISCVInDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "__riscv_in";
+ let Content = [{
+The ``__riscv_in(S)`` attribute indicates that a function reads from state S.
+This attribute is usually used in RISC-V matrix extensions to specify that the
+function will read from a matrix state passed as arguments.
+This helps compiler checks to prevent common programming errors that could lead
+to undefined behavior, data corruption, or incorrect computation results when
+working with matrix operations.
+ }];
+}
+
+def RISCVOutDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "__riscv_out";
+ let Content = [{
+The ``__riscv_out(S)`` attribute indicates that a function writes to state S.
+This attribute is usually used in RISC-V matrix extensions to specify that the
+function will write to a matrix state passed as arguments.
+This helps compiler checks to prevent common programming errors that could lead
+to undefined behavior, data corruption, or incorrect computation results when
+working with matrix operations.
+ }];
+}
+
+def RISCVInOutDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "__riscv_inout";
+ let Content = [{
+The ``__riscv_inout(S)`` attribute indicates that a function reads from and
+writes to state S.
+This attribute is usually used in RISC-V matrix extensions to specify that the
+function will read from and write to a matrix state passed as arguments.
+This helps compiler checks to prevent common programming errors that could lead
+to undefined behavior, data corruption, or incorrect computation results when
+working with matrix operations.
+ }];
+}
+
+def RISCVPreservesDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "__riscv_preserves";
+ let Content = [{
+The ``__riscv_preserves(S)`` attribute indicates that a function neither reads
+from nor writes to state S.
+This attribute is usually used in RISC-V matrix extensions to specify that the
+function will not read from or write to a matrix state passed as arguments.
+This helps compiler checks to prevent common programming errors that could lead
+to undefined behavior, data corruption, or incorrect computation results when
+working with matrix operations.
+ }];
+}
+
+def RISCVNewDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "__riscv_new";
+ let Content = [{
+The ``__riscv_new(S)`` attribute indicates that a function initiates a new state.
+This attribute is usually used in RISC-V matrix extensions to specify that the
+function will initiate a new matrix state passed as arguments.
+This helps compiler checks to prevent common programming errors that could lead
+to undefined behavior, data corruption, or incorrect computation results when
+working with matrix operations.
+ }];
+}
+
def PreferredNameDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f7fba8df1e4d7..42a55dcdf0128 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13619,6 +13619,15 @@ def err_riscv_attribute_interrupt_requires_extension : Error<
def err_riscv_attribute_interrupt_invalid_combination : Error<
"RISC-V 'interrupt' attribute contains invalid combination of interrupt types">;
def err_riscv_builtin_invalid_twiden : Error<"RISC-V XSfmm twiden must be 1, 2 or 4">;
+// RISC-V errors
+def err_riscv_call_invalid_features : Error<
+ "call to an attributed function requires %0">;
+def err_missing_riscv_state : Error<"missing state for %0">;
+def err_unknown_riscv_state : Error<"unknown state '%0'">;
+def err_conflicting_attributes_riscv_state : Error<
+ "conflicting attribute. Description: %0">;
+def err_mutually_exclusive_attributes_riscv_state : Error<
+ "mutually exclusive attributes for state '%0'">;
def err_std_source_location_impl_not_found : Error<
"'std::source_location::__impl' was not found; it must be defined before '__builtin_source_location' is called">;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index abf0cd5e18c2b..c02b43c947072 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5161,12 +5161,14 @@ QualType ASTContext::getFunctionTypeInternal(
size_t Size = FunctionProtoType::totalSizeToAlloc<
QualType, SourceLocation, FunctionType::FunctionTypeExtraBitfields,
FunctionType::FunctionTypeExtraAttributeInfo,
- FunctionType::FunctionTypeArmAttributes, FunctionType::ExceptionType,
+ FunctionType::FunctionTypeArmAttributes,
+ FunctionType::FunctionTypeRISCVAttributes, FunctionType::ExceptionType,
Expr *, FunctionDecl *, FunctionProtoType::ExtParameterInfo, Qualifiers,
FunctionEffect, EffectConditionExpr>(
NumArgs, EPI.Variadic, EPI.requiresFunctionProtoTypeExtraBitfields(),
EPI.requiresFunctionProtoTypeExtraAttributeInfo(),
- EPI.requiresFunctionProtoTypeArmAttributes(), ESH.NumExceptionType,
+ EPI.requiresFunctionProtoTypeArmAttributes(),
+ EPI.requiresFunctionProtoTypeRISCVAttributes(), ESH.NumExceptionType,
ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
EPI.ExtParameterInfos ? NumArgs : 0,
EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0, EPI.FunctionEffects.size(),
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index b7bef40ca89f3..f704f748f7055 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -3819,6 +3819,15 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
ExtraBits.HasArmTypeAttributes = true;
}
+ if (epi.requiresFunctionProtoTypeRISCVAttributes()) {
+ auto &RISCVTypeAttrs = *getTrailingObjects<FunctionTypeRISCVAttributes>();
+ RISCVTypeAttrs = FunctionTypeRISCVAttributes();
+
+ // Also set the bit in FunctionTypeExtraBitfields
+ auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>();
+ ExtraBits.HasRISCVTypeAttributes = true;
+ }
+
// Fill in the trailing argument array.
auto *argSlot = getTrailingObjects<QualType>();
for (unsigned i = 0; i != getNumParams(); ++i) {
@@ -3835,6 +3844,14 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
ArmTypeAttrs.AArch64SMEAttributes = epi.AArch64SMEAttributes;
}
+ // Propagate the RISC-V state attributes.
+ if (epi.RISCVAttributes != RISCVNormalFunction) {
+ auto &RISCVTypeAttrs = *getTrailingObjects<FunctionTypeRISCVAttributes>();
+ assert(epi.RISCVAttributes <= RISCVAttributeMask &&
+ "Not enough bits to encode RISC-V attributes");
+ RISCVTypeAttrs.RISCVAttributes = epi.RISCVAttributes;
+ }
+
// Fill in the exception type array if present.
if (getExceptionSpecType() == EST_Dynamic) {
auto &ExtraBits = *getTrailingObjects<FunctionTypeExtraBitfields>();
@@ -4071,6 +4088,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
ID.AddInteger((EffectCount << 3) | (HasConds << 2) |
(epi.AArch64SMEAttributes << 1) | epi.HasTrailingReturn);
ID.AddInteger(epi.CFIUncheckedCallee);
+ ID.AddInteger(epi.RISCVAttributes);
for (unsigned Idx = 0; Idx != EffectCount; ++Idx) {
ID.AddInteger(epi.FunctionEffects.Effects[Idx].toOpaqueInt32());
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index e8fbffb9f954d..04d990d028694 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2060,6 +2060,11 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case attr::ArmOut:
case attr::ArmInOut:
case attr::ArmPreserves:
+ case attr::RISCVIn:
+ case attr::RISCVOut:
+ case attr::RISCVInOut:
+ case attr::RISCVPreserves:
+ case attr::RISCVNew:
case attr::NonBlocking:
case attr::NonAllocating:
case attr::Blocking:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ec4a9037f5c23..13a15f4bb0b83 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4536,6 +4536,106 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
Diag(Loc, diag::note_sme_use_preserves_za);
}
}
+
+ // Check if there's any conflicting call for every state, it should not be
+ // any conflict if caller and callee are in different state.
+
+ if (CallerFD &&
+ (!FD || !FD->getBuiltinID() ||
+ Context.BuiltinInfo.isLibFunction(FD->getBuiltinID()) ||
+ Context.BuiltinInfo.isPredefinedLibFunction(FD->getBuiltinID()))) {
+ QualType CallerType = CallerFD->getType();
+ if (!CallerType.isNull()) {
+ if (const auto *FPT = CallerType->getAs<FunctionProtoType>()) {
+ FunctionProtoType::ExtProtoInfo CallerExtInfo =
+ FPT->getExtProtoInfo();
+ llvm::StringMap<bool> CallerFeatureMap;
+ if (CallerExtInfo.RISCVAttributes & FunctionType::RISCVAttributeMask)
+ Context.getFunctionFeatureMap(CallerFeatureMap, CallerFD);
+ // tuple(CallerAttr, CalleeAttr, required feature)
+ const std::tuple<FunctionType::RISCVStateValue,
+ FunctionType::RISCVStateValue, StringRef>
+ RISCVStateInfo[] = {
+ {FunctionType::getRISCVXsfmmState(
+ CallerExtInfo.RISCVAttributes),
+ FunctionType::getRISCVXsfmmState(ExtInfo.RISCVAttributes),
+ "xsfmmbase"}};
+ for (auto [CallerAttr, CalleeAttr, RequiredFeature] :
+ RISCVStateInfo) {
+ // If both caller and callee are not attributed, then we're fine.
+ if (CallerAttr == FunctionType::RISCVNone &&
+ CalleeAttr == FunctionType::RISCVNone)
+ continue;
+
+ if (!Context.getTargetInfo().hasFeature(RequiredFeature) &&
+ !CallerFeatureMap.lookup(RequiredFeature)) {
+ // check if corresponding attributes are enabled.
+ Diag(Loc, diag::err_riscv_call_invalid_features)
+ << RequiredFeature;
+ continue;
+ }
+
+ switch (CallerAttr) {
+ case FunctionType::RISCVNone:
+ if (CalleeAttr != FunctionType::RISCVNew) {
+ // Check limitation:
+ // 1. Only __riscv_new function can be called in non-attributed
+ // function.
+ Diag(Loc, diag::err_conflicting_attributes_riscv_state)
+ << "Only __riscv_new function can be called in "
+ "non-attributed function.";
+ }
+ break;
+ case FunctionType::RISCVIn:
+ if (CalleeAttr != FunctionType::RISCVIn &&
+ CalleeAttr != FunctionType::RISCVPreserves) {
+ // 2. Function with __riscv_in can only call __ris...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/206260
More information about the cfe-commits
mailing list