[ARM,CDE] Generalize MVE intrinsics infrastructure to support CDE

Summary:
This patch generalizes the existing code to support CDE intrinsics
which will share some properties with existing MVE intrinsics
(some of the intrinsics will be polymorphic and accept/return values
of MVE vector types).
Specifically the patch:
* Adds new tablegen backends -gen-arm-cde-builtin-def,
  -gen-arm-cde-builtin-codegen, -gen-arm-cde-builtin-sema,
  -gen-arm-cde-builtin-aliases, -gen-arm-cde-builtin-header based on
  existing MVE backends.
* Renames the '__clang_arm_mve_alias' attribute into
  '__clang_arm_builtin_alias' (it will be used with CDE intrinsics as
  well as MVE intrinsics)
* Implements semantic checks for the coprocessor argument of the CDE
  intrinsics as well as the existing coprocessor intrinsics.
* Adds one CDE intrinsic __arm_cx1 to test the above changes

Reviewers: simon_tatham, MarkMurrayARM, ostannard, dmgreen

Reviewed By: simon_tatham

Subscribers: sdesmalen, mgorny, kristof.beyls, danielkiss, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D75850
This commit is contained in:
Mikhail Maltsev 2020-03-10 14:01:42 +00:00
parent c2dafe12dc
commit 47edf5bafb
23 changed files with 837 additions and 326 deletions

View File

@ -622,11 +622,11 @@ def Alias : Attr {
let Documentation = [Undocumented];
}
def ArmMveAlias : InheritableAttr, TargetSpecificAttr<TargetARM> {
let Spellings = [Clang<"__clang_arm_mve_alias">];
def ArmBuiltinAlias : InheritableAttr, TargetSpecificAttr<TargetARM> {
let Spellings = [Clang<"__clang_arm_builtin_alias">];
let Args = [IdentifierArgument<"BuiltinName">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [ArmMveAliasDocs];
let Documentation = [ArmBuiltinAliasDocs];
}
def Aligned : InheritableAttr {

View File

@ -4669,11 +4669,11 @@ When the Owner's lifetime ends, it will consider the Pointer to be dangling.
}];
}
def ArmMveAliasDocs : Documentation {
def ArmBuiltinAliasDocs : 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
This attribute is used in the implementation of the ACLE intrinsics.
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
@ -4684,8 +4684,8 @@ 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``,
This attribute can only be used to set up the aliases for certain Arm
intrinsic functions; it is intended for use only inside ``arm_*.h``
and is not a general mechanism for declaring arbitrary aliases for
clang builtin functions.
}];

View File

@ -202,6 +202,8 @@ BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
// aren't included from both here and BuiltinsAArch64.def.)
#include "clang/Basic/arm_mve_builtins.inc"
#include "clang/Basic/arm_cde_builtins.inc"
// MSVC
LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)

View File

@ -60,3 +60,16 @@ clang_tablegen(arm_mve_builtin_sema.inc -gen-arm-mve-builtin-sema
clang_tablegen(arm_mve_builtin_aliases.inc -gen-arm-mve-builtin-aliases
SOURCE arm_mve.td
TARGET ClangARMMveBuiltinAliases)
clang_tablegen(arm_cde_builtins.inc -gen-arm-cde-builtin-def
SOURCE arm_cde.td
TARGET ClangARMCdeBuiltinsDef)
clang_tablegen(arm_cde_builtin_cg.inc -gen-arm-cde-builtin-codegen
SOURCE arm_cde.td
TARGET ClangARMCdeBuiltinCG)
clang_tablegen(arm_cde_builtin_sema.inc -gen-arm-cde-builtin-sema
SOURCE arm_cde.td
TARGET ClangARMCdeBuiltinSema)
clang_tablegen(arm_cde_builtin_aliases.inc -gen-arm-cde-builtin-aliases
SOURCE arm_cde.td
TARGET ClangARMCdeBuiltinAliases)

View File

@ -639,6 +639,8 @@ def warn_redecl_library_builtin : Warning<
def err_builtin_definition : Error<"definition of builtin function %0">;
def err_builtin_redeclare : Error<"cannot redeclare builtin function %0">;
def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
def err_arm_invalid_coproc : Error<"coprocessor %0 must be configured as "
"%select{GCP|CDE}1">;
def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
def err_invalid_cpu_is : Error<"invalid cpu name for builtin">;
def err_invalid_cpu_specific_dispatch_value : Error<
@ -6722,8 +6724,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 err_attribute_arm_builtin_alias : Error<
"'__clang_arm_builtin_alias' attribute can only be applied to an ARM builtin">;
def err_attribute_arm_mve_polymorphism : Error<
"'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type">;

View File

@ -0,0 +1,45 @@
//===--- arm_cde.td - ACLE intrinsic functions for CDE --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the set of ACLE-specified source-level intrinsic
// functions wrapping the CDE instructions.
//
//===----------------------------------------------------------------------===//
include "arm_mve_defs.td"
class CDEIntrinsic<Type ret, dag args, dag codegen>
: Intrinsic<ret, args, codegen> {
let builtinExtension = "cde";
}
// Immediate (in range [0, 2^numBits - 1])
class IB_ConstBits<int numBits> : IB_ConstRange<0, !add(!shl(1, numBits), -1)>;
// numBits-wide immediate of type u32
class CDEImmediateBits<int numBits> : Immediate<u32, IB_ConstBits<numBits>>;
// LLVM IR CDE intrinsic
class CDEIRInt<string name, list<Type> params = [], bit appendKind = 0>
: IRIntBase<"arm_cde_" # name, params, appendKind>;
// Coprocessor immediate
def imm_coproc : Immediate<sint, IB_ConstRange<0, 7>>;
// Immediate integer parameters
def imm_3b : CDEImmediateBits<3>;
def imm_4b : CDEImmediateBits<4>;
def imm_6b : CDEImmediateBits<6>;
def imm_7b : CDEImmediateBits<7>;
def imm_9b : CDEImmediateBits<9>;
def imm_11b : CDEImmediateBits<11>;
def imm_12b : CDEImmediateBits<12>;
def imm_13b : CDEImmediateBits<13>;
let pnt = PNT_None, params = T.None in
def cx1 : CDEIntrinsic<u32, (args imm_coproc:$cp, imm_13b:$imm),
(CDEIRInt<"cx1"> $cp, $imm)>;

View File

@ -476,9 +476,16 @@ class Intrinsic<Type ret_, dag args_, dag codegen_> {
// True if the builtin has to avoid evaluating its arguments.
bit nonEvaluating = 0;
// True if the intrinsic needs only the C header part (no codegen, semantic
// checks, etc). Used for redeclaring MVE intrinsics in the arm_cde.h header.
bit headerOnly = 0;
// Use to override the suffix letter to make e.g.vfooq_p16
// with an override suffix letter of "p".
string overrideKindLetter = "";
// Name of the architecture extension, used in the Clang builtin name
string builtinExtension = "mve";
}
// Sometimes you have to use two separate Intrinsic declarations to
@ -553,6 +560,7 @@ multiclass IntrinsicMXNameOverride<Type rettype, dag arguments, dag cg,
// instead of having to repeat a long list every time.
def T {
list<Type> None = [Void];
list<Type> Signed = [s8, s16, s32];
list<Type> Unsigned = [u8, u16, u32];
list<Type> Int = Signed # Unsigned;

View File

@ -11764,6 +11764,8 @@ private:
unsigned MaxWidth);
bool CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckCDEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckARMCoprocessorImmediate(const Expr *CoprocArg, bool WantCDE);
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);

View File

@ -3148,8 +3148,8 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
unsigned BuiltinID;
if (const auto *AMAA = getAttr<ArmMveAliasAttr>()) {
BuiltinID = AMAA->getBuiltinName()->getBuiltinID();
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
} else {
if (!getIdentifier())
return 0;
@ -3181,7 +3181,7 @@ 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>() &&
!hasAttr<ArmMveAliasAttr>())
!hasAttr<ArmBuiltinAliasAttr>())
return 0;
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))

View File

@ -6538,6 +6538,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
// Deal with MVE builtins
if (Value *Result = EmitARMMVEBuiltinExpr(BuiltinID, E, ReturnValue, Arch))
return Result;
// Handle CDE builtins
if (Value *Result = EmitARMCDEBuiltinExpr(BuiltinID, E, ReturnValue, Arch))
return Result;
// Find out if any arguments are required to be integer constant
// expressions.
@ -7212,6 +7215,17 @@ Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID,
llvm_unreachable("unknown custom codegen type.");
}
Value *CodeGenFunction::EmitARMCDEBuiltinExpr(unsigned BuiltinID,
const CallExpr *E,
ReturnValueSlot ReturnValue,
llvm::Triple::ArchType Arch) {
switch (BuiltinID) {
default:
return nullptr;
#include "clang/Basic/arm_cde_builtin_cg.inc"
}
}
static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID,
const CallExpr *E,
SmallVectorImpl<Value *> &Ops,

View File

