forked from OSchip/llvm-project
[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:
parent
c2dafe12dc
commit
47edf5bafb
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
}];
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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">;
|
||||
|
||||
|
|
|
@ -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)>;
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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>
|
|
@ -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)
|
||||
|
|
|
@ -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]}}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue