summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Attr.td7
-rw-r--r--clang/include/clang/Basic/AttrDocs.td22
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/AST/Decl.cpp16
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp29
-rw-r--r--clang/test/Misc/pragma-attribute-supported-attributes-list.test1
-rw-r--r--clang/test/Sema/arm-mve-alias-attribute.c22
7 files changed, 95 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index c3a2ee325df..4557a614d36 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -594,6 +594,13 @@ def Alias : Attr {
let Documentation = [Undocumented];
}
+def ArmMveAlias : InheritableAttr, TargetSpecificAttr<TargetARM> {
+ let Spellings = [Clang<"__clang_arm_mve_alias">];
+ let Args = [IdentifierArgument<"BuiltinName">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [ArmMveAliasDocs];
+}
+
def Aligned : InheritableAttr {
let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">,
Keyword<"_Alignas">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 114a9856c5f..6e79d0bb363 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -4391,3 +4391,25 @@ When the Owner's lifetime ends, it will consider the Pointer to be dangling.
}];
}
+
+def ArmMveAliasDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+This attribute is used in the implementation of the ACLE intrinsics
+for the Arm MVE instruction set. It allows the intrinsic functions to
+be declared using the names defined in ACLE, and still be recognized
+as clang builtins equivalent to the underlying name. For example,
+``arm_mve.h`` declares the function ``vaddq_u32`` with
+``__attribute__((__clang_arm_mve_alias(__builtin_arm_mve_vaddq_u32)))``,
+and similarly, one of the type-overloaded declarations of ``vaddq``
+will have the same attribute. This ensures that both functions are
+recognized as that clang builtin, and in the latter case, the choice
+of which builtin to identify the function as can be deferred until
+after overload resolution.
+
+This attribute can only be used to set up the aliases for the MVE
+intrinsic functions; it is intended for use only inside ``arm_mve.h``,
+and is not a general mechanism for declaring arbitrary aliases for
+clang builtin functions.
+ }];
+}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f7b98bb9ea8..0b669324589 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6430,6 +6430,8 @@ def warn_objc_unsafe_perform_selector : Warning<
InGroup<DiagGroup<"objc-unsafe-perform-selector">>;
def note_objc_unsafe_perform_selector_method_declared_here : Note<
"method %0 that returns %1 declared here">;
+def err_attribute_arm_mve_alias : Error<
+ "'__clang_arm_mve_alias' attribute can only be applied to an ARM MVE builtin">;
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index dae4af8bb24..66446626c2e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3115,10 +3115,17 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
/// functions as their wrapped builtins. This shouldn't be done in general, but
/// it's useful in Sema to diagnose calls to wrappers based on their semantics.
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
- if (!getIdentifier())
- return 0;
+ unsigned BuiltinID;
+
+ if (const auto *AMAA = getAttr<ArmMveAliasAttr>()) {
+ BuiltinID = AMAA->getBuiltinName()->getBuiltinID();
+ } else {
+ if (!getIdentifier())
+ return 0;
+
+ BuiltinID = getIdentifier()->getBuiltinID();
+ }
- unsigned BuiltinID = getIdentifier()->getBuiltinID();
if (!BuiltinID)
return 0;
@@ -3142,7 +3149,8 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
// If the function is marked "overloadable", it has a different mangled name
// and is not the C library function.
- if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>())
+ if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
+ !hasAttr<ArmMveAliasAttr>())
return 0;
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b2be6245a81..cebb1c642b9 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
@@ -4830,6 +4831,30 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex()));
}
+static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) {
+ // FIXME: this will be filled in by Tablegen which isn't written yet
+ return false;
+}
+
+static void handleArmMveAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL << 1 << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
+ unsigned BuiltinID = Ident->getBuiltinID();
+
+ if (!ArmMveAliasValid(BuiltinID,
+ cast<FunctionDecl>(D)->getIdentifier()->getName())) {
+ S.Diag(AL.getLoc(), diag::err_attribute_arm_mve_alias);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) ArmMveAliasAttr(S.Context, AL, Ident));
+}
+
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
@@ -7160,6 +7185,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_MSAllocator:
handleMSAllocatorAttr(S, D, AL);
break;
+
+ case ParsedAttr::AT_ArmMveAlias:
+ handleArmMveAliasAttr(S, D, AL);
+ break;
}
}
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 311ba1a857b..25802bd73c5 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -17,6 +17,7 @@
// CHECK-NEXT: Annotate ()
// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface)
+// CHECK-NEXT: ArmMveAlias (SubjectMatchRule_function)
// CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
// CHECK-NEXT: CFAuditedTransfer (SubjectMatchRule_function)
diff --git a/clang/test/Sema/arm-mve-alias-attribute.c b/clang/test/Sema/arm-mve-alias-attribute.c
new file mode 100644
index 00000000000..c2f526df490
--- /dev/null
+++ b/clang/test/Sema/arm-mve-alias-attribute.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple armv8.1m.main-arm-none-eabi -verify -fsyntax-only %s
+
+static __inline__ __attribute__((__clang_arm_mve_alias(__builtin_arm_nop))) // expected-error {{'__clang_arm_mve_alias' attribute can only be applied to an ARM MVE builtin}}
+void nop(void);
+
+static __inline__ __attribute__((__clang_arm_mve_alias)) // expected-error {{'__clang_arm_mve_alias' attribute takes one argument}}
+void noparens(void);
+
+static __inline__ __attribute__((__clang_arm_mve_alias())) // expected-error {{'__clang_arm_mve_alias' attribute takes one argument}}
+void emptyparens(void);
+
+static __inline__ __attribute__((__clang_arm_mve_alias("string literal"))) // expected-error {{'__clang_arm_mve_alias' attribute requires parameter 1 to be an identifier}}
+void stringliteral(void);
+
+static __inline__ __attribute__((__clang_arm_mve_alias(1))) // expected-error {{'__clang_arm_mve_alias' attribute requires parameter 1 to be an identifier}}
+void integer(void);
+
+static __inline__ __attribute__((__clang_arm_mve_alias(__builtin_arm_nop, 2))) // expected-error {{'__clang_arm_mve_alias' attribute takes one argument}}
+void twoargs(void);
+
+static __attribute__((__clang_arm_mve_alias(__builtin_arm_nop))) // expected-error {{'__clang_arm_mve_alias' attribute only applies to functions}}
+int variable;
OpenPOWER on IntegriCloud