@ -3873,6 +3873,9 @@ public:
llvm::Value *EmitARMMVEBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue,
llvm::Triple::ArchType Arch);
llvm::Value *EmitARMCDEBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue,
llvm::Triple::ArchType Arch);
llvm::Value *EmitCommonNeonBuiltinExpr(unsigned BuiltinID,
unsigned LLVMIntrinsic,

View File

@ -186,6 +186,8 @@ clang_generate_header(-gen-arm-neon arm_neon.td arm_neon.h)
clang_generate_header(-gen-arm-fp16 arm_fp16.td arm_fp16.h)
# Generate arm_mve.h
clang_generate_header(-gen-arm-mve-header arm_mve.td arm_mve.h)
# Generate arm_cde.h
clang_generate_header(-gen-arm-cde-header arm_cde.td arm_cde.h)
add_custom_target(clang-resource-headers ALL DEPENDS ${out_files})
set_target_properties(clang-resource-headers PROPERTIES

View File

@ -2070,6 +2070,44 @@ bool Sema::CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
}
}
bool Sema::CheckCDEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
bool Err = false;
switch (BuiltinID) {
default:
return false;
#include "clang/Basic/arm_cde_builtin_sema.inc"
}
if (Err)
return true;
return CheckARMCoprocessorImmediate(TheCall->getArg(0), /*WantCDE*/ true);
}
bool Sema::CheckARMCoprocessorImmediate(const Expr *CoprocArg, bool WantCDE) {
if (isConstantEvaluated())
return false;
// We can't check the value of a dependent argument.
if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
return false;
llvm::APSInt CoprocNoAP;
bool IsICE = CoprocArg->isIntegerConstantExpr(CoprocNoAP, Context);
assert(IsICE && "Coprocossor immediate is not a constant expression");
int64_t CoprocNo = CoprocNoAP.getExtValue();
assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
uint32_t CDECoprocMask = Context.getTargetInfo().getARMCDECoprocMask();
bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
if (IsCDECoproc != WantCDE)
return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
<< (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
return false;
}
bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
unsigned MaxWidth) {
assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
@ -2212,6 +2250,8 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
return true;
if (CheckCDEBuiltinFunctionCall(BuiltinID, TheCall))
return true;
// For intrinsics which take an immediate value as part of the instruction,
// range check them here.
@ -2234,6 +2274,26 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case ARM::BI__builtin_arm_isb:
case ARM::BI__builtin_arm_dbg:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 15);
case ARM::BI__builtin_arm_cdp:
case ARM::BI__builtin_arm_cdp2:
case ARM::BI__builtin_arm_mcr:
case ARM::BI__builtin_arm_mcr2:
case ARM::BI__builtin_arm_mrc:
case ARM::BI__builtin_arm_mrc2:
case ARM::BI__builtin_arm_mcrr:
case ARM::BI__builtin_arm_mcrr2:
case ARM::BI__builtin_arm_mrrc:
case ARM::BI__builtin_arm_mrrc2:
case ARM::BI__builtin_arm_ldc:
case ARM::BI__builtin_arm_ldcl:
case ARM::BI__builtin_arm_ldc2:
case ARM::BI__builtin_arm_ldc2l:
case ARM::BI__builtin_arm_stc:
case ARM::BI__builtin_arm_stcl:
case ARM::BI__builtin_arm_stc2:
case ARM::BI__builtin_arm_stc2l:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 15) ||
CheckARMCoprocessorImmediate(TheCall->getArg(0), /*WantCDE*/ false);
}
}

View File

@ -4937,13 +4937,47 @@ static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
PatchableFunctionEntryAttr(S.Context, AL, Count, Offset));
}
static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) {
namespace {
struct IntrinToName {
uint32_t Id;
int32_t FullName;
int32_t ShortName;
};
} // unnamed namespace
static bool ArmBuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
ArrayRef<IntrinToName> Map,
const char *IntrinNames) {
if (AliasName.startswith("__arm_"))
AliasName = AliasName.substr(6);
#include "clang/Basic/arm_mve_builtin_aliases.inc"
const IntrinToName *It = std::lower_bound(
Map.begin(), Map.end(), BuiltinID,
[](const IntrinToName &L, unsigned Id) { return L.Id < Id; });
if (It == Map.end() || It->Id != BuiltinID)
return false;
StringRef FullName(&IntrinNames[It->FullName]);
if (AliasName == FullName)
return true;
if (It->ShortName == -1)
return false;
StringRef ShortName(&IntrinNames[It->ShortName]);
return AliasName == ShortName;
}
static void handleArmMveAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) {
#include "clang/Basic/arm_mve_builtin_aliases.inc"
// The included file defines:
// - ArrayRef<IntrinToName> Map
// - const char IntrinNames[]
return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}
static bool ArmCdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
#include "clang/Basic/arm_cde_builtin_aliases.inc"
return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}
static void handleArmBuiltinAliasAttr(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;
@ -4952,14 +4986,15 @@ static void handleArmMveAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
unsigned BuiltinID = Ident->getBuiltinID();
StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
if (!ArmMveAliasValid(BuiltinID,
cast<FunctionDecl>(D)->getIdentifier()->getName())) {
S.Diag(AL.getLoc(), diag::err_attribute_arm_mve_alias);
if (!ArmMveAliasValid(BuiltinID, AliasName) &&
!ArmCdeAliasValid(BuiltinID, AliasName)) {
S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
return;
}
D->addAttr(::new (S.Context) ArmMveAliasAttr(S.Context, AL, Ident));
D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident));
}
//===----------------------------------------------------------------------===//
@ -7441,8 +7476,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleMSAllocatorAttr(S, D, AL);
break;
case ParsedAttr::AT_ArmMveAlias:
handleArmMveAliasAttr(S, D, AL);
case ParsedAttr::AT_ArmBuiltinAlias:
handleArmBuiltinAliasAttr(S, D, AL);
break;
case ParsedAttr::AT_AcquireHandle:

View File

@ -0,0 +1,16 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi \
// RUN: -target-feature +cdecp0 -target-feature +cdecp1 \
// RUN: -mfloat-abi hard -O0 -disable-O0-optnone \
// RUN: -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
#include <arm_cde.h>
// CHECK-LABEL: @test_cx1(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.arm.cde.cx1(i32 0, i32 123)
// CHECK-NEXT: ret i32 [[TMP0]]
//
uint32_t test_cx1() {
return __arm_cx1(0, 123);
}

View File

@ -0,0 +1,8 @@
// RUN: %clang_cc1 -std=c89 -triple thumbv8.1m.main-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +mve.fp -target-feature +cdecp0 -fsyntax-only %s
// RUN: %clang_cc1 -std=c99 -triple thumbv8.1m.main-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +mve.fp -target-feature +cdecp0 -fsyntax-only %s
// RUN: %clang_cc1 -std=c11 -triple thumbv8.1m.main-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +mve.fp -target-feature +cdecp0 -fsyntax-only %s
// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +mve.fp -target-feature +cdecp0 -fsyntax-only %s
// Check that the headers don't conflict with each other
#include <arm_cde.h>
#include <arm_mve.h>

View File

@ -18,7 +18,7 @@
// CHECK-NEXT: Annotate ()
// CHECK-NEXT: AnyX86NoCfCheck (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface)
// CHECK-NEXT: ArmMveAlias (SubjectMatchRule_function)
// CHECK-NEXT: ArmBuiltinAlias (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: BPFPreserveAccessIndex (SubjectMatchRule_record)

View File

@ -0,0 +1,40 @@
// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -fallow-half-arguments-and-returns -target-feature +mve.fp -target-feature +cdecp0 -verify -fsyntax-only %s
#include <arm_cde.h>
#include <arm_acle.h>
void test_coproc_gcp_instr(int a) {
__builtin_arm_cdp(0, 2, 3, 4, 5, 6); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_cdp2(0, 2, 3, 4, 5, 6); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mcr(0, 0, a, 13, 0, 3); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mcr2(0, 0, a, 13, 0, 3); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mrc(0, 0, 13, 0, 3); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mrc2(0, 0, 13, 0, 3); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mcrr(0, 0, a, 0); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mcrr2(0, 0, a, 0); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mrrc(0, 0, 0); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_mrrc2(0, 0, 0); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_ldc(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_ldcl(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_ldc2(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_ldc2l(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_stc(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_stcl(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_stc2(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
__builtin_arm_stc2l(0, 2, &a); // expected-error {{coprocessor 0 must be configured as GCP}}
}
void test_coproc(uint32_t a) {
(void)__arm_cx1(0, 0);
__arm_cx1(a, 0); // expected-error {{argument to '__arm_cx1' must be a constant integer}}
__arm_cx1(-1, 0); // expected-error {{argument value -1 is outside the valid range [0, 7]}}
__arm_cx1(8, 0); // expected-error {{argument value 8 is outside the valid range [0, 7]}}
__arm_cx1(1, 0); // expected-error {{coprocessor 1 must be configured as CDE}}
}
void test_cx(uint32_t a) {
(void)__arm_cx1(0, 0);
__arm_cx1(a, 0); // expected-error {{argument to '__arm_cx1' must be a constant integer}}
__arm_cx1(0, a); // expected-error {{argument to '__arm_cx1' must be a constant integer}}
__arm_cx1(0, 8192); // expected-error {{argument value 8192 is outside the valid range [0, 8191]}}
}

View File

@ -1,22 +1,28 @@
// 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_builtin_alias(__builtin_arm_nop))) // expected-error {{'__clang_arm_builtin_alias' attribute can only be applied to an ARM 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_builtin_alias)) // expected-error {{'__clang_arm_builtin_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_builtin_alias())) // expected-error {{'__clang_arm_builtin_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_builtin_alias("string literal"))) // expected-error {{'__clang_arm_builtin_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_builtin_alias(1))) // expected-error {{'__clang_arm_builtin_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 __inline__ __attribute__((__clang_arm_builtin_alias(__builtin_arm_nop, 2))) // expected-error {{'__clang_arm_builtin_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}}
static __attribute__((__clang_arm_builtin_alias(__builtin_arm_nop))) // expected-error {{'__clang_arm_builtin_alias' attribute only applies to functions}}
int variable;

File diff suppressed because it is too large Load Diff

View File

@ -70,6 +70,11 @@ enum ActionType {
GenArmMveBuiltinSema,
GenArmMveBuiltinCG,
GenArmMveBuiltinAliases,
GenArmCdeHeader,
GenArmCdeBuiltinDef,
GenArmCdeBuiltinSema,
GenArmCdeBuiltinCG,
GenArmCdeBuiltinAliases,
GenAttrDocs,
GenDiagDocs,
GenOptDocs,
@ -190,6 +195,16 @@ cl::opt<ActionType> Action(
"Generate ARM MVE builtin code-generator for clang"),
clEnumValN(GenArmMveBuiltinAliases, "gen-arm-mve-builtin-aliases",
"Generate list of valid ARM MVE builtin aliases for clang"),
clEnumValN(GenArmCdeHeader, "gen-arm-cde-header",
"Generate arm_cde.h for clang"),
clEnumValN(GenArmCdeBuiltinDef, "gen-arm-cde-builtin-def",
"Generate ARM CDE builtin definitions for clang"),
clEnumValN(GenArmCdeBuiltinSema, "gen-arm-cde-builtin-sema",
"Generate ARM CDE builtin sema checks for clang"),
clEnumValN(GenArmCdeBuiltinCG, "gen-arm-cde-builtin-codegen",
"Generate ARM CDE builtin code-generator for clang"),
clEnumValN(GenArmCdeBuiltinAliases, "gen-arm-cde-builtin-aliases",
"Generate list of valid ARM CDE builtin aliases for clang"),
clEnumValN(GenAttrDocs, "gen-attr-docs",
"Generate attribute documentation"),
clEnumValN(GenDiagDocs, "gen-diag-docs",
@ -351,6 +366,21 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenArmMveBuiltinAliases:
EmitMveBuiltinAliases(Records, OS);
break;
case GenArmCdeHeader:
EmitCdeHeader(Records, OS);
break;
case GenArmCdeBuiltinDef:
EmitCdeBuiltinDef(Records, OS);
break;
case GenArmCdeBuiltinSema:
EmitCdeBuiltinSema(Records, OS);
break;
case GenArmCdeBuiltinCG:
EmitCdeBuiltinCG(Records, OS);
break;
case GenArmCdeBuiltinAliases:
EmitCdeBuiltinAliases(Records, OS);
break;
case GenAttrDocs:
EmitClangAttrDocs(Records, OS);
break;

View File

@ -97,6 +97,12 @@ void EmitMveBuiltinSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitMveBuiltinCG(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitMveBuiltinAliases(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitCdeHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitCdeBuiltinDef(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitCdeBuiltinSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitCdeBuiltinCG(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitCdeBuiltinAliases(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrDocs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangDiagDocs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangOptDocs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);

View File

@ -1243,4 +1243,11 @@ def int_arm_mve_vqmovn_predicated: Intrinsic<[llvm_anyvector_ty],
llvm_i32_ty /* unsigned output */, llvm_i32_ty /* unsigned input */,
llvm_i32_ty /* top half */, llvm_anyvector_ty /* pred */], [IntrNoMem]>;
// CDE (Custom Datapath Extension)
def int_arm_cde_cx1: Intrinsic<
[llvm_i32_ty],
[llvm_i32_ty /* coproc */, llvm_i32_ty /* imm */],
[IntrNoMem, ImmArg<0>, ImmArg<1>]>;
} // end TargetPrefix