Merge llvm-project main llvmorg-18-init-18359-g93248729cfae

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvm-project main llvmorg-18-init-18359-g93248729cfae, the
last commit before the upstream release/18.x branch was created.

PR:		276104
MFC after:	1 month

(cherry picked from commit 7a6dacaca1)
This commit is contained in:
Dimitry Andric 2024-01-24 20:17:23 +01:00
parent 412542983a
commit ab50317e96
1204 changed files with 53598 additions and 35958 deletions

View File

@ -4,6 +4,7 @@
.clang-format
.clang-tidy
.git-blame-ignore-revs
.gitattributes
.github/
.gitignore
.mailmap
@ -266,7 +267,6 @@ libcxx/include/__config_site.in
libcxx/include/__support/
libcxx/lib/
libcxx/modules/CMakeLists.txt
libcxx/modules/CMakeLists.txt.in
libcxx/modules/README.md
libcxx/src/CMakeLists.txt
libcxx/src/support/win32/
@ -549,7 +549,8 @@ llvm/lib/CodeGen/MIRParser/CMakeLists.txt
llvm/lib/CodeGen/README.txt
llvm/lib/CodeGen/SelectionDAG/CMakeLists.txt
llvm/lib/DWARFLinker/CMakeLists.txt
llvm/lib/DWARFLinkerParallel/CMakeLists.txt
llvm/lib/DWARFLinker/Classic/CMakeLists.txt
llvm/lib/DWARFLinker/Parallel/CMakeLists.txt
llvm/lib/DWP/CMakeLists.txt
llvm/lib/DebugInfo/BTF/CMakeLists.txt
llvm/lib/DebugInfo/CMakeLists.txt
@ -751,6 +752,7 @@ llvm/lib/TargetParser/CMakeLists.txt
llvm/lib/Testing/Annotations/CMakeLists.txt
llvm/lib/Testing/CMakeLists.txt
llvm/lib/Testing/Support/CMakeLists.txt
llvm/lib/TextAPI/BinaryReader/CMakeLists.txt
llvm/lib/TextAPI/CMakeLists.txt
llvm/lib/ToolDrivers/CMakeLists.txt
llvm/lib/ToolDrivers/llvm-dlltool/CMakeLists.txt
@ -936,6 +938,7 @@ llvm/utils/llvm-native-gxx
llvm/utils/llvm-original-di-preservation.py
llvm/utils/llvm.grm
llvm/utils/merge-stats.py
llvm/utils/mlgo-utils/
llvm/utils/not/
llvm/utils/pipeline.py
llvm/utils/prepare-code-coverage-artifact.py

View File

@ -0,0 +1,71 @@
//===--- APNumericStorage.h - Store APInt/APFloat in ASTContext -*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_APNUMERICSTORAGE_H
#define LLVM_CLANG_AST_APNUMERICSTORAGE_H
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
namespace clang {
class ASTContext;
/// Used by IntegerLiteral/FloatingLiteral/EnumConstantDecl to store the
/// numeric without leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
/// the APFloat/APInt values will never get freed. APNumericStorage uses
/// ASTContext's allocator for memory allocation.
class APNumericStorage {
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
unsigned BitWidth;
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
APNumericStorage(const APNumericStorage &) = delete;
void operator=(const APNumericStorage &) = delete;
protected:
APNumericStorage() : VAL(0), BitWidth(0) {}
llvm::APInt getIntValue() const {
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
if (NumWords > 1)
return llvm::APInt(BitWidth, NumWords, pVal);
else
return llvm::APInt(BitWidth, VAL);
}
void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};
class APIntStorage : private APNumericStorage {
public:
llvm::APInt getValue() const { return getIntValue(); }
void setValue(const ASTContext &C, const llvm::APInt &Val) {
setIntValue(C, Val);
}
};
class APFloatStorage : private APNumericStorage {
public:
llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
return llvm::APFloat(Semantics, getIntValue());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
}
};
} // end namespace clang
#endif // LLVM_CLANG_AST_APNUMERICSTORAGE_H

View File

@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_DECL_H
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/APNumericStorage.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/DeclAccessPair.h"
@ -2293,8 +2294,8 @@ public:
/// Whether this virtual function is pure, i.e. makes the containing class
/// abstract.
bool isPure() const { return FunctionDeclBits.IsPure; }
void setPure(bool P = true);
bool isPureVirtual() const { return FunctionDeclBits.IsPureVirtual; }
void setIsPureVirtual(bool P = true);
/// Whether this templated function will be late parsed.
bool isLateTemplateParsed() const {
@ -3251,15 +3252,16 @@ public:
/// that is defined. For example, in "enum X {a,b}", each of a/b are
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
/// TagType for the X EnumDecl.
class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> {
class EnumConstantDecl : public ValueDecl,
public Mergeable<EnumConstantDecl>,
public APIntStorage {
Stmt *Init; // an integer constant expression
llvm::APSInt Val; // The value.
bool IsUnsigned;
protected:
EnumConstantDecl(DeclContext *DC, SourceLocation L,
EnumConstantDecl(const ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, Expr *E,
const llvm::APSInt &V)
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
const llvm::APSInt &V);
public:
friend class StmtIteratorBase;
@ -3272,10 +3274,15 @@ public:
const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; }
llvm::APSInt getInitVal() const {
return llvm::APSInt(getValue(), IsUnsigned);
}
void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
void setInitVal(const ASTContext &C, const llvm::APSInt &V) {
setValue(C, V);
IsUnsigned = V.isUnsigned();
}
SourceRange getSourceRange() const override LLVM_READONLY;

View File

@ -548,17 +548,18 @@ public:
return hasAttrs() ? getAttrs().end() : nullptr;
}
template <typename T>
void dropAttr() {
template <typename... Ts> void dropAttrs() {
if (!HasAttrs) return;
AttrVec &Vec = getAttrs();
llvm::erase_if(Vec, [](Attr *A) { return isa<T>(A); });
llvm::erase_if(Vec, [](Attr *A) { return isa<Ts...>(A); });
if (Vec.empty())
HasAttrs = false;
}
template <typename T> void dropAttr() { dropAttrs<T>(); }
template <typename T>
llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const {
return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>());
@ -1707,7 +1708,7 @@ class DeclContext {
LLVM_PREFERRED_TYPE(bool)
uint64_t IsVirtualAsWritten : 1;
LLVM_PREFERRED_TYPE(bool)
uint64_t IsPure : 1;
uint64_t IsPureVirtual : 1;
LLVM_PREFERRED_TYPE(bool)
uint64_t HasInheritedPrototype : 1;
LLVM_PREFERRED_TYPE(bool)

View File

@ -266,7 +266,7 @@ class CXXRecordDecl : public RecordDecl {
friend class LambdaExpr;
friend class ODRDiagsEmitter;
friend void FunctionDecl::setPure(bool);
friend void FunctionDecl::setIsPureVirtual(bool);
friend void TagDecl::startDefinition();
/// Values used in DefinitionData fields to represent special members.
@ -1439,31 +1439,20 @@ public:
/// Determine whether this class is a literal type.
///
/// C++11 [basic.types]p10:
/// C++20 [basic.types]p10:
/// A class type that has all the following properties:
/// - it has a trivial destructor
/// - every constructor call and full-expression in the
/// brace-or-equal-intializers for non-static data members (if any) is
/// a constant expression.
/// - it is an aggregate type or has at least one constexpr constructor
/// or constructor template that is not a copy or move constructor, and
/// - all of its non-static data members and base classes are of literal
/// types
///
/// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
/// treating types with trivial default constructors as literal types.
///
/// Only in C++17 and beyond, are lambdas literal types.
bool isLiteral() const {
const LangOptions &LangOpts = getLangOpts();
return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
: hasTrivialDestructor()) &&
(!isLambda() || LangOpts.CPlusPlus17) &&
!hasNonLiteralTypeFieldsOrBases() &&
(isAggregate() || isLambda() ||
hasConstexprNonCopyMoveConstructor() ||
hasTrivialDefaultConstructor());
}
/// - it has a constexpr destructor
/// - all of its non-static non-variant data members and base classes
/// are of non-volatile literal types, and it:
/// - is a closure type
/// - is an aggregate union type that has either no variant members
/// or at least one variant member of non-volatile literal type
/// - is a non-union aggregate type for which each of its anonymous
/// union members satisfies the above requirements for an aggregate
/// union type, or
/// - has at least one constexpr constructor or constructor template
/// that is not a copy or move constructor.
bool isLiteral() const;
/// Determine whether this is a structural type.
bool isStructural() const {
@ -2121,7 +2110,7 @@ public:
// Member function is virtual if it is marked explicitly so, or if it is
// declared in __interface -- then it is automatically pure virtual.
if (CD->isVirtualAsWritten() || CD->isPure())
if (CD->isVirtualAsWritten() || CD->isPureVirtual())
return true;
return CD->size_overridden_methods() != 0;

View File

@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_EXPR_H
#define LLVM_CLANG_AST_EXPR_H
#include "clang/AST/APNumericStorage.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/ComputeDependence.h"
@ -1135,7 +1136,6 @@ public:
return ConstantExprBits.APValueKind != APValue::None;
}
APValue getAPValueResult() const;
APValue &getResultAsAPValue() const { return APValueResult(); }
llvm::APSInt getResultAsAPSInt() const;
// Iterators
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
@ -1479,57 +1479,6 @@ public:
}
};
/// Used by IntegerLiteral/FloatingLiteral to store the numeric without
/// leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
/// the APFloat/APInt values will never get freed. APNumericStorage uses
/// ASTContext's allocator for memory allocation.
class APNumericStorage {
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
unsigned BitWidth;
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
APNumericStorage(const APNumericStorage &) = delete;
void operator=(const APNumericStorage &) = delete;
protected:
APNumericStorage() : VAL(0), BitWidth(0) { }
llvm::APInt getIntValue() const {
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
if (NumWords > 1)
return llvm::APInt(BitWidth, NumWords, pVal);
else
return llvm::APInt(BitWidth, VAL);
}
void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};
class APIntStorage : private APNumericStorage {
public:
llvm::APInt getValue() const { return getIntValue(); }
void setValue(const ASTContext &C, const llvm::APInt &Val) {
setIntValue(C, Val);
}
};
class APFloatStorage : private APNumericStorage {
public:
llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
return llvm::APFloat(Semantics, getIntValue());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
}
};
class IntegerLiteral : public Expr, public APIntStorage {
SourceLocation Loc;
@ -4806,6 +4755,17 @@ public:
return T->getStmtClass() == SourceLocExprClass;
}
static bool MayBeDependent(SourceLocIdentKind Kind) {
switch (Kind) {
case SourceLocIdentKind::Function:
case SourceLocIdentKind::FuncSig:
case SourceLocIdentKind::SourceLocStruct:
return true;
default:
return false;
}
}
private:
friend class ASTStmtReader;
};

View File

@ -2210,14 +2210,11 @@ enum class CXXNewInitializationStyle {
/// New-expression has no initializer as written.
None,
/// New-expression has no written initializer, but has an implicit one.
Implicit,
/// New-expression has a C++98 paren-delimited initializer.
Call,
Parens,
/// New-expression has a C++11 list-initializer.
List
Braces
};
/// Represents a new-expression for memory allocation and constructor
@ -2388,17 +2385,7 @@ public:
bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; }
/// Whether this new-expression has any initializer at all.
bool hasInitializer() const {
switch (getInitializationStyle()) {
case CXXNewInitializationStyle::None:
return false;
case CXXNewInitializationStyle::Implicit:
case CXXNewInitializationStyle::Call:
case CXXNewInitializationStyle::List:
return true;
}
llvm_unreachable("Unknown initializer");
}
bool hasInitializer() const { return CXXNewExprBits.HasInitializer; }
/// The kind of initializer this new-expression has.
CXXNewInitializationStyle getInitializationStyle() const {

View File

@ -25,6 +25,7 @@
namespace clang {
class APValue;
class Decl;
class IdentifierInfo;
class NestedNameSpecifier;
@ -101,6 +102,8 @@ public:
// Save booleans until the end to lower the size of data to process.
void AddBoolean(bool value);
void AddStructuralValue(const APValue &);
static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent);
private:

View File

@ -808,6 +808,20 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
return TemplateArgument(ctx, value, type, isDefaulted);
}]>;
}
let Class = PropertyTypeCase<TemplateArgument, "StructuralValue"> in {
def : Property<"value", APValue> {
let Read = [{ node.getAsStructuralValue() }];
}
def : Property<"type", QualType> {
let Read = [{ node.getStructuralValueType() }];
}
def : Property<"isDefaulted", Bool> {
let Read = [{ node.getIsDefaulted() }];
}
def : Creator<[{
return TemplateArgument(ctx, type, value, isDefaulted);
}]>;
}
let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
def : Property<"name", TemplateName> {
let Read = [{ node.getAsTemplateOrTemplatePattern() }];

View File

@ -850,6 +850,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::NullPtr:
case TemplateArgument::StructuralValue:
return true;
case TemplateArgument::Type:
@ -882,6 +883,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::NullPtr:
case TemplateArgument::StructuralValue:
return true;
case TemplateArgument::Type: {

View File

@ -868,9 +868,11 @@ protected:
LLVM_PREFERRED_TYPE(bool)
unsigned UsualArrayDeleteWantsSize : 1;
/// What kind of initializer do we have? Could be none, parens, or braces.
/// In storage, we distinguish between "none, and no initializer expr", and
/// "none, but an implicit initializer expr".
// Is initializer expr present?
LLVM_PREFERRED_TYPE(bool)
unsigned HasInitializer : 1;
/// What kind of initializer syntax used? Could be none, parens, or braces.
LLVM_PREFERRED_TYPE(CXXNewInitializationStyle)
unsigned StoredInitializationStyle : 2;

View File

@ -37,6 +37,7 @@ public:
DISPATCH(Declaration);
DISPATCH(NullPtr);
DISPATCH(Integral);
DISPATCH(StructuralValue);
DISPATCH(Template);
DISPATCH(TemplateExpansion);
DISPATCH(Expression);
@ -59,6 +60,7 @@ public:
VISIT_METHOD(Declaration);
VISIT_METHOD(NullPtr);
VISIT_METHOD(Integral);
VISIT_METHOD(StructuralValue);
VISIT_METHOD(Template);
VISIT_METHOD(TemplateExpansion);
VISIT_METHOD(Expression);

View File

@ -50,6 +50,7 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> {
namespace clang {
class APValue;
class ASTContext;
class Expr;
struct PrintingPolicy;
@ -80,6 +81,13 @@ public:
/// that was provided for an integral non-type template parameter.
Integral,
/// The template argument is a non-type template argument that can't be
/// represented by the special-case Declaration, NullPtr, or Integral
/// forms. These values are only ever produced by constant evaluation,
/// so cannot be dependent.
/// TODO: merge Declaration, NullPtr and Integral into this?
StructuralValue,
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
@ -130,6 +138,14 @@ private:
};
void *Type;
};
struct V {
LLVM_PREFERRED_TYPE(ArgKind)
unsigned Kind : 31;
LLVM_PREFERRED_TYPE(bool)
unsigned IsDefaulted : 1;
APValue *Value;
void *Type;
};
struct A {
LLVM_PREFERRED_TYPE(ArgKind)
unsigned Kind : 31;
@ -156,11 +172,19 @@ private:
union {
struct DA DeclArg;
struct I Integer;
struct V Value;
struct A Args;
struct TA TemplateArg;
struct TV TypeOrValue;
};
void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted);
void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted);
void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value,
QualType Type, bool IsDefaulted);
void initFromStructural(const ASTContext &Ctx, QualType Type,
const APValue &V, bool IsDefaulted);
public:
/// Construct an empty, invalid template argument.
constexpr TemplateArgument() : TypeOrValue({Null, 0, /* IsDefaulted */ 0}) {}
@ -168,25 +192,22 @@ public:
/// Construct a template type argument.
TemplateArgument(QualType T, bool isNullPtr = false,
bool IsDefaulted = false) {
TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
TypeOrValue.IsDefaulted = IsDefaulted;
TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
initFromType(T, isNullPtr, IsDefaulted);
}
/// Construct a template argument that refers to a
/// declaration, which is either an external declaration or a
/// template declaration.
/// Construct a template argument that refers to a (non-dependent)
/// declaration.
TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) {
assert(D && "Expected decl");
DeclArg.Kind = Declaration;
DeclArg.IsDefaulted = IsDefaulted;
DeclArg.QT = QT.getAsOpaquePtr();
DeclArg.D = D;
initFromDeclaration(D, QT, IsDefaulted);
}
/// Construct an integral constant template argument. The memory to
/// store the value is allocated with Ctx.
TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type,
TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value,
QualType Type, bool IsDefaulted = false);
/// Construct a template argument from an arbitrary constant value.
TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value,
bool IsDefaulted = false);
/// Construct an integral constant template argument with the same
@ -297,7 +318,7 @@ public:
/// Retrieve the type for a type template argument.
QualType getAsType() const {
assert(getKind() == Type && "Unexpected kind");
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V));
}
/// Retrieve the declaration for a declaration non-type
@ -315,7 +336,7 @@ public:
/// Retrieve the type for null non-type template argument.
QualType getNullPtrType() const {
assert(getKind() == NullPtr && "Unexpected kind");
return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V));
}
/// Retrieve the template name for a template name argument.
@ -371,6 +392,14 @@ public:
/// default template parameter.
bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; }
/// Get the value of a StructuralValue.
const APValue &getAsStructuralValue() const { return *Value.Value; }
/// Get the type of a StructuralValue.
QualType getStructuralValueType() const {
return QualType::getFromOpaquePtr(Value.Type);
}
/// If this is a non-type template argument, get its type. Otherwise,
/// returns a null QualType.
QualType getNonTypeTemplateArgumentType() const;
@ -516,6 +545,7 @@ public:
assert(Argument.getKind() == TemplateArgument::NullPtr ||
Argument.getKind() == TemplateArgument::Integral ||
Argument.getKind() == TemplateArgument::Declaration ||
Argument.getKind() == TemplateArgument::StructuralValue ||
Argument.getKind() == TemplateArgument::Expression);
}
@ -541,13 +571,9 @@ public:
/// - Fetches the full source range of the argument.
SourceRange getSourceRange() const LLVM_READONLY;
const TemplateArgument &getArgument() const {
return Argument;
}
const TemplateArgument &getArgument() const { return Argument; }
TemplateArgumentLocInfo getLocInfo() const {
return LocInfo;
}
TemplateArgumentLocInfo getLocInfo() const { return LocInfo; }
TypeSourceInfo *getTypeSourceInfo() const {
if (Argument.getKind() != TemplateArgument::Type)
@ -575,6 +601,11 @@ public:
return LocInfo.getAsExpr();
}
Expr *getSourceStructuralValueExpression() const {
assert(Argument.getKind() == TemplateArgument::StructuralValue);
return LocInfo.getAsExpr();
}
NestedNameSpecifierLoc getTemplateQualifierLoc() const {
if (Argument.getKind() != TemplateArgument::Template &&
Argument.getKind() != TemplateArgument::TemplateExpansion)
@ -606,8 +637,7 @@ class TemplateArgumentListInfo {
public:
TemplateArgumentListInfo() = default;
TemplateArgumentListInfo(SourceLocation LAngleLoc,
SourceLocation RAngleLoc)
TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc)
: LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
@ -626,21 +656,15 @@ public:
return Arguments.data();
}
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
return Arguments;
}
llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; }
const TemplateArgumentLoc &operator[](unsigned I) const {
return Arguments[I];
}
TemplateArgumentLoc &operator[](unsigned I) {
return Arguments[I];
}
TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; }
void addArgument(const TemplateArgumentLoc &Loc) {
Arguments.push_back(Loc);
}
void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); }
};
/// Represents an explicit template argument list in C++, e.g.,

View File

@ -4029,19 +4029,6 @@ public:
/// because TrailingObjects cannot handle repeated types.
struct ExceptionType { QualType Type; };
/// The AArch64 SME ACLE (Arm C/C++ Language Extensions) define a number
/// of function type attributes that can be set on function types, including
/// function pointers.
enum AArch64SMETypeAttributes : unsigned {
SME_NormalFunction = 0,
SME_PStateSMEnabledMask = 1 << 0,
SME_PStateSMCompatibleMask = 1 << 1,
SME_PStateZASharedMask = 1 << 2,
SME_PStateZAPreservedMask = 1 << 3,
SME_AttributeMask = 0b111'111 // We only support maximum 6 bits because of the
// bitmask in FunctionTypeExtraBitfields.
};
/// A simple holder for various uncommon bits which do not fit in
/// FunctionTypeBitfields. Aligned to alignof(void *) to maintain the
/// alignment of subsequent objects in TrailingObjects.
@ -4051,11 +4038,57 @@ public:
/// [implimits] 8 bits would be enough here.
unsigned NumExceptionType : 10;
LLVM_PREFERRED_TYPE(bool)
unsigned HasArmTypeAttributes : 1;
FunctionTypeExtraBitfields()
: NumExceptionType(0), HasArmTypeAttributes(false) {}
};
/// The AArch64 SME ACLE (Arm C/C++ Language Extensions) define a number
/// of function type attributes that can be set on function types, including
/// function pointers.
enum AArch64SMETypeAttributes : unsigned {
SME_NormalFunction = 0,
SME_PStateSMEnabledMask = 1 << 0,
SME_PStateSMCompatibleMask = 1 << 1,
// Describes the value of the state using ArmStateValue.
SME_ZAShift = 2,
SME_ZAMask = 0b111 << SME_ZAShift,
SME_ZT0Shift = 5,
SME_ZT0Mask = 0b111 << SME_ZT0Shift,
SME_AttributeMask =
0b111'111'11 // We can't support more than 8 bits because of
// the bitmask in FunctionTypeExtraBitfields.
};
enum ArmStateValue : unsigned {
ARM_None = 0,
ARM_Preserves = 1,
ARM_In = 2,
ARM_Out = 3,
ARM_InOut = 4,
};
static ArmStateValue getArmZAState(unsigned AttrBits) {
return (ArmStateValue)((AttrBits & SME_ZAMask) >> SME_ZAShift);
}
static ArmStateValue getArmZT0State(unsigned AttrBits) {
return (ArmStateValue)((AttrBits & SME_ZT0Mask) >> SME_ZT0Shift);
}
/// 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.
struct alignas(void *) FunctionTypeArmAttributes {
/// Any AArch64 SME ACLE type attributes that need to be propagated
/// on declarations and function pointers.
unsigned AArch64SMEAttributes : 6;
FunctionTypeExtraBitfields()
: NumExceptionType(0), AArch64SMEAttributes(SME_NormalFunction) {}
unsigned AArch64SMEAttributes : 8;
FunctionTypeArmAttributes() : AArch64SMEAttributes(SME_NormalFunction) {}
};
protected:
@ -4154,7 +4187,8 @@ class FunctionProtoType final
public llvm::FoldingSetNode,
private llvm::TrailingObjects<
FunctionProtoType, QualType, SourceLocation,
FunctionType::FunctionTypeExtraBitfields, FunctionType::ExceptionType,
FunctionType::FunctionTypeExtraBitfields,
FunctionType::FunctionTypeArmAttributes, FunctionType::ExceptionType,
Expr *, FunctionDecl *, FunctionType::ExtParameterInfo, Qualifiers> {
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;
@ -4238,7 +4272,7 @@ public:
FunctionType::ExtInfo ExtInfo;
unsigned Variadic : 1;
unsigned HasTrailingReturn : 1;
unsigned AArch64SMEAttributes : 6;
unsigned AArch64SMEAttributes : 8;
Qualifiers TypeQuals;
RefQualifierKind RefQualifier = RQ_None;
ExceptionSpecInfo ExceptionSpec;
@ -4261,7 +4295,11 @@ public:
bool requiresFunctionProtoTypeExtraBitfields() const {
return ExceptionSpec.Type == EST_Dynamic ||
AArch64SMEAttributes != SME_NormalFunction;
requiresFunctionProtoTypeArmAttributes();
}
bool requiresFunctionProtoTypeArmAttributes() const {
return AArch64SMEAttributes != SME_NormalFunction;
}
void setArmSMEAttribute(AArch64SMETypeAttributes Kind, bool Enable = true) {
@ -4281,6 +4319,10 @@ private:
return isVariadic();
}
unsigned numTrailingObjects(OverloadToken<FunctionTypeArmAttributes>) const {
return hasArmTypeAttributes();
}
unsigned numTrailingObjects(OverloadToken<FunctionTypeExtraBitfields>) const {
return hasExtraBitfields();
}
@ -4369,6 +4411,12 @@ private:
}
bool hasArmTypeAttributes() const {
return FunctionTypeBits.HasExtraBitfields &&
getTrailingObjects<FunctionTypeExtraBitfields>()
->HasArmTypeAttributes;
}
bool hasExtQualifiers() const {
return FunctionTypeBits.HasExtQuals;
}
@ -4580,9 +4628,9 @@ public:
/// Return a bitmask describing the SME attributes on the function type, see
/// AArch64SMETypeAttributes for their values.
unsigned getAArch64SMEAttributes() const {
if (!hasExtraBitfields())
if (!hasArmTypeAttributes())
return SME_NormalFunction;
return getTrailingObjects<FunctionTypeExtraBitfields>()
return getTrailingObjects<FunctionTypeArmAttributes>()
->AArch64SMEAttributes;
}

View File

@ -2062,6 +2062,18 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
cxxOperatorCallExpr;
/// Matches C++17 fold expressions.
///
/// Example matches `(0 + ... + args)`:
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
/// \endcode
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr>
cxxFoldExpr;
/// Matches rewritten binary operators
///
/// Example matches use of "<":
@ -3881,7 +3893,7 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
return Node.getSelector().getNumArgs() == N;
}
/// Matches if the call expression's callee expression matches.
/// Matches if the call or fold expression's callee expression matches.
///
/// Given
/// \code
@ -3893,13 +3905,32 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
/// with callee(...)
/// matching this->x, x, y.x, f respectively
///
/// Given
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ... * 1);
/// }
/// \endcode
/// cxxFoldExpr(callee(expr()))
/// matches (args * ... * 1)
/// with callee(...)
/// matching *
///
/// Note: Callee cannot take the more general internal::Matcher<Expr>
/// because this introduces ambiguous overloads with calls to Callee taking a
/// internal::Matcher<Decl>, as the matcher hierarchy is purely
/// implemented in terms of implicit casts.
AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
InnerMatcher) {
const Expr *ExprNode = Node.getCallee();
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(callee,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
CXXFoldExpr),
internal::Matcher<Stmt>, InnerMatcher, 0) {
const auto *ExprNode = Node.getCallee();
return (ExprNode != nullptr &&
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
@ -4532,6 +4563,121 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
return InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, Builder);
}
/// Matches the operand that does not contain the parameter pack.
///
/// Example matches `(0 + ... + args)` and `(args * ... * 1)`
/// (matcher = cxxFoldExpr(hasFoldInit(expr())))
/// with hasFoldInit(...)
/// matching `0` and `1` respectively
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ... * 1);
/// }
/// \endcode
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
InnerMacher) {
const auto *const Init = Node.getInit();
return Init && InnerMacher.matches(*Init, Finder, Builder);
}
/// Matches the operand that contains the parameter pack.
///
/// Example matches `(0 + ... + args)`
/// (matcher = cxxFoldExpr(hasPattern(expr())))
/// with hasPattern(...)
/// matching `args`
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ... * 1);
/// }
/// \endcode
AST_MATCHER_P(CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher<Expr>,
InnerMacher) {
const Expr *const Pattern = Node.getPattern();
return Pattern && InnerMacher.matches(*Pattern, Finder, Builder);
}
/// Matches right-folding fold expressions.
///
/// Example matches `(args * ... * 1)`
/// (matcher = cxxFoldExpr(isRightFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ... * 1);
/// }
/// \endcode
AST_MATCHER(CXXFoldExpr, isRightFold) { return Node.isRightFold(); }
/// Matches left-folding fold expressions.
///
/// Example matches `(0 + ... + args)`
/// (matcher = cxxFoldExpr(isLeftFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ... * 1);
/// }
/// \endcode
AST_MATCHER(CXXFoldExpr, isLeftFold) { return Node.isLeftFold(); }
/// Matches unary fold expressions, i.e. fold expressions without an
/// initializer.
///
/// Example matches `(args * ...)`
/// (matcher = cxxFoldExpr(isUnaryFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ...);
/// }
/// \endcode
AST_MATCHER(CXXFoldExpr, isUnaryFold) { return Node.getInit() == nullptr; }
/// Matches binary fold expressions, i.e. fold expressions with an initializer.
///
/// Example matches `(0 + ... + args)`
/// (matcher = cxxFoldExpr(isBinaryFold()))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
///
/// template <typename... Args>
/// auto multiply(Args... args) {
/// return (args * ...);
/// }
/// \endcode
AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; }
/// Matches the n'th item of an initializer list expression.
///
/// Example matches y.
@ -5709,17 +5855,27 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
.matchesNode(Node);
}
/// Matches the operator Name of operator expressions (binary or
/// unary).
/// Matches the operator Name of operator expressions and fold expressions
/// (binary or unary).
///
/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
/// \code
/// !(a || b)
/// \endcode
///
/// Example matches `(0 + ... + args)`
/// (matcher = cxxFoldExpr(hasOperatorName("+")))
/// \code
/// template <typename... Args>
/// auto sum(Args... args) {
/// return (0 + ... + args);
/// }
/// \endcode
AST_POLYMORPHIC_MATCHER_P(
hasOperatorName,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator, UnaryOperator),
CXXRewrittenBinaryOperator, CXXFoldExpr,
UnaryOperator),
std::string, Name) {
if (std::optional<StringRef> OpName = internal::getOpName(Node))
return *OpName == Name;
@ -5789,11 +5945,12 @@ AST_POLYMORPHIC_MATCHER(
/// \code
/// a || b
/// \endcode
AST_POLYMORPHIC_MATCHER_P(hasLHS,
AST_POLYMORPHIC_SUPPORTED_TYPES(
BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator, ArraySubscriptExpr),
internal::Matcher<Expr>, InnerMatcher) {
AST_POLYMORPHIC_MATCHER_P(
hasLHS,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator,
ArraySubscriptExpr, CXXFoldExpr),
internal::Matcher<Expr>, InnerMatcher) {
const Expr *LeftHandSide = internal::getLHS(Node);
return (LeftHandSide != nullptr &&
InnerMatcher.matches(*LeftHandSide, Finder, Builder));
@ -5805,29 +5962,31 @@ AST_POLYMORPHIC_MATCHER_P(hasLHS,
/// \code
/// a || b
/// \endcode
AST_POLYMORPHIC_MATCHER_P(hasRHS,
AST_POLYMORPHIC_SUPPORTED_TYPES(
BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator, ArraySubscriptExpr),
internal::Matcher<Expr>, InnerMatcher) {
AST_POLYMORPHIC_MATCHER_P(
hasRHS,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator,
ArraySubscriptExpr, CXXFoldExpr),
internal::Matcher<Expr>, InnerMatcher) {
const Expr *RightHandSide = internal::getRHS(Node);
return (RightHandSide != nullptr &&
InnerMatcher.matches(*RightHandSide, Finder, Builder));
}
/// Matches if either the left hand side or the right hand side of a
/// binary operator matches.
/// binary operator or fold expression matches.
AST_POLYMORPHIC_MATCHER_P(
hasEitherOperand,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator),
CXXFoldExpr, CXXRewrittenBinaryOperator),
internal::Matcher<Expr>, InnerMatcher) {
return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()(
anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)))
.matches(Node, Finder, Builder);
}
/// Matches if both matchers match with opposite sides of the binary operator.
/// Matches if both matchers match with opposite sides of the binary operator
/// or fold expression.
///
/// Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
/// integerLiteral(equals(2)))
@ -5840,7 +5999,7 @@ AST_POLYMORPHIC_MATCHER_P(
AST_POLYMORPHIC_MATCHER_P2(
hasOperands,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator),
CXXFoldExpr, CXXRewrittenBinaryOperator),
internal::Matcher<Expr>, Matcher1, internal::Matcher<Expr>, Matcher2) {
return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()(
anyOf(allOf(hasLHS(Matcher1), hasRHS(Matcher2)),
@ -6192,9 +6351,7 @@ AST_POLYMORPHIC_MATCHER(isFinal,
/// };
/// \endcode
/// matches A::x
AST_MATCHER(CXXMethodDecl, isPure) {
return Node.isPure();
}
AST_MATCHER(CXXMethodDecl, isPure) { return Node.isPureVirtual(); }
/// Matches if the given method declaration is const.
///

View File

@ -2195,6 +2195,9 @@ inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
}
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
}
inline StringRef getOpName(const CXXFoldExpr &Node) {
return BinaryOperator::getOpcodeStr(Node.getOperator());
}
/// Matches overloaded operators with a specific name.
///

View File

@ -32,7 +32,8 @@ namespace dataflow {
class ControlFlowContext {
public:
/// Builds a ControlFlowContext from a `FunctionDecl`.
/// `Func.hasBody()` must be true, and `Func.isTemplated()` must be false.
/// `Func.doesThisDeclarationHaveABody()` must be true, and
/// `Func.isTemplated()` must be false.
static llvm::Expected<ControlFlowContext> build(const FunctionDecl &Func);
/// Builds a ControlFlowContext from an AST node. `D` is the function in which

View File

@ -186,6 +186,12 @@ template <typename LatticeT> struct DataflowAnalysisState {
/// the dataflow analysis cannot be performed successfully. Otherwise, calls
/// `PostVisitCFG` on each CFG element with the final analysis results at that
/// program point.
///
/// `MaxBlockVisits` caps the number of block visits during analysis. See
/// `runTypeErasedDataflowAnalysis` for a full description. The default value is
/// essentially arbitrary -- large enough to accommodate what seems like any
/// reasonable CFG, but still small enough to limit the cost of hitting the
/// limit.
template <typename AnalysisT>
llvm::Expected<std::vector<
std::optional<DataflowAnalysisState<typename AnalysisT::Lattice>>>>
@ -194,7 +200,8 @@ runDataflowAnalysis(
const Environment &InitEnv,
std::function<void(const CFGElement &, const DataflowAnalysisState<
typename AnalysisT::Lattice> &)>
PostVisitCFG = nullptr) {
PostVisitCFG = nullptr,
std::int32_t MaxBlockVisits = 20'000) {
std::function<void(const CFGElement &,
const TypeErasedDataflowAnalysisState &)>
PostVisitCFGClosure = nullptr;
@ -212,7 +219,7 @@ runDataflowAnalysis(
}
auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis(
CFCtx, Analysis, InitEnv, PostVisitCFGClosure);
CFCtx, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits);
if (!TypeErasedBlockStates)
return TypeErasedBlockStates.takeError();
@ -261,6 +268,10 @@ auto createAnalysis(ASTContext &ASTCtx, Environment &Env)
/// iterations.
/// - This limit is still low enough to keep runtimes acceptable (on typical
/// machines) in cases where we hit the limit.
///
/// `MaxBlockVisits` caps the number of block visits during analysis. See
/// `runDataflowAnalysis` for a full description and explanation of the default
/// value.
template <typename AnalysisT, typename Diagnostic>
llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
@ -268,7 +279,8 @@ llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
const CFGElement &, ASTContext &,
const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>
Diagnoser,
std::int64_t MaxSATIterations = 1'000'000'000) {
std::int64_t MaxSATIterations = 1'000'000'000,
std::int32_t MaxBlockVisits = 20'000) {
llvm::Expected<ControlFlowContext> Context =
ControlFlowContext::build(FuncDecl);
if (!Context)
@ -293,7 +305,8 @@ llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
State.Lattice.Value),
State.Env));
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
})
},
MaxBlockVisits)
.takeError())
return std::move(Err);

View File

@ -172,7 +172,8 @@ public:
///
/// Requirements:
///
/// The function must have a body.
/// The function must have a body, i.e.
/// `FunctionDecl::doesThisDecalarationHaveABody()` must be true.
void initialize();
/// Returns a new environment that is a copy of this one.

View File

@ -75,6 +75,10 @@ public:
return static_cast<bool>(Value);
}
bool isLiteral(bool b) const {
return kind() == Literal && static_cast<bool>(Value) == b;
}
ArrayRef<const Formula *> operands() const {
return ArrayRef(reinterpret_cast<Formula *const *>(this + 1),
numOperands(kind()));

View File

@ -25,10 +25,17 @@ namespace dataflow {
/// Maps statements to the environments of basic blocks that contain them.
class StmtToEnvMap {
public:
// `CurBlockID` is the ID of the block currently being processed, and
// `CurState` is the pending state currently associated with this block. These
// are supplied separately as the pending state for the current block may not
// yet be represented in `BlockToState`.
StmtToEnvMap(const ControlFlowContext &CFCtx,
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>>
BlockToState)
: CFCtx(CFCtx), BlockToState(BlockToState) {}
BlockToState,
unsigned CurBlockID,
const TypeErasedDataflowAnalysisState &CurState)
: CFCtx(CFCtx), BlockToState(BlockToState), CurBlockID(CurBlockID),
CurState(CurState) {}
/// Returns the environment of the basic block that contains `S`.
/// The result is guaranteed never to be null.
@ -37,6 +44,8 @@ public:
private:
const ControlFlowContext &CFCtx;
llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockToState;
unsigned CurBlockID;
const TypeErasedDataflowAnalysisState &CurState;
};
/// Evaluates `S` and updates `Env` accordingly.

View File

@ -138,13 +138,20 @@ struct TypeErasedDataflowAnalysisState {
/// dataflow analysis cannot be performed successfully. Otherwise, calls
/// `PostVisitCFG` on each CFG element with the final analysis results at that
/// program point.
///
/// `MaxBlockVisits` caps the number of block visits during analysis. It doesn't
/// distinguish between repeat visits to the same block and visits to distinct
/// blocks. This parameter is a backstop to prevent infinite loops, in the case
/// of bugs in the lattice and/or transfer functions that prevent the analysis
/// from converging.
llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>>
runTypeErasedDataflowAnalysis(
const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv,
std::function<void(const CFGElement &,
const TypeErasedDataflowAnalysisState &)>
PostVisitCFG = nullptr);
PostVisitCFG,
std::int32_t MaxBlockVisits);
} // namespace dataflow
} // namespace clang

View File

@ -306,6 +306,9 @@ class VariadicEnumArgument<string name, string type, list<string> values,
bit IsExternalType = isExternalType;
}
// Represents an attribute wrapped by another attribute.
class WrappedAttr<string name, bit opt = 0> : Argument<name, opt>;
// This handles one spelling of an attribute.
class Spelling<string name, string variety, int version = 1> {
string Name = name;
@ -2291,7 +2294,7 @@ def ObjCBridgeRelated : InheritableAttr {
def NSErrorDomain : InheritableAttr {
let Spellings = [GNU<"ns_error_domain">];
let Subjects = SubjectList<[Enum], ErrorDiag>;
let Args = [DeclArgument<Var, "ErrorDomain">];
let Args = [IdentifierArgument<"ErrorDomain">];
let Documentation = [NSErrorDomainDocs];
}
@ -2539,16 +2542,48 @@ def ArmStreamingCompatible : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Documentation = [ArmSmeStreamingCompatibleDocs];
}
def ArmSharedZA : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_shared_za">];
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
let Documentation = [ArmSmeSharedZADocs];
def ArmNew : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_new">];
let Args = [VariadicStringArgument<"NewArgs">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [ArmNewDocs];
let AdditionalMembers = [{
bool isNewZA() const {
return llvm::is_contained(newArgs(), "za");
}
bool isNewZT0() const {
return llvm::is_contained(newArgs(), "zt0");
}
}];
}
def ArmPreservesZA : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_preserves_za">];
def ArmIn : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_in">];
let Args = [VariadicStringArgument<"InArgs">];
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
let Documentation = [ArmSmePreservesZADocs];
let Documentation = [ArmInDocs];
}
def ArmOut : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_out">];
let Args = [VariadicStringArgument<"OutArgs">];
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
let Documentation = [ArmOutDocs];
}
def ArmInOut : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_inout">];
let Args = [VariadicStringArgument<"InOutArgs">];
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
let Documentation = [ArmInOutDocs];
}
def ArmPreserves : TypeAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_preserves">];
let Args = [VariadicStringArgument<"PreserveArgs">];
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
let Documentation = [ArmPreservesDocs];
}
def ArmLocallyStreaming : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
@ -2557,14 +2592,6 @@ def ArmLocallyStreaming : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
let Documentation = [ArmSmeLocallyStreamingDocs];
}
def ArmNewZA : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
let Spellings = [RegularKeyword<"__arm_new_za">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [ArmSmeNewZADocs];
}
def : MutualExclusions<[ArmNewZA, ArmSharedZA]>;
def : MutualExclusions<[ArmNewZA, ArmPreservesZA]>;
def Pure : InheritableAttr {
let Spellings = [GCC<"pure">];
@ -2627,6 +2654,22 @@ def SwiftError : InheritableAttr {
let Documentation = [SwiftErrorDocs];
}
def SwiftImportAsNonGeneric : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly
// from API notes.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [InternalOnly];
}
def SwiftImportPropertyAsAccessors : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly
// from API notes.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [InternalOnly];
}
def SwiftName : InheritableAttr {
let Spellings = [GNU<"swift_name">];
let Args = [StringArgument<"Name">];
@ -2648,6 +2691,31 @@ def SwiftPrivate : InheritableAttr {
let SimpleHandler = 1;
}
def SwiftVersionedAddition : Attr {
// This attribute has no spellings as it is only ever created implicitly
// from API notes.
let Spellings = [];
let Args = [VersionArgument<"Version">, WrappedAttr<"AdditionalAttr">,
BoolArgument<"IsReplacedByActive">];
let SemaHandler = 0;
let Documentation = [InternalOnly];
}
def SwiftVersionedRemoval : Attr {
// This attribute has no spellings as it is only ever created implicitly
// from API notes.
let Spellings = [];
let Args = [VersionArgument<"Version">, UnsignedArgument<"RawKind">,
BoolArgument<"IsReplacedByActive">];
let SemaHandler = 0;
let Documentation = [InternalOnly];
let AdditionalMembers = [{
attr::Kind getAttrKindToRemove() const {
return static_cast<attr::Kind>(getRawKind());
}
}];
}
def NoDeref : TypeAttr {
let Spellings = [Clang<"noderef">];
let Documentation = [NoDerefDocs];

View File

@ -3621,7 +3621,7 @@ Attribute ``trivial_abi`` has no effect in the following cases:
def MSInheritanceDocs : Documentation {
let Category = DocCatDecl;
let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance";
let Heading = "__single_inheritance, __multiple_inheritance, __virtual_inheritance";
let Content = [{
This collection of keywords is enabled under ``-fms-extensions`` and controls
the pointer-to-member representation used on ``*-*-win32`` targets.
@ -6861,30 +6861,73 @@ without changing modes.
}];
}
def ArmSmeSharedZADocs : Documentation {
def ArmInDocs : Documentation {
let Category = DocCatArmSmeAttributes;
let Content = [{
The ``__arm_shared_za`` keyword applies to prototyped function types and specifies
that the function shares SME's matrix storage (ZA) with its caller. This
means that:
The ``__arm_in`` keyword applies to prototyped function types and specifies
that the function shares a given state S with its caller. For ``__arm_in``, the
function takes the state S as input and returns with the state S unchanged.
* the function requires that the processor implements the Scalable Matrix
Extension (SME).
The attribute takes string arguments to instruct the compiler which state
is shared. The supported states for S are:
* the function enters with ZA in an active state.
* ``"za"`` for Matrix Storage (requires SME)
* the function returns with ZA in an active state.
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
}];
}
def ArmSmePreservesZADocs : Documentation {
def ArmOutDocs : Documentation {
let Category = DocCatArmSmeAttributes;
let Content = [{
The ``__arm_preserves_za`` keyword applies to prototyped function types and
specifies that the function does not modify ZA state.
The ``__arm_out`` keyword applies to prototyped function types and specifies
that the function shares a given state S with its caller. For ``__arm_out``,
the function ignores the incoming state for S and returns new state for S.
The attribute takes string arguments to instruct the compiler which state
is shared. The supported states for S are:
* ``"za"`` for Matrix Storage (requires SME)
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
}];
}
def ArmInOutDocs : Documentation {
let Category = DocCatArmSmeAttributes;
let Content = [{
The ``__arm_inout`` keyword applies to prototyped function types and specifies
that the function shares a given state S with its caller. For ``__arm_inout``,
the function takes the state S as input and returns new state for S.
The attribute takes string arguments to instruct the compiler which state
is shared. The supported states for S are:
* ``"za"`` for Matrix Storage (requires SME)
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
}];
}
def ArmPreservesDocs : Documentation {
let Category = DocCatArmSmeAttributes;
let Content = [{
The ``__arm_preserves`` keyword applies to prototyped function types and
specifies that the function does not read a given state S and returns
with state S unchanged.
The attribute takes string arguments to instruct the compiler which state
is shared. The supported states for S are:
* ``"za"`` for Matrix Storage (requires SME)
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
}];
}
def ArmSmeLocallyStreamingDocs : Documentation {
let Category = DocCatArmSmeAttributes;
@ -6907,13 +6950,18 @@ at the end of the function.
}];
}
def ArmSmeNewZADocs : Documentation {
def ArmNewDocs : Documentation {
let Category = DocCatArmSmeAttributes;
let Content = [{
The ``__arm_new_za`` keyword applies to function declarations and specifies
that the function will be set up with a fresh ZA context.
The ``__arm_new`` keyword applies to function declarations and specifies
that the function will create a new scope for state S.
This means that:
The attribute takes string arguments to instruct the compiler for which state
to create new scope. The supported states for S are:
* ``"za"`` for Matrix Storage (requires SME)
For state ``"za"``, this means that:
* the function requires that the target processor implements the Scalable Matrix
Extension (SME).
@ -6924,8 +6972,8 @@ This means that:
* the function will disable PSTATE.ZA (by setting it to 0) before returning.
For ``__arm_new_za`` functions Clang will set up the ZA context automatically
on entry to the function, and disable it before returning. For example, if ZA is
For ``__arm_new("za")`` functions Clang will set up the ZA context automatically
on entry to the function and disable it before returning. For example, if ZA is
in a dormant state Clang will generate the code to commit a lazy-save and set up
a new ZA state before executing user code.
}];

View File

@ -255,6 +255,19 @@ protected:
return SpellingIndex != SpellingNotCalculated;
}
};
inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) {
switch (Kind) {
default:
return false;
#define KEYWORD_ATTRIBUTE(NAME, HASARG, ...) \
case tok::kw_##NAME: \
return HASARG;
#include "clang/Basic/RegularKeywordAttrInfo.inc"
#undef KEYWORD_ATTRIBUTE
}
}
} // namespace clang
#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H

View File

@ -255,6 +255,10 @@ TARGET_BUILTIN(__builtin_amdgcn_sudot4, "iIbiIbiiIb", "nc", "dot8-insts")
TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot1-insts")
TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot7-insts")
TARGET_BUILTIN(__builtin_amdgcn_sudot8, "iIbiIbiiIb", "nc", "dot8-insts")
TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_fp8_bf8, "fUiUif", "nc", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_fp8, "fUiUif", "nc", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_fp8_fp8, "fUiUif", "nc", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "gfx12-insts")
//===----------------------------------------------------------------------===//
// GFX10+ only builtins.
@ -397,19 +401,20 @@ TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_bf8_fp8, "V16fV2iV4iV16fiIiI
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_fp8_bf8, "V16fV2iV4iV16fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_fp8_fp8, "V16fV2iV4iV16fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_f32_bf8, "fiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_f32_fp8, "fiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f32_bf8, "V2fiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f32_fp8, "V2fiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_bf8_f32, "iffiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f32, "iffiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f32, "ifiiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f32, "ifiiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_f32_bf8, "fiIi", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_f32_fp8, "fiIi", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f32_bf8, "V2fiIb", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f32_fp8, "V2fiIb", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_bf8_f32, "iffiIb", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f32, "iffiIb", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f32, "ifiiIi", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f32, "ifiiIi", "nc", "fp8-conversion-insts")
//===----------------------------------------------------------------------===//
// GFX12+ only builtins.
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_s_sleep_var, "vUi", "n", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_permlane16_var, "UiUiUiUiIbIb", "nc", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_permlanex16_var, "UiUiUiUiIbIb", "nc", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_barrier_signal, "vIi", "n", "gfx12-insts")
@ -423,6 +428,13 @@ TARGET_BUILTIN(__builtin_amdgcn_s_wakeup_barrier, "vi", "n", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_barrier_leave, "b", "n", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_get_barrier_state, "Uii", "n", "gfx12-insts")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v2i32, "V2iV2i*1", "nc", "gfx12-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v8i16, "V8sV8s*1", "nc", "gfx12-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v8f16, "V8hV8h*1", "nc", "gfx12-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v4i16, "V4sV4s*1", "nc", "gfx12-insts,wavefrontsize64")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v4f16, "V4hV4h*1", "nc", "gfx12-insts,wavefrontsize64")
#undef BUILTIN
#undef TARGET_BUILTIN

View File

@ -51,3 +51,8 @@ TARGET_BUILTIN(__builtin_loongarch_iocsrwr_d, "vUWiUi", "nc", "64bit")
TARGET_BUILTIN(__builtin_loongarch_lddir_d, "WiWiIUWi", "nc", "64bit")
TARGET_BUILTIN(__builtin_loongarch_ldpte_d, "vWiIUWi", "nc", "64bit")
TARGET_BUILTIN(__builtin_loongarch_frecipe_s, "ff", "nc", "f,frecipe")
TARGET_BUILTIN(__builtin_loongarch_frecipe_d, "dd", "nc", "d,frecipe")
TARGET_BUILTIN(__builtin_loongarch_frsqrte_s, "ff", "nc", "f,frecipe")
TARGET_BUILTIN(__builtin_loongarch_frsqrte_d, "dd", "nc", "d,frecipe")

View File

@ -657,9 +657,15 @@ TARGET_BUILTIN(__builtin_lasx_xvfsqrt_d, "V4dV4d", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfrecip_s, "V8fV8f", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfrecip_d, "V4dV4d", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfrecipe_s, "V8fV8f", "nc", "lasx,frecipe")
TARGET_BUILTIN(__builtin_lasx_xvfrecipe_d, "V4dV4d", "nc", "lasx,frecipe")
TARGET_BUILTIN(__builtin_lasx_xvfrsqrt_s, "V8fV8f", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfrsqrt_d, "V4dV4d", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfrsqrte_s, "V8fV8f", "nc", "lasx,frecipe")
TARGET_BUILTIN(__builtin_lasx_xvfrsqrte_d, "V4dV4d", "nc", "lasx,frecipe")
TARGET_BUILTIN(__builtin_lasx_xvfcvtl_s_h, "V8fV16s", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfcvth_s_h, "V8fV16s", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvfcvtl_d_s, "V4dV8f", "nc", "lasx")

View File

@ -641,9 +641,15 @@ TARGET_BUILTIN(__builtin_lsx_vfsqrt_d, "V2dV2d", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vfrecip_s, "V4fV4f", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vfrecip_d, "V2dV2d", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vfrecipe_s, "V4fV4f", "nc", "lsx,frecipe")
TARGET_BUILTIN(__builtin_lsx_vfrecipe_d, "V2dV2d", "nc", "lsx,frecipe")
TARGET_BUILTIN(__builtin_lsx_vfrsqrt_s, "V4fV4f", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vfrsqrt_d, "V2dV2d", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vfrsqrte_s, "V4fV4f", "nc", "lsx,frecipe")
TARGET_BUILTIN(__builtin_lsx_vfrsqrte_d, "V2dV2d", "nc", "lsx,frecipe")
TARGET_BUILTIN(__builtin_lsx_vfcvtl_s_h, "V4fV8s", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vfcvtl_d_s, "V2dV4f", "nc", "lsx")

View File

@ -110,6 +110,10 @@ BUILTIN(__builtin_ppc_fctiw, "dd", "")
BUILTIN(__builtin_ppc_fctiwz, "dd", "")
BUILTIN(__builtin_ppc_fctudz, "dd", "")
BUILTIN(__builtin_ppc_fctuwz, "dd", "")
// fence builtin prevents all instructions moved across it
BUILTIN(__builtin_ppc_fence, "v", "")
BUILTIN(__builtin_ppc_swdiv_nochk, "ddd", "")
BUILTIN(__builtin_ppc_swdivs_nochk, "fff", "")
BUILTIN(__builtin_ppc_alignx, "vIivC*", "nc")

View File

@ -12,6 +12,9 @@
// that have enumeration type and VALUE_CODEGENOPT is a code
// generation option that describes a value rather than a flag.
//
// AFFECTING_VALUE_CODEGENOPT is used for code generation options that can
// affect the AST.
//
//===----------------------------------------------------------------------===//
#ifndef CODEGENOPT
# error Define the CODEGENOPT macro to handle language options
@ -27,6 +30,11 @@ CODEGENOPT(Name, Bits, Default)
CODEGENOPT(Name, Bits, Default)
#endif
#ifndef AFFECTING_VALUE_CODEGENOPT
# define AFFECTING_VALUE_CODEGENOPT(Name, Bits, Default) \
VALUE_CODEGENOPT(Name, Bits, Default)
#endif
CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
CODEGENOPT(RelaxELFRelocations, 1, 1) ///< -Wa,-mrelax-relocations={yes,no}
CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm.
@ -193,8 +201,10 @@ ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
CODEGENOPT(ObjCConvertMessagesToRuntimeCalls , 1, 1)
CODEGENOPT(ObjCAvoidHeapifyLocalBlocks, 1, 0)
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
// The optimization options affect frontend options, whicn in turn do affect the AST.
AFFECTING_VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic
/// Choose profile instrumenation kind or no instrumentation.
@ -437,3 +447,4 @@ CODEGENOPT(CtorDtorReturnThis, 1, 0)
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
#undef VALUE_CODEGENOPT
#undef AFFECTING_VALUE_CODEGENOPT

View File

@ -494,6 +494,9 @@ public:
return getProfileInstr() == ProfileCSIRInstr;
}
/// Check if any form of instrumentation is on.
bool hasProfileInstr() const { return getProfileInstr() != ProfileNone; }
/// Check if Clang profile use is on.
bool hasProfileClangUse() const {
return getProfileUse() == ProfileClangInstr;

View File

@ -70,6 +70,10 @@ def warn_pragma_debug_missing_argument : Warning<
def warn_pragma_debug_unexpected_argument : Warning<
"unexpected argument to debug command">, InGroup<IgnoredPragmas>;
def warn_fp_nan_inf_when_disabled : Warning<
"use of %select{infinity|NaN}0%select{| via a macro}1 is undefined behavior "
"due to the currently enabled floating-point options">,
InGroup<DiagGroup<"nan-infinity-disabled">>;
}
// Parse && Sema
@ -358,9 +362,9 @@ def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
def err_file_modified : Error<
"file '%0' modified since it was first processed">, DefaultFatal;
def err_file_too_large : Error<
"sorry, unsupported: file '%0' is too large for Clang to process">;
"file '%0' is too large for Clang to process">;
def err_sloc_space_too_large : Error<
"sorry, the translation unit is too large for Clang to process: ran out of source locations">, DefaultFatal;
"translation unit is too large for Clang to process: ran out of source locations">, DefaultFatal;
def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but "
"encoding is not supported">, DefaultFatal;
def err_unable_to_rename_temp : Error<

View File

@ -427,6 +427,8 @@ def warn_drv_clang_unsupported : Warning<
"the clang compiler does not support '%0'">;
def warn_drv_deprecated_arg : Warning<
"argument '%0' is deprecated, use '%1' instead">, InGroup<Deprecated>;
def warn_drv_deprecated_custom : Warning<
"argument '%0' is deprecated, %1">, InGroup<Deprecated>;
def warn_drv_assuming_mfloat_abi_is : Warning<
"unknown platform, assuming -mfloat-abi=%0">;
def warn_drv_unsupported_float_abi_by_lib : Warning<
@ -472,7 +474,7 @@ def warn_unsupported_branch_protection: Warning <
def err_sls_hardening_arm_not_supported : Error<
"-mharden-sls is only supported on armv7-a or later">;
def warn_drv_large_data_threshold_invalid_code_model: Warning<
"'%0' only applies to medium code model">,
"'%0' only applies to medium and large code models">,
InGroup<UnusedCommandLineArgument>;
def note_drv_command_failed_diag_msg : Note<
@ -656,6 +658,13 @@ def err_drv_trivial_auto_var_init_stop_after_missing_dependency : Error<
def err_drv_trivial_auto_var_init_stop_after_invalid_value : Error<
"'-ftrivial-auto-var-init-stop-after=*' only accepts positive integers">;
def err_drv_trivial_auto_var_init_max_size_missing_dependency : Error<
"'-ftrivial-auto-var-init-max-size=*' is used without "
"'-ftrivial-auto-var-init=zero' or '-ftrivial-auto-var-init=pattern'">;
def err_drv_trivial_auto_var_init_max_size_invalid_value : Error<
"'-ftrivial-auto-var-init-max-size=*' only accepts positive integers (in bytes)">;
def warn_drv_msp430_hwmult_unsupported : Warning<
"the given MCU does not support hardware multiply, but '-mhwmult' is set to "
"%0">, InGroup<InvalidCommandLineArgument>;
@ -735,10 +744,10 @@ def err_drv_dxc_missing_target_profile : Error<
def err_drv_hlsl_unsupported_target : Error<
"HLSL code generation is unsupported for target '%0'">;
def err_drv_hlsl_bad_shader_required_in_target : Error<
"shader %select{model|stage}0 is required in target '%1' for HLSL code generation">;
"%select{shader model|Vulkan environment|shader stage}0 is required as %select{OS|environment}1 in target '%2' for HLSL code generation">;
def err_drv_hlsl_bad_shader_unsupported : Error<
"shader %select{model|stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
"%select{shader model|Vulkan environment|shader stage}0 '%1' in target '%2' is invalid for HLSL code generation">;
def warn_drv_dxc_missing_dxv : Warning<"dxv not found. "
"Resulting DXIL will not be validated or signed for use in release environments.">,
InGroup<DXILValidation>;

View File

@ -1366,6 +1366,15 @@ def err_acc_invalid_open_paren
: Error<"expected clause-list or newline in OpenACC directive">;
def err_acc_invalid_default_clause_kind
: Error<"invalid value for 'default' clause; expected 'present' or 'none'">;
def err_acc_invalid_tag_kind
: Error<"invalid tag %0 on '%1' %select{directive|clause}2">;
def err_acc_expected_reduction_operator
: Error<"missing reduction operator, expected '+', '*', 'max', 'min', '&', "
"'|', '^', '&&', or '||', follwed by a ':'">;
def err_acc_invalid_reduction_operator
: Error<"invalid reduction operator, expected '+', '*', 'max', 'min', "
"'&', '|', '^', '&&', or '||'">;
def err_acc_incorrect_bind_arg : Error<"expected identifier or string literal">;
// OpenMP support.
def warn_pragma_omp_ignored : Warning<
@ -1609,6 +1618,9 @@ def err_pragma_invalid_keyword : Error<
def err_pragma_pipeline_invalid_keyword : Error<
"invalid argument; expected 'disable'">;
// API notes.
def err_type_unparsed : Error<"unparsed tokens following type">;
// Pragma unroll support.
def warn_pragma_unroll_cuda_value_in_parens : Warning<
"argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">,

View File

@ -692,6 +692,13 @@ def warn_maybe_falloff_nonvoid_function : Warning<
def warn_falloff_nonvoid_function : Warning<
"non-void function does not return a value">,
InGroup<ReturnType>;
def warn_const_attr_with_pure_attr : Warning<
"'const' attribute imposes more restrictions; 'pure' attribute ignored">,
InGroup<IgnoredAttributes>;
def warn_pure_function_returns_void : Warning<
"'%select{pure|const}0' attribute on function returning 'void'; attribute ignored">,
InGroup<IgnoredAttributes>;
def err_maybe_falloff_nonvoid_block : Error<
"non-void block does not return a value in all control paths">;
def err_falloff_nonvoid_block : Error<
@ -2411,7 +2418,8 @@ def err_auto_not_allowed : Error<
"|in type allocated by 'new'|in K&R-style function parameter"
"|in template parameter|in friend declaration|in function prototype that is "
"not a function declaration|in requires expression parameter"
"|in array declaration}1">;
"|in array declaration"
"|in declaration of conversion function template}1">;
def err_dependent_deduced_tst : Error<
"typename specifier refers to "
"%select{class template|function template|variable template|alias template|"
@ -3113,6 +3121,8 @@ def err_musttail_scope : Error<
"cannot perform a tail call from this return statement">;
def err_musttail_no_variadic : Error<
"%0 attribute may not be used with variadic functions">;
def err_musttail_no_return : Error<
"%0 attribute may not be used with no-return-attribute functions">;
def err_nsobject_attribute : Error<
"'NSObject' attribute is for pointer types only">;
@ -3160,6 +3170,9 @@ def warn_attribute_arm_sm_incompat_builtin : Warning<
def warn_attribute_arm_za_builtin_no_za_state : Warning<
"builtin call is not valid when calling from a function without active ZA state">,
InGroup<DiagGroup<"undefined-arm-za">>;
def warn_attribute_arm_zt0_builtin_no_zt0_state : Warning<
"builtin call is not valid when calling from a function without active ZT0 state">,
InGroup<DiagGroup<"undefined-arm-zt0">>;
def err_sve_vector_in_non_sve_target : Error<
"SVE vector type %0 cannot be used in a target without sve">;
def err_attribute_riscv_rvv_bits_unsupported : Error<
@ -3696,10 +3709,20 @@ def err_sme_call_in_non_sme_target : Error<
"call to a streaming function requires 'sme'">;
def err_sme_za_call_no_za_state : Error<
"call to a shared ZA function requires the caller to have ZA state">;
def err_sme_zt0_call_no_zt0_state : Error<
"call to a shared ZT0 function requires the caller to have ZT0 state">;
def err_sme_definition_using_sm_in_non_sme_target : Error<
"function executed in streaming-SVE mode requires 'sme'">;
def err_sme_definition_using_za_in_non_sme_target : Error<
"function using ZA state requires 'sme'">;
def err_sme_definition_using_zt0_in_non_sme2_target : Error<
"function using ZT0 state requires 'sme2'">;
def err_conflicting_attributes_arm_state : Error<
"conflicting attributes for state '%0'">;
def err_unknown_arm_state : Error<
"unknown state '%0'">;
def err_missing_arm_state : Error<
"missing state for %0">;
def err_cconv_change : Error<
"function declared '%0' here was previously declared "
"%select{'%2'|without calling convention}1">;
@ -5138,8 +5161,6 @@ def err_non_type_template_arg_subobject : Error<
"non-type template argument refers to subobject '%0'">;
def err_non_type_template_arg_addr_label_diff : Error<
"template argument / label address difference / what did you expect?">;
def err_non_type_template_arg_unsupported : Error<
"sorry, non-type template argument of type %0 is not yet supported">;
def err_template_arg_not_convertible : Error<
"non-type template argument of type %0 cannot be converted to a value "
"of type %1">;
@ -5191,9 +5212,6 @@ def err_template_arg_not_object_or_func : Error<
"non-type template argument does not refer to an object or function">;
def err_template_arg_not_pointer_to_member_form : Error<
"non-type template argument is not a pointer to member constant">;
def err_template_arg_member_ptr_base_derived_not_supported : Error<
"sorry, non-type template argument of pointer-to-member type %1 that refers "
"to member %q0 of a different class is not supported yet">;
def err_template_arg_invalid : Error<
"non-type template argument '%0' is invalid">;
def ext_template_arg_extra_parens : ExtWarn<
@ -7000,6 +7018,11 @@ def err_member_decl_does_not_match : Error<
"does not match any declaration in %1">;
def err_friend_decl_with_def_arg_must_be_def : Error<
"friend declaration specifying a default argument must be a definition">;
def err_friend_decl_with_enclosing_temp_constraint_must_be_def : Error<
"friend declaration with a constraint that depends on an enclosing "
"template parameter must be a definition">;
def err_non_temp_friend_decl_with_requires_clause_must_be_def : Error<
"non-template friend declaration with a requires clause must be a definition">;
def err_friend_decl_with_def_arg_redeclared : Error<
"friend declaration specifying a default argument must be the only declaration">;
def err_friend_decl_does_not_match : Error<
@ -9926,10 +9949,10 @@ def warn_new_dangling_initializer_list : Warning<
"will be destroyed at the end of the full-expression">,
InGroup<DanglingInitializerList>;
def warn_unsupported_lifetime_extension : Warning<
"sorry, lifetime extension of "
"lifetime extension of "
"%select{temporary|backing array of initializer list}0 created "
"by aggregate initialization using default member initializer "
"is not supported; lifetime of %select{temporary|backing array}0 "
"by aggregate initialization using a default member initializer "
"is not yet supported; lifetime of %select{temporary|backing array}0 "
"will end at the end of the full-expression">, InGroup<Dangling>;
// For non-floating point, expressions of the form x == x or x != x

View File

@ -129,10 +129,8 @@ def warn_module_system_bit_conflict : Warning<
"as a non-system module; any difference in diagnostic options will be ignored">,
InGroup<ModuleConflict>;
def warn_reading_std_cxx_module_by_implicit_paths : Warning<
"it is deprecated to read module '%0' implicitly; it is going to be removed in clang 18; "
"consider to specify the dependencies explicitly">,
InGroup<DiagGroup<"read-modules-implicitly">>;
def err_failed_to_find_module_file : Error<
"failed to find module file for module '%0'">;
} // let CategoryName
let CategoryName = "AST Serialization Issue" in {

View File

@ -269,6 +269,10 @@ EXTENSION(cxx_fixed_enum, true)
EXTENSION(cxx_binary_literals, true)
EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11)
EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus)
//C++20
EXTENSION(cxx_generalized_nttp, LangOpts.CPlusPlus20)
//C++23
EXTENSION(cxx_explicit_this_parameter, LangOpts.CPlusPlus23)
// Miscellaneous language extensions
EXTENSION(overloadable_unmarked, true)
EXTENSION(pragma_clang_attribute_namespaces, true)

View File

@ -220,7 +220,7 @@ BENIGN_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization wit
BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal")
BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation")
ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 2, CX_Full, "Enable use of range reduction for complex arithmetics.")
ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 2, CX_None, "Enable use of range reduction for complex arithmetics.")
BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
@ -260,6 +260,7 @@ LANGOPT(OpenMPTeamSubscription , 1, 0, "Assume distributed loops do not have mo
LANGOPT(OpenMPNoThreadState , 1, 0, "Assume that no thread in a parallel region will modify an ICV.")
LANGOPT(OpenMPNoNestedParallelism , 1, 0, "Assume that no thread in a parallel region will encounter a parallel region")
LANGOPT(OpenMPOffloadMandatory , 1, 0, "Assert that offloading is mandatory and do not create a host fallback.")
LANGOPT(OpenMPForceUSM , 1, 0, "Enable OpenMP unified shared memory mode via compiler.")
LANGOPT(NoGPULib , 1, 0, "Indicate a build without the standard GPU libraries.")
LANGOPT(RenderScript , 1, 0, "RenderScript")
@ -308,7 +309,8 @@ BENIGN_LANGOPT(IgnoreXCOFFVisibility, 1, 0, "All the visibility attributes that
BENIGN_LANGOPT(VisibilityInlinesHiddenStaticLocalVar, 1, 0,
"hidden visibility for static local variables in inline C++ "
"methods when -fvisibility-inlines hidden is enabled")
LANGOPT(GlobalAllocationFunctionVisibilityHidden , 1, 0, "hidden visibility for global operator new and delete declaration")
ENUM_LANGOPT(GlobalAllocationFunctionVisibility, VisibilityForcedKinds, 3, VisibilityForcedKinds::ForceDefault,
"How to apply visibility to global operator new and delete declarations")
LANGOPT(NewInfallible , 1, 0, "Treats throwing global C++ operator new as always returning valid memory (annotates with __attribute__((returns_nonnull)) and throw()). This is detectable in source.")
BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype")
BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support")
@ -359,16 +361,16 @@ BENIGN_ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility,
"default visibility for types [-ftype-visibility]")
LANGOPT(SetVisibilityForExternDecls, 1, 0,
"apply global symbol visibility to external declarations without an explicit visibility")
LANGOPT(VisibilityFromDLLStorageClass, 1, 0,
"set the visiblity of globals from their DLL storage class [-fvisibility-from-dllstorageclass]")
ENUM_LANGOPT(DLLExportVisibility, Visibility, 3, DefaultVisibility,
"visibility for functions and variables with dllexport annotations [-fvisibility-from-dllstorageclass]")
ENUM_LANGOPT(NoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility,
"visibility for functions and variables without an explicit DLL storage class [-fvisibility-from-dllstorageclass]")
ENUM_LANGOPT(ExternDeclDLLImportVisibility, Visibility, 3, DefaultVisibility,
"visibility for external declarations with dllimport annotations [-fvisibility-from-dllstorageclass]")
ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility,
"visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]")
BENIGN_LANGOPT(VisibilityFromDLLStorageClass, 1, 0,
"override the visibility of globals based on their final DLL storage class [-fvisibility-from-dllstorageclass]")
BENIGN_ENUM_LANGOPT(DLLExportVisibility, VisibilityFromDLLStorageClassKinds, 3, VisibilityFromDLLStorageClassKinds::Default,
"how to adjust the visibility for functions and variables with dllexport annotations [-fvisibility-dllexport]")
BENIGN_ENUM_LANGOPT(NoDLLStorageClassVisibility, VisibilityFromDLLStorageClassKinds, 3, VisibilityFromDLLStorageClassKinds::Hidden,
"how to adjust the visibility for functions and variables without an explicit DLL storage class [-fvisibility-nodllstorageclass]")
BENIGN_ENUM_LANGOPT(ExternDeclDLLImportVisibility, VisibilityFromDLLStorageClassKinds, 3, VisibilityFromDLLStorageClassKinds::Default,
"how to adjust the visibility for external declarations with dllimport annotations [-fvisibility-externs-dllimport]")
BENIGN_ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, VisibilityFromDLLStorageClassKinds, 3, VisibilityFromDLLStorageClassKinds::Hidden,
"how to adjust the visibility for external declarations without an explicit DLL storage class [-fvisibility-externs-nodllstorageclass]")
BENIGN_LANGOPT(SemanticInterposition , 1, 0, "semantic interposition")
BENIGN_LANGOPT(HalfNoSemanticInterposition, 1, 0,
"Like -fno-semantic-interposition but don't use local aliases")
@ -378,6 +380,8 @@ ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKi
"trivial automatic variable initialization")
VALUE_LANGOPT(TrivialAutoVarInitStopAfter, 32, 0,
"stop trivial automatic variable initialization after the specified number of instances. Must be greater than 0.")
VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
"stop trivial automatic variable initialization if var size exceeds the specified size (in bytes). Must be greater than 0.")
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
"signed integer overflow handling")
ENUM_LANGOPT(ThreadModel , ThreadModelKind, 2, ThreadModelKind::POSIX, "Thread Model")

View File

@ -381,6 +381,28 @@ public:
All,
};
enum class VisibilityForcedKinds {
/// Force hidden visibility
ForceHidden,
/// Force protected visibility
ForceProtected,
/// Force default visibility
ForceDefault,
/// Don't alter the visibility
Source,
};
enum class VisibilityFromDLLStorageClassKinds {
/// Keep the IR-gen assigned visibility.
Keep,
/// Override the IR-gen assigned visibility with default visibility.
Default,
/// Override the IR-gen assigned visibility with hidden visibility.
Hidden,
/// Override the IR-gen assigned visibility with protected visibility.
Protected,
};
enum class StrictFlexArraysLevelKind {
/// Any trailing array member is a FAM.
Default = 0,
@ -392,7 +414,7 @@ public:
IncompleteOnly = 3,
};
enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran };
enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran, CX_None };
public:
/// The used language standard.
@ -662,6 +684,26 @@ public:
DefaultVisiblityExportMapping::All;
}
bool hasGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() !=
VisibilityForcedKinds::Source;
}
bool hasDefaultGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() ==
VisibilityForcedKinds::ForceDefault;
}
bool hasProtectedGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() ==
VisibilityForcedKinds::ForceProtected;
}
bool hasHiddenGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() ==
VisibilityForcedKinds::ForceHidden;
}
/// Remap path prefix according to -fmacro-prefix-path option.
void remapPathPrefix(SmallVectorImpl<char> &Path) const;

View File

@ -211,7 +211,13 @@ public:
case GCC:
return false;
case GNUstep:
return false;
// This could be enabled for all versions, except for the fact that the
// implementation of `objc_retain` and friends prior to 2.2 call [object
// retain] in their fall-back paths, which leads to infinite recursion if
// the runtime is built with this enabled. Since distributions typically
// build all Objective-C things with the same compiler version and flags,
// it's better to be conservative here.
return (getVersion() >= VersionTuple(2, 2));
case ObjFW:
return false;
}
@ -248,7 +254,7 @@ public:
case GCC:
return false;
case GNUstep:
return false;
return getVersion() >= VersionTuple(2, 2);
case ObjFW:
return false;
}
@ -266,6 +272,8 @@ public:
return getVersion() >= VersionTuple(12, 2);
case WatchOS:
return getVersion() >= VersionTuple(5, 2);
case GNUstep:
return getVersion() >= VersionTuple(2, 2);
default:
return false;
}
@ -463,7 +471,8 @@ public:
case iOS: return true;
case WatchOS: return true;
case GCC: return false;
case GNUstep: return false;
case GNUstep:
return (getVersion() >= VersionTuple(2, 2));
case ObjFW: return false;
}
llvm_unreachable("bad kind");

View File

@ -14,6 +14,9 @@
#ifndef LLVM_CLANG_BASIC_OPENACCKINDS_H
#define LLVM_CLANG_BASIC_OPENACCKINDS_H
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
// Represents the Construct/Directive kind of a pragma directive. Note the
// OpenACC standard is inconsistent between calling these Construct vs
@ -62,6 +65,75 @@ enum class OpenACCDirectiveKind {
Invalid,
};
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
OpenACCDirectiveKind K) {
switch (K) {
case OpenACCDirectiveKind::Parallel:
return Out << "parallel";
case OpenACCDirectiveKind::Serial:
return Out << "serial";
case OpenACCDirectiveKind::Kernels:
return Out << "kernels";
case OpenACCDirectiveKind::Data:
return Out << "data";
case OpenACCDirectiveKind::EnterData:
return Out << "enter data";
case OpenACCDirectiveKind::ExitData:
return Out << "exit data";
case OpenACCDirectiveKind::HostData:
return Out << "host_data";
case OpenACCDirectiveKind::Loop:
return Out << "loop";
case OpenACCDirectiveKind::Cache:
return Out << "cache";
case OpenACCDirectiveKind::ParallelLoop:
return Out << "parallel loop";
case OpenACCDirectiveKind::SerialLoop:
return Out << "serial loop";
case OpenACCDirectiveKind::KernelsLoop:
return Out << "kernels loop";
case OpenACCDirectiveKind::Atomic:
return Out << "atomic";
case OpenACCDirectiveKind::Declare:
return Out << "declare";
case OpenACCDirectiveKind::Init:
return Out << "init";
case OpenACCDirectiveKind::Shutdown:
return Out << "shutdown";
case OpenACCDirectiveKind::Set:
return Out << "set";
case OpenACCDirectiveKind::Update:
return Out << "update";
case OpenACCDirectiveKind::Wait:
return Out << "wait";
case OpenACCDirectiveKind::Routine:
return Out << "routine";
case OpenACCDirectiveKind::Invalid:
return Out << "<invalid>";
}
llvm_unreachable("Uncovered directive kind");
}
enum class OpenACCAtomicKind {
Read,
Write,
@ -82,11 +154,9 @@ enum class OpenACCClauseKind {
Independent,
/// 'auto' clause, allowed on 'loop' directives.
Auto,
/// 'worker' clause, allowed on 'loop' and 'routine' directives.
/// 'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
Worker,
/// 'vector' clause, allowed on 'loop' and 'routine' directives. Takes no
/// arguments for 'routine', so the 'loop' version is not yet implemented
/// completely.
/// 'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
Vector,
/// 'nohost' clause, allowed on 'routine' directives.
NoHost,
@ -98,10 +168,203 @@ enum class OpenACCClauseKind {
If,
/// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
Self,
/// 'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and
/// 'declare'.
Copy,
/// 'use_device' clause, allowed on 'host_data' construct.
UseDevice,
/// 'attach' clause, allowed on Compute and Combined constructs, plus 'data'
/// and 'enter data'.
Attach,
/// 'delete' clause, allowed on the 'exit data' construct.
Delete,
/// 'detach' clause, allowed on the 'exit data' construct.
Detach,
/// 'device' clause, allowed on the 'update' construct.
Device,
/// 'deviceptr' clause, allowed on Compute and Combined Constructs, plus
/// 'data' and 'declare'.
DevicePtr,
/// 'device_resident' clause, allowed on the 'declare' construct.
DeviceResident,
/// 'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop',
/// and 'serial loop' constructs.
FirstPrivate,
/// 'host' clause, allowed on 'update' construct.
Host,
/// 'link' clause, allowed on 'declare' construct.
Link,
/// 'no_create' clause, allowed on allowed on Compute and Combined constructs,
/// plus 'data'.
NoCreate,
/// 'present' clause, allowed on Compute and Combined constructs, plus 'data'
/// and 'declare'.
Present,
/// 'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel
/// loop', and 'serial loop' constructs.
Private,
/// 'copyout' clause, allowed on Compute and Combined constructs, plus 'data',
/// 'exit data', and 'declare'.
CopyOut,
/// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
/// 'enter data', and 'declare'.
CopyIn,
/// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
/// 'enter data', and 'declare'.
Create,
/// 'reduction' clause, allowed on Parallel, Serial, Loop, and the combined
/// constructs.
Reduction,
/// 'collapse' clause, allowed on 'loop' and Combined constructs.
Collapse,
/// 'bind' clause, allowed on routine constructs.
Bind,
/// 'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop',
/// and 'kernels loop' constructs.
VectorLength,
/// 'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and
/// 'kernels loop' constructs.
NumGangs,
/// 'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop',
/// and 'kernels loop' constructs.
NumWorkers,
/// 'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
DeviceNum,
/// 'default_async' clause, allowed on 'set' construct.
DefaultAsync,
/// 'device_type' clause, allowed on Constructs, 'data', 'init', 'shutdown',
/// 'set', update', 'loop', 'routine', and Combined constructs.
DeviceType,
/// 'dtype' clause, an alias for 'device_type', stored separately for
/// diagnostic purposes.
DType,
/// Represents an invalid clause, for the purposes of parsing.
Invalid,
};
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
OpenACCClauseKind K) {
switch (K) {
case OpenACCClauseKind::Finalize:
return Out << "finalize";
case OpenACCClauseKind::IfPresent:
return Out << "if_present";
case OpenACCClauseKind::Seq:
return Out << "seq";
case OpenACCClauseKind::Independent:
return Out << "independent";
case OpenACCClauseKind::Auto:
return Out << "auto";
case OpenACCClauseKind::Worker:
return Out << "worker";
case OpenACCClauseKind::Vector:
return Out << "vector";
case OpenACCClauseKind::NoHost:
return Out << "nohost";
case OpenACCClauseKind::Default:
return Out << "default";
case OpenACCClauseKind::If:
return Out << "if";
case OpenACCClauseKind::Self:
return Out << "self";
case OpenACCClauseKind::Copy:
return Out << "copy";
case OpenACCClauseKind::UseDevice:
return Out << "use_device";
case OpenACCClauseKind::Attach:
return Out << "attach";
case OpenACCClauseKind::Delete:
return Out << "delete";
case OpenACCClauseKind::Detach:
return Out << "detach";
case OpenACCClauseKind::Device:
return Out << "device";
case OpenACCClauseKind::DevicePtr:
return Out << "deviceptr";
case OpenACCClauseKind::DeviceResident:
return Out << "device_resident";
case OpenACCClauseKind::FirstPrivate:
return Out << "firstprivate";
case OpenACCClauseKind::Host:
return Out << "host";
case OpenACCClauseKind::Link:
return Out << "link";
case OpenACCClauseKind::NoCreate:
return Out << "no_create";
case OpenACCClauseKind::Present:
return Out << "present";
case OpenACCClauseKind::Private:
return Out << "private";
case OpenACCClauseKind::CopyOut:
return Out << "copyout";
case OpenACCClauseKind::CopyIn:
return Out << "copyin";
case OpenACCClauseKind::Create:
return Out << "create";
case OpenACCClauseKind::Reduction:
return Out << "reduction";
case OpenACCClauseKind::Collapse:
return Out << "collapse";
case OpenACCClauseKind::Bind:
return Out << "bind";
case OpenACCClauseKind::VectorLength:
return Out << "vector_length";
case OpenACCClauseKind::NumGangs:
return Out << "num_gangs";
case OpenACCClauseKind::NumWorkers:
return Out << "num_workers";
case OpenACCClauseKind::DeviceNum:
return Out << "device_num";
case OpenACCClauseKind::DefaultAsync:
return Out << "default_async";
case OpenACCClauseKind::DeviceType:
return Out << "device_type";
case OpenACCClauseKind::DType:
return Out << "dtype";
case OpenACCClauseKind::Invalid:
return Out << "<invalid>";
}
llvm_unreachable("Uncovered clause kind");
}
enum class OpenACCDefaultClauseKind {
/// 'none' option.
None,
@ -110,6 +373,29 @@ enum class OpenACCDefaultClauseKind {
/// Not a valid option.
Invalid,
};
enum class OpenACCReductionOperator {
/// '+'.
Addition,
/// '*'.
Multiplication,
/// 'max'.
Max,
/// 'min'.
Min,
/// '&'.
BitwiseAnd,
/// '|'.
BitwiseOr,
/// '^'.
BitwiseXOr,
/// '&&'.
And,
/// '||'.
Or,
/// Invalid Reduction Clause Kind.
Invalid,
};
} // namespace clang
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H

View File

@ -291,7 +291,9 @@ namespace clang {
bool isZExtReturn() const { return Flags & IsZExtReturn; }
bool isByteIndexed() const { return Flags & IsByteIndexed; }
bool isOverloadNone() const { return Flags & IsOverloadNone; }
bool isOverloadWhile() const { return Flags & IsOverloadWhile; }
bool isOverloadWhileOrMultiVecCvt() const {
return Flags & IsOverloadWhileOrMultiVecCvt;
}
bool isOverloadDefault() const { return !(Flags & OverloadKindMask); }
bool isOverloadWhileRW() const { return Flags & IsOverloadWhileRW; }
bool isOverloadCvt() const { return Flags & IsOverloadCvt; }

View File

@ -760,10 +760,11 @@ KEYWORD(__builtin_available , KEYALL)
KEYWORD(__builtin_sycl_unique_stable_name, KEYSYCL)
// Keywords defined by Attr.td.
// The "EMPTY ## X" is used to prevent early macro-expansion of the keyword.
#ifndef KEYWORD_ATTRIBUTE
#define KEYWORD_ATTRIBUTE(X) KEYWORD(X, KEYALL)
#define KEYWORD_ATTRIBUTE(X, HASARG, EMPTY) KEYWORD(EMPTY ## X, KEYALL)
#endif
#include "clang/Basic/AttrTokenKinds.inc"
#include "clang/Basic/RegularKeywordAttrInfo.inc"
// Clang-specific keywords enabled only in testing.
TESTING_KEYWORD(__unknown_anytype , KEYALL)

View File

@ -109,8 +109,8 @@ bool isPragmaAnnotation(TokenKind K);
inline constexpr bool isRegularKeywordAttribute(TokenKind K) {
return (false
#define KEYWORD_ATTRIBUTE(X) || (K == tok::kw_##X)
#include "clang/Basic/AttrTokenKinds.inc"
#define KEYWORD_ATTRIBUTE(X, ...) || (K == tok::kw_##X)
#include "clang/Basic/RegularKeywordAttrInfo.inc"
);
}

View File

@ -21,19 +21,19 @@ include "arm_sve_sme_incl.td"
multiclass ZALoad<string n_suffix, string t, string i_prefix, list<ImmCheck> ch> {
let TargetGuard = "sme" in {
def NAME # _H : MInst<"svld1_hor_" # n_suffix, "vimPQ", t,
[IsLoad, IsOverloadNone, IsStreaming, IsSharedZA],
[IsLoad, IsOverloadNone, IsStreaming, IsInOutZA],
MemEltTyDefault, i_prefix # "_horiz", ch>;
def NAME # _H_VNUM : MInst<"svld1_hor_vnum_" # n_suffix, "vimPQl", t,
[IsLoad, IsOverloadNone, IsStreaming, IsSharedZA],
[IsLoad, IsOverloadNone, IsStreaming, IsInOutZA],
MemEltTyDefault, i_prefix # "_horiz", ch>;
def NAME # _V : MInst<"svld1_ver_" # n_suffix, "vimPQ", t,
[IsLoad, IsOverloadNone, IsStreaming, IsSharedZA],
[IsLoad, IsOverloadNone, IsStreaming, IsInOutZA],
MemEltTyDefault, i_prefix # "_vert", ch>;
def NAME # _V_VNUM : MInst<"svld1_ver_vnum_" # n_suffix, "vimPQl", t,
[IsLoad, IsOverloadNone, IsStreaming, IsSharedZA],
[IsLoad, IsOverloadNone, IsStreaming, IsInOutZA],
MemEltTyDefault, i_prefix # "_vert", ch>;
}
}
@ -45,11 +45,11 @@ defm SVLD1_ZA64 : ZALoad<"za64", "l", "aarch64_sme_ld1d", [ImmCheck<0, ImmCheck0
defm SVLD1_ZA128 : ZALoad<"za128", "q", "aarch64_sme_ld1q", [ImmCheck<0, ImmCheck0_15>]>;
def SVLDR_VNUM_ZA : MInst<"svldr_vnum_za", "vmQl", "",
[IsOverloadNone, IsStreamingCompatible, IsSharedZA],
[IsOverloadNone, IsStreamingCompatible, IsInOutZA],
MemEltTyDefault, "aarch64_sme_ldr">;
def SVLDR_ZA : MInst<"svldr_za", "vmQ", "",
[IsOverloadNone, IsStreamingCompatible, IsSharedZA],
[IsOverloadNone, IsStreamingCompatible, IsInOutZA],
MemEltTyDefault, "aarch64_sme_ldr", []>;
////////////////////////////////////////////////////////////////////////////////
@ -58,19 +58,19 @@ def SVLDR_ZA : MInst<"svldr_za", "vmQ", "",
multiclass ZAStore<string n_suffix, string t, string i_prefix, list<ImmCheck> ch> {
let TargetGuard = "sme" in {
def NAME # _H : MInst<"svst1_hor_" # n_suffix, "vimP%", t,
[IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA],
[IsStore, IsOverloadNone, IsStreaming, IsInZA],
MemEltTyDefault, i_prefix # "_horiz", ch>;
def NAME # _H_VNUM : MInst<"svst1_hor_vnum_" # n_suffix, "vimP%l", t,
[IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA],
[IsStore, IsOverloadNone, IsStreaming, IsInZA],
MemEltTyDefault, i_prefix # "_horiz", ch>;
def NAME # _V : MInst<"svst1_ver_" # n_suffix, "vimP%", t,
[IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA],
[IsStore, IsOverloadNone, IsStreaming, IsInZA],
MemEltTyDefault, i_prefix # "_vert", ch>;
def NAME # _V_VNUM : MInst<"svst1_ver_vnum_" # n_suffix, "vimP%l", t,
[IsStore, IsOverloadNone, IsStreaming, IsSharedZA, IsPreservesZA],
[IsStore, IsOverloadNone, IsStreaming, IsInZA],
MemEltTyDefault, i_prefix # "_vert", ch>;
}
}
@ -82,11 +82,11 @@ defm SVST1_ZA64 : ZAStore<"za64", "l", "aarch64_sme_st1d", [ImmCheck<0, ImmCheck
defm SVST1_ZA128 : ZAStore<"za128", "q", "aarch64_sme_st1q", [ImmCheck<0, ImmCheck0_15>]>;
def SVSTR_VNUM_ZA : MInst<"svstr_vnum_za", "vm%l", "",
[IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA],
[IsOverloadNone, IsStreamingCompatible, IsInZA],
MemEltTyDefault, "aarch64_sme_str">;
def SVSTR_ZA : MInst<"svstr_za", "vm%", "",
[IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA],
[IsOverloadNone, IsStreamingCompatible, IsInZA],
MemEltTyDefault, "aarch64_sme_str", []>;
////////////////////////////////////////////////////////////////////////////////
@ -96,11 +96,11 @@ multiclass ZARead<string n_suffix, string t, string i_prefix, list<ImmCheck> ch>
let TargetGuard = "sme" in {
def NAME # _H : SInst<"svread_hor_" # n_suffix # "[_{d}]", "ddPim", t,
MergeOp1, i_prefix # "_horiz",
[IsReadZA, IsStreaming, IsSharedZA, IsPreservesZA], ch>;
[IsReadZA, IsStreaming, IsInZA], ch>;
def NAME # _V : SInst<"svread_ver_" # n_suffix # "[_{d}]", "ddPim", t,
MergeOp1, i_prefix # "_vert",
[IsReadZA, IsStreaming, IsSharedZA, IsPreservesZA], ch>;
[IsReadZA, IsStreaming, IsInZA], ch>;
}
}
@ -117,11 +117,11 @@ multiclass ZAWrite<string n_suffix, string t, string i_prefix, list<ImmCheck> ch
let TargetGuard = "sme" in {
def NAME # _H : SInst<"svwrite_hor_" # n_suffix # "[_{d}]", "vimPd", t,
MergeOp1, i_prefix # "_horiz",
[IsWriteZA, IsStreaming, IsSharedZA], ch>;
[IsWriteZA, IsStreaming, IsInOutZA], ch>;
def NAME # _V : SInst<"svwrite_ver_" # n_suffix # "[_{d}]", "vimPd", t,
MergeOp1, i_prefix # "_vert",
[IsWriteZA, IsStreaming, IsSharedZA], ch>;
[IsWriteZA, IsStreaming, IsInOutZA], ch>;
}
}
@ -136,10 +136,10 @@ defm SVWRITE_ZA128 : ZAWrite<"za128", "csilUcUsUiUlhbfd", "aarch64_sme_writeq",
let TargetGuard = "sme" in {
def SVZERO_MASK_ZA : SInst<"svzero_mask_za", "vi", "", MergeNone, "aarch64_sme_zero",
[IsOverloadNone, IsStreamingCompatible, IsSharedZA],
[IsOverloadNone, IsStreamingCompatible, IsInOutZA],
[ImmCheck<0, ImmCheck0_255>]>;
def SVZERO_ZA : SInst<"svzero_za", "v", "", MergeNone, "aarch64_sme_zero",
[IsOverloadNone, IsStreamingCompatible, IsSharedZA]>;
[IsOverloadNone, IsStreamingCompatible, IsOutZA]>;
}
////////////////////////////////////////////////////////////////////////////////
@ -149,7 +149,7 @@ multiclass ZACount<string n_suffix> {
let TargetGuard = "sme" in {
def NAME : SInst<"sv" # n_suffix, "nv", "", MergeNone,
"aarch64_sme_" # n_suffix,
[IsOverloadNone, IsStreamingCompatible, IsPreservesZA]>;
[IsOverloadNone, IsStreamingCompatible]>;
}
}
@ -164,13 +164,13 @@ defm SVCNTSD : ZACount<"cntsd">;
multiclass ZAAdd<string n_suffix> {
let TargetGuard = "sme" in {
def NAME # _ZA32: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPd", "iUi", MergeOp1,
"aarch64_sme_" # n_suffix, [IsStreaming, IsSharedZA],
"aarch64_sme_" # n_suffix, [IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_3>]>;
}
let TargetGuard = "sme-i16i64" in {
def NAME # _ZA64: SInst<"sv" # n_suffix # "_za64[_{d}]", "viPPd", "lUl", MergeOp1,
"aarch64_sme_" # n_suffix, [IsStreaming, IsSharedZA],
"aarch64_sme_" # n_suffix, [IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_7>]>;
}
}
@ -186,7 +186,7 @@ multiclass ZAIntOuterProd<string n_suffix1, string n_suffix2> {
def NAME # _ZA32_B: SInst<"sv" # n_suffix2 # "_za32[_{d}]",
"viPPdd", !cond(!eq(n_suffix1, "s") : "", true: "U") # "c",
MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide",
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_3>]>;
}
@ -194,7 +194,7 @@ multiclass ZAIntOuterProd<string n_suffix1, string n_suffix2> {
def NAME # _ZA64_H: SInst<"sv" # n_suffix2 # "_za64[_{d}]",
"viPPdd", !cond(!eq(n_suffix1, "s") : "", true: "U") # "s",
MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide",
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_7>]>;
}
}
@ -213,7 +213,7 @@ multiclass ZAIntOuterProdMixedSigns<string n_suffix1, string n_suffix2> {
"viPPd" # !cond(!eq(n_suffix1, "su") : "u", true: "x"),
!cond(!eq(n_suffix1, "su") : "", true: "U") # "c",
MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide",
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_3>]>;
}
@ -222,7 +222,7 @@ multiclass ZAIntOuterProdMixedSigns<string n_suffix1, string n_suffix2> {
"viPPd" # !cond(!eq(n_suffix1, "su") : "u", true: "x"),
!cond(!eq(n_suffix1, "su") : "", true: "U") # "s",
MergeOp1, "aarch64_sme_" # n_suffix1 # n_suffix2 # "_wide",
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_7>]>;
}
}
@ -239,24 +239,24 @@ multiclass ZAFPOuterProd<string n_suffix> {
let TargetGuard = "sme" in {
def NAME # _ZA32_B: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPdd", "h",
MergeOp1, "aarch64_sme_" # n_suffix # "_wide",
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_3>]>;
def NAME # _ZA32_H: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPdd", "b",
MergeOp1, "aarch64_sme_" # n_suffix # "_wide",
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_3>]>;
def NAME # _ZA32_S: SInst<"sv" # n_suffix # "_za32[_{d}]", "viPPdd", "f",
MergeOp1, "aarch64_sme_" # n_suffix,
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_3>]>;
}
let TargetGuard = "sme-f64f64" in {
def NAME # _ZA64_D: SInst<"sv" # n_suffix # "_za64[_{d}]", "viPPdd", "d",
MergeOp1, "aarch64_sme_" # n_suffix,
[IsStreaming, IsSharedZA],
[IsStreaming, IsInOutZA],
[ImmCheck<0, ImmCheck0_7>]>;
}
}
@ -269,29 +269,29 @@ defm SVMOPS : ZAFPOuterProd<"mops">;
multiclass ZAAddSub<string n_suffix> {
let TargetGuard = "sme2" in {
def NAME # _WRITE_SINGLE_ZA32_VG1X2_I32 : Inst<"sv" # n_suffix # "_write[_single]_za32[_{d}]_vg1x2", "vm2d", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_SINGLE_ZA32_VG1X4_I32 : Inst<"sv" # n_suffix # "_write[_single]_za32[_{d}]_vg1x4", "vm4d", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_SINGLE_ZA32_VG1X2_I32 : Inst<"sv" # n_suffix # "_write[_single]_za32[_{d}]_vg1x2", "vm2d", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _WRITE_SINGLE_ZA32_VG1X4_I32 : Inst<"sv" # n_suffix # "_write[_single]_za32[_{d}]_vg1x4", "vm4d", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x4", [IsStreaming, IsInOutZA], []>;
def NAME # _WRITE_ZA32_VG1X2_I32 : Inst<"sv" # n_suffix # "_write_za32[_{d}]_vg1x2", "vm22", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_ZA32_VG1X4_I32 : Inst<"sv" # n_suffix # "_write_za32[_{d}]_vg1x4", "vm44", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_ZA32_VG1X2_I32 : Inst<"sv" # n_suffix # "_write_za32[_{d}]_vg1x2", "vm22", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _WRITE_ZA32_VG1X4_I32 : Inst<"sv" # n_suffix # "_write_za32[_{d}]_vg1x4", "vm44", "iUi", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x4", [IsStreaming, IsInOutZA], []>;
def NAME # _ZA32_VG1x2_I32 : Inst<"sv" # n_suffix # "_za32[_{d}]_vg1x2", "vm2", "iUif", MergeNone, "aarch64_sme_" # n_suffix # "_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _ZA32_VG1X4_I32 : Inst<"sv" # n_suffix # "_za32[_{d}]_vg1x4", "vm4", "iUif", MergeNone, "aarch64_sme_" # n_suffix # "_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _ZA32_VG1x2_I32 : Inst<"sv" # n_suffix # "_za32[_{d}]_vg1x2", "vm2", "iUif", MergeNone, "aarch64_sme_" # n_suffix # "_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _ZA32_VG1X4_I32 : Inst<"sv" # n_suffix # "_za32[_{d}]_vg1x4", "vm4", "iUif", MergeNone, "aarch64_sme_" # n_suffix # "_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
let TargetGuard = "sme-i16i64" in {
def NAME # _WRITE_SINGLE_ZA64_VG1X2_I64 : Inst<"sv" # n_suffix # "_write[_single]_za64[_{d}]_vg1x2", "vm2d", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_SINGLE_ZA64_VG1X4_I64 : Inst<"sv" # n_suffix # "_write[_single]_za64[_{d}]_vg1x4", "vm4d", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_SINGLE_ZA64_VG1X2_I64 : Inst<"sv" # n_suffix # "_write[_single]_za64[_{d}]_vg1x2", "vm2d", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _WRITE_SINGLE_ZA64_VG1X4_I64 : Inst<"sv" # n_suffix # "_write[_single]_za64[_{d}]_vg1x4", "vm4d", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_single_za_vg1x4", [IsStreaming, IsInOutZA], []>;
def NAME # _WRITE_ZA64_VG1x2_I64 : Inst<"sv" # n_suffix # "_write_za64[_{d}]_vg1x2", "vm22", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_ZA64_VG1x4_I64 : Inst<"sv" # n_suffix # "_write_za64[_{d}]_vg1x4", "vm44", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _WRITE_ZA64_VG1x2_I64 : Inst<"sv" # n_suffix # "_write_za64[_{d}]_vg1x2", "vm22", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _WRITE_ZA64_VG1x4_I64 : Inst<"sv" # n_suffix # "_write_za64[_{d}]_vg1x4", "vm44", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_write_za_vg1x4", [IsStreaming, IsInOutZA], []>;
def NAME # _ZA64_VG1X2_I64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x2", "vm2", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _ZA64_VG1X4_I64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x4", "vm4", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _ZA64_VG1X2_I64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x2", "vm2", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _ZA64_VG1X4_I64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x4", "vm4", "lUl", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x4", [IsStreaming, IsInOutZA], []>;
}
let TargetGuard = "sme-f64f64" in {
def NAME # _ZA64_VG1X2_F64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x2", "vm2", "d", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x2", [IsStreaming, IsSharedZA], []>;
def NAME # _ZA64_VG1X4_F64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x4", "vm4", "d", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x4", [IsStreaming, IsSharedZA], []>;
def NAME # _ZA64_VG1X2_F64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x2", "vm2", "d", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x2", [IsStreaming, IsInOutZA], []>;
def NAME # _ZA64_VG1X4_F64 : Inst<"sv" # n_suffix # "_za64[_{d}]_vg1x4", "vm4", "d", MergeNone, "aarch64_sme_" # n_suffix # "_za64_vg1x4", [IsStreaming, IsInOutZA], []>;
}
}
}
@ -306,12 +306,12 @@ defm SVSUB : ZAAddSub<"sub">;
//
multiclass ZAWrite_VG<string n, string t, string i, list<ImmCheck> checks> {
def NAME # _VG2_H : Inst<"svwrite_hor_" # n # "[_{d}]_vg2", "vim2", t, MergeNone, i # "_hor_vg2", [IsSharedZA, IsStreaming], checks>;
def NAME # _VG2_V : Inst<"svwrite_ver_" # n # "[_{d}]_vg2", "vim2", t, MergeNone, i # "_ver_vg2", [IsSharedZA, IsStreaming], checks>;
def NAME # _VG4_H : Inst<"svwrite_hor_" # n # "[_{d}]_vg4", "vim4", t, MergeNone, i # "_hor_vg4", [IsSharedZA, IsStreaming], checks>;
def NAME # _VG4_V : Inst<"svwrite_ver_" # n # "[_{d}]_vg4", "vim4", t, MergeNone, i # "_ver_vg4", [IsSharedZA, IsStreaming], checks>;
def NAME # _VG1x2 : Inst<"svwrite_" # n # "[_{d}]_vg1x2", "vm2", t, MergeNone, i # "_vg1x2", [IsSharedZA, IsStreaming], []>;
def NAME # _VG1x4 : Inst<"svwrite_" # n # "[_{d}]_vg1x4", "vm4", t, MergeNone, i # "_vg1x4", [IsSharedZA, IsStreaming], []>;
def NAME # _VG2_H : Inst<"svwrite_hor_" # n # "[_{d}]_vg2", "vim2", t, MergeNone, i # "_hor_vg2", [IsInOutZA, IsStreaming], checks>;
def NAME # _VG2_V : Inst<"svwrite_ver_" # n # "[_{d}]_vg2", "vim2", t, MergeNone, i # "_ver_vg2", [IsInOutZA, IsStreaming], checks>;
def NAME # _VG4_H : Inst<"svwrite_hor_" # n # "[_{d}]_vg4", "vim4", t, MergeNone, i # "_hor_vg4", [IsInOutZA, IsStreaming], checks>;
def NAME # _VG4_V : Inst<"svwrite_ver_" # n # "[_{d}]_vg4", "vim4", t, MergeNone, i # "_ver_vg4", [IsInOutZA, IsStreaming], checks>;
def NAME # _VG1x2 : Inst<"svwrite_" # n # "[_{d}]_vg1x2", "vm2", t, MergeNone, i # "_vg1x2", [IsInOutZA, IsStreaming], []>;
def NAME # _VG1x4 : Inst<"svwrite_" # n # "[_{d}]_vg1x4", "vm4", t, MergeNone, i # "_vg1x4", [IsInOutZA, IsStreaming], []>;
}
let TargetGuard = "sme2" in {
@ -322,12 +322,12 @@ let TargetGuard = "sme2" in {
}
multiclass ZARead_VG<string n, string t, string i, list<ImmCheck> checks> {
def NAME # _VG2_H : Inst<"svread_hor_" # n # "_{d}_vg2", "2im", t, MergeNone, i # "_hor_vg2", [IsSharedZA, IsPreservesZA, IsStreaming], checks>;
def NAME # _VG2_V : Inst<"svread_ver_" # n # "_{d}_vg2", "2im", t, MergeNone, i # "_ver_vg2", [IsSharedZA, IsPreservesZA, IsStreaming], checks>;
def NAME # _VG4_H : Inst<"svread_hor_" # n # "_{d}_vg4", "4im", t, MergeNone, i # "_hor_vg4", [IsSharedZA, IsPreservesZA, IsStreaming], checks>;
def NAME # _VG4_V : Inst<"svread_ver_" # n # "_{d}_vg4", "4im", t, MergeNone, i # "_ver_vg4", [IsSharedZA, IsPreservesZA, IsStreaming], checks>;
def NAME # _VG1x2 : Inst<"svread_" # n # "_{d}_vg1x2", "2m", t, MergeNone, i # "_vg1x2", [IsSharedZA, IsPreservesZA, IsStreaming], []>;
def NAME # _VG1x4 : Inst<"svread_" # n # "_{d}_vg1x4", "4m", t, MergeNone, i # "_vg1x4", [IsSharedZA, IsPreservesZA, IsStreaming], []>;
def NAME # _VG2_H : Inst<"svread_hor_" # n # "_{d}_vg2", "2im", t, MergeNone, i # "_hor_vg2", [IsInZA, IsStreaming], checks>;
def NAME # _VG2_V : Inst<"svread_ver_" # n # "_{d}_vg2", "2im", t, MergeNone, i # "_ver_vg2", [IsInZA, IsStreaming], checks>;
def NAME # _VG4_H : Inst<"svread_hor_" # n # "_{d}_vg4", "4im", t, MergeNone, i # "_hor_vg4", [IsInZA, IsStreaming], checks>;
def NAME # _VG4_V : Inst<"svread_ver_" # n # "_{d}_vg4", "4im", t, MergeNone, i # "_ver_vg4", [IsInZA, IsStreaming], checks>;
def NAME # _VG1x2 : Inst<"svread_" # n # "_{d}_vg1x2", "2m", t, MergeNone, i # "_vg1x2", [IsInZA, IsStreaming], []>;
def NAME # _VG1x4 : Inst<"svread_" # n # "_{d}_vg1x4", "4m", t, MergeNone, i # "_vg1x4", [IsInZA, IsStreaming], []>;
}
let TargetGuard = "sme2" in {
@ -342,331 +342,331 @@ let TargetGuard = "sme2" in {
//
let TargetGuard = "sme2" in {
def SVSMOPA : Inst<"svmopa_za32[_{d}]_m", "viPPdd", "s", MergeNone, "aarch64_sme_smopa_za32", [IsSharedZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVUSMOPA : Inst<"svmopa_za32[_{d}]_m", "viPPdd", "Us", MergeNone, "aarch64_sme_umopa_za32", [IsSharedZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVSMOPA : Inst<"svmopa_za32[_{d}]_m", "viPPdd", "s", MergeNone, "aarch64_sme_smopa_za32", [IsInOutZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVUSMOPA : Inst<"svmopa_za32[_{d}]_m", "viPPdd", "Us", MergeNone, "aarch64_sme_umopa_za32", [IsInOutZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVSMOPS : Inst<"svmops_za32[_{d}]_m", "viPPdd", "s", MergeNone, "aarch64_sme_smops_za32", [IsSharedZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVUSMOPS : Inst<"svmops_za32[_{d}]_m", "viPPdd", "Us", MergeNone, "aarch64_sme_umops_za32", [IsSharedZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVSMOPS : Inst<"svmops_za32[_{d}]_m", "viPPdd", "s", MergeNone, "aarch64_sme_smops_za32", [IsInOutZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVUSMOPS : Inst<"svmops_za32[_{d}]_m", "viPPdd", "Us", MergeNone, "aarch64_sme_umops_za32", [IsInOutZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVBMOPA : Inst<"svbmopa_za32[_{d}]_m", "viPPdd", "iUi", MergeNone, "aarch64_sme_bmopa_za32", [IsSharedZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVBMOPA : Inst<"svbmopa_za32[_{d}]_m", "viPPdd", "iUi", MergeNone, "aarch64_sme_bmopa_za32", [IsInOutZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVBMOPS : Inst<"svbmops_za32[_{d}]_m", "viPPdd", "iUi", MergeNone, "aarch64_sme_bmops_za32", [IsSharedZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
def SVBMOPS : Inst<"svbmops_za32[_{d}]_m", "viPPdd", "iUi", MergeNone, "aarch64_sme_bmops_za32", [IsInOutZA, IsStreaming], [ImmCheck<0, ImmCheck0_3>]>;
// VERTICAL DOT-PRODUCT
def SVVDOT_LANE_ZA32_VG1x2_S : Inst<"svvdot_lane_za32[_{d}]_vg1x2", "vm2di", "s", MergeNone, "aarch64_sme_svdot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x4_S : Inst<"svvdot_lane_za32[_{d}]_vg1x4", "vm4di", "c", MergeNone, "aarch64_sme_svdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x2_U : Inst<"svvdot_lane_za32[_{d}]_vg1x2", "vm2di", "Us", MergeNone, "aarch64_sme_uvdot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x4_U : Inst<"svvdot_lane_za32[_{d}]_vg1x4", "vm4di", "Uc", MergeNone, "aarch64_sme_uvdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x2_F : Inst<"svvdot_lane_za32[_{d}]_vg1x2", "vm2di", "hb", MergeNone, "aarch64_sme_fvdot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVSUVDOT_LANE_ZA32_VG1x4 : Inst<"svsuvdot_lane_za32[_{d}]_vg1x4", "vm4di", "c", MergeNone, "aarch64_sme_suvdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVUSVDOT_LANE_ZA32_VG1x4 : Inst<"svusvdot_lane_za32[_{d}]_vg1x4", "vm4di", "Uc", MergeNone, "aarch64_sme_usvdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x2_S : Inst<"svvdot_lane_za32[_{d}]_vg1x2", "vm2di", "s", MergeNone, "aarch64_sme_svdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x4_S : Inst<"svvdot_lane_za32[_{d}]_vg1x4", "vm4di", "c", MergeNone, "aarch64_sme_svdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x2_U : Inst<"svvdot_lane_za32[_{d}]_vg1x2", "vm2di", "Us", MergeNone, "aarch64_sme_uvdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x4_U : Inst<"svvdot_lane_za32[_{d}]_vg1x4", "vm4di", "Uc", MergeNone, "aarch64_sme_uvdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVVDOT_LANE_ZA32_VG1x2_F : Inst<"svvdot_lane_za32[_{d}]_vg1x2", "vm2di", "hb", MergeNone, "aarch64_sme_fvdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVSUVDOT_LANE_ZA32_VG1x4 : Inst<"svsuvdot_lane_za32[_{d}]_vg1x4", "vm4di", "c", MergeNone, "aarch64_sme_suvdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVUSVDOT_LANE_ZA32_VG1x4 : Inst<"svusvdot_lane_za32[_{d}]_vg1x4", "vm4di", "Uc", MergeNone, "aarch64_sme_usvdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
// Multi-vector signed & unsigned integer dot-product
def SVDOT_MULTI_ZA32_VG1x2_S : Inst<"svdot_za32[_{d}]_vg1x2", "vm22", "cs", MergeNone, "aarch64_sme_sdot_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA32_VG1x4_S : Inst<"svdot_za32[_{d}]_vg1x4", "vm44", "cs", MergeNone, "aarch64_sme_sdot_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA32_VG1x2_U : Inst<"svdot_za32[_{d}]_vg1x2", "vm22", "UcUs", MergeNone, "aarch64_sme_udot_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA32_VG1x4_U : Inst<"svdot_za32[_{d}]_vg1x4", "vm44", "UcUs", MergeNone, "aarch64_sme_udot_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA32_VG1x2_S : Inst<"svdot[_single]_za32[_{d}]_vg1x2", "vm2d", "cs", MergeNone, "aarch64_sme_sdot_single_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA32_VG1x4_S : Inst<"svdot[_single]_za32[_{d}]_vg1x4", "vm4d", "cs", MergeNone, "aarch64_sme_sdot_single_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA32_VG1x2_U : Inst<"svdot[_single]_za32[_{d}]_vg1x2", "vm2d", "UcUs", MergeNone, "aarch64_sme_udot_single_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA32_VG1x4_U : Inst<"svdot[_single]_za32[_{d}]_vg1x4", "vm4d", "UcUs", MergeNone, "aarch64_sme_udot_single_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_LANE_ZA32_VG1x2_S : Inst<"svdot_lane_za32[_{d}]_vg1x2", "vm2di", "cs", MergeNone, "aarch64_sme_sdot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x4_S : Inst<"svdot_lane_za32[_{d}]_vg1x4", "vm4di", "cs", MergeNone, "aarch64_sme_sdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x2_U : Inst<"svdot_lane_za32[_{d}]_vg1x2", "vm2di", "UcUs", MergeNone, "aarch64_sme_udot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x4_U : Inst<"svdot_lane_za32[_{d}]_vg1x4", "vm4di", "UcUs", MergeNone, "aarch64_sme_udot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_MULTI_ZA32_VG1x2_S : Inst<"svdot_za32[_{d}]_vg1x2", "vm22", "cs", MergeNone, "aarch64_sme_sdot_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA32_VG1x4_S : Inst<"svdot_za32[_{d}]_vg1x4", "vm44", "cs", MergeNone, "aarch64_sme_sdot_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA32_VG1x2_U : Inst<"svdot_za32[_{d}]_vg1x2", "vm22", "UcUs", MergeNone, "aarch64_sme_udot_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA32_VG1x4_U : Inst<"svdot_za32[_{d}]_vg1x4", "vm44", "UcUs", MergeNone, "aarch64_sme_udot_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA32_VG1x2_S : Inst<"svdot[_single]_za32[_{d}]_vg1x2", "vm2d", "cs", MergeNone, "aarch64_sme_sdot_single_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA32_VG1x4_S : Inst<"svdot[_single]_za32[_{d}]_vg1x4", "vm4d", "cs", MergeNone, "aarch64_sme_sdot_single_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA32_VG1x2_U : Inst<"svdot[_single]_za32[_{d}]_vg1x2", "vm2d", "UcUs", MergeNone, "aarch64_sme_udot_single_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA32_VG1x4_U : Inst<"svdot[_single]_za32[_{d}]_vg1x4", "vm4d", "UcUs", MergeNone, "aarch64_sme_udot_single_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_LANE_ZA32_VG1x2_S : Inst<"svdot_lane_za32[_{d}]_vg1x2", "vm2di", "cs", MergeNone, "aarch64_sme_sdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x4_S : Inst<"svdot_lane_za32[_{d}]_vg1x4", "vm4di", "cs", MergeNone, "aarch64_sme_sdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x2_U : Inst<"svdot_lane_za32[_{d}]_vg1x2", "vm2di", "UcUs", MergeNone, "aarch64_sme_udot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x4_U : Inst<"svdot_lane_za32[_{d}]_vg1x4", "vm4di", "UcUs", MergeNone, "aarch64_sme_udot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVUSDOT_SINGLE_ZA32_VG1x2 : Inst<"svusdot[_single]_za32[_{d}]_vg1x2", "vm2.dx", "Uc", MergeNone, "aarch64_sme_usdot_single_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVUSDOT_SINGLE_ZA32_VG1x4 : Inst<"svusdot[_single]_za32[_{d}]_vg1x4", "vm4.dx", "Uc", MergeNone, "aarch64_sme_usdot_single_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVUSDOT_MULTI_ZA32_VG1x2 : Inst<"svusdot_za32[_{d}]_vg1x2", "vm2.d2.x", "Uc", MergeNone, "aarch64_sme_usdot_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVUSDOT_MULTI_ZA32_VG1x4 : Inst<"svusdot_za32[_{d}]_vg1x4", "vm4.d4.x", "Uc", MergeNone, "aarch64_sme_usdot_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVUSDOT_LANE_ZA32_VG1x2 : Inst<"svusdot_lane_za32[_{d}]_vg1x2", "vm2.dxi", "Uc", MergeNone, "aarch64_sme_usdot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVUSDOT_LANE_ZA32_VG1x4 : Inst<"svusdot_lane_za32[_{d}]_vg1x4", "vm4.dxi", "Uc", MergeNone, "aarch64_sme_usdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVUSDOT_SINGLE_ZA32_VG1x2 : Inst<"svusdot[_single]_za32[_{d}]_vg1x2", "vm2.dx", "Uc", MergeNone, "aarch64_sme_usdot_single_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVUSDOT_SINGLE_ZA32_VG1x4 : Inst<"svusdot[_single]_za32[_{d}]_vg1x4", "vm4.dx", "Uc", MergeNone, "aarch64_sme_usdot_single_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVUSDOT_MULTI_ZA32_VG1x2 : Inst<"svusdot_za32[_{d}]_vg1x2", "vm2.d2.x", "Uc", MergeNone, "aarch64_sme_usdot_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVUSDOT_MULTI_ZA32_VG1x4 : Inst<"svusdot_za32[_{d}]_vg1x4", "vm4.d4.x", "Uc", MergeNone, "aarch64_sme_usdot_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVUSDOT_LANE_ZA32_VG1x2 : Inst<"svusdot_lane_za32[_{d}]_vg1x2", "vm2.dxi", "Uc", MergeNone, "aarch64_sme_usdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVUSDOT_LANE_ZA32_VG1x4 : Inst<"svusdot_lane_za32[_{d}]_vg1x4", "vm4.dxi", "Uc", MergeNone, "aarch64_sme_usdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVSUDOT_SINGLE_ZA32_VG1x2 : Inst<"svsudot[_single]_za32[_{d}]_vg1x2", "vm2.du", "c", MergeNone, "aarch64_sme_sudot_single_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVSUDOT_SINGLE_ZA32_VG1x4 : Inst<"svsudot[_single]_za32[_{d}]_vg1x4", "vm4.du", "c", MergeNone, "aarch64_sme_sudot_single_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVSUDOT_SINGLE_ZA32_VG1x2 : Inst<"svsudot[_single]_za32[_{d}]_vg1x2", "vm2.du", "c", MergeNone, "aarch64_sme_sudot_single_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVSUDOT_SINGLE_ZA32_VG1x4 : Inst<"svsudot[_single]_za32[_{d}]_vg1x4", "vm4.du", "c", MergeNone, "aarch64_sme_sudot_single_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
// Multi-multi sudot builtins are mapped to usdot, with zn & zm operands swapped
def SVSUDOT_MULTI_ZA32_VG1x2 : Inst<"svsudot_za32[_{d}]_vg1x2", "vm2.d2.u", "c", MergeNone, "aarch64_sme_usdot_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVSUDOT_MULTI_ZA32_VG1x4 : Inst<"svsudot_za32[_{d}]_vg1x4", "vm4.d4.u", "c", MergeNone, "aarch64_sme_usdot_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVSUDOT_MULTI_ZA32_VG1x2 : Inst<"svsudot_za32[_{d}]_vg1x2", "vm2.d2.u", "c", MergeNone, "aarch64_sme_usdot_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVSUDOT_MULTI_ZA32_VG1x4 : Inst<"svsudot_za32[_{d}]_vg1x4", "vm4.d4.u", "c", MergeNone, "aarch64_sme_usdot_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVSUDOT_LANE_ZA32_VG1x2 : Inst<"svsudot_lane_za32[_{d}]_vg1x2", "vm2.dui", "c", MergeNone, "aarch64_sme_sudot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVSUDOT_LANE_ZA32_VG1x4 : Inst<"svsudot_lane_za32[_{d}]_vg1x4", "vm4.dui", "c", MergeNone, "aarch64_sme_sudot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVSUDOT_LANE_ZA32_VG1x2 : Inst<"svsudot_lane_za32[_{d}]_vg1x2", "vm2.dui", "c", MergeNone, "aarch64_sme_sudot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVSUDOT_LANE_ZA32_VG1x4 : Inst<"svsudot_lane_za32[_{d}]_vg1x4", "vm4.dui", "c", MergeNone, "aarch64_sme_sudot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
// Multi-vector half-precision/BFloat16 floating-point dot-product
def SVDOT_MULTI_ZA32_VG1x2_F16 : Inst<"svdot_za32[_{d}]_vg1x2", "vm22", "bh", MergeNone, "aarch64_sme_fdot_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA32_VG1x4_F16 : Inst<"svdot_za32[_{d}]_vg1x4", "vm44", "bh", MergeNone, "aarch64_sme_fdot_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA32_VG1x2_F16 : Inst<"svdot[_single]_za32[_{d}]_vg1x2", "vm2d", "bh", MergeNone, "aarch64_sme_fdot_single_za32_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA32_VG1x4_F16 : Inst<"svdot[_single]_za32[_{d}]_vg1x4", "vm4d", "bh", MergeNone, "aarch64_sme_fdot_single_za32_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_LANE_ZA32_VG1x2_F16 : Inst<"svdot_lane_za32[_{d}]_vg1x2", "vm2di", "bh", MergeNone, "aarch64_sme_fdot_lane_za32_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x4_F16 : Inst<"svdot_lane_za32[_{d}]_vg1x4", "vm4di", "bh", MergeNone, "aarch64_sme_fdot_lane_za32_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_MULTI_ZA32_VG1x2_F16 : Inst<"svdot_za32[_{d}]_vg1x2", "vm22", "bh", MergeNone, "aarch64_sme_fdot_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA32_VG1x4_F16 : Inst<"svdot_za32[_{d}]_vg1x4", "vm44", "bh", MergeNone, "aarch64_sme_fdot_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA32_VG1x2_F16 : Inst<"svdot[_single]_za32[_{d}]_vg1x2", "vm2d", "bh", MergeNone, "aarch64_sme_fdot_single_za32_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA32_VG1x4_F16 : Inst<"svdot[_single]_za32[_{d}]_vg1x4", "vm4d", "bh", MergeNone, "aarch64_sme_fdot_single_za32_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_LANE_ZA32_VG1x2_F16 : Inst<"svdot_lane_za32[_{d}]_vg1x2", "vm2di", "bh", MergeNone, "aarch64_sme_fdot_lane_za32_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_ZA32_VG1x4_F16 : Inst<"svdot_lane_za32[_{d}]_vg1x4", "vm4di", "bh", MergeNone, "aarch64_sme_fdot_lane_za32_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
}
let TargetGuard = "sme2,sme-i16i64" in {
def SVVDOT_LANE_ZA64_VG1x4_S : Inst<"svvdot_lane_za64[_{d}]_vg1x4", "vm4di", "s", MergeNone, "aarch64_sme_svdot_lane_za64_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVVDOT_LANE_ZA64_VG1x4_U : Inst<"svvdot_lane_za64[_{d}]_vg1x4", "vm4di", "Us", MergeNone, "aarch64_sme_uvdot_lane_za64_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVVDOT_LANE_ZA64_VG1x4_S : Inst<"svvdot_lane_za64[_{d}]_vg1x4", "vm4di", "s", MergeNone, "aarch64_sme_svdot_lane_za64_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVVDOT_LANE_ZA64_VG1x4_U : Inst<"svvdot_lane_za64[_{d}]_vg1x4", "vm4di", "Us", MergeNone, "aarch64_sme_uvdot_lane_za64_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_MULTI_ZA64_VG1x2_S16 : Inst<"svdot_za64[_{d}]_vg1x2", "vm22", "s", MergeNone, "aarch64_sme_sdot_za64_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA64_VG1x4_S16 : Inst<"svdot_za64[_{d}]_vg1x4", "vm44", "s", MergeNone, "aarch64_sme_sdot_za64_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA64_VG1x2_U16 : Inst<"svdot_za64[_{d}]_vg1x2", "vm22", "Us", MergeNone, "aarch64_sme_udot_za64_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_MULTI_ZA64_VG1x4_U16 : Inst<"svdot_za64[_{d}]_vg1x4", "vm44", "Us", MergeNone, "aarch64_sme_udot_za64_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA64_VG1x2_S16 : Inst<"svdot[_single]_za64[_{d}]_vg1x2", "vm2d", "s", MergeNone, "aarch64_sme_sdot_single_za64_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA64_VG1x4_S16 : Inst<"svdot[_single]_za64[_{d}]_vg1x4", "vm4d", "s", MergeNone, "aarch64_sme_sdot_single_za64_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA64_VG1x2_U16 : Inst<"svdot[_single]_za64[_{d}]_vg1x2", "vm2d", "Us", MergeNone, "aarch64_sme_udot_single_za64_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVDOT_SINGLE_ZA64_VG1x4_U16 : Inst<"svdot[_single]_za64[_{d}]_vg1x4", "vm4d", "Us", MergeNone, "aarch64_sme_udot_single_za64_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVDOT_LANE_ZA64_VG1x2_S16 : Inst<"svdot_lane_za64[_{d}]_vg1x2", "vm2di", "s", MergeNone, "aarch64_sme_sdot_lane_za64_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_LANE_ZA64_VG1x4_S16 : Inst<"svdot_lane_za64[_{d}]_vg1x4", "vm4di", "s", MergeNone, "aarch64_sme_sdot_lane_za64_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_LANE_ZA64_VG1x2_U16 : Inst<"svdot_lane_za64[_{d}]_vg1x2", "vm2di", "Us", MergeNone, "aarch64_sme_udot_lane_za64_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_LANE_ZA64_VG1x4_U16 : Inst<"svdot_lane_za64[_{d}]_vg1x4", "vm4di", "Us", MergeNone, "aarch64_sme_udot_lane_za64_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_MULTI_ZA64_VG1x2_S16 : Inst<"svdot_za64[_{d}]_vg1x2", "vm22", "s", MergeNone, "aarch64_sme_sdot_za64_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA64_VG1x4_S16 : Inst<"svdot_za64[_{d}]_vg1x4", "vm44", "s", MergeNone, "aarch64_sme_sdot_za64_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA64_VG1x2_U16 : Inst<"svdot_za64[_{d}]_vg1x2", "vm22", "Us", MergeNone, "aarch64_sme_udot_za64_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_MULTI_ZA64_VG1x4_U16 : Inst<"svdot_za64[_{d}]_vg1x4", "vm44", "Us", MergeNone, "aarch64_sme_udot_za64_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA64_VG1x2_S16 : Inst<"svdot[_single]_za64[_{d}]_vg1x2", "vm2d", "s", MergeNone, "aarch64_sme_sdot_single_za64_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA64_VG1x4_S16 : Inst<"svdot[_single]_za64[_{d}]_vg1x4", "vm4d", "s", MergeNone, "aarch64_sme_sdot_single_za64_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA64_VG1x2_U16 : Inst<"svdot[_single]_za64[_{d}]_vg1x2", "vm2d", "Us", MergeNone, "aarch64_sme_udot_single_za64_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVDOT_SINGLE_ZA64_VG1x4_U16 : Inst<"svdot[_single]_za64[_{d}]_vg1x4", "vm4d", "Us", MergeNone, "aarch64_sme_udot_single_za64_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVDOT_LANE_ZA64_VG1x2_S16 : Inst<"svdot_lane_za64[_{d}]_vg1x2", "vm2di", "s", MergeNone, "aarch64_sme_sdot_lane_za64_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_LANE_ZA64_VG1x4_S16 : Inst<"svdot_lane_za64[_{d}]_vg1x4", "vm4di", "s", MergeNone, "aarch64_sme_sdot_lane_za64_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_LANE_ZA64_VG1x2_U16 : Inst<"svdot_lane_za64[_{d}]_vg1x2", "vm2di", "Us", MergeNone, "aarch64_sme_udot_lane_za64_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVDOT_LANE_ZA64_VG1x4_U16 : Inst<"svdot_lane_za64[_{d}]_vg1x4", "vm4di", "Us", MergeNone, "aarch64_sme_udot_lane_za64_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
}
// FMLA/FMLS
let TargetGuard = "sme2" in {
def SVMLA_MULTI_VG1x2_F32 : Inst<"svmla_za32[_{d}]_vg1x2", "vm22", "f", MergeNone, "aarch64_sme_fmla_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLA_MULTI_VG1x4_F32 : Inst<"svmla_za32[_{d}]_vg1x4", "vm44", "f", MergeNone, "aarch64_sme_fmla_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLS_MULTI_VG1x2_F32 : Inst<"svmls_za32[_{d}]_vg1x2", "vm22", "f", MergeNone, "aarch64_sme_fmls_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLS_MULTI_VG1x4_F32 : Inst<"svmls_za32[_{d}]_vg1x4", "vm44", "f", MergeNone, "aarch64_sme_fmls_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLA_MULTI_VG1x2_F32 : Inst<"svmla_za32[_{d}]_vg1x2", "vm22", "f", MergeNone, "aarch64_sme_fmla_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLA_MULTI_VG1x4_F32 : Inst<"svmla_za32[_{d}]_vg1x4", "vm44", "f", MergeNone, "aarch64_sme_fmla_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLS_MULTI_VG1x2_F32 : Inst<"svmls_za32[_{d}]_vg1x2", "vm22", "f", MergeNone, "aarch64_sme_fmls_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLS_MULTI_VG1x4_F32 : Inst<"svmls_za32[_{d}]_vg1x4", "vm44", "f", MergeNone, "aarch64_sme_fmls_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLA_SINGLE_VG1x2_F32 : Inst<"svmla[_single]_za32[_{d}]_vg1x2", "vm2d", "f", MergeNone, "aarch64_sme_fmla_single_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLA_SINGLE_VG1x4_F32 : Inst<"svmla[_single]_za32[_{d}]_vg1x4", "vm4d", "f", MergeNone, "aarch64_sme_fmla_single_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLS_SINGLE_VG1x2_F32 : Inst<"svmls[_single]_za32[_{d}]_vg1x2", "vm2d", "f", MergeNone, "aarch64_sme_fmls_single_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLS_SINGLE_VG1x4_F32 : Inst<"svmls[_single]_za32[_{d}]_vg1x4", "vm4d", "f", MergeNone, "aarch64_sme_fmls_single_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLA_SINGLE_VG1x2_F32 : Inst<"svmla[_single]_za32[_{d}]_vg1x2", "vm2d", "f", MergeNone, "aarch64_sme_fmla_single_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLA_SINGLE_VG1x4_F32 : Inst<"svmla[_single]_za32[_{d}]_vg1x4", "vm4d", "f", MergeNone, "aarch64_sme_fmla_single_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLS_SINGLE_VG1x2_F32 : Inst<"svmls[_single]_za32[_{d}]_vg1x2", "vm2d", "f", MergeNone, "aarch64_sme_fmls_single_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLS_SINGLE_VG1x4_F32 : Inst<"svmls[_single]_za32[_{d}]_vg1x4", "vm4d", "f", MergeNone, "aarch64_sme_fmls_single_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLA_LANE_VG1x2_F32 : Inst<"svmla_lane_za32[_{d}]_vg1x2", "vm2di", "f", MergeNone, "aarch64_sme_fmla_lane_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLA_LANE_VG1x4_F32 : Inst<"svmla_lane_za32[_{d}]_vg1x4", "vm4di", "f", MergeNone, "aarch64_sme_fmla_lane_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLS_LANE_VG1x2_F32 : Inst<"svmls_lane_za32[_{d}]_vg1x2", "vm2di", "f", MergeNone, "aarch64_sme_fmls_lane_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLS_LANE_VG1x4_F32 : Inst<"svmls_lane_za32[_{d}]_vg1x4", "vm4di", "f", MergeNone, "aarch64_sme_fmls_lane_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLA_LANE_VG1x2_F32 : Inst<"svmla_lane_za32[_{d}]_vg1x2", "vm2di", "f", MergeNone, "aarch64_sme_fmla_lane_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLA_LANE_VG1x4_F32 : Inst<"svmla_lane_za32[_{d}]_vg1x4", "vm4di", "f", MergeNone, "aarch64_sme_fmla_lane_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLS_LANE_VG1x2_F32 : Inst<"svmls_lane_za32[_{d}]_vg1x2", "vm2di", "f", MergeNone, "aarch64_sme_fmls_lane_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
def SVMLS_LANE_VG1x4_F32 : Inst<"svmls_lane_za32[_{d}]_vg1x4", "vm4di", "f", MergeNone, "aarch64_sme_fmls_lane_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_3>]>;
}
let TargetGuard = "sme2,sme-f64f64" in {
def SVMLA_MULTI_VG1x2_F64 : Inst<"svmla_za64[_{d}]_vg1x2", "vm22", "d", MergeNone, "aarch64_sme_fmla_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLA_MULTI_VG1x4_F64 : Inst<"svmla_za64[_{d}]_vg1x4", "vm44", "d", MergeNone, "aarch64_sme_fmla_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLS_MULTI_VG1x2_F64 : Inst<"svmls_za64[_{d}]_vg1x2", "vm22", "d", MergeNone, "aarch64_sme_fmls_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLS_MULTI_VG1x4_F64 : Inst<"svmls_za64[_{d}]_vg1x4", "vm44", "d", MergeNone, "aarch64_sme_fmls_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLA_MULTI_VG1x2_F64 : Inst<"svmla_za64[_{d}]_vg1x2", "vm22", "d", MergeNone, "aarch64_sme_fmla_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLA_MULTI_VG1x4_F64 : Inst<"svmla_za64[_{d}]_vg1x4", "vm44", "d", MergeNone, "aarch64_sme_fmla_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLS_MULTI_VG1x2_F64 : Inst<"svmls_za64[_{d}]_vg1x2", "vm22", "d", MergeNone, "aarch64_sme_fmls_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLS_MULTI_VG1x4_F64 : Inst<"svmls_za64[_{d}]_vg1x4", "vm44", "d", MergeNone, "aarch64_sme_fmls_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLA_SINGLE_VG1x2_F64 : Inst<"svmla[_single]_za64[_{d}]_vg1x2", "vm2d", "d", MergeNone, "aarch64_sme_fmla_single_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLA_SINGLE_VG1x4_F64 : Inst<"svmla[_single]_za64[_{d}]_vg1x4", "vm4d", "d", MergeNone, "aarch64_sme_fmla_single_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLS_SINGLE_VG1x2_F64 : Inst<"svmls[_single]_za64[_{d}]_vg1x2", "vm2d", "d", MergeNone, "aarch64_sme_fmls_single_vg1x2", [IsStreaming, IsSharedZA], []>;
def SVMLS_SINGLE_VG1x4_F64 : Inst<"svmls[_single]_za64[_{d}]_vg1x4", "vm4d", "d", MergeNone, "aarch64_sme_fmls_single_vg1x4", [IsStreaming, IsSharedZA], []>;
def SVMLA_SINGLE_VG1x2_F64 : Inst<"svmla[_single]_za64[_{d}]_vg1x2", "vm2d", "d", MergeNone, "aarch64_sme_fmla_single_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLA_SINGLE_VG1x4_F64 : Inst<"svmla[_single]_za64[_{d}]_vg1x4", "vm4d", "d", MergeNone, "aarch64_sme_fmla_single_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLS_SINGLE_VG1x2_F64 : Inst<"svmls[_single]_za64[_{d}]_vg1x2", "vm2d", "d", MergeNone, "aarch64_sme_fmls_single_vg1x2", [IsStreaming, IsInOutZA], []>;
def SVMLS_SINGLE_VG1x4_F64 : Inst<"svmls[_single]_za64[_{d}]_vg1x4", "vm4d", "d", MergeNone, "aarch64_sme_fmls_single_vg1x4", [IsStreaming, IsInOutZA], []>;
def SVMLA_LANE_VG1x2_F64 : Inst<"svmla_lane_za64[_{d}]_vg1x2", "vm2di", "d", MergeNone, "aarch64_sme_fmla_lane_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLA_LANE_VG1x4_F64 : Inst<"svmla_lane_za64[_{d}]_vg1x4", "vm4di", "d", MergeNone, "aarch64_sme_fmla_lane_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLS_LANE_VG1x2_F64 : Inst<"svmls_lane_za64[_{d}]_vg1x2", "vm2di", "d", MergeNone, "aarch64_sme_fmls_lane_vg1x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLS_LANE_VG1x4_F64 : Inst<"svmls_lane_za64[_{d}]_vg1x4", "vm4di", "d", MergeNone, "aarch64_sme_fmls_lane_vg1x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLA_LANE_VG1x2_F64 : Inst<"svmla_lane_za64[_{d}]_vg1x2", "vm2di", "d", MergeNone, "aarch64_sme_fmla_lane_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLA_LANE_VG1x4_F64 : Inst<"svmla_lane_za64[_{d}]_vg1x4", "vm4di", "d", MergeNone, "aarch64_sme_fmla_lane_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLS_LANE_VG1x2_F64 : Inst<"svmls_lane_za64[_{d}]_vg1x2", "vm2di", "d", MergeNone, "aarch64_sme_fmls_lane_vg1x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
def SVMLS_LANE_VG1x4_F64 : Inst<"svmls_lane_za64[_{d}]_vg1x4", "vm4di", "d", MergeNone, "aarch64_sme_fmls_lane_vg1x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_1>]>;
}
// FMLAL/FMLSL/UMLAL/SMLAL
// SMLALL/UMLALL/USMLALL/SUMLALL
let TargetGuard = "sme2" in {
// MULTI MLAL
def SVMLAL_MULTI_VG2x2_F16 : Inst<"svmla_za32[_{d}]_vg2x2", "vm22", "bh", MergeNone, "aarch64_sme_fmlal_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG2x4_F16 : Inst<"svmla_za32[_{d}]_vg2x4", "vm44", "bh", MergeNone, "aarch64_sme_fmlal_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG2x2_S16 : Inst<"svmla_za32[_{d}]_vg2x2", "vm22", "s", MergeNone, "aarch64_sme_smlal_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG2x4_S16 : Inst<"svmla_za32[_{d}]_vg2x4", "vm44", "s", MergeNone, "aarch64_sme_smlal_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG2x2_U16 : Inst<"svmla_za32[_{d}]_vg2x2", "vm22", "Us", MergeNone, "aarch64_sme_umlal_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG2x4_U16 : Inst<"svmla_za32[_{d}]_vg2x4", "vm44", "Us", MergeNone, "aarch64_sme_umlal_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG2x2_F16 : Inst<"svmla_za32[_{d}]_vg2x2", "vm22", "bh", MergeNone, "aarch64_sme_fmlal_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG2x4_F16 : Inst<"svmla_za32[_{d}]_vg2x4", "vm44", "bh", MergeNone, "aarch64_sme_fmlal_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG2x2_S16 : Inst<"svmla_za32[_{d}]_vg2x2", "vm22", "s", MergeNone, "aarch64_sme_smlal_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG2x4_S16 : Inst<"svmla_za32[_{d}]_vg2x4", "vm44", "s", MergeNone, "aarch64_sme_smlal_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG2x2_U16 : Inst<"svmla_za32[_{d}]_vg2x2", "vm22", "Us", MergeNone, "aarch64_sme_umlal_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG2x4_U16 : Inst<"svmla_za32[_{d}]_vg2x4", "vm44", "Us", MergeNone, "aarch64_sme_umlal_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x2_S8 : Inst<"svmla_za32[_{d}]_vg4x2", "vm22", "c", MergeNone, "aarch64_sme_smla_za32_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x2_U8 : Inst<"svmla_za32[_{d}]_vg4x2", "vm22", "Uc", MergeNone, "aarch64_sme_umla_za32_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x4_S8 : Inst<"svmla_za32[_{d}]_vg4x4", "vm44", "c", MergeNone, "aarch64_sme_smla_za32_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x4_U8 : Inst<"svmla_za32[_{d}]_vg4x4", "vm44", "Uc", MergeNone, "aarch64_sme_umla_za32_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x2_S8 : Inst<"svmla_za32[_{d}]_vg4x2", "vm22", "c", MergeNone, "aarch64_sme_smla_za32_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x2_U8 : Inst<"svmla_za32[_{d}]_vg4x2", "vm22", "Uc", MergeNone, "aarch64_sme_umla_za32_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x4_S8 : Inst<"svmla_za32[_{d}]_vg4x4", "vm44", "c", MergeNone, "aarch64_sme_smla_za32_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x4_U8 : Inst<"svmla_za32[_{d}]_vg4x4", "vm44", "Uc", MergeNone, "aarch64_sme_umla_za32_vg4x4", [IsStreaming, IsInOutZA], []>;
// MULTI MLSL
def SVMLSL_MULTI_VG2x2_F16 : Inst<"svmls_za32[_{d}]_vg2x2", "vm22", "bh", MergeNone, "aarch64_sme_fmlsl_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG2x4_F16 : Inst<"svmls_za32[_{d}]_vg2x4", "vm44", "bh", MergeNone, "aarch64_sme_fmlsl_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG2x2_S16 : Inst<"svmls_za32[_{d}]_vg2x2", "vm22", "s", MergeNone, "aarch64_sme_smlsl_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG2x4_S16 : Inst<"svmls_za32[_{d}]_vg2x4", "vm44", "s", MergeNone, "aarch64_sme_smlsl_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG2x2_U16 : Inst<"svmls_za32[_{d}]_vg2x2", "vm22", "Us", MergeNone, "aarch64_sme_umlsl_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG2x4_U16 : Inst<"svmls_za32[_{d}]_vg2x4", "vm44", "Us", MergeNone, "aarch64_sme_umlsl_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG2x2_F16 : Inst<"svmls_za32[_{d}]_vg2x2", "vm22", "bh", MergeNone, "aarch64_sme_fmlsl_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG2x4_F16 : Inst<"svmls_za32[_{d}]_vg2x4", "vm44", "bh", MergeNone, "aarch64_sme_fmlsl_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG2x2_S16 : Inst<"svmls_za32[_{d}]_vg2x2", "vm22", "s", MergeNone, "aarch64_sme_smlsl_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG2x4_S16 : Inst<"svmls_za32[_{d}]_vg2x4", "vm44", "s", MergeNone, "aarch64_sme_smlsl_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG2x2_U16 : Inst<"svmls_za32[_{d}]_vg2x2", "vm22", "Us", MergeNone, "aarch64_sme_umlsl_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG2x4_U16 : Inst<"svmls_za32[_{d}]_vg2x4", "vm44", "Us", MergeNone, "aarch64_sme_umlsl_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x2_S8 : Inst<"svmls_za32[_{d}]_vg4x2", "vm22", "c", MergeNone, "aarch64_sme_smls_za32_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x2_U8 : Inst<"svmls_za32[_{d}]_vg4x2", "vm22", "Uc", MergeNone, "aarch64_sme_umls_za32_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x4_S8 : Inst<"svmls_za32[_{d}]_vg4x4", "vm44", "c", MergeNone, "aarch64_sme_smls_za32_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x4_U8 : Inst<"svmls_za32[_{d}]_vg4x4", "vm44", "Uc", MergeNone, "aarch64_sme_umls_za32_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x2_S8 : Inst<"svmls_za32[_{d}]_vg4x2", "vm22", "c", MergeNone, "aarch64_sme_smls_za32_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x2_U8 : Inst<"svmls_za32[_{d}]_vg4x2", "vm22", "Uc", MergeNone, "aarch64_sme_umls_za32_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x4_S8 : Inst<"svmls_za32[_{d}]_vg4x4", "vm44", "c", MergeNone, "aarch64_sme_smls_za32_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x4_U8 : Inst<"svmls_za32[_{d}]_vg4x4", "vm44", "Uc", MergeNone, "aarch64_sme_umls_za32_vg4x4", [IsStreaming, IsInOutZA], []>;
// SINGLE MLAL
def SVMLAL_SINGLE_VG2x1_F16 : Inst<"svmla_za32[_{d}]_vg2x1", "vmdd", "bh", MergeNone, "aarch64_sme_fmlal_single_vg2x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x2_F16 : Inst<"svmla[_single]_za32[_{d}]_vg2x2", "vm2d", "bh", MergeNone, "aarch64_sme_fmlal_single_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x4_F16 : Inst<"svmla[_single]_za32[_{d}]_vg2x4", "vm4d", "bh", MergeNone, "aarch64_sme_fmlal_single_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x1_S16 : Inst<"svmla_za32[_{d}]_vg2x1", "vmdd", "s", MergeNone, "aarch64_sme_smlal_single_vg2x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x2_S16 : Inst<"svmla[_single]_za32[_{d}]_vg2x2", "vm2d", "s", MergeNone, "aarch64_sme_smlal_single_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x4_S16 : Inst<"svmla[_single]_za32[_{d}]_vg2x4", "vm4d", "s", MergeNone, "aarch64_sme_smlal_single_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x1_U16 : Inst<"svmla_za32[_{d}]_vg2x1", "vmdd", "Us", MergeNone, "aarch64_sme_umlal_single_vg2x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x2_U16 : Inst<"svmla[_single]_za32[_{d}]_vg2x2", "vm2d", "Us", MergeNone, "aarch64_sme_umlal_single_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x4_U16 : Inst<"svmla[_single]_za32[_{d}]_vg2x4", "vm4d", "Us", MergeNone, "aarch64_sme_umlal_single_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG2x1_F16 : Inst<"svmla_za32[_{d}]_vg2x1", "vmdd", "bh", MergeNone, "aarch64_sme_fmlal_single_vg2x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x2_F16 : Inst<"svmla[_single]_za32[_{d}]_vg2x2", "vm2d", "bh", MergeNone, "aarch64_sme_fmlal_single_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x4_F16 : Inst<"svmla[_single]_za32[_{d}]_vg2x4", "vm4d", "bh", MergeNone, "aarch64_sme_fmlal_single_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x1_S16 : Inst<"svmla_za32[_{d}]_vg2x1", "vmdd", "s", MergeNone, "aarch64_sme_smlal_single_vg2x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x2_S16 : Inst<"svmla[_single]_za32[_{d}]_vg2x2", "vm2d", "s", MergeNone, "aarch64_sme_smlal_single_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x4_S16 : Inst<"svmla[_single]_za32[_{d}]_vg2x4", "vm4d", "s", MergeNone, "aarch64_sme_smlal_single_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x1_U16 : Inst<"svmla_za32[_{d}]_vg2x1", "vmdd", "Us", MergeNone, "aarch64_sme_umlal_single_vg2x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x2_U16 : Inst<"svmla[_single]_za32[_{d}]_vg2x2", "vm2d", "Us", MergeNone, "aarch64_sme_umlal_single_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG2x4_U16 : Inst<"svmla[_single]_za32[_{d}]_vg2x4", "vm4d", "Us", MergeNone, "aarch64_sme_umlal_single_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x1_S8 : Inst<"svmla_za32[_{d}]_vg4x1", "vmdd", "c", MergeNone, "aarch64_sme_smla_za32_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x1_U8 : Inst<"svmla_za32[_{d}]_vg4x1", "vmdd", "Uc", MergeNone, "aarch64_sme_umla_za32_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x2_S8 : Inst<"svmla[_single]_za32[_{d}]_vg4x2", "vm2d", "c", MergeNone, "aarch64_sme_smla_za32_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x2_U8 : Inst<"svmla[_single]_za32[_{d}]_vg4x2", "vm2d", "Uc", MergeNone, "aarch64_sme_umla_za32_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x4_S8 : Inst<"svmla[_single]_za32[_{d}]_vg4x4", "vm4d", "c", MergeNone, "aarch64_sme_smla_za32_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x4_U8 : Inst<"svmla[_single]_za32[_{d}]_vg4x4", "vm4d", "Uc", MergeNone, "aarch64_sme_umla_za32_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x1_S8 : Inst<"svmla_za32[_{d}]_vg4x1", "vmdd", "c", MergeNone, "aarch64_sme_smla_za32_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x1_U8 : Inst<"svmla_za32[_{d}]_vg4x1", "vmdd", "Uc", MergeNone, "aarch64_sme_umla_za32_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x2_S8 : Inst<"svmla[_single]_za32[_{d}]_vg4x2", "vm2d", "c", MergeNone, "aarch64_sme_smla_za32_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x2_U8 : Inst<"svmla[_single]_za32[_{d}]_vg4x2", "vm2d", "Uc", MergeNone, "aarch64_sme_umla_za32_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x4_S8 : Inst<"svmla[_single]_za32[_{d}]_vg4x4", "vm4d", "c", MergeNone, "aarch64_sme_smla_za32_single_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x4_U8 : Inst<"svmla[_single]_za32[_{d}]_vg4x4", "vm4d", "Uc", MergeNone, "aarch64_sme_umla_za32_single_vg4x4", [IsStreaming, IsInOutZA], []>;
// SINGLE MLSL
def SVMLSL_SINGLE_VG2x1_F16 : Inst<"svmls_za32[_{d}]_vg2x1", "vmdd", "bh", MergeNone, "aarch64_sme_fmlsl_single_vg2x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x2_F16 : Inst<"svmls[_single]_za32[_{d}]_vg2x2", "vm2d", "bh", MergeNone, "aarch64_sme_fmlsl_single_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x4_F16 : Inst<"svmls[_single]_za32[_{d}]_vg2x4", "vm4d", "bh", MergeNone, "aarch64_sme_fmlsl_single_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x1_S16 : Inst<"svmls_za32[_{d}]_vg2x1", "vmdd", "s", MergeNone, "aarch64_sme_smlsl_single_vg2x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x2_S16 : Inst<"svmls[_single]_za32[_{d}]_vg2x2", "vm2d", "s", MergeNone, "aarch64_sme_smlsl_single_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x4_S16 : Inst<"svmls[_single]_za32[_{d}]_vg2x4", "vm4d", "s", MergeNone, "aarch64_sme_smlsl_single_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x1_U16 : Inst<"svmls_za32[_{d}]_vg2x1", "vmdd", "Us", MergeNone, "aarch64_sme_umlsl_single_vg2x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x2_U16 : Inst<"svmls[_single]_za32[_{d}]_vg2x2", "vm2d", "Us", MergeNone, "aarch64_sme_umlsl_single_vg2x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x4_U16 : Inst<"svmls[_single]_za32[_{d}]_vg2x4", "vm4d", "Us", MergeNone, "aarch64_sme_umlsl_single_vg2x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG2x1_F16 : Inst<"svmls_za32[_{d}]_vg2x1", "vmdd", "bh", MergeNone, "aarch64_sme_fmlsl_single_vg2x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x2_F16 : Inst<"svmls[_single]_za32[_{d}]_vg2x2", "vm2d", "bh", MergeNone, "aarch64_sme_fmlsl_single_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x4_F16 : Inst<"svmls[_single]_za32[_{d}]_vg2x4", "vm4d", "bh", MergeNone, "aarch64_sme_fmlsl_single_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x1_S16 : Inst<"svmls_za32[_{d}]_vg2x1", "vmdd", "s", MergeNone, "aarch64_sme_smlsl_single_vg2x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x2_S16 : Inst<"svmls[_single]_za32[_{d}]_vg2x2", "vm2d", "s", MergeNone, "aarch64_sme_smlsl_single_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x4_S16 : Inst<"svmls[_single]_za32[_{d}]_vg2x4", "vm4d", "s", MergeNone, "aarch64_sme_smlsl_single_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x1_U16 : Inst<"svmls_za32[_{d}]_vg2x1", "vmdd", "Us", MergeNone, "aarch64_sme_umlsl_single_vg2x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x2_U16 : Inst<"svmls[_single]_za32[_{d}]_vg2x2", "vm2d", "Us", MergeNone, "aarch64_sme_umlsl_single_vg2x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG2x4_U16 : Inst<"svmls[_single]_za32[_{d}]_vg2x4", "vm4d", "Us", MergeNone, "aarch64_sme_umlsl_single_vg2x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x1_S8 : Inst<"svmls_za32[_{d}]_vg4x1", "vmdd", "c", MergeNone, "aarch64_sme_smls_za32_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x1_U8 : Inst<"svmls_za32[_{d}]_vg4x1", "vmdd", "Uc", MergeNone, "aarch64_sme_umls_za32_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x2_S8 : Inst<"svmls[_single]_za32[_{d}]_vg4x2", "vm2d", "c", MergeNone, "aarch64_sme_smls_za32_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x2_U8 : Inst<"svmls[_single]_za32[_{d}]_vg4x2", "vm2d", "Uc", MergeNone, "aarch64_sme_umls_za32_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x4_S8 : Inst<"svmls[_single]_za32[_{d}]_vg4x4", "vm4d", "c", MergeNone, "aarch64_sme_smls_za32_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x4_U8 : Inst<"svmls[_single]_za32[_{d}]_vg4x4", "vm4d", "Uc", MergeNone, "aarch64_sme_umls_za32_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x1_S8 : Inst<"svmls_za32[_{d}]_vg4x1", "vmdd", "c", MergeNone, "aarch64_sme_smls_za32_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x1_U8 : Inst<"svmls_za32[_{d}]_vg4x1", "vmdd", "Uc", MergeNone, "aarch64_sme_umls_za32_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x2_S8 : Inst<"svmls[_single]_za32[_{d}]_vg4x2", "vm2d", "c", MergeNone, "aarch64_sme_smls_za32_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x2_U8 : Inst<"svmls[_single]_za32[_{d}]_vg4x2", "vm2d", "Uc", MergeNone, "aarch64_sme_umls_za32_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x4_S8 : Inst<"svmls[_single]_za32[_{d}]_vg4x4", "vm4d", "c", MergeNone, "aarch64_sme_smls_za32_single_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x4_U8 : Inst<"svmls[_single]_za32[_{d}]_vg4x4", "vm4d", "Uc", MergeNone, "aarch64_sme_umls_za32_single_vg4x4", [IsStreaming, IsInOutZA], []>;
// INDEXED MLAL
def SVMLAL_LANE_VG2x1_F16 : Inst<"svmla_lane_za32[_{d}]_vg2x1", "vmddi", "bh", MergeNone, "aarch64_sme_fmlal_lane_vg2x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x2_F16 : Inst<"svmla_lane_za32[_{d}]_vg2x2", "vm2di", "bh", MergeNone, "aarch64_sme_fmlal_lane_vg2x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x4_F16 : Inst<"svmla_lane_za32[_{d}]_vg2x4", "vm4di", "bh", MergeNone, "aarch64_sme_fmlal_lane_vg2x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x1_S16 : Inst<"svmla_lane_za32[_{d}]_vg2x1", "vmddi", "s", MergeNone, "aarch64_sme_smlal_lane_vg2x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x2_S16 : Inst<"svmla_lane_za32[_{d}]_vg2x2", "vm2di", "s", MergeNone, "aarch64_sme_smlal_lane_vg2x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x4_S16 : Inst<"svmla_lane_za32[_{d}]_vg2x4", "vm4di", "s", MergeNone, "aarch64_sme_smlal_lane_vg2x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x1_U16 : Inst<"svmla_lane_za32[_{d}]_vg2x1", "vmddi", "Us", MergeNone, "aarch64_sme_umlal_lane_vg2x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x2_U16 : Inst<"svmla_lane_za32[_{d}]_vg2x2", "vm2di", "Us", MergeNone, "aarch64_sme_umlal_lane_vg2x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x4_U16 : Inst<"svmla_lane_za32[_{d}]_vg2x4", "vm4di", "Us", MergeNone, "aarch64_sme_umlal_lane_vg2x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x1_F16 : Inst<"svmla_lane_za32[_{d}]_vg2x1", "vmddi", "bh", MergeNone, "aarch64_sme_fmlal_lane_vg2x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x2_F16 : Inst<"svmla_lane_za32[_{d}]_vg2x2", "vm2di", "bh", MergeNone, "aarch64_sme_fmlal_lane_vg2x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x4_F16 : Inst<"svmla_lane_za32[_{d}]_vg2x4", "vm4di", "bh", MergeNone, "aarch64_sme_fmlal_lane_vg2x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x1_S16 : Inst<"svmla_lane_za32[_{d}]_vg2x1", "vmddi", "s", MergeNone, "aarch64_sme_smlal_lane_vg2x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x2_S16 : Inst<"svmla_lane_za32[_{d}]_vg2x2", "vm2di", "s", MergeNone, "aarch64_sme_smlal_lane_vg2x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x4_S16 : Inst<"svmla_lane_za32[_{d}]_vg2x4", "vm4di", "s", MergeNone, "aarch64_sme_smlal_lane_vg2x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x1_U16 : Inst<"svmla_lane_za32[_{d}]_vg2x1", "vmddi", "Us", MergeNone, "aarch64_sme_umlal_lane_vg2x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x2_U16 : Inst<"svmla_lane_za32[_{d}]_vg2x2", "vm2di", "Us", MergeNone, "aarch64_sme_umlal_lane_vg2x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG2x4_U16 : Inst<"svmla_lane_za32[_{d}]_vg2x4", "vm4di", "Us", MergeNone, "aarch64_sme_umlal_lane_vg2x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x1_S8 : Inst<"svmla_lane_za32[_{d}]_vg4x1", "vmddi", "c", MergeNone, "aarch64_sme_smla_za32_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x1_U8 : Inst<"svmla_lane_za32[_{d}]_vg4x1", "vmddi", "Uc", MergeNone, "aarch64_sme_umla_za32_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x2_S8 : Inst<"svmla_lane_za32[_{d}]_vg4x2", "vm2di", "c", MergeNone, "aarch64_sme_smla_za32_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x2_U8 : Inst<"svmla_lane_za32[_{d}]_vg4x2", "vm2di", "Uc", MergeNone, "aarch64_sme_umla_za32_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x4_S8 : Inst<"svmla_lane_za32[_{d}]_vg4x4", "vm4di", "c", MergeNone, "aarch64_sme_smla_za32_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x4_U8 : Inst<"svmla_lane_za32[_{d}]_vg4x4", "vm4di", "Uc", MergeNone, "aarch64_sme_umla_za32_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x1_S8 : Inst<"svmla_lane_za32[_{d}]_vg4x1", "vmddi", "c", MergeNone, "aarch64_sme_smla_za32_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x1_U8 : Inst<"svmla_lane_za32[_{d}]_vg4x1", "vmddi", "Uc", MergeNone, "aarch64_sme_umla_za32_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x2_S8 : Inst<"svmla_lane_za32[_{d}]_vg4x2", "vm2di", "c", MergeNone, "aarch64_sme_smla_za32_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x2_U8 : Inst<"svmla_lane_za32[_{d}]_vg4x2", "vm2di", "Uc", MergeNone, "aarch64_sme_umla_za32_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x4_S8 : Inst<"svmla_lane_za32[_{d}]_vg4x4", "vm4di", "c", MergeNone, "aarch64_sme_smla_za32_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLAL_LANE_VG4x4_U8 : Inst<"svmla_lane_za32[_{d}]_vg4x4", "vm4di", "Uc", MergeNone, "aarch64_sme_umla_za32_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
// INDEXED MLSL
def SVMLSL_LANE_VG2x1_F16 : Inst<"svmls_lane_za32[_{d}]_vg2x1", "vmddi", "bh", MergeNone, "aarch64_sme_fmlsl_lane_vg2x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x2_F16 : Inst<"svmls_lane_za32[_{d}]_vg2x2", "vm2di", "bh", MergeNone, "aarch64_sme_fmlsl_lane_vg2x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x4_F16 : Inst<"svmls_lane_za32[_{d}]_vg2x4", "vm4di", "bh", MergeNone, "aarch64_sme_fmlsl_lane_vg2x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x1_S16 : Inst<"svmls_lane_za32[_{d}]_vg2x1", "vmddi", "s", MergeNone, "aarch64_sme_smlsl_lane_vg2x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x2_S16 : Inst<"svmls_lane_za32[_{d}]_vg2x2", "vm2di", "s", MergeNone, "aarch64_sme_smlsl_lane_vg2x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x4_S16 : Inst<"svmls_lane_za32[_{d}]_vg2x4", "vm4di", "s", MergeNone, "aarch64_sme_smlsl_lane_vg2x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x1_U16 : Inst<"svmls_lane_za32[_{d}]_vg2x1", "vmddi", "Us", MergeNone, "aarch64_sme_umlsl_lane_vg2x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x2_U16 : Inst<"svmls_lane_za32[_{d}]_vg2x2", "vm2di", "Us", MergeNone, "aarch64_sme_umlsl_lane_vg2x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x4_U16 : Inst<"svmls_lane_za32[_{d}]_vg2x4", "vm4di", "Us", MergeNone, "aarch64_sme_umlsl_lane_vg2x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x1_F16 : Inst<"svmls_lane_za32[_{d}]_vg2x1", "vmddi", "bh", MergeNone, "aarch64_sme_fmlsl_lane_vg2x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x2_F16 : Inst<"svmls_lane_za32[_{d}]_vg2x2", "vm2di", "bh", MergeNone, "aarch64_sme_fmlsl_lane_vg2x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x4_F16 : Inst<"svmls_lane_za32[_{d}]_vg2x4", "vm4di", "bh", MergeNone, "aarch64_sme_fmlsl_lane_vg2x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x1_S16 : Inst<"svmls_lane_za32[_{d}]_vg2x1", "vmddi", "s", MergeNone, "aarch64_sme_smlsl_lane_vg2x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x2_S16 : Inst<"svmls_lane_za32[_{d}]_vg2x2", "vm2di", "s", MergeNone, "aarch64_sme_smlsl_lane_vg2x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x4_S16 : Inst<"svmls_lane_za32[_{d}]_vg2x4", "vm4di", "s", MergeNone, "aarch64_sme_smlsl_lane_vg2x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x1_U16 : Inst<"svmls_lane_za32[_{d}]_vg2x1", "vmddi", "Us", MergeNone, "aarch64_sme_umlsl_lane_vg2x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x2_U16 : Inst<"svmls_lane_za32[_{d}]_vg2x2", "vm2di", "Us", MergeNone, "aarch64_sme_umlsl_lane_vg2x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG2x4_U16 : Inst<"svmls_lane_za32[_{d}]_vg2x4", "vm4di", "Us", MergeNone, "aarch64_sme_umlsl_lane_vg2x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x1_S8 : Inst<"svmls_lane_za32[_{d}]_vg4x1", "vmddi", "c", MergeNone, "aarch64_sme_smls_za32_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x1_U8 : Inst<"svmls_lane_za32[_{d}]_vg4x1", "vmddi", "Uc", MergeNone, "aarch64_sme_umls_za32_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x2_S8 : Inst<"svmls_lane_za32[_{d}]_vg4x2", "vm2di", "c", MergeNone, "aarch64_sme_smls_za32_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x2_U8 : Inst<"svmls_lane_za32[_{d}]_vg4x2", "vm2di", "Uc", MergeNone, "aarch64_sme_umls_za32_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x4_S8 : Inst<"svmls_lane_za32[_{d}]_vg4x4", "vm4di", "c", MergeNone, "aarch64_sme_smls_za32_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x4_U8 : Inst<"svmls_lane_za32[_{d}]_vg4x4", "vm4di", "Uc", MergeNone, "aarch64_sme_umls_za32_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x1_S8 : Inst<"svmls_lane_za32[_{d}]_vg4x1", "vmddi", "c", MergeNone, "aarch64_sme_smls_za32_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x1_U8 : Inst<"svmls_lane_za32[_{d}]_vg4x1", "vmddi", "Uc", MergeNone, "aarch64_sme_umls_za32_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x2_S8 : Inst<"svmls_lane_za32[_{d}]_vg4x2", "vm2di", "c", MergeNone, "aarch64_sme_smls_za32_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x2_U8 : Inst<"svmls_lane_za32[_{d}]_vg4x2", "vm2di", "Uc", MergeNone, "aarch64_sme_umls_za32_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x4_S8 : Inst<"svmls_lane_za32[_{d}]_vg4x4", "vm4di", "c", MergeNone, "aarch64_sme_smls_za32_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVMLSL_LANE_VG4x4_U8 : Inst<"svmls_lane_za32[_{d}]_vg4x4", "vm4di", "Uc", MergeNone, "aarch64_sme_umls_za32_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
// SINGLE SUMLALL
// Single sumla maps to usmla, with zn & zm operands swapped
def SVSUMLALL_SINGLE_VG4x1 : Inst<"svsumla_za32[_{d}]_vg4x1", "vmdu", "c", MergeNone, "aarch64_sme_usmla_za32_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVSUMLALL_SINGLE_VG4x1 : Inst<"svsumla_za32[_{d}]_vg4x1", "vmdu", "c", MergeNone, "aarch64_sme_usmla_za32_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVSUMLALL_SINGLE_VG4x2 : Inst<"svsumla[_single]_za32[_{d}]_vg4x2", "vm2.du", "c", MergeNone, "aarch64_sme_sumla_za32_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVSUMLALL_SINGLE_VG4x4 : Inst<"svsumla[_single]_za32[_{d}]_vg4x4", "vm4.du", "c", MergeNone, "aarch64_sme_sumla_za32_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVSUMLALL_SINGLE_VG4x2 : Inst<"svsumla[_single]_za32[_{d}]_vg4x2", "vm2.du", "c", MergeNone, "aarch64_sme_sumla_za32_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVSUMLALL_SINGLE_VG4x4 : Inst<"svsumla[_single]_za32[_{d}]_vg4x4", "vm4.du", "c", MergeNone, "aarch64_sme_sumla_za32_single_vg4x4", [IsStreaming, IsInOutZA], []>;
// Multi-multi sumla builtins are mapped to usmla, with zn & zm operands swapped
def SVSUMLALL_MULTI_VG4x2 : Inst<"svsumla_za32[_{d}]_vg4x2", "vm2.d2.u", "c", MergeNone, "aarch64_sme_usmla_za32_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVSUMLALL_MULTI_VG4x4 : Inst<"svsumla_za32[_{d}]_vg4x4", "vm4.d4.u", "c", MergeNone, "aarch64_sme_usmla_za32_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVSUMLALL_MULTI_VG4x2 : Inst<"svsumla_za32[_{d}]_vg4x2", "vm2.d2.u", "c", MergeNone, "aarch64_sme_usmla_za32_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVSUMLALL_MULTI_VG4x4 : Inst<"svsumla_za32[_{d}]_vg4x4", "vm4.d4.u", "c", MergeNone, "aarch64_sme_usmla_za32_vg4x4", [IsStreaming, IsInOutZA], []>;
// INDEXED SUMLALL
def SVSUMLALL_LANE_VG4x1 : Inst<"svsumla_lane_za32[_{d}]_vg4x1", "vmdui", "c", MergeNone, "aarch64_sme_sumla_za32_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVSUMLALL_LANE_VG4x2 : Inst<"svsumla_lane_za32[_{d}]_vg4x2", "vm2ui", "c", MergeNone, "aarch64_sme_sumla_za32_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVSUMLALL_LANE_VG4x4 : Inst<"svsumla_lane_za32[_{d}]_vg4x4", "vm4ui", "c", MergeNone, "aarch64_sme_sumla_za32_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVSUMLALL_LANE_VG4x1 : Inst<"svsumla_lane_za32[_{d}]_vg4x1", "vmdui", "c", MergeNone, "aarch64_sme_sumla_za32_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVSUMLALL_LANE_VG4x2 : Inst<"svsumla_lane_za32[_{d}]_vg4x2", "vm2ui", "c", MergeNone, "aarch64_sme_sumla_za32_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVSUMLALL_LANE_VG4x4 : Inst<"svsumla_lane_za32[_{d}]_vg4x4", "vm4ui", "c", MergeNone, "aarch64_sme_sumla_za32_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
// SINGLE USMLALL
def SVUSMLALL_SINGLE_VG4x1 : Inst<"svusmla_za32[_{d}]_vg4x1", "vmdx", "Uc", MergeNone, "aarch64_sme_usmla_za32_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVUSMLALL_SINGLE_VG4x2 : Inst<"svusmla[_single]_za32[_{d}]_vg4x2", "vm2.dx", "Uc", MergeNone, "aarch64_sme_usmla_za32_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVUSMLALL_SINGLE_VG4x4 : Inst<"svusmla[_single]_za32[_{d}]_vg4x4", "vm4.dx", "Uc", MergeNone, "aarch64_sme_usmla_za32_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVUSMLALL_SINGLE_VG4x1 : Inst<"svusmla_za32[_{d}]_vg4x1", "vmdx", "Uc", MergeNone, "aarch64_sme_usmla_za32_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVUSMLALL_SINGLE_VG4x2 : Inst<"svusmla[_single]_za32[_{d}]_vg4x2", "vm2.dx", "Uc", MergeNone, "aarch64_sme_usmla_za32_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVUSMLALL_SINGLE_VG4x4 : Inst<"svusmla[_single]_za32[_{d}]_vg4x4", "vm4.dx", "Uc", MergeNone, "aarch64_sme_usmla_za32_single_vg4x4", [IsStreaming, IsInOutZA], []>;
// MULTI USMLALL
def SVUSMLALL_MULTI_VG4x2 : Inst<"svusmla_za32[_{d}]_vg4x2", "vm2.d2.x", "Uc", MergeNone, "aarch64_sme_usmla_za32_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVUSMLALL_MULTI_VG4x4 : Inst<"svusmla_za32[_{d}]_vg4x4", "vm4.d4.x", "Uc", MergeNone, "aarch64_sme_usmla_za32_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVUSMLALL_MULTI_VG4x2 : Inst<"svusmla_za32[_{d}]_vg4x2", "vm2.d2.x", "Uc", MergeNone, "aarch64_sme_usmla_za32_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVUSMLALL_MULTI_VG4x4 : Inst<"svusmla_za32[_{d}]_vg4x4", "vm4.d4.x", "Uc", MergeNone, "aarch64_sme_usmla_za32_vg4x4", [IsStreaming, IsInOutZA], []>;
// INDEXED USMLALL
def SVUSMLALL_LANE_VG4x1 : Inst<"svusmla_lane_za32[_{d}]_vg4x1", "vmdxi", "Uc", MergeNone, "aarch64_sme_usmla_za32_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVUSMLALL_LANE_VG4x2 : Inst<"svusmla_lane_za32[_{d}]_vg4x2", "vm2xi", "Uc", MergeNone, "aarch64_sme_usmla_za32_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVUSMLALL_LANE_VG4x4 : Inst<"svusmla_lane_za32[_{d}]_vg4x4", "vm4xi", "Uc", MergeNone, "aarch64_sme_usmla_za32_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVUSMLALL_LANE_VG4x1 : Inst<"svusmla_lane_za32[_{d}]_vg4x1", "vmdxi", "Uc", MergeNone, "aarch64_sme_usmla_za32_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVUSMLALL_LANE_VG4x2 : Inst<"svusmla_lane_za32[_{d}]_vg4x2", "vm2xi", "Uc", MergeNone, "aarch64_sme_usmla_za32_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
def SVUSMLALL_LANE_VG4x4 : Inst<"svusmla_lane_za32[_{d}]_vg4x4", "vm4xi", "Uc", MergeNone, "aarch64_sme_usmla_za32_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_15>]>;
}
let TargetGuard = "sme2,sme-i16i64" in {
// MULTI MLAL
def SVMLAL_MULTI_VG4x2_S16 : Inst<"svmla_za64[_{d}]_vg4x2", "vm22", "s", MergeNone, "aarch64_sme_smla_za64_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x2_U16 : Inst<"svmla_za64[_{d}]_vg4x2", "vm22", "Us", MergeNone, "aarch64_sme_umla_za64_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x4_S16 : Inst<"svmla_za64[_{d}]_vg4x4", "vm44", "s", MergeNone, "aarch64_sme_smla_za64_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x4_U16 : Inst<"svmla_za64[_{d}]_vg4x4", "vm44", "Us", MergeNone, "aarch64_sme_umla_za64_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_MULTI_VG4x2_S16 : Inst<"svmla_za64[_{d}]_vg4x2", "vm22", "s", MergeNone, "aarch64_sme_smla_za64_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x2_U16 : Inst<"svmla_za64[_{d}]_vg4x2", "vm22", "Us", MergeNone, "aarch64_sme_umla_za64_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x4_S16 : Inst<"svmla_za64[_{d}]_vg4x4", "vm44", "s", MergeNone, "aarch64_sme_smla_za64_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_MULTI_VG4x4_U16 : Inst<"svmla_za64[_{d}]_vg4x4", "vm44", "Us", MergeNone, "aarch64_sme_umla_za64_vg4x4", [IsStreaming, IsInOutZA], []>;
// MULTI MLSL
def SVMLSL_MULTI_VG4x2_S16 : Inst<"svmls_za64[_{d}]_vg4x2", "vm22", "s", MergeNone, "aarch64_sme_smls_za64_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x2_U16 : Inst<"svmls_za64[_{d}]_vg4x2", "vm22", "Us", MergeNone, "aarch64_sme_umls_za64_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x4_S16 : Inst<"svmls_za64[_{d}]_vg4x4", "vm44", "s", MergeNone, "aarch64_sme_smls_za64_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x4_U16 : Inst<"svmls_za64[_{d}]_vg4x4", "vm44", "Us", MergeNone, "aarch64_sme_umls_za64_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_MULTI_VG4x2_S16 : Inst<"svmls_za64[_{d}]_vg4x2", "vm22", "s", MergeNone, "aarch64_sme_smls_za64_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x2_U16 : Inst<"svmls_za64[_{d}]_vg4x2", "vm22", "Us", MergeNone, "aarch64_sme_umls_za64_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x4_S16 : Inst<"svmls_za64[_{d}]_vg4x4", "vm44", "s", MergeNone, "aarch64_sme_smls_za64_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_MULTI_VG4x4_U16 : Inst<"svmls_za64[_{d}]_vg4x4", "vm44", "Us", MergeNone, "aarch64_sme_umls_za64_vg4x4", [IsStreaming, IsInOutZA], []>;
// SINGLE MLAL
def SVMLAL_SINGLE_VG4x1_S16 : Inst<"svmla_za64[_{d}]_vg4x1", "vmdd", "s", MergeNone, "aarch64_sme_smla_za64_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x1_U16 : Inst<"svmla_za64[_{d}]_vg4x1", "vmdd", "Us", MergeNone, "aarch64_sme_umla_za64_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x2_S16 : Inst<"svmla[_single]_za64[_{d}]_vg4x2", "vm2d", "s", MergeNone, "aarch64_sme_smla_za64_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x2_U16 : Inst<"svmla[_single]_za64[_{d}]_vg4x2", "vm2d", "Us", MergeNone, "aarch64_sme_umla_za64_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x4_S16 : Inst<"svmla[_single]_za64[_{d}]_vg4x4", "vm4d", "s", MergeNone, "aarch64_sme_smla_za64_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x4_U16 : Inst<"svmla[_single]_za64[_{d}]_vg4x4", "vm4d", "Us", MergeNone, "aarch64_sme_umla_za64_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLAL_SINGLE_VG4x1_S16 : Inst<"svmla_za64[_{d}]_vg4x1", "vmdd", "s", MergeNone, "aarch64_sme_smla_za64_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x1_U16 : Inst<"svmla_za64[_{d}]_vg4x1", "vmdd", "Us", MergeNone, "aarch64_sme_umla_za64_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x2_S16 : Inst<"svmla[_single]_za64[_{d}]_vg4x2", "vm2d", "s", MergeNone, "aarch64_sme_smla_za64_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x2_U16 : Inst<"svmla[_single]_za64[_{d}]_vg4x2", "vm2d", "Us", MergeNone, "aarch64_sme_umla_za64_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x4_S16 : Inst<"svmla[_single]_za64[_{d}]_vg4x4", "vm4d", "s", MergeNone, "aarch64_sme_smla_za64_single_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLAL_SINGLE_VG4x4_U16 : Inst<"svmla[_single]_za64[_{d}]_vg4x4", "vm4d", "Us", MergeNone, "aarch64_sme_umla_za64_single_vg4x4", [IsStreaming, IsInOutZA], []>;
// SINGLE MLSL
def SVMLSL_SINGLE_VG4x1_S16 : Inst<"svmls_za64[_{d}]_vg4x1", "vmdd", "s", MergeNone, "aarch64_sme_smls_za64_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x1_U16 : Inst<"svmls_za64[_{d}]_vg4x1", "vmdd", "Us", MergeNone, "aarch64_sme_umls_za64_single_vg4x1", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x2_S16 : Inst<"svmls[_single]_za64[_{d}]_vg4x2", "vm2d", "s", MergeNone, "aarch64_sme_smls_za64_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x2_U16 : Inst<"svmls[_single]_za64[_{d}]_vg4x2", "vm2d", "Us", MergeNone, "aarch64_sme_umls_za64_single_vg4x2", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x4_S16 : Inst<"svmls[_single]_za64[_{d}]_vg4x4", "vm4d", "s", MergeNone, "aarch64_sme_smls_za64_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x4_U16 : Inst<"svmls[_single]_za64[_{d}]_vg4x4", "vm4d", "Us", MergeNone, "aarch64_sme_umls_za64_single_vg4x4", [IsStreaming, IsSharedZA], []>;
def SVMLSL_SINGLE_VG4x1_S16 : Inst<"svmls_za64[_{d}]_vg4x1", "vmdd", "s", MergeNone, "aarch64_sme_smls_za64_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x1_U16 : Inst<"svmls_za64[_{d}]_vg4x1", "vmdd", "Us", MergeNone, "aarch64_sme_umls_za64_single_vg4x1", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x2_S16 : Inst<"svmls[_single]_za64[_{d}]_vg4x2", "vm2d", "s", MergeNone, "aarch64_sme_smls_za64_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x2_U16 : Inst<"svmls[_single]_za64[_{d}]_vg4x2", "vm2d", "Us", MergeNone, "aarch64_sme_umls_za64_single_vg4x2", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x4_S16 : Inst<"svmls[_single]_za64[_{d}]_vg4x4", "vm4d", "s", MergeNone, "aarch64_sme_smls_za64_single_vg4x4", [IsStreaming, IsInOutZA], []>;
def SVMLSL_SINGLE_VG4x4_U16 : Inst<"svmls[_single]_za64[_{d}]_vg4x4", "vm4d", "Us", MergeNone, "aarch64_sme_umls_za64_single_vg4x4", [IsStreaming, IsInOutZA], []>;
// INDEXED MLAL
def SVMLAL_LANE_VG4x1_S16 : Inst<"svmla_lane_za64[_{d}]_vg4x1", "vmddi", "s", MergeNone, "aarch64_sme_smla_za64_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x1_U16 : Inst<"svmla_lane_za64[_{d}]_vg4x1", "vmddi", "Us", MergeNone, "aarch64_sme_umla_za64_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x2_S16 : Inst<"svmla_lane_za64[_{d}]_vg4x2", "vm2di", "s", MergeNone, "aarch64_sme_smla_za64_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x2_U16 : Inst<"svmla_lane_za64[_{d}]_vg4x2", "vm2di", "Us", MergeNone, "aarch64_sme_umla_za64_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x4_S16 : Inst<"svmla_lane_za64[_{d}]_vg4x4", "vm4di", "s", MergeNone, "aarch64_sme_smla_za64_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x4_U16 : Inst<"svmla_lane_za64[_{d}]_vg4x4", "vm4di", "Us", MergeNone, "aarch64_sme_umla_za64_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x1_S16 : Inst<"svmla_lane_za64[_{d}]_vg4x1", "vmddi", "s", MergeNone, "aarch64_sme_smla_za64_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x1_U16 : Inst<"svmla_lane_za64[_{d}]_vg4x1", "vmddi", "Us", MergeNone, "aarch64_sme_umla_za64_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x2_S16 : Inst<"svmla_lane_za64[_{d}]_vg4x2", "vm2di", "s", MergeNone, "aarch64_sme_smla_za64_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x2_U16 : Inst<"svmla_lane_za64[_{d}]_vg4x2", "vm2di", "Us", MergeNone, "aarch64_sme_umla_za64_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x4_S16 : Inst<"svmla_lane_za64[_{d}]_vg4x4", "vm4di", "s", MergeNone, "aarch64_sme_smla_za64_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLAL_LANE_VG4x4_U16 : Inst<"svmla_lane_za64[_{d}]_vg4x4", "vm4di", "Us", MergeNone, "aarch64_sme_umla_za64_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
// INDEXED MLSL
def SVMLSL_LANE_VG4x1_S16 : Inst<"svmls_lane_za64[_{d}]_vg4x1", "vmddi", "s", MergeNone, "aarch64_sme_smls_za64_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x1_U16 : Inst<"svmls_lane_za64[_{d}]_vg4x1", "vmddi", "Us", MergeNone, "aarch64_sme_umls_za64_lane_vg4x1", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x2_S16 : Inst<"svmls_lane_za64[_{d}]_vg4x2", "vm2di", "s", MergeNone, "aarch64_sme_smls_za64_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x2_U16 : Inst<"svmls_lane_za64[_{d}]_vg4x2", "vm2di", "Us", MergeNone, "aarch64_sme_umls_za64_lane_vg4x2", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x4_S16 : Inst<"svmls_lane_za64[_{d}]_vg4x4", "vm4di", "s", MergeNone, "aarch64_sme_smls_za64_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x4_U16 : Inst<"svmls_lane_za64[_{d}]_vg4x4", "vm4di", "Us", MergeNone, "aarch64_sme_umls_za64_lane_vg4x4", [IsStreaming, IsSharedZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x1_S16 : Inst<"svmls_lane_za64[_{d}]_vg4x1", "vmddi", "s", MergeNone, "aarch64_sme_smls_za64_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x1_U16 : Inst<"svmls_lane_za64[_{d}]_vg4x1", "vmddi", "Us", MergeNone, "aarch64_sme_umls_za64_lane_vg4x1", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x2_S16 : Inst<"svmls_lane_za64[_{d}]_vg4x2", "vm2di", "s", MergeNone, "aarch64_sme_smls_za64_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x2_U16 : Inst<"svmls_lane_za64[_{d}]_vg4x2", "vm2di", "Us", MergeNone, "aarch64_sme_umls_za64_lane_vg4x2", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x4_S16 : Inst<"svmls_lane_za64[_{d}]_vg4x4", "vm4di", "s", MergeNone, "aarch64_sme_smls_za64_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
def SVMLSL_LANE_VG4x4_U16 : Inst<"svmls_lane_za64[_{d}]_vg4x4", "vm4di", "Us", MergeNone, "aarch64_sme_umls_za64_lane_vg4x4", [IsStreaming, IsInOutZA], [ImmCheck<3, ImmCheck0_7>]>;
}
//
// Spill and fill of ZT0
//
let TargetGuard = "sme2" in {
def SVLDR_ZT : Inst<"svldr_zt", "viQ", "", MergeNone, "aarch64_sme_ldr_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA], [ImmCheck<0, ImmCheck0_0>]>;
def SVSTR_ZT : Inst<"svstr_zt", "vi%", "", MergeNone, "aarch64_sme_str_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>]>;
def SVLDR_ZT : Inst<"svldr_zt", "viQ", "", MergeNone, "aarch64_sme_ldr_zt", [IsOverloadNone, IsStreamingCompatible, IsInOutZT0], [ImmCheck<0, ImmCheck0_0>]>;
def SVSTR_ZT : Inst<"svstr_zt", "vi%", "", MergeNone, "aarch64_sme_str_zt", [IsOverloadNone, IsStreamingCompatible, IsInZT0], [ImmCheck<0, ImmCheck0_0>]>;
}
//
// Zero ZT0
//
let TargetGuard = "sme2" in {
def SVZERO_ZT : Inst<"svzero_zt", "vi", "", MergeNone, "aarch64_sme_zero_zt", [IsOverloadNone, IsStreamingCompatible, IsSharedZA], [ImmCheck<0, ImmCheck0_0>]>;
def SVZERO_ZT : Inst<"svzero_zt", "vi", "", MergeNone, "aarch64_sme_zero_zt", [IsOverloadNone, IsStreamingCompatible, IsOutZT0], [ImmCheck<0, ImmCheck0_0>]>;
}
//
// lookup table expand four contiguous registers
//
let TargetGuard = "sme2" in {
def SVLUTI2_LANE_ZT_X4 : Inst<"svluti2_lane_zt_{d}_x4", "4.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x4", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;
def SVLUTI4_LANE_ZT_X4 : Inst<"svluti4_lane_zt_{d}_x4", "4.di[i", "sUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x4", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_1>]>;
def SVLUTI2_LANE_ZT_X4 : Inst<"svluti2_lane_zt_{d}_x4", "4.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;
def SVLUTI4_LANE_ZT_X4 : Inst<"svluti4_lane_zt_{d}_x4", "4.di[i", "sUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_1>]>;
}
//
// lookup table expand one register
//
let TargetGuard = "sme2" in {
def SVLUTI2_LANE_ZT : Inst<"svluti2_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>;
def SVLUTI4_LANE_ZT : Inst<"svluti4_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;
def SVLUTI2_LANE_ZT : Inst<"svluti2_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_15>]>;
def SVLUTI4_LANE_ZT : Inst<"svluti4_lane_zt_{d}", "di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;
}
//
// lookup table expand two contiguous registers
//
let TargetGuard = "sme2" in {
def SVLUTI2_LANE_ZT_X2 : Inst<"svluti2_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x2", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;
def SVLUTI4_LANE_ZT_X2 : Inst<"svluti4_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x2", [IsStreaming, IsSharedZA, IsPreservesZA], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;
def SVLUTI2_LANE_ZT_X2 : Inst<"svluti2_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti2_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_7>]>;
def SVLUTI4_LANE_ZT_X2 : Inst<"svluti4_lane_zt_{d}_x2", "2.di[i", "cUcsUsiUibhf", MergeNone, "aarch64_sme_luti4_lane_zt_x2", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck0_3>]>;
}

View File

@ -543,13 +543,13 @@ def SVADRD : SInst<"svadrd[_{0}base]_[{2}]index", "uud", "ilUiUl", MergeNone, "
////////////////////////////////////////////////////////////////////////////////
// Scalar to vector
def SVDUPQ_8 : SInst<"svdupq[_n]_{d}", "dssssssssssssssss", "cUc", MergeNone>;
def SVDUPQ_16 : SInst<"svdupq[_n]_{d}", "dssssssss", "sUsh", MergeNone>;
def SVDUPQ_8 : SInst<"svdupq[_n]_{d}", "dssssssssssssssss", "cUc", MergeNone, "", [IsStreamingCompatible]>;
def SVDUPQ_16 : SInst<"svdupq[_n]_{d}", "dssssssss", "sUsh", MergeNone, "", [IsStreamingCompatible]>;
let TargetGuard = "sve,bf16" in {
def SVDUPQ_BF16 : SInst<"svdupq[_n]_{d}", "dssssssss", "b", MergeNone>;
def SVDUPQ_BF16 : SInst<"svdupq[_n]_{d}", "dssssssss", "b", MergeNone, "", [IsStreamingCompatible]>;
}
def SVDUPQ_32 : SInst<"svdupq[_n]_{d}", "dssss", "iUif", MergeNone>;
def SVDUPQ_64 : SInst<"svdupq[_n]_{d}", "dss", "lUld", MergeNone>;
def SVDUPQ_32 : SInst<"svdupq[_n]_{d}", "dssss", "iUif", MergeNone, "", [IsStreamingCompatible]>;
def SVDUPQ_64 : SInst<"svdupq[_n]_{d}", "dss", "lUld", MergeNone, "", [IsStreamingCompatible]>;
multiclass svdup_base<string n, string p, MergeType mt, string i> {
def NAME : SInst<n, p, "csilUcUsUiUlhfd", mt, i, [IsStreamingCompatible]>;
@ -638,8 +638,8 @@ def SVQADD_N_U : SInst<"svqadd[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64
def SVQSUB_N_S : SInst<"svqsub[_n_{d}]", "dda", "csil", MergeNone, "aarch64_sve_sqsub_x", [IsStreamingCompatible]>;
def SVQSUB_N_U : SInst<"svqsub[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sve_uqsub_x", [IsStreamingCompatible]>;
def SVDOT_LANE_S : SInst<"svdot_lane[_{d}]", "ddqqi", "il", MergeNone, "aarch64_sve_sdot_lane", [], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>;
def SVDOT_LANE_U : SInst<"svdot_lane[_{d}]", "ddqqi", "UiUl", MergeNone, "aarch64_sve_udot_lane", [], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>;
def SVDOT_LANE_S : SInst<"svdot_lane[_{d}]", "ddqqi", "il", MergeNone, "aarch64_sve_sdot_lane", [IsStreamingCompatible], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>;
def SVDOT_LANE_U : SInst<"svdot_lane[_{d}]", "ddqqi", "UiUl", MergeNone, "aarch64_sve_udot_lane", [IsStreamingCompatible], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>;
////////////////////////////////////////////////////////////////////////////////
// Logical operations
@ -749,14 +749,14 @@ def SVCMPLS_WIDE_N : SInst<"svcmple_wide[_n_{d}]", "PPdj", "UcUsUi", MergeNone,
////////////////////////////////////////////////////////////////////////////////
// While comparisons
def SVWHILELE_S32 : SInst<"svwhilele_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilele", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELE_S64 : SInst<"svwhilele_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilele", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELO_U32 : SInst<"svwhilelt_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilelo", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELO_U64 : SInst<"svwhilelt_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilelo", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELS_U32 : SInst<"svwhilele_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilels", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELS_U64 : SInst<"svwhilele_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilels", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELT_S32 : SInst<"svwhilelt_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilelt", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELT_S64 : SInst<"svwhilelt_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilelt", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILELE_S32 : SInst<"svwhilele_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilele", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELE_S64 : SInst<"svwhilele_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilele", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELO_U32 : SInst<"svwhilelt_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilelo", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELO_U64 : SInst<"svwhilelt_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilelo", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELS_U32 : SInst<"svwhilele_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilels", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELS_U64 : SInst<"svwhilele_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilels", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELT_S32 : SInst<"svwhilelt_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilelt", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILELT_S64 : SInst<"svwhilelt_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilelt", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
////////////////////////////////////////////////////////////////////////////////
// Counting bit
@ -835,14 +835,14 @@ def SVSCALE_N_M : SInst<"svscale[_n_{d}]", "dPdK", "hfd", MergeOp1, "aarch64_sv
def SVSCALE_N_X : SInst<"svscale[_n_{d}]", "dPdK", "hfd", MergeAny, "aarch64_sve_fscale", [IsStreamingCompatible]>;
def SVSCALE_N_Z : SInst<"svscale[_n_{d}]", "dPdK", "hfd", MergeZero, "aarch64_sve_fscale", [IsStreamingCompatible]>;
defm SVMAD_F : SInstZPZZZ<"svmad", "hfd", "aarch64_sve_fmad", "aarch64_sve_fmla_u", [ReverseMergeAnyAccOp]>;
defm SVMLA_F : SInstZPZZZ<"svmla", "hfd", "aarch64_sve_fmla", "aarch64_sve_fmla_u">;
defm SVMLS_F : SInstZPZZZ<"svmls", "hfd", "aarch64_sve_fmls", "aarch64_sve_fmls_u">;
defm SVMSB_F : SInstZPZZZ<"svmsb", "hfd", "aarch64_sve_fmsb", "aarch64_sve_fmls_u", [ReverseMergeAnyAccOp]>;
defm SVNMAD_F : SInstZPZZZ<"svnmad", "hfd", "aarch64_sve_fnmad", "aarch64_sve_fnmla_u", [ReverseMergeAnyAccOp]>;
defm SVNMLA_F : SInstZPZZZ<"svnmla", "hfd", "aarch64_sve_fnmla", "aarch64_sve_fnmla_u">;
defm SVNMLS_F : SInstZPZZZ<"svnmls", "hfd", "aarch64_sve_fnmls", "aarch64_sve_fnmls_u">;
defm SVNMSB_F : SInstZPZZZ<"svnmsb", "hfd", "aarch64_sve_fnmsb", "aarch64_sve_fnmls_u", [ReverseMergeAnyAccOp]>;
defm SVMAD_F : SInstZPZZZ<"svmad", "hfd", "aarch64_sve_fmad", "aarch64_sve_fmla_u", [IsStreamingCompatible, ReverseMergeAnyAccOp]>;
defm SVMLA_F : SInstZPZZZ<"svmla", "hfd", "aarch64_sve_fmla", "aarch64_sve_fmla_u", [IsStreamingCompatible]>;
defm SVMLS_F : SInstZPZZZ<"svmls", "hfd", "aarch64_sve_fmls", "aarch64_sve_fmls_u", [IsStreamingCompatible]>;
defm SVMSB_F : SInstZPZZZ<"svmsb", "hfd", "aarch64_sve_fmsb", "aarch64_sve_fmls_u", [IsStreamingCompatible, ReverseMergeAnyAccOp]>;
defm SVNMAD_F : SInstZPZZZ<"svnmad", "hfd", "aarch64_sve_fnmad", "aarch64_sve_fnmla_u", [IsStreamingCompatible, ReverseMergeAnyAccOp]>;
defm SVNMLA_F : SInstZPZZZ<"svnmla", "hfd", "aarch64_sve_fnmla", "aarch64_sve_fnmla_u", [IsStreamingCompatible]>;
defm SVNMLS_F : SInstZPZZZ<"svnmls", "hfd", "aarch64_sve_fnmls", "aarch64_sve_fnmls_u", [IsStreamingCompatible]>;
defm SVNMSB_F : SInstZPZZZ<"svnmsb", "hfd", "aarch64_sve_fnmsb", "aarch64_sve_fnmls_u", [IsStreamingCompatible, ReverseMergeAnyAccOp]>;
def SVCADD_M : SInst<"svcadd[_{d}]", "dPddi", "hfd", MergeOp1, "aarch64_sve_fcadd", [IsStreamingCompatible], [ImmCheck<3, ImmCheckComplexRot90_270>]>;
def SVCADD_X : SInst<"svcadd[_{d}]", "dPddi", "hfd", MergeAny, "aarch64_sve_fcadd", [IsStreamingCompatible], [ImmCheck<3, ImmCheckComplexRot90_270>]>;
@ -881,11 +881,11 @@ def SVACLE : SInst<"svacle[_{d}]", "PPdd", "hfd", MergeNone, "aarch64_sve_facg
def SVACLT : SInst<"svaclt[_{d}]", "PPdd", "hfd", MergeNone, "aarch64_sve_facgt", [ReverseCompare, IsStreamingCompatible]>;
def SVCMPUO : SInst<"svcmpuo[_{d}]", "PPdd", "hfd", MergeNone, "aarch64_sve_fcmpuo", [IsStreamingCompatible]>;
def SVACGE_N : SInst<"svacge[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facge">;
def SVACGT_N : SInst<"svacgt[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facgt">;
def SVACLE_N : SInst<"svacle[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facge", [ReverseCompare]>;
def SVACLT_N : SInst<"svaclt[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facgt", [ReverseCompare]>;
def SVCMPUO_N : SInst<"svcmpuo[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_fcmpuo">;
def SVACGE_N : SInst<"svacge[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facge", [IsStreamingCompatible]>;
def SVACGT_N : SInst<"svacgt[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facgt", [IsStreamingCompatible]>;
def SVACLE_N : SInst<"svacle[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facge", [ReverseCompare, IsStreamingCompatible]>;
def SVACLT_N : SInst<"svaclt[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_facgt", [ReverseCompare, IsStreamingCompatible]>;
def SVCMPUO_N : SInst<"svcmpuo[_n_{d}]", "PPda", "hfd", MergeNone, "aarch64_sve_fcmpuo", [IsStreamingCompatible]>;
def SVCMPEQ_F : SInst<"svcmpeq[_{d}]", "PPdd", "hfd", MergeNone, "aarch64_sve_fcmpeq", [IsStreamingCompatible]>;
def SVCMPNE_F : SInst<"svcmpne[_{d}]", "PPdd", "hfd", MergeNone, "aarch64_sve_fcmpne", [IsStreamingCompatible]>;
@ -1023,15 +1023,15 @@ def SVCOMPACT : SInst<"svcompact[_{d}]", "dPd", "ilUiUlfd", MergeNo
// splat of any possible lane. It is upto LLVM to pick a more efficient
// instruction such as DUP (indexed) if the lane index fits the range of the
// instruction's immediate.
def SVDUP_LANE : SInst<"svdup_lane[_{d}]", "ddL", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_tbl">;
def SVDUP_LANE : SInst<"svdup_lane[_{d}]", "ddL", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_tbl", [IsStreamingCompatible]>;
let TargetGuard = "sve,bf16" in {
def SVDUP_LANE_BF16 :
SInst<"svdup_lane[_{d}]", "ddL", "b", MergeNone, "aarch64_sve_tbl">;
SInst<"svdup_lane[_{d}]", "ddL", "b", MergeNone, "aarch64_sve_tbl", [IsStreamingCompatible]>;
}
def SVDUPQ_LANE : SInst<"svdupq_lane[_{d}]", "ddn", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_dupq_lane">;
def SVDUPQ_LANE : SInst<"svdupq_lane[_{d}]", "ddn", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_dupq_lane", [IsStreamingCompatible]>;
let TargetGuard = "sve,bf16" in {
def SVDUPQ_LANE_BF16 : SInst<"svdupq_lane[_{d}]", "ddn", "b", MergeNone, "aarch64_sve_dupq_lane">;
def SVDUPQ_LANE_BF16 : SInst<"svdupq_lane[_{d}]", "ddn", "b", MergeNone, "aarch64_sve_dupq_lane", [IsStreamingCompatible]>;
}
def SVEXT : SInst<"svext[_{d}]", "dddi", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_ext", [IsStreamingCompatible], [ImmCheck<2, ImmCheckExtract, 1>]>;
defm SVLASTA : SVEPerm<"svlasta[_{d}]", "sPd", "aarch64_sve_lasta">;
@ -1109,11 +1109,11 @@ def SVPFALSE : SInst<"svpfalse[_b]", "Pv", "", MergeNone, "", [IsOverloadNone, I
def SVPTRUE_PAT : SInst<"svptrue_pat_{d}", "PI", "PcPsPiPl", MergeNone, "aarch64_sve_ptrue", [IsStreamingCompatible]>;
def SVPTRUE : SInst<"svptrue_{d}", "Pv", "PcPsPiPl", MergeNone, "aarch64_sve_ptrue", [IsAppendSVALL, IsStreamingCompatible]>;
def SVDUPQ_B8 : SInst<"svdupq[_n]_{d}", "Pssssssssssssssss", "Pc", MergeNone>;
def SVDUPQ_B16 : SInst<"svdupq[_n]_{d}", "Pssssssss", "Ps", MergeNone>;
def SVDUPQ_B32 : SInst<"svdupq[_n]_{d}", "Pssss", "Pi", MergeNone>;
def SVDUPQ_B64 : SInst<"svdupq[_n]_{d}", "Pss", "Pl", MergeNone>;
def SVDUP_N_B : SInst<"svdup[_n]_{d}", "Ps", "PcPsPiPl", MergeNone>;
def SVDUPQ_B8 : SInst<"svdupq[_n]_{d}", "Pssssssssssssssss", "Pc", MergeNone, "", [IsStreamingCompatible]>;
def SVDUPQ_B16 : SInst<"svdupq[_n]_{d}", "Pssssssss", "Ps", MergeNone, "", [IsStreamingCompatible]>;
def SVDUPQ_B32 : SInst<"svdupq[_n]_{d}", "Pssss", "Pi", MergeNone, "", [IsStreamingCompatible]>;
def SVDUPQ_B64 : SInst<"svdupq[_n]_{d}", "Pss", "Pl", MergeNone, "", [IsStreamingCompatible]>;
def SVDUP_N_B : SInst<"svdup[_n]_{d}", "Ps", "PcPsPiPl", MergeNone, "", [IsStreamingCompatible]>;
////////////////////////////////////////////////////////////////////////////////
@ -1268,10 +1268,10 @@ def SVZIP2Q : SInst<"svzip2q[_{d}]", "ddd", "csilUcUsUiUlhfd", MergeNo
let TargetGuard = "sve,bf16,f64mm" in {
def SVTRN1Q_BF16 : SInst<"svtrn1q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_trn1q">;
def SVTRN2Q_BF16 : SInst<"svtrn2q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_trn2q">;
def SVUZP1Q_BF16 : SInst<"svuzp1q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_uzp1q">;
def SVUZP2Q_BF16 : SInst<"svuzp2q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_uzp2q">;
def SVZIP1Q_BF16 : SInst<"svzip1q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_zip1q">;
def SVZIP2Q_BF16 : SInst<"svzip2q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_zip2q">;
def SVUZP1Q_BF16 : SInst<"svuzp1q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_uzp1q", [IsStreamingCompatible]>;
def SVUZP2Q_BF16 : SInst<"svuzp2q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_uzp2q", [IsStreamingCompatible]>;
def SVZIP1Q_BF16 : SInst<"svzip1q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_zip1q", [IsStreamingCompatible]>;
def SVZIP2Q_BF16 : SInst<"svzip2q[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_zip2q", [IsStreamingCompatible]>;
}
////////////////////////////////////////////////////////////////////////////////
@ -1281,9 +1281,9 @@ def SVUNDEF_2 : SInst<"svundef2_{d}", "2v", "csilUcUsUiUlhfd", MergeNone, "", [I
def SVUNDEF_3 : SInst<"svundef3_{d}", "3v", "csilUcUsUiUlhfd", MergeNone, "", [IsUndef, IsStreamingCompatible]>;
def SVUNDEF_4 : SInst<"svundef4_{d}", "4v", "csilUcUsUiUlhfd", MergeNone, "", [IsUndef, IsStreamingCompatible]>;
def SVCREATE_2 : SInst<"svcreate2[_{d}]", "2dd", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_3 : SInst<"svcreate3[_{d}]", "3ddd", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_4 : SInst<"svcreate4[_{d}]", "4dddd", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_2 : SInst<"svcreate2[_{d}]", "2dd", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
def SVCREATE_3 : SInst<"svcreate3[_{d}]", "3ddd", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
def SVCREATE_4 : SInst<"svcreate4[_{d}]", "4dddd", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
let TargetGuard = "sve,bf16" in {
def SVUNDEF_1_BF16 : SInst<"svundef_{d}", "dv", "b", MergeNone, "", [IsUndef, IsStreamingCompatible]>;
@ -1291,65 +1291,70 @@ def SVUNDEF_2_BF16 : SInst<"svundef2_{d}", "2v", "b", MergeNone, "", [IsUndef, I
def SVUNDEF_3_BF16 : SInst<"svundef3_{d}", "3v", "b", MergeNone, "", [IsUndef, IsStreamingCompatible]>;
def SVUNDEF_4_BF16 : SInst<"svundef4_{d}", "4v", "b", MergeNone, "", [IsUndef, IsStreamingCompatible]>;
def SVCREATE_2_BF16 : SInst<"svcreate2[_{d}]", "2dd", "b", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_3_BF16 : SInst<"svcreate3[_{d}]", "3ddd", "b", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_4_BF16 : SInst<"svcreate4[_{d}]", "4dddd", "b", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_2_BF16 : SInst<"svcreate2[_{d}]", "2dd", "b", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
def SVCREATE_3_BF16 : SInst<"svcreate3[_{d}]", "3ddd", "b", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
def SVCREATE_4_BF16 : SInst<"svcreate4[_{d}]", "4dddd", "b", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
}
let TargetGuard = "sve2p1" in {
def SVCREATE_2_B : SInst<"svcreate2[_{d}]", "2dd", "Pc", MergeNone, "", [IsTupleCreate]>;
def SVCREATE_4_B : SInst<"svcreate4[_{d}]", "4dddd", "Pc", MergeNone, "", [IsTupleCreate]>;
let TargetGuard = "sve2p1|sme2" in {
def SVCREATE_2_B : SInst<"svcreate2[_b]", "2dd", "Pc", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
def SVCREATE_4_B : SInst<"svcreate4[_b]", "4dddd", "Pc", MergeNone, "", [IsTupleCreate, IsStreamingCompatible]>;
}
////////////////////////////////////////////////////////////////////////////////
// Vector insertion and extraction
def SVGET_2 : SInst<"svget2[_{d}]", "d2i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_1>]>;
def SVGET_3 : SInst<"svget3[_{d}]", "d3i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_2>]>;
def SVGET_4 : SInst<"svget4[_{d}]", "d4i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_3>]>;
def SVGET_2 : SInst<"svget2[_{d}]", "d2i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
def SVGET_3 : SInst<"svget3[_{d}]", "d3i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_2>]>;
def SVGET_4 : SInst<"svget4[_{d}]", "d4i", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
def SVSET_2 : SInst<"svset2[_{d}]", "22id", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_1>]>;
def SVSET_3 : SInst<"svset3[_{d}]", "33id", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_2>]>;
def SVSET_4 : SInst<"svset4[_{d}]", "44id", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_3>]>;
def SVSET_2 : SInst<"svset2[_{d}]", "22id", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
def SVSET_3 : SInst<"svset3[_{d}]", "33id", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_2>]>;
def SVSET_4 : SInst<"svset4[_{d}]", "44id", "csilUcUsUiUlhfd", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
let TargetGuard = "sve,bf16" in {
def SVGET_2_BF16 : SInst<"svget2[_{d}]", "d2i", "b", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_1>]>;
def SVGET_3_BF16 : SInst<"svget3[_{d}]", "d3i", "b", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_2>]>;
def SVGET_4_BF16 : SInst<"svget4[_{d}]", "d4i", "b", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_3>]>;
def SVGET_2_BF16 : SInst<"svget2[_{d}]", "d2i", "b", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
def SVGET_3_BF16 : SInst<"svget3[_{d}]", "d3i", "b", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_2>]>;
def SVGET_4_BF16 : SInst<"svget4[_{d}]", "d4i", "b", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
def SVSET_2_BF16 : SInst<"svset2[_{d}]", "22id", "b", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_1>]>;
def SVSET_3_BF16 : SInst<"svset3[_{d}]", "33id", "b", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_2>]>;
def SVSET_4_BF16 : SInst<"svset4[_{d}]", "44id", "b", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_3>]>;
def SVSET_2_BF16 : SInst<"svset2[_{d}]", "22id", "b", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
def SVSET_3_BF16 : SInst<"svset3[_{d}]", "33id", "b", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_2>]>;
def SVSET_4_BF16 : SInst<"svset4[_{d}]", "44id", "b", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
}
let TargetGuard = "sve2p1" in {
def SVGET_2_B : SInst<"svget2[_{d}]", "d2i", "Pc", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_1>]>;
def SVGET_4_B : SInst<"svget4[_{d}]", "d4i", "Pc", MergeNone, "", [IsTupleGet], [ImmCheck<1, ImmCheck0_3>]>;
let TargetGuard = "sve2p1|sme2" in {
def SVGET_2_B : SInst<"svget2[_b]", "d2i", "Pc", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
def SVGET_4_B : SInst<"svget4[_b]", "d4i", "Pc", MergeNone, "", [IsTupleGet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
def SVSET_2_B : SInst<"svset2[_{d}]", "22id", "Pc", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_1>]>;
def SVSET_4_B : SInst<"svset4[_{d}]", "44id", "Pc", MergeNone, "", [IsTupleSet], [ImmCheck<1, ImmCheck0_3>]>;
def SVSET_2_B : SInst<"svset2[_b]", "22id", "Pc", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
def SVSET_4_B : SInst<"svset4[_b]", "44id", "Pc", MergeNone, "", [IsTupleSet, IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
}
let TargetGuard = "sve2p1|sme2" in {
def SVUNDEF_2_B: Inst<"svundef2_b", "2", "Pc", MergeNone, "", [IsUndef, IsStreamingCompatible], []>;
def SVUNDEF_4_B: Inst<"svundef4_b", "4", "Pc", MergeNone, "", [IsUndef, IsStreamingCompatible], []>;
}
////////////////////////////////////////////////////////////////////////////////
// SVE2 WhileGE/GT
let TargetGuard = "sve2" in {
def SVWHILEGE_S32 : SInst<"svwhilege_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilege", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEGE_S64 : SInst<"svwhilege_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilege", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEGT_S32 : SInst<"svwhilegt_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilegt", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEGT_S64 : SInst<"svwhilegt_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilegt", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEHI_U32 : SInst<"svwhilegt_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehi", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEHI_U64 : SInst<"svwhilegt_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehi", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEHS_U32 : SInst<"svwhilege_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehs", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEHS_U64 : SInst<"svwhilege_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehs", [IsOverloadWhile, IsStreamingCompatible]>;
def SVWHILEGE_S32 : SInst<"svwhilege_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilege", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEGE_S64 : SInst<"svwhilege_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilege", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEGT_S32 : SInst<"svwhilegt_{d}[_{1}]", "Pkk", "PcPsPiPl", MergeNone, "aarch64_sve_whilegt", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEGT_S64 : SInst<"svwhilegt_{d}[_{1}]", "Pll", "PcPsPiPl", MergeNone, "aarch64_sve_whilegt", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEHI_U32 : SInst<"svwhilegt_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehi", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEHI_U64 : SInst<"svwhilegt_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehi", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEHS_U32 : SInst<"svwhilege_{d}[_{1}]", "Pmm", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehs", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
def SVWHILEHS_U64 : SInst<"svwhilege_{d}[_{1}]", "Pnn", "PUcPUsPUiPUl", MergeNone, "aarch64_sve_whilehs", [IsOverloadWhileOrMultiVecCvt, IsStreamingCompatible]>;
}
let TargetGuard = "sve2p1|sme2" in {
def SVWHILEGE_S64_X2 : SInst<"svwhilege_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilege_x2">;
def SVWHILEGT_S64_X2 : SInst<"svwhilegt_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilegt_x2">;
def SVWHILEHI_U64_X2 : SInst<"svwhilegt_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilehi_x2">;
def SVWHILEHS_U64_X2 : SInst<"svwhilege_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilehs_x2">;
def SVWHILELE_S64_X2 : SInst<"svwhilele_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilele_x2">;
def SVWHILELT_S64_X2 : SInst<"svwhilelt_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilelt_x2">;
def SVWHILELO_U64_X2 : SInst<"svwhilelt_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilelo_x2">;
def SVWHILELS_U64_X2 : SInst<"svwhilele_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilels_x2">;
def SVWHILEGE_S64_X2 : SInst<"svwhilege_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilege_x2", [IsStreamingOrSVE2p1]>;
def SVWHILEGT_S64_X2 : SInst<"svwhilegt_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilegt_x2", [IsStreamingOrSVE2p1]>;
def SVWHILEHI_U64_X2 : SInst<"svwhilegt_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilehi_x2", [IsStreamingOrSVE2p1]>;
def SVWHILEHS_U64_X2 : SInst<"svwhilege_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilehs_x2", [IsStreamingOrSVE2p1]>;
def SVWHILELE_S64_X2 : SInst<"svwhilele_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilele_x2", [IsStreamingOrSVE2p1]>;
def SVWHILELT_S64_X2 : SInst<"svwhilelt_{d}[_{1}]_x2", "2ll", "PcPsPiPl", MergeNone, "aarch64_sve_whilelt_x2", [IsStreamingOrSVE2p1]>;
def SVWHILELO_U64_X2 : SInst<"svwhilelt_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilelo_x2", [IsStreamingOrSVE2p1]>;
def SVWHILELS_U64_X2 : SInst<"svwhilele_{d}[_{1}]_x2", "2nn", "PcPsPiPl", MergeNone, "aarch64_sve_whilels_x2", [IsStreamingOrSVE2p1]>;
}
@ -1826,8 +1831,8 @@ def SVPMULLB_PAIR : SInst<"svpmullb_pair[_{d}]", "ddd", "UcUi", Mer
def SVPMULLB_PAIR_N : SInst<"svpmullb_pair[_n_{d}]", "dda", "UcUi", MergeNone, "aarch64_sve_pmullb_pair", [IsStreamingCompatible]>;
def SVPMULLT : SInst<"svpmullt[_{d}]", "dhh", "UsUl", MergeNone, "", [IsStreamingCompatible]>;
def SVPMULLT_N : SInst<"svpmullt[_n_{d}]", "dhR", "UsUl", MergeNone, "", [IsStreamingCompatible]>;
def SVPMULLT_PAIR : SInst<"svpmullt_pair[_{d}]", "ddd", "UcUi", MergeNone, "aarch64_sve_pmullt_pair">;
def SVPMULLT_PAIR_N : SInst<"svpmullt_pair[_n_{d}]", "dda", "UcUi", MergeNone, "aarch64_sve_pmullt_pair">;
def SVPMULLT_PAIR : SInst<"svpmullt_pair[_{d}]", "ddd", "UcUi", MergeNone, "aarch64_sve_pmullt_pair", [IsStreamingCompatible]>;
def SVPMULLT_PAIR_N : SInst<"svpmullt_pair[_n_{d}]", "dda", "UcUi", MergeNone, "aarch64_sve_pmullt_pair", [IsStreamingCompatible]>;
}
////////////////////////////////////////////////////////////////////////////////
@ -1948,14 +1953,10 @@ def SVBGRP_N : SInst<"svbgrp[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sv
}
let TargetGuard = "sve2p1|sme" in {
def SVPSEL_B : SInst<"svpsel_lane_b8", "PPPm", "Pc", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_H : SInst<"svpsel_lane_b16", "PPPm", "Ps", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_S : SInst<"svpsel_lane_b32", "PPPm", "Pi", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_D : SInst<"svpsel_lane_b64", "PPPm", "Pl", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_COUNT_ALIAS_B : SInst<"svpsel_lane_c8", "}}Pm", "Pc", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_COUNT_ALIAS_H : SInst<"svpsel_lane_c16", "}}Pm", "Ps", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_COUNT_ALIAS_S : SInst<"svpsel_lane_c32", "}}Pm", "Pi", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_COUNT_ALIAS_D : SInst<"svpsel_lane_c64", "}}Pm", "Pl", MergeNone, "", [IsStreamingCompatible], []>;
def SVPSEL_B : SInst<"svpsel_lane_b8", "PPPm", "Pc", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVPSEL_H : SInst<"svpsel_lane_b16", "PPPm", "Ps", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVPSEL_S : SInst<"svpsel_lane_b32", "PPPm", "Pi", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVPSEL_D : SInst<"svpsel_lane_b64", "PPPm", "Pl", MergeNone, "", [IsStreamingOrSVE2p1], []>;
}
// Standalone sve2.1 builtins
@ -1979,6 +1980,11 @@ let TargetGuard = "sve2p1|sme2" in {
def SVPEXT_SINGLE : SInst<"svpext_lane_{d}", "P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext", [IsStreamingOrSVE2p1], [ImmCheck<1, ImmCheck0_3>]>;
def SVPEXT_X2 : SInst<"svpext_lane_{d}_x2", "2.P}i", "QcQsQiQl", MergeNone, "aarch64_sve_pext_x2", [IsStreamingOrSVE2p1], [ImmCheck<1, ImmCheck0_1>]>;
def SVPSEL_COUNT_ALIAS_B : SInst<"svpsel_lane_c8", "}}Pm", "Pc", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVPSEL_COUNT_ALIAS_H : SInst<"svpsel_lane_c16", "}}Pm", "Ps", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVPSEL_COUNT_ALIAS_S : SInst<"svpsel_lane_c32", "}}Pm", "Pi", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVPSEL_COUNT_ALIAS_D : SInst<"svpsel_lane_c64", "}}Pm", "Pl", MergeNone, "", [IsStreamingOrSVE2p1], []>;
def SVWHILEGE_COUNT : SInst<"svwhilege_{d}[_{1}]", "}lli", "QcQsQiQl", MergeNone, "aarch64_sve_whilege_{d}", [IsOverloadNone, IsStreamingOrSVE2p1], [ImmCheck<2, ImmCheck2_4_Mul2>]>;
def SVWHILEGT_COUNT : SInst<"svwhilegt_{d}[_{1}]", "}lli", "QcQsQiQl", MergeNone, "aarch64_sve_whilegt_{d}", [IsOverloadNone, IsStreamingOrSVE2p1], [ImmCheck<2, ImmCheck2_4_Mul2>]>;
def SVWHILELE_COUNT : SInst<"svwhilele_{d}[_{1}]", "}lli", "QcQsQiQl", MergeNone, "aarch64_sve_whilele_{d}", [IsOverloadNone, IsStreamingOrSVE2p1], [ImmCheck<2, ImmCheck2_4_Mul2>]>;
@ -2039,13 +2045,13 @@ let TargetGuard = "sve2p1|sme2" in {
defm STNT1 : MultiVecStore<"stnt1">;
}
let TargetGuard = "sve2p1" in {
def SVDOT_X2_S : SInst<"svdot[_{d}_{2}]", "ddhh", "i", MergeNone, "aarch64_sve_sdot_x2", [], []>;
def SVDOT_X2_U : SInst<"svdot[_{d}_{2}]", "ddhh", "Ui", MergeNone, "aarch64_sve_udot_x2", [], []>;
def SVDOT_X2_F : SInst<"svdot[_{d}_{2}]", "ddhh", "f", MergeNone, "aarch64_sve_fdot_x2", [], []>;
def SVDOT_LANE_X2_S : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "i", MergeNone, "aarch64_sve_sdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_U : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "Ui", MergeNone, "aarch64_sve_udot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_F : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "f", MergeNone, "aarch64_sve_fdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
let TargetGuard = "sve2p1|sme2" in {
def SVDOT_X2_S : SInst<"svdot[_{d}_{2}]", "ddhh", "i", MergeNone, "aarch64_sve_sdot_x2", [IsStreamingOrSVE2p1], []>;
def SVDOT_X2_U : SInst<"svdot[_{d}_{2}]", "ddhh", "Ui", MergeNone, "aarch64_sve_udot_x2", [IsStreamingOrSVE2p1], []>;
def SVDOT_X2_F : SInst<"svdot[_{d}_{2}]", "ddhh", "f", MergeNone, "aarch64_sve_fdot_x2", [IsStreamingOrSVE2p1], []>;
def SVDOT_LANE_X2_S : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "i", MergeNone, "aarch64_sve_sdot_lane_x2", [IsStreamingOrSVE2p1], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_U : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "Ui", MergeNone, "aarch64_sve_udot_lane_x2", [IsStreamingOrSVE2p1], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_F : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "f", MergeNone, "aarch64_sve_fdot_lane_x2", [IsStreamingOrSVE2p1], [ImmCheck<3, ImmCheck0_3>]>;
}
let TargetGuard = "sve2p1|sme2" in {
@ -2238,15 +2244,15 @@ let TargetGuard = "sme2" in {
def SVCVT_F16_X2 : SInst<"svcvt_f16[_f32_x2]", "e2", "f", MergeNone, "aarch64_sve_fcvt_x2", [IsStreaming],[]>;
def SVCVT_BF16_X2 : SInst<"svcvt_bf16[_f32_x2]", "$2", "f", MergeNone, "aarch64_sve_bfcvt_x2", [IsOverloadNone, IsStreaming],[]>;
def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_fcvtu_x2", [IsStreaming], []>;
def SVCVT_U32_F32_X2 : SInst<"svcvt_u32[_{d}_x2]", "2.u2.d", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming], []>;
def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_fcvts_x2", [IsStreaming], []>;
def SVCVT_S32_F32_X2 : SInst<"svcvt_s32[_{d}_x2]", "2.x2.d", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming], []>;
def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_U32_F32_X2 : SInst<"svcvt_{d}[_f32_x2]", "2.d2.M", "Ui", MergeNone, "aarch64_sve_fcvtzu_x2", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_S32_F32_X2 : SInst<"svcvt_{d}[_f32_x2]", "2.d2.M", "i", MergeNone, "aarch64_sve_fcvtzs_x2", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_fcvtu_x4", [IsStreaming], []>;
def SVCVT_U32_F32_X4 : SInst<"svcvt_u32[_{d}_x4]", "4.u4.d", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming], []>;
def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_fcvts_x4", [IsStreaming], []>;
def SVCVT_S32_F32_X4 : SInst<"svcvt_s32[_{d}_x4]", "4.x4.d", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming], []>;
def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_U32_F32_X4 : SInst<"svcvt_{d}[_f32_x4]", "4.d4.M", "Ui", MergeNone, "aarch64_sve_fcvtzu_x4", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
def SVCVT_S32_F32_X4 : SInst<"svcvt_{d}[_f32_x4]", "4.d4.M", "i", MergeNone, "aarch64_sve_fcvtzs_x4", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>;
}
//

View File

@ -194,40 +194,44 @@ def FirstSplatOperand : FlagType<0x00000400>;
// These flags are used to specify which scalar operand
// needs to be duplicated/splatted into a vector.
// : :
def SplatOperandMask : FlagType<0x00001C00>;
def IsLoad : FlagType<0x00002000>;
def IsStore : FlagType<0x00004000>;
def IsGatherLoad : FlagType<0x00008000>;
def IsScatterStore : FlagType<0x00010000>;
def IsStructLoad : FlagType<0x00020000>;
def IsStructStore : FlagType<0x00040000>;
def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default
def IsOverloadNone : FlagType<0x00100000>; // Intrinsic does not take any overloaded types.
def IsOverloadWhile : FlagType<0x00200000>; // Use {default type, typeof(operand1)} as overloaded types.
def IsOverloadWhileRW : FlagType<0x00400000>; // Use {pred(default type), typeof(operand0)} as overloaded types.
def IsOverloadCvt : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types.
def OverloadKindMask : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type.
def IsByteIndexed : FlagType<0x01000000>;
def IsAppendSVALL : FlagType<0x02000000>; // Appends SV_ALL as the last operand.
def IsInsertOp1SVALL : FlagType<0x04000000>; // Inserts SV_ALL as the second operand.
def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches.
def IsGatherPrefetch : FlagType<0x10000000>;
def ReverseCompare : FlagType<0x20000000>; // Compare operands must be swapped.
def ReverseUSDOT : FlagType<0x40000000>; // Unsigned/signed operands must be swapped.
def IsUndef : FlagType<0x80000000>; // Codegen `undef` of given type.
def IsTupleCreate : FlagType<0x100000000>;
def IsTupleGet : FlagType<0x200000000>;
def IsTupleSet : FlagType<0x400000000>;
def ReverseMergeAnyBinOp : FlagType<0x800000000>; // e.g. Implement SUBR_X using SUB_X.
def ReverseMergeAnyAccOp : FlagType<0x1000000000>; // e.g. Implement MSB_X using MLS_X.
def IsStreaming : FlagType<0x2000000000>;
def IsStreamingCompatible : FlagType<0x4000000000>;
def IsSharedZA : FlagType<0x8000000000>;
def IsPreservesZA : FlagType<0x10000000000>;
def IsReadZA : FlagType<0x20000000000>;
def IsWriteZA : FlagType<0x40000000000>;
def IsReductionQV : FlagType<0x80000000000>;
def IsStreamingOrSVE2p1 : FlagType<0x80000000000>; // Use for intrinsics that are common between sme/sme2 and sve2p1.
def SplatOperandMask : FlagType<0x00001C00>;
def IsLoad : FlagType<0x00002000>;
def IsStore : FlagType<0x00004000>;
def IsGatherLoad : FlagType<0x00008000>;
def IsScatterStore : FlagType<0x00010000>;
def IsStructLoad : FlagType<0x00020000>;
def IsStructStore : FlagType<0x00040000>;
def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default
def IsOverloadNone : FlagType<0x00100000>; // Intrinsic does not take any overloaded types.
def IsOverloadWhileOrMultiVecCvt : FlagType<0x00200000>; // Use {default type, typeof(operand1)} as overloaded types.
def IsOverloadWhileRW : FlagType<0x00400000>; // Use {pred(default type), typeof(operand0)} as overloaded types.
def IsOverloadCvt : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types.
def OverloadKindMask : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type.
def IsByteIndexed : FlagType<0x01000000>;
def IsAppendSVALL : FlagType<0x02000000>; // Appends SV_ALL as the last operand.
def IsInsertOp1SVALL : FlagType<0x04000000>; // Inserts SV_ALL as the second operand.
def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches.
def IsGatherPrefetch : FlagType<0x10000000>;
def ReverseCompare : FlagType<0x20000000>; // Compare operands must be swapped.
def ReverseUSDOT : FlagType<0x40000000>; // Unsigned/signed operands must be swapped.
def IsUndef : FlagType<0x80000000>; // Codegen `undef` of given type.
def IsTupleCreate : FlagType<0x100000000>;
def IsTupleGet : FlagType<0x200000000>;
def IsTupleSet : FlagType<0x400000000>;
def ReverseMergeAnyBinOp : FlagType<0x800000000>; // e.g. Implement SUBR_X using SUB_X.
def ReverseMergeAnyAccOp : FlagType<0x1000000000>; // e.g. Implement MSB_X using MLS_X.
def IsStreaming : FlagType<0x2000000000>;
def IsStreamingCompatible : FlagType<0x4000000000>;
def IsReadZA : FlagType<0x8000000000>;
def IsWriteZA : FlagType<0x10000000000>;
def IsReductionQV : FlagType<0x20000000000>;
def IsStreamingOrSVE2p1 : FlagType<0x40000000000>; // Use for intrinsics that are common between sme/sme2 and sve2p1.
def IsInZA : FlagType<0x80000000000>;
def IsOutZA : FlagType<0x100000000000>;
def IsInOutZA : FlagType<0x200000000000>;
def IsInZT0 : FlagType<0x400000000000>;
def IsOutZT0 : FlagType<0x800000000000>;
def IsInOutZT0 : FlagType<0x1000000000000>;
// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h
class ImmCheckType<int val> {

View File

@ -117,7 +117,7 @@ multiclass RVVIndexedLoad<string op> {
defvar eew = eew_list[0];
defvar eew_type = eew_list[1];
let Name = op # eew # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>) in {
def: RVVOutOp1Builtin<"v", "vPCe" # eew_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
@ -128,7 +128,7 @@ multiclass RVVIndexedLoad<string op> {
defvar eew64 = "64";
defvar eew64_type = "(Log2EEW:6)";
let Name = op # eew64 # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh", "RV64"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin", "RV64"],
["RV64"]) in {
def: RVVOutOp1Builtin<"v", "vPCe" # eew64_type # "Uv", type>;
if !not(IsFloat<type>.val) then {
@ -222,7 +222,7 @@ multiclass RVVIndexedStore<string op> {
defvar eew = eew_list[0];
defvar eew_type = eew_list[1];
let Name = op # eew # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>) in {
def : RVVBuiltin<"v", "0Pe" # eew_type # "Uvv", type>;
if !not(IsFloat<type>.val) then {
@ -233,7 +233,7 @@ multiclass RVVIndexedStore<string op> {
defvar eew64 = "64";
defvar eew64_type = "(Log2EEW:6)";
let Name = op # eew64 # "_v", IRName = op, MaskedIRName = op # "_mask",
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh", "RV64"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin", "RV64"],
["RV64"]) in {
def : RVVBuiltin<"v", "0Pe" # eew64_type # "Uvv", type>;
if !not(IsFloat<type>.val) then {
@ -681,7 +681,7 @@ let HasBuiltinAlias = false,
def vlm: RVVVLEMaskBuiltin;
defm vle8: RVVVLEBuiltin<["c"]>;
defm vle16: RVVVLEBuiltin<["s"]>;
let Name = "vle16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vle16_v", RequiredFeatures = ["Zvfhmin"] in
defm vle16_h: RVVVLEBuiltin<["x"]>;
defm vle32: RVVVLEBuiltin<["i","f"]>;
defm vle64: RVVVLEBuiltin<["l","d"]>;
@ -689,7 +689,7 @@ defm vle64: RVVVLEBuiltin<["l","d"]>;
def vsm : RVVVSEMaskBuiltin;
defm vse8 : RVVVSEBuiltin<["c"]>;
defm vse16: RVVVSEBuiltin<["s"]>;
let Name = "vse16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vse16_v", RequiredFeatures = ["Zvfhmin"] in
defm vse16_h: RVVVSEBuiltin<["x"]>;
defm vse32: RVVVSEBuiltin<["i","f"]>;
defm vse64: RVVVSEBuiltin<["l","d"]>;
@ -697,14 +697,14 @@ defm vse64: RVVVSEBuiltin<["l","d"]>;
// 7.5. Vector Strided Instructions
defm vlse8: RVVVLSEBuiltin<["c"]>;
defm vlse16: RVVVLSEBuiltin<["s"]>;
let Name = "vlse16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vlse16_v", RequiredFeatures = ["Zvfhmin"] in
defm vlse16_h: RVVVLSEBuiltin<["x"]>;
defm vlse32: RVVVLSEBuiltin<["i","f"]>;
defm vlse64: RVVVLSEBuiltin<["l","d"]>;
defm vsse8 : RVVVSSEBuiltin<["c"]>;
defm vsse16: RVVVSSEBuiltin<["s"]>;
let Name = "vsse16_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vsse16_v", RequiredFeatures = ["Zvfhmin"] in
defm vsse16_h: RVVVSSEBuiltin<["x"]>;
defm vsse32: RVVVSSEBuiltin<["i","f"]>;
defm vsse64: RVVVSSEBuiltin<["l","d"]>;
@ -719,7 +719,7 @@ defm : RVVIndexedStore<"vsoxei">;
// 7.7. Unit-stride Fault-Only-First Loads
defm vle8ff: RVVVLEFFBuiltin<["c"]>;
defm vle16ff: RVVVLEFFBuiltin<["s"]>;
let Name = "vle16ff_v", RequiredFeatures = ["ZvfhminOrZvfh"] in
let Name = "vle16ff_v", RequiredFeatures = ["Zvfhmin"] in
defm vle16ff: RVVVLEFFBuiltin<["x"]>;
defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>;
defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>;
@ -738,7 +738,7 @@ multiclass RVVUnitStridedSegLoadTuple<string op> {
IRName = op # nf,
MaskedIRName = op # nf # "_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -800,7 +800,7 @@ multiclass RVVUnitStridedSegStoreTuple<string op> {
MaskedIRName = op # nf # "_mask",
NF = nf,
HasMaskedOffOperand = false,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -852,7 +852,7 @@ multiclass RVVUnitStridedSegLoadFFTuple<string op> {
IRName = op # nf # "ff",
MaskedIRName = op # nf # "ff_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -927,7 +927,7 @@ multiclass RVVStridedSegLoadTuple<string op> {
IRName = op # nf,
MaskedIRName = op # nf # "_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -991,7 +991,7 @@ multiclass RVVStridedSegStoreTuple<string op> {
NF = nf,
HasMaskedOffOperand = false,
MaskedPolicyScheme = NonePolicy,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -1040,7 +1040,7 @@ multiclass RVVIndexedSegLoadTuple<string op> {
IRName = op # nf,
MaskedIRName = op # nf # "_mask",
NF = nf,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -1103,7 +1103,7 @@ multiclass RVVIndexedSegStoreTuple<string op> {
NF = nf,
HasMaskedOffOperand = false,
MaskedPolicyScheme = NonePolicy,
RequiredFeatures = !if(!eq(type, "x"), ["ZvfhminOrZvfh"],
RequiredFeatures = !if(!eq(type, "x"), ["Zvfhmin"],
[]<string>),
ManualCodegen = [{
{
@ -1345,7 +1345,7 @@ let HasMasked = false,
[["v", "Uv", "UvUv"]]>;
defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csilfd",
[["v", "v", "vv"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "x",
[["v", "v", "vv"]]>;
let SupportOverloading = false in
@ -1841,7 +1841,7 @@ let HasMasked = false,
}] in {
defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "fd",
[["vvm", "v", "vvvm"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "x",
[["vvm", "v", "vvvm"]]>;
defm vfmerge : RVVOutOp1BuiltinSet<"vfmerge", "xfd",
@ -1869,7 +1869,7 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">;
def vfwcvt_f_x_v : RVVConvBuiltin<"Fw", "Fwv", "csi", "vfwcvt_f">;
def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "f", "vfwcvt_f">;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
def vfwcvt_f_f_v_fp16 : RVVConvBuiltin<"w", "wv", "x", "vfwcvt_f"> {
let Name = "vfwcvt_f_f_v";
let IRName = "vfwcvt_f_f_v";
@ -1966,7 +1966,7 @@ let ManualCodegen = [{
}
let OverloadedName = "vfncvt_f" in {
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "f", [["v", "vwu"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vwu"]]>;
}
}
@ -2011,7 +2011,7 @@ let ManualCodegen = [{
}
let OverloadedName = "vfncvt_f" in {
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "f", [["v", "vw"]]>;
let RequiredFeatures = ["ZvfhminOrZvfh"] in
let RequiredFeatures = ["Zvfhmin"] in
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vw"]]>;
}
}
@ -2271,7 +2271,7 @@ let HasMasked = false, HasVL = false, IRName = "" in {
def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "il", "Uv">;
def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "il", "Fv">;
def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "il", "Fv">;
let RequiredFeatures = ["ZvfhminOrZvfh"] in {
let RequiredFeatures = ["Zvfhmin"] in {
def vreinterpret_i_h : RVVBuiltin<"Fvv", "vFv", "s", "v">;
def vreinterpret_u_h : RVVBuiltin<"FvUv", "UvFv", "s", "Uv">;
def vreinterpret_h_i : RVVBuiltin<"vFv", "Fvv", "s", "Fv">;

View File

@ -3459,6 +3459,10 @@ def fopenmp_offload_mandatory : Flag<["-"], "fopenmp-offload-mandatory">, Group<
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Do not create a host fallback if offloading to the device fails.">,
MarshallingInfoFlag<LangOpts<"OpenMPOffloadMandatory">>;
def fopenmp_force_usm : Flag<["-"], "fopenmp-force-usm">, Group<f_Group>,
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Force behvaior as if the user specified pragma omp requires unified_shared_memory.">,
MarshallingInfoFlag<LangOpts<"OpenMPForceUSM">>;
def fopenmp_target_jit : Flag<["-"], "fopenmp-target-jit">, Group<f_Group>,
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CLOption]>,
HelpText<"Emit code that can be JIT compiled for OpenMP offloading. Implies -foffload-lto=full">;
@ -3664,6 +3668,10 @@ def ftrivial_auto_var_init_stop_after : Joined<["-"], "ftrivial-auto-var-init-st
Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
HelpText<"Stop initializing trivial automatic stack variables after the specified number of instances">,
MarshallingInfoInt<LangOpts<"TrivialAutoVarInitStopAfter">>;
def ftrivial_auto_var_init_max_size : Joined<["-"], "ftrivial-auto-var-init-max-size=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
HelpText<"Stop initializing trivial automatic stack variables if var size exceeds the specified number of instances (in bytes)">,
MarshallingInfoInt<LangOpts<"TrivialAutoVarInitMaxSize">>;
def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>,
Visibility<[ClangOption, CLOption, DXCOption]>,
HelpText<"Emit full debug info for all types used by the program">;
@ -3858,27 +3866,32 @@ def dA : Flag<["-"], "dA">, Alias<fverbose_asm>;
defm visibility_from_dllstorageclass : BoolFOption<"visibility-from-dllstorageclass",
LangOpts<"VisibilityFromDLLStorageClass">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Set the visibility of symbols in the generated code from their DLL storage class">,
"Override the visibility of globals based on their final DLL storage class.">,
NegFlag<SetFalse>>;
class MarshallingInfoVisibilityFromDLLStorage<KeyPathAndMacro kpm, code default>
: MarshallingInfoEnum<kpm, default>,
Values<"keep,hidden,protected,default">,
NormalizedValuesScope<"LangOptions::VisibilityFromDLLStorageClassKinds">,
NormalizedValues<["Keep", "Hidden", "Protected", "Default"]> {}
def fvisibility_dllexport_EQ : Joined<["-"], "fvisibility-dllexport=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"The visibility for dllexport definitions [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibility<LangOpts<"DLLExportVisibility">, "DefaultVisibility">,
HelpText<"The visibility for dllexport definitions. If Keep is specified the visibility is not adjusted [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibilityFromDLLStorage<LangOpts<"DLLExportVisibility">, "Default">,
ShouldParseIf<fvisibility_from_dllstorageclass.KeyPath>;
def fvisibility_nodllstorageclass_EQ : Joined<["-"], "fvisibility-nodllstorageclass=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"The visibility for definitions without an explicit DLL export class [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibility<LangOpts<"NoDLLStorageClassVisibility">, "HiddenVisibility">,
HelpText<"The visibility for definitions without an explicit DLL storage class. If Keep is specified the visibility is not adjusted [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibilityFromDLLStorage<LangOpts<"NoDLLStorageClassVisibility">, "Hidden">,
ShouldParseIf<fvisibility_from_dllstorageclass.KeyPath>;
def fvisibility_externs_dllimport_EQ : Joined<["-"], "fvisibility-externs-dllimport=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibility<LangOpts<"ExternDeclDLLImportVisibility">, "DefaultVisibility">,
HelpText<"The visibility for dllimport external declarations. If Keep is specified the visibility is not adjusted [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibilityFromDLLStorage<LangOpts<"ExternDeclDLLImportVisibility">, "Default">,
ShouldParseIf<fvisibility_from_dllstorageclass.KeyPath>;
def fvisibility_externs_nodllstorageclass_EQ : Joined<["-"], "fvisibility-externs-nodllstorageclass=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"The visibility for external declarations without an explicit DLL dllstorageclass [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibility<LangOpts<"ExternDeclNoDLLStorageClassVisibility">, "HiddenVisibility">,
HelpText<"The visibility for external declarations without an explicit DLL storage class. If Keep is specified the visibility is not adjusted [-fvisibility-from-dllstorageclass]">,
MarshallingInfoVisibilityFromDLLStorage<LangOpts<"ExternDeclNoDLLStorageClassVisibility">, "Hidden">,
ShouldParseIf<fvisibility_from_dllstorageclass.KeyPath>;
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
@ -3901,9 +3914,16 @@ def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>
HelpText<"Give global types 'default' visibility and global functions and "
"variables 'hidden' visibility by default">;
def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group<f_Group>,
HelpText<"Give global C++ operator new and delete declarations hidden visibility">,
HelpText<"Give global C++ operator new and delete declarations hidden visibility">;
class MarshallingInfoVisibilityGlobalNewDelete<KeyPathAndMacro kpm, code default>
: MarshallingInfoEnum<kpm, default>,
Values<"force-default,force-protected,force-hidden,source">,
NormalizedValuesScope<"LangOptions::VisibilityForcedKinds">,
NormalizedValues<["ForceDefault", "ForceProtected", "ForceHidden", "Source"]> {}
def fvisibility_global_new_delete_EQ : Joined<["-"], "fvisibility-global-new-delete=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoFlag<LangOpts<"GlobalAllocationFunctionVisibilityHidden">>;
HelpText<"The visibility for global C++ operator new and delete declarations. If 'source' is specified the visibility is not adjusted">,
MarshallingInfoVisibilityGlobalNewDelete<LangOpts<"GlobalAllocationFunctionVisibility">, "ForceDefault">;
def mdefault_visibility_export_mapping_EQ : Joined<["-"], "mdefault-visibility-export-mapping=">,
Values<"none,explicit,all">,
NormalizedValuesScope<"LangOptions::DefaultVisiblityExportMapping">,
@ -4392,8 +4412,8 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>;
def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "65535">;
Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>,
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "0">;
def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): "
@ -4761,12 +4781,12 @@ defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee",
NegFlag<SetFalse, [], [ClangOption, CC1Option]>>, Group<m_Group>;
def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group<m_Group>,
HelpText<"Specify code object ABI version. Defaults to 4. (AMDGPU only)">,
HelpText<"Specify code object ABI version. Defaults to 5. (AMDGPU only)">,
Visibility<[ClangOption, FlangOption, CC1Option, FC1Option]>,
Values<"none,4,5">,
NormalizedValuesScope<"llvm::CodeObjectVersionKind">,
NormalizedValues<["COV_None", "COV_4", "COV_5"]>,
MarshallingInfoEnum<TargetOpts<"CodeObjectVersion">, "COV_4">;
MarshallingInfoEnum<TargetOpts<"CodeObjectVersion">, "COV_5">;
defm cumode : SimpleMFlag<"cumode",
"Specify CU wavefront", "Specify WGP wavefront",
@ -5172,7 +5192,7 @@ def module_file_info : Flag<["-"], "module-file-info">, Flags<[]>,
HelpText<"Provide information about a particular module file">;
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>,
HelpText<"Only supported on AArch64, PowerPC, RISC-V, SystemZ, and X86">;
HelpText<"Only supported on AArch64, PowerPC, RISC-V, SPARC, SystemZ, and X86">;
def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
@ -5307,7 +5327,8 @@ def pthreads : Flag<["-"], "pthreads">;
defm pthread : BoolOption<"", "pthread",
LangOpts<"POSIXThreads">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Support POSIX threads in generated code">,
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;
NegFlag<SetFalse>,
BothFlags<[], [ClangOption, CC1Option, FlangOption, FC1Option]>>;
def pie : Flag<["-"], "pie">, Group<Link_Group>;
def static_pie : Flag<["-"], "static-pie">, Group<Link_Group>;
def read__only__relocs : Separate<["-"], "read_only_relocs">;
@ -6043,11 +6064,11 @@ def mapx_features_EQ : CommaJoined<["-"], "mapx-features=">, Group<m_x86_Feature
HelpText<"Enable features of APX">, Values<"egpr,push2pop2,ppx,ndd,ccmp,cf">;
def mno_apx_features_EQ : CommaJoined<["-"], "mno-apx-features=">, Group<m_x86_Features_Group>,
HelpText<"Disable features of APX">, Values<"egpr,push2pop2,ppx,ndd,ccmp,cf">;
// Features egpr, push2pop2 and ppx are validated with llvm-test-suite && cpu2017 on Intel SDE.
// Features egpr, push2pop2, ppx and ndd are validated with llvm-test-suite && cpu2017 on Intel SDE.
// For stability, we turn on these features only for -mapxf. After a feature pass the validation,
// we will add it to -mapxf.
def mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx"]>;
def mno_apxf : Flag<["-"], "mno-apxf">, Alias<mno_apx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx"]>;
def mapxf : Flag<["-"], "mapxf">, Alias<mapx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx", "ndd"]>;
def mno_apxf : Flag<["-"], "mno-apxf">, Alias<mno_apx_features_EQ>, AliasArgs<["egpr","push2pop2","ppx","ndd"]>;
} // let Flags = [TargetSpecific]
// VE feature flags
@ -6297,6 +6318,11 @@ def fno_sycl : Flag<["-"], "fno-sycl">,
Visibility<[ClangOption, CLOption]>,
Group<sycl_Group>, HelpText<"Disables SYCL kernels compilation for device">;
// OS-specific options
let Flags = [TargetSpecific] in {
defm android_pad_segment : BooleanFFlag<"android-pad-segment">, Group<f_Group>;
} // let Flags = [TargetSpecific]
//===----------------------------------------------------------------------===//
// FLangOption + NoXarchOption
//===----------------------------------------------------------------------===//
@ -8457,3 +8483,6 @@ def : Option<["/", "-"], "Qembed_debug", KIND_FLAG>, Group<dxc_Group>,
HelpText<"Embed PDB in shader container (ignored)">;
def spirv : DXCFlag<"spirv">,
HelpText<"Generate SPIR-V code">;
def fspv_target_env_EQ : Joined<["-"], "fspv-target-env=">, Group<dxc_Group>,
HelpText<"Specify the target environment">,
Values<"vulkan1.2, vulkan1.3">;

View File

@ -37,8 +37,10 @@
// C family source language (with and without preprocessing).
TYPE("cpp-output", PP_C, INVALID, "i", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("c", C, PP_C, "c", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("cl", CL, PP_C, "cl", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("clcpp", CLCXX, PP_CXX, "clcpp", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("cl", CL, PP_CL, "cl", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("cl-cpp-output", PP_CL, INVALID, "cli", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("clcpp", CLCXX, PP_CLCXX, "clcpp", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("clcpp-cpp-output", PP_CLCXX, INVALID, "clii", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("cuda", CUDA, PP_CUDA, "cu", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)

View File

@ -169,6 +169,7 @@ struct APIRecord {
RK_Enum,
RK_StructField,
RK_Struct,
RK_UnionField,
RK_Union,
RK_StaticField,
RK_CXXField,
@ -224,7 +225,7 @@ struct APIRecord {
StringRef USR;
StringRef Name;
PresumedLoc Location;
AvailabilitySet Availabilities;
AvailabilityInfo Availability;
LinkageInfo Linkage;
/// Documentation comment lines attached to this symbol declaration.
@ -256,12 +257,12 @@ public:
APIRecord() = delete;
APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Location, AvailabilitySet Availabilities,
PresumedLoc Location, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
bool IsFromSystemHeader)
: USR(USR), Name(Name), Location(Location),
Availabilities(std::move(Availabilities)), Linkage(Linkage),
Availability(std::move(Availability)), Linkage(Linkage),
Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
IsFromSystemHeader(IsFromSystemHeader), Kind(Kind) {}
@ -274,10 +275,10 @@ public:
struct NamespaceRecord : APIRecord {
NamespaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_Namespace, USR, Name, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
@ -291,23 +292,23 @@ struct GlobalFunctionRecord : APIRecord {
FunctionSignature Signature;
GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: APIRecord(RK_GlobalFunction, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_GlobalFunction, USR, Name, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), Linkage,
: APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
Comment, Declaration, SubHeading, IsFromSystemHeader),
Signature(Signature) {}
@ -323,14 +324,14 @@ struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
Template Templ;
GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, Template Template,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc,
std::move(Availabilities), Linkage, Comment,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature,
IsFromSystemHeader),
Templ(Template) {}
@ -343,12 +344,12 @@ struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
Loc, std::move(Availabilities), Linkage, Comment,
Loc, std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature,
IsFromSystemHeader) {}
@ -360,20 +361,20 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_GlobalVariable, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_GlobalVariable, USR, Name, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), Linkage,
: APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
@ -388,13 +389,13 @@ struct GlobalVariableTemplateRecord : GlobalVariableRecord {
Template Templ;
GlobalVariableTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
class Template Template, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Loc,
std::move(Availabilities), Linkage, Comment,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
Templ(Template) {}
@ -406,11 +407,11 @@ struct GlobalVariableTemplateRecord : GlobalVariableRecord {
struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
Loc, std::move(Availabilities), Linkage, Comment,
Loc, std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
@ -424,12 +425,12 @@ struct GlobalVariableTemplatePartialSpecializationRecord
GlobalVariableTemplatePartialSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, class Template Template,
bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
USR, Name, Loc, std::move(Availabilities), Linkage,
USR, Name, Loc, std::move(Availability), Linkage,
Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
@ -442,10 +443,10 @@ struct GlobalVariableTemplatePartialSpecializationRecord
/// This holds information associated with enum constants.
struct EnumConstantRecord : APIRecord {
EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_EnumConstant, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_EnumConstant, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
@ -462,10 +463,10 @@ struct EnumRecord : APIRecord {
SmallVector<std::unique_ptr<EnumConstantRecord>> Constants;
EnumRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
bool IsFromSystemHeader)
: APIRecord(RK_Enum, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_Enum, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
@ -478,17 +479,19 @@ private:
};
/// This holds information associated with struct fields.
struct StructFieldRecord : APIRecord {
StructFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
struct RecordFieldRecord : APIRecord {
RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_StructField, USR, Name, Loc, std::move(Availabilities),
DeclarationFragments SubHeading, RecordKind Kind,
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_StructField;
return Record->getKind() == RK_StructField ||
Record->getKind() == RK_UnionField;
}
private:
@ -496,19 +499,20 @@ private:
};
/// This holds information associated with structs.
struct StructRecord : APIRecord {
SmallVector<std::unique_ptr<StructFieldRecord>> Fields;
struct RecordRecord : APIRecord {
SmallVector<std::unique_ptr<RecordFieldRecord>> Fields;
StructRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_Struct, USR, Name, Loc, std::move(Availabilities),
DeclarationFragments SubHeading, RecordKind Kind,
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_Struct;
return Record->getKind() == RK_Struct || Record->getKind() == RK_Union;
}
private:
@ -519,21 +523,21 @@ struct CXXFieldRecord : APIRecord {
AccessControl Access;
CXXFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Access(Access) {}
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Access(Access) {}
@ -550,13 +554,13 @@ struct CXXFieldTemplateRecord : CXXFieldRecord {
Template Templ;
CXXFieldTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
Template Template, bool IsFromSystemHeader)
: CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Access, IsFromSystemHeader),
Templ(Template) {}
@ -572,11 +576,11 @@ struct CXXMethodRecord : APIRecord {
CXXMethodRecord() = delete;
CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature), Access(Access) {}
@ -586,14 +590,13 @@ struct CXXMethodRecord : APIRecord {
struct CXXConstructorRecord : CXXMethodRecord {
CXXConstructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_CXXConstructorMethod;
@ -605,13 +608,13 @@ private:
struct CXXDestructorRecord : CXXMethodRecord {
CXXDestructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_CXXDestructorMethod;
@ -623,14 +626,14 @@ private:
struct CXXStaticMethodRecord : CXXMethodRecord {
CXXStaticMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_CXXStaticMethod;
@ -642,14 +645,14 @@ private:
struct CXXInstanceMethodRecord : CXXMethodRecord {
CXXInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
@ -664,14 +667,14 @@ struct CXXMethodTemplateRecord : CXXMethodRecord {
Template Templ;
CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
Template Template, bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader),
Templ(Template) {}
@ -683,12 +686,12 @@ struct CXXMethodTemplateRecord : CXXMethodRecord {
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
@ -711,13 +714,13 @@ struct ObjCPropertyRecord : APIRecord {
bool IsOptional;
ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AttributeKind Attributes,
StringRef GetterName, StringRef SetterName,
bool IsOptional, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
@ -731,7 +734,7 @@ struct ObjCPropertyRecord : APIRecord {
struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
ObjCInstancePropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
@ -739,7 +742,7 @@ struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
StringRef SetterName, bool IsOptional,
bool IsFromSystemHeader)
: ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
@ -753,7 +756,7 @@ private:
struct ObjCClassPropertyRecord : ObjCPropertyRecord {
ObjCClassPropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
@ -761,7 +764,7 @@ struct ObjCClassPropertyRecord : ObjCPropertyRecord {
StringRef SetterName, bool IsOptional,
bool IsFromSystemHeader)
: ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
@ -779,12 +782,12 @@ struct ObjCInstanceVariableRecord : APIRecord {
AccessControl Access;
ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(RK_ObjCIvar, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_ObjCIvar, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Access(Access) {}
@ -804,11 +807,11 @@ struct ObjCMethodRecord : APIRecord {
ObjCMethodRecord() = delete;
ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
@ -818,13 +821,13 @@ struct ObjCMethodRecord : APIRecord {
struct ObjCInstanceMethodRecord : ObjCMethodRecord {
ObjCInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCInstanceMethod;
@ -836,13 +839,13 @@ private:
struct ObjCClassMethodRecord : ObjCMethodRecord {
ObjCClassMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
@ -880,13 +883,13 @@ struct StaticFieldRecord : CXXFieldRecord {
SymbolReference Context;
StaticFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Context,
AccessControl Access, bool IsFromSystemHeader)
: CXXFieldRecord(RK_StaticField, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
SubHeading, Access, IsFromSystemHeader),
: CXXFieldRecord(RK_StaticField, USR, Name, Loc, std::move(Availability),
Comment, Declaration, SubHeading, Access,
IsFromSystemHeader),
Context(Context) {}
static bool classof(const APIRecord *Record) {
@ -905,11 +908,11 @@ struct ObjCContainerRecord : APIRecord {
ObjCContainerRecord() = delete;
ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, AvailabilitySet Availabilities,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), Linkage,
: APIRecord(Kind, USR, Name, Loc, std::move(Availability), Linkage,
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
virtual ~ObjCContainerRecord() = 0;
@ -922,11 +925,11 @@ struct CXXClassRecord : APIRecord {
AccessControl Access;
CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
: APIRecord(Kind, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Access(Access) {}
@ -943,11 +946,11 @@ struct ClassTemplateRecord : CXXClassRecord {
Template Templ;
ClassTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
AccessControl Access, bool IsFromSystemHeader)
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
: CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplate, Access,
IsFromSystemHeader),
Templ(Template) {}
@ -960,10 +963,10 @@ struct ClassTemplateRecord : CXXClassRecord {
struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader)
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
: CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplateSpecialization,
Access, IsFromSystemHeader) {}
@ -976,10 +979,10 @@ struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
Template Templ;
ClassTemplatePartialSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader)
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
: CXXClassRecord(USR, Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplateSpecialization,
Access, IsFromSystemHeader),
Templ(Template) {}
@ -993,11 +996,11 @@ struct ConceptRecord : APIRecord {
Template Templ;
ConceptRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader)
: APIRecord(RK_Concept, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_Concept, USR, Name, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
@ -1010,12 +1013,12 @@ struct ObjCCategoryRecord : ObjCContainerRecord {
bool IsFromExternalModule = false;
ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface,
bool IsFromSystemHeader)
: ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc,
std::move(Availabilities), LinkageInfo::none(),
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader),
Interface(Interface) {}
@ -1035,13 +1038,13 @@ struct ObjCInterfaceRecord : ObjCContainerRecord {
SmallVector<ObjCCategoryRecord *> Categories;
ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass, bool IsFromSystemHeader)
: ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc,
std::move(Availabilities), Linkage, Comment,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
SuperClass(SuperClass) {}
@ -1056,11 +1059,11 @@ private:
/// This holds information associated with Objective-C protocols.
struct ObjCProtocolRecord : ObjCContainerRecord {
ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc,
std::move(Availabilities), LinkageInfo::none(),
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
@ -1078,7 +1081,7 @@ struct MacroDefinitionRecord : APIRecord {
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader)
: APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilitySet(),
: APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(),
LinkageInfo(), {}, Declaration, SubHeading,
IsFromSystemHeader) {}
@ -1099,11 +1102,11 @@ struct TypedefRecord : APIRecord {
SymbolReference UnderlyingType;
TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference UnderlyingType,
bool IsFromSystemHeader)
: APIRecord(RK_Typedef, USR, Name, Loc, std::move(Availabilities),
: APIRecord(RK_Typedef, USR, Name, Loc, std::move(Availability),
LinkageInfo(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
UnderlyingType(UnderlyingType) {}
@ -1191,7 +1194,7 @@ class APISet {
public:
NamespaceRecord *addNamespace(APIRecord *Parent, StringRef Name,
StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
@ -1204,13 +1207,13 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
GlobalVariableRecord *
addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeadin, bool IsFromSystemHeaderg);
GlobalVariableTemplateRecord *
addGlobalVariableTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
@ -1224,14 +1227,14 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
GlobalFunctionRecord *
addGlobalFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader);
GlobalFunctionTemplateRecord *addGlobalFunctionTemplate(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
Template Template, bool IsFromSystemHeader);
@ -1239,7 +1242,7 @@ public:
GlobalFunctionTemplateSpecializationRecord *
addGlobalFunctionTemplateSpecialization(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader);
@ -1252,7 +1255,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
EnumConstantRecord *
addEnumConstant(EnumRecord *Enum, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader);
@ -1263,45 +1266,46 @@ public:
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
/// to generate the USR for \c D and keep it alive in APISet.
EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader);
/// Create and add a struct field record into the API set.
/// Create and add a record field record into the API set.
///
/// Note: the caller is responsible for keeping the StringRef \p Name and
/// \p USR alive. APISet::copyString provides a way to copy strings into
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
/// to generate the USR for \c D and keep it alive in APISet.
StructFieldRecord *
addStructField(StructRecord *Struct, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability,
RecordFieldRecord *
addRecordField(RecordRecord *Record, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader);
DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
bool IsFromSystemHeader);
/// Create and add a struct record into the API set.
/// Create and add a record record into the API set.
///
/// Note: the caller is responsible for keeping the StringRef \p Name and
/// \p USR alive. APISet::copyString provides a way to copy strings into
/// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
/// to generate the USR for \c D and keep it alive in APISet.
StructRecord *addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability,
RecordRecord *addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader);
APIRecord::RecordKind Kind, bool IsFromSystemHeader);
StaticFieldRecord *
addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availabilities, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Context,
AccessControl Access, bool IsFromSystemHeaderg);
CXXFieldRecord *addCXXField(APIRecord *CXXClass, StringRef Name,
StringRef USR, PresumedLoc Loc,
AvailabilitySet Availabilities,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
@ -1309,12 +1313,12 @@ public:
CXXFieldTemplateRecord *addCXXFieldTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, Template Template, bool IsFromSystemHeader);
CXXClassRecord *addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
@ -1323,76 +1327,76 @@ public:
ClassTemplateRecord *
addClassTemplate(APIRecord *Parent, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
AccessControl Access, bool IsFromSystemHeader);
ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader);
ClassTemplatePartialSpecializationRecord *
addClassTemplatePartialSpecialization(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader);
GlobalVariableTemplateSpecializationRecord *
addGlobalVariableTemplateSpecialization(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader);
GlobalVariableTemplatePartialSpecializationRecord *
addGlobalVariableTemplatePartialSpecialization(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader);
CXXMethodRecord *addCXXInstanceMethod(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader);
CXXMethodRecord *addCXXStaticMethod(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader);
CXXMethodRecord *addCXXSpecialMethod(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader);
CXXMethodTemplateRecord *addCXXMethodTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access, Template Template,
bool IsFromSystemHeader);
CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader);
ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
@ -1406,7 +1410,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
ObjCCategoryRecord *
addObjCCategory(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface,
bool IsFromSystemHeader, bool IsFromExternalModule);
@ -1419,7 +1423,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
ObjCInterfaceRecord *
addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, LinkageInfo Linkage,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference SuperClass,
bool IsFromSystemHeader);
@ -1432,7 +1436,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
ObjCMethodRecord *
addObjCMethod(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsInstanceMethod, bool IsFromSystemHeader);
@ -1445,7 +1449,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
ObjCPropertyRecord *
addObjCProperty(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
ObjCPropertyRecord::AttributeKind Attributes,
@ -1460,7 +1464,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
ObjCInstanceVariableRecord *addObjCInstanceVariable(
ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
ObjCInstanceVariableRecord::AccessControl Access,
bool IsFromSystemHeader);
@ -1473,7 +1477,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
ObjCProtocolRecord *
addObjCProtocol(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader);
@ -1498,7 +1502,7 @@ public:
/// to generate the USR for \c D and keep it alive in APISet.
TypedefRecord *
addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
SymbolReference UnderlyingType, bool IsFromSystemHeader);
@ -1545,7 +1549,7 @@ public:
return GlobalVariableTemplatePartialSpecializations;
}
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
const RecordMap<StructRecord> &getStructs() const { return Structs; }
const RecordMap<RecordRecord> &getRecords() const { return Records; }
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
return CXXMethodTemplates;
@ -1564,7 +1568,6 @@ public:
const RecordMap<CXXFieldTemplateRecord> &getCXXFieldTemplates() const {
return CXXFieldTemplates;
}
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
return ClassTemplates;
}
@ -1576,7 +1579,7 @@ public:
getClassTemplatePartialSpecializations() const {
return ClassTemplatePartialSpecializations;
}
const RecordMap<ConceptRecord> &getRecords() const { return Concepts; }
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
return ObjCCategories;
}
@ -1642,7 +1645,7 @@ private:
RecordMap<ConceptRecord> Concepts;
RecordMap<StaticFieldRecord> StaticFields;
RecordMap<EnumRecord> Enums;
RecordMap<StructRecord> Structs;
RecordMap<RecordRecord> Records;
RecordMap<CXXClassRecord> CXXClasses;
RecordMap<CXXFieldRecord> CXXFields;
RecordMap<CXXMethodRecord> CXXMethods;

View File

@ -16,56 +16,31 @@
#define LLVM_CLANG_EXTRACTAPI_AVAILABILITY_INFO_H
#include "clang/AST/Decl.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
using llvm::VersionTuple;
namespace clang {
namespace extractapi {
/// Stores availability attributes of a symbol in a given domain.
/// Stores availability attributes of a symbol.
struct AvailabilityInfo {
/// The domain for which this availability info item applies
std::string Domain;
VersionTuple Introduced;
VersionTuple Deprecated;
VersionTuple Obsoleted;
bool Unavailable;
AvailabilityInfo() = default;
AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D,
VersionTuple O, bool U)
: Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O),
Unavailable(U) {}
};
class AvailabilitySet {
private:
using AvailabilityList = llvm::SmallVector<AvailabilityInfo, 4>;
AvailabilityList Availabilities;
bool UnconditionallyDeprecated = false;
bool UnconditionallyUnavailable = false;
public:
AvailabilitySet(const Decl *Decl);
AvailabilitySet() = default;
AvailabilityList::const_iterator begin() const {
return Availabilities.begin();
}
AvailabilityList::const_iterator end() const { return Availabilities.end(); }
AvailabilityInfo() = default;
/// Determine if this AvailabilityInfo represents the default availability.
bool isDefault() const { return *this == AvailabilityInfo(); }
/// Check if the symbol is unconditionally deprecated.
///
/// i.e. \code __attribute__((deprecated)) \endcode
bool isUnconditionallyDeprecated() const { return UnconditionallyDeprecated; }
/// Check if the symbol is unconditionally unavailable.
///
/// i.e. \code __attribute__((unavailable)) \endcode
@ -73,10 +48,28 @@ public:
return UnconditionallyUnavailable;
}
/// Determine if this AvailabilitySet represents default availability.
bool isDefault() const { return Availabilities.empty(); }
AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D,
VersionTuple O, bool UD, bool UU)
: Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O),
UnconditionallyDeprecated(UD), UnconditionallyUnavailable(UU) {}
friend bool operator==(const AvailabilityInfo &Lhs,
const AvailabilityInfo &Rhs);
public:
static AvailabilityInfo createFromDecl(const Decl *Decl);
};
inline bool operator==(const AvailabilityInfo &Lhs,
const AvailabilityInfo &Rhs) {
return std::tie(Lhs.Introduced, Lhs.Deprecated, Lhs.Obsoleted,
Lhs.UnconditionallyDeprecated,
Lhs.UnconditionallyUnavailable) ==
std::tie(Rhs.Introduced, Rhs.Deprecated, Rhs.Obsoleted,
Rhs.UnconditionallyDeprecated,
Rhs.UnconditionallyUnavailable);
}
} // namespace extractapi
} // namespace clang

View File

@ -295,8 +295,9 @@ public:
/// Build DeclarationFragments for a field declaration FieldDecl.
static DeclarationFragments getFragmentsForField(const FieldDecl *);
/// Build DeclarationFragments for a struct record declaration RecordDecl.
static DeclarationFragments getFragmentsForStruct(const RecordDecl *);
/// Build DeclarationFragments for a struct/union record declaration
/// RecordDecl.
static DeclarationFragments getFragmentsForRecordDecl(const RecordDecl *);
static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *);

View File

@ -14,10 +14,12 @@
#ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
#define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
#include "clang/ExtractAPI/AvailabilityInfo.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/FunctionExtras.h"
@ -128,9 +130,10 @@ protected:
void recordEnumConstants(EnumRecord *EnumRecord,
const EnumDecl::enumerator_range Constants);
/// Collect API information for the struct fields and associate with the
/// Collect API information for the record fields and associate with the
/// parent struct.
void recordStructFields(StructRecord *StructRecord,
void recordRecordFields(RecordRecord *RecordRecord,
APIRecord::RecordKind FieldKind,
const RecordDecl::field_range Fields);
/// Collect API information for the Objective-C methods and associate with the
@ -263,7 +266,6 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForVar(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
if (Decl->isStaticDataMember()) {
SymbolReference Context;
// getDeclContext() should return a RecordDecl since we
@ -272,13 +274,14 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
Context.Name = Record->getName();
Context.USR = API.recordUSR(Record);
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
API.addStaticField(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
Declaration, SubHeading, Context, Access,
isInSystemHeader(Decl));
API.addStaticField(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
Linkage, Comment, Declaration, SubHeading, Context,
Access, isInSystemHeader(Decl));
} else
// Add the global variable record to the API set.
API.addGlobalVar(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
Declaration, SubHeading, isInSystemHeader(Decl));
API.addGlobalVar(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
Linkage, Comment, Declaration, SubHeading,
isInSystemHeader(Decl));
return true;
}
@ -333,19 +336,19 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
DeclarationFragmentsBuilder::getSubHeading(Decl);
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
if (Decl->getTemplateSpecializationInfo())
API.addGlobalFunctionTemplateSpecialization(
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, isInSystemHeader(Decl));
else
// Add the function record to the API set.
API.addGlobalFunction(
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
Signature, isInSystemHeader(Decl));
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage,
Comment, DeclarationFragmentsBuilder::getFragmentsForFunction(Decl),
SubHeading, Signature, isInSystemHeader(Decl));
return true;
}
@ -379,10 +382,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
EnumRecord *EnumRecord =
API.addEnum(API.copyString(Name), USR, Loc, AvailabilitySet(Decl),
Comment, Declaration, SubHeading, isInSystemHeader(Decl));
EnumRecord *EnumRecord = API.addEnum(
API.copyString(Name), USR, Loc, AvailabilityInfo::createFromDecl(Decl),
Comment, Declaration, SubHeading, isInSystemHeader(Decl));
// Now collect information about the enumerators in this enum.
getDerivedExtractAPIVisitor().recordEnumConstants(EnumRecord,
@ -496,8 +498,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
API.addNamespace(Parent, Name, USR, Loc, AvailabilitySet(Decl), Linkage,
Comment, Declaration, SubHeading, isInSystemHeader(Decl));
API.addNamespace(Parent, Name, USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
Declaration, SubHeading, isInSystemHeader(Decl));
return true;
}
@ -524,17 +527,25 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
// Build declaration fragments and sub-heading for the struct.
DeclarationFragments Declaration =
DeclarationFragmentsBuilder::getFragmentsForStruct(Decl);
DeclarationFragmentsBuilder::getFragmentsForRecordDecl(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
StructRecord *StructRecord =
API.addStruct(Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
auto RecordKind = APIRecord::RK_Struct;
auto FieldRecordKind = APIRecord::RK_StructField;
if (Decl->isUnion()) {
RecordKind = APIRecord::RK_Union;
FieldRecordKind = APIRecord::RK_UnionField;
}
RecordRecord *RecordRecord = API.addRecord(
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, RecordKind, isInSystemHeader(Decl));
// Now collect information about the fields in this struct.
getDerivedExtractAPIVisitor().recordStructFields(StructRecord,
Decl->fields());
getDerivedExtractAPIVisitor().recordRecordFields(
RecordRecord, FieldRecordKind, Decl->fields());
return true;
}
@ -578,13 +589,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
CXXClassRecord = API.addClassTemplate(
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Template(Decl->getDescribedClassTemplate()), Access,
isInSystemHeader(Decl));
Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()),
Access, isInSystemHeader(Decl));
} else
CXXClassRecord = API.addCXXClass(
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Kind, Access, isInSystemHeader(Decl));
Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Kind, Access, isInSystemHeader(Decl));
CXXClassRecord->Bases = getBases(Decl);
@ -624,7 +635,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
API.addCXXMethodTemplate(
API.findRecordForUSR(ParentUSR), Decl->getName(), USR, Loc,
AvailabilitySet(Decl), Comment,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
TemplateDecl),
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
@ -632,24 +643,27 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
Template(TemplateDecl), isInSystemHeader(Decl));
} else if (Decl->getTemplateSpecializationInfo())
API.addCXXMethodTemplateSpec(
Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment,
Parent, Decl->getName(), USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isOverloadedOperator())
API.addCXXInstanceMethod(
Parent, API.copyString(Decl->getNameAsString()), USR, Loc,
AvailabilitySet(Decl), Comment,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl),
SubHeading, Signature, Access, isInSystemHeader(Decl));
else if (Decl->isStatic())
API.addCXXStaticMethod(
Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment,
Parent, Decl->getName(), USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
else
API.addCXXInstanceMethod(
Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment,
Parent, Decl->getName(), USR, Loc,
AvailabilityInfo::createFromDecl(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
Signature, Access, isInSystemHeader(Decl));
@ -678,13 +692,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
SmallString<128> ParentUSR;
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
ParentUSR);
API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Signature, Access,
AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Signature, Access,
isInSystemHeader(Decl));
return true;
}
@ -711,13 +724,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
SmallString<128> ParentUSR;
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
ParentUSR);
API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Signature, Access,
AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Signature, Access,
isInSystemHeader(Decl));
return true;
}
@ -740,8 +752,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
DeclarationFragmentsBuilder::getFragmentsForConcept(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
API.addConcept(Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Template(Decl), isInSystemHeader(Decl));
API.addConcept(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
Comment, Declaration, SubHeading, Template(Decl),
isInSystemHeader(Decl));
return true;
}
@ -768,8 +781,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
auto *ClassTemplateSpecializationRecord = API.addClassTemplateSpecialization(
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl),
Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading,
DeclarationFragmentsBuilder::getAccessControl(Decl),
isInSystemHeader(Decl));
ClassTemplateSpecializationRecord->Bases = getBases(Decl);
@ -797,12 +811,11 @@ bool ExtractAPIVisitorBase<Derived>::
getFragmentsForClassTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
APIRecord *Parent = determineParentRecord(Decl->getDeclContext());
auto *ClassTemplatePartialSpecRecord =
API.addClassTemplatePartialSpecialization(
Parent, Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Template(Decl),
Parent, Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
Comment, Declaration, SubHeading, Template(Decl),
DeclarationFragmentsBuilder::getAccessControl(Decl),
isInSystemHeader(Decl));
@ -845,12 +858,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
ParentUSR);
if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord)
API.addCXXFieldTemplate(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
AvailabilitySet(Decl), Comment, Declaration,
SubHeading,
AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading,
DeclarationFragmentsBuilder::getAccessControl(Decl),
Template(Decl), isInSystemHeader(Decl));
else
API.addGlobalVariableTemplate(Name, USR, Loc, AvailabilitySet(Decl),
API.addGlobalVariableTemplate(Name, USR, Loc,
AvailabilityInfo::createFromDecl(Decl),
Linkage, Comment, Declaration, SubHeading,
Template(Decl), isInSystemHeader(Decl));
return true;
@ -880,10 +894,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
API.addGlobalVariableTemplateSpecialization(
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
Declaration, SubHeading, isInSystemHeader(Decl));
return true;
}
@ -910,10 +923,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
getFragmentsForVarTemplatePartialSpecialization(Decl);
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
API.addGlobalVariableTemplatePartialSpecialization(
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration,
SubHeading, Template(Decl), isInSystemHeader(Decl));
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
Declaration, SubHeading, Template(Decl), isInSystemHeader(Decl));
return true;
}
@ -942,9 +954,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(
Decl->getTemplatedDecl());
API.addGlobalFunctionTemplate(
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
@ -983,8 +994,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
}
ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration,
SubHeading, SuperClass, isInSystemHeader(Decl));
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
Declaration, SubHeading, SuperClass, isInSystemHeader(Decl));
// Record all methods (selectors). This doesn't include automatically
// synthesized property methods.
@ -1023,9 +1034,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
ObjCProtocolRecord *ObjCProtocolRecord =
API.addObjCProtocol(Name, USR, Loc, AvailabilitySet(Decl), Comment,
Declaration, SubHeading, isInSystemHeader(Decl));
ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, isInSystemHeader(Decl));
getDerivedExtractAPIVisitor().recordObjCMethods(ObjCProtocolRecord,
Decl->methods());
@ -1055,8 +1066,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
dyn_cast<ElaboratedType>(Decl->getUnderlyingType())) {
if (const TagType *TagTy = dyn_cast<TagType>(ET->desugar())) {
if (Decl->getName() == TagTy->getDecl()->getName()) {
if (TagTy->getDecl()->isStruct()) {
modifyRecords(API.getStructs(), Decl->getName());
if (isa<RecordDecl>(TagTy->getDecl())) {
modifyRecords(API.getRecords(), Decl->getName());
}
if (TagTy->getDecl()->isEnum()) {
modifyRecords(API.getEnums(), Decl->getName());
@ -1080,7 +1091,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
API);
API.addTypedef(Name, USR, Loc, AvailabilitySet(Decl), Comment,
API.addTypedef(Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl),
Comment,
DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
isInSystemHeader(Decl));
@ -1122,8 +1134,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
}
ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory(
Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
Interface, isInSystemHeader(Decl), IsFromExternalModule);
Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Interface, isInSystemHeader(Decl),
IsFromExternalModule);
getDerivedExtractAPIVisitor().recordObjCMethods(ObjCCategoryRecord,
Decl->methods());
@ -1160,17 +1173,18 @@ void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Constant);
API.addEnumConstant(EnumRecord, Name, USR, Loc, AvailabilitySet(Constant),
Comment, Declaration, SubHeading,
isInSystemHeader(Constant));
API.addEnumConstant(EnumRecord, Name, USR, Loc,
AvailabilityInfo::createFromDecl(Constant), Comment,
Declaration, SubHeading, isInSystemHeader(Constant));
}
}
/// Collect API information for the struct fields and associate with the
/// parent struct.
template <typename Derived>
void ExtractAPIVisitorBase<Derived>::recordStructFields(
StructRecord *StructRecord, const RecordDecl::field_range Fields) {
void ExtractAPIVisitorBase<Derived>::recordRecordFields(
RecordRecord *RecordRecord, APIRecord::RecordKind FieldKind,
const RecordDecl::field_range Fields) {
for (const auto *Field : Fields) {
// Collect symbol information.
StringRef Name = Field->getName();
@ -1189,9 +1203,9 @@ void ExtractAPIVisitorBase<Derived>::recordStructFields(
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Field);
API.addStructField(StructRecord, Name, USR, Loc, AvailabilitySet(Field),
Comment, Declaration, SubHeading,
isInSystemHeader(Field));
API.addRecordField(
RecordRecord, Name, USR, Loc, AvailabilityInfo::createFromDecl(Field),
Comment, Declaration, SubHeading, FieldKind, isInSystemHeader(Field));
}
}
@ -1223,8 +1237,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
ParentUSR);
API.addCXXField(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
AvailabilitySet(Decl), Comment, Declaration, SubHeading,
Access, isInSystemHeader(Decl));
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
return true;
}
@ -1255,13 +1269,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
ParentUSR);
if (Decl->isStatic())
API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Signature, Access,
AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Signature, Access,
isInSystemHeader(Decl));
else
API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
AvailabilitySet(Decl), Comment, Declaration,
SubHeading, Signature, Access,
AvailabilityInfo::createFromDecl(Decl), Comment,
Declaration, SubHeading, Signature, Access,
isInSystemHeader(Decl));
return true;
}
@ -1295,8 +1309,9 @@ void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
FunctionSignature Signature =
DeclarationFragmentsBuilder::getFunctionSignature(Method);
API.addObjCMethod(Container, Name, USR, Loc, AvailabilitySet(Method),
Comment, Declaration, SubHeading, Signature,
API.addObjCMethod(Container, Name, USR, Loc,
AvailabilityInfo::createFromDecl(Method), Comment,
Declaration, SubHeading, Signature,
Method->isInstanceMethod(), isInSystemHeader(Method));
}
}
@ -1334,8 +1349,8 @@ void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
Attributes |= ObjCPropertyRecord::ReadOnly;
API.addObjCProperty(
Container, Name, USR, Loc, AvailabilitySet(Property), Comment,
Declaration, SubHeading,
Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Property),
Comment, Declaration, SubHeading,
static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), GetterName,
SetterName, Property->isOptional(),
!(Property->getPropertyAttributes() &
@ -1370,9 +1385,9 @@ void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
ObjCInstanceVariableRecord::AccessControl Access =
Ivar->getCanonicalAccessControl();
API.addObjCInstanceVariable(Container, Name, USR, Loc,
AvailabilitySet(Ivar), Comment, Declaration,
SubHeading, Access, isInSystemHeader(Ivar));
API.addObjCInstanceVariable(
Container, Name, USR, Loc, AvailabilityInfo::createFromDecl(Ivar),
Comment, Declaration, SubHeading, Access, isInSystemHeader(Ivar));
}
}

View File

@ -65,7 +65,7 @@ public:
getDerived()->traverseGlobalFunctionTemplateSpecializationRecords();
getDerived()->traverseStructRecords();
getDerived()->traverseRecordRecords();
getDerived()->traverseObjCInterfaces();
@ -98,9 +98,9 @@ public:
getDerived()->visitEnumRecord(*Enum.second);
}
void traverseStructRecords() {
for (const auto &Struct : API.getStructs())
getDerived()->visitStructRecord(*Struct.second);
void traverseRecordRecords() {
for (const auto &Record : API.getRecords())
getDerived()->visitRecordRecord(*Record.second);
}
void traverseStaticFieldRecords() {
@ -238,8 +238,8 @@ public:
/// Visit an enum record.
void visitEnumRecord(const EnumRecord &Record){};
/// Visit a struct record.
void visitStructRecord(const StructRecord &Record){};
/// Visit a record record.
void visitRecordRecord(const RecordRecord &Record){};
void visitStaticFieldRecord(const StaticFieldRecord &Record){};

View File

@ -170,8 +170,8 @@ public:
/// Visit an enum record.
void visitEnumRecord(const EnumRecord &Record);
/// Visit a struct record.
void visitStructRecord(const StructRecord &Record);
/// Visit a record record.
void visitRecordRecord(const RecordRecord &Record);
void visitStaticFieldRecord(const StaticFieldRecord &Record);

View File

@ -3055,6 +3055,7 @@ struct FormatStyle {
bool isProto() const {
return Language == LK_Proto || Language == LK_TextProto;
}
bool isTableGen() const { return Language == LK_TableGen; }
/// Language, this format style is targeted at.
/// \version 3.5
@ -3397,6 +3398,10 @@ struct FormatStyle {
/// \version 14
unsigned PenaltyBreakOpenParenthesis;
/// The penalty for breaking after ``::``.
/// \version 18
unsigned PenaltyBreakScopeResolution;
/// The penalty for each line break introduced inside a string literal.
/// \version 3.7
unsigned PenaltyBreakString;
@ -3927,6 +3932,10 @@ struct FormatStyle {
/// \version 13
unsigned ShortNamespaceLines;
/// Do not format macro definition body.
/// \version 18
bool SkipMacroDefinitionBody;
/// Include sorting options.
enum SortIncludesOptions : int8_t {
/// Includes are never sorted.
@ -4872,6 +4881,7 @@ struct FormatStyle {
PenaltyBreakComment == R.PenaltyBreakComment &&
PenaltyBreakFirstLessLess == R.PenaltyBreakFirstLessLess &&
PenaltyBreakOpenParenthesis == R.PenaltyBreakOpenParenthesis &&
PenaltyBreakScopeResolution == R.PenaltyBreakScopeResolution &&
PenaltyBreakString == R.PenaltyBreakString &&
PenaltyBreakTemplateDeclaration ==
R.PenaltyBreakTemplateDeclaration &&
@ -4889,6 +4899,7 @@ struct FormatStyle {
RequiresExpressionIndentation == R.RequiresExpressionIndentation &&
SeparateDefinitionBlocks == R.SeparateDefinitionBlocks &&
ShortNamespaceLines == R.ShortNamespaceLines &&
SkipMacroDefinitionBody == R.SkipMacroDefinitionBody &&
SortIncludes == R.SortIncludes &&
SortJavaStaticImport == R.SortJavaStaticImport &&
SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&

View File

@ -902,7 +902,7 @@ public:
SourceManager &SourceMgr, FileManager &FileMgr,
SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers,
std::unique_ptr<SyntaxOnlyAction> Act = nullptr);
std::unique_ptr<SyntaxOnlyAction> Act);
/// Save this translation unit to a file with the given name.
///

View File

@ -43,12 +43,14 @@ class PCHContainerReader;
class Preprocessor;
class PreprocessorOptions;
class PreprocessorOutputOptions;
class CodeGenOptions;
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file.
void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts,
const PCHContainerReader &PCHContainerRdr,
const FrontendOptions &FEOpts);
const FrontendOptions &FEOpts,
const CodeGenOptions &CodeGenOpts);
/// DoPrintPreprocessedInput - Implement -E mode.
void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,

View File

@ -129,7 +129,7 @@ public:
llvm::Expected<llvm::orc::ExecutorAddr>
getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const;
enum InterfaceKind { NoAlloc, WithAlloc, CopyArray };
enum InterfaceKind { NoAlloc, WithAlloc, CopyArray, NewTag };
const llvm::SmallVectorImpl<Expr *> &getValuePrintingInfo() const {
return ValuePrintingInfo;
@ -144,7 +144,7 @@ private:
llvm::DenseMap<CXXRecordDecl *, llvm::orc::ExecutorAddr> Dtors;
llvm::SmallVector<Expr *, 3> ValuePrintingInfo;
llvm::SmallVector<Expr *, 4> ValuePrintingInfo;
};
} // namespace clang

View File

@ -198,11 +198,11 @@ public:
/// from. Currently this is only used by _Pragma handling.
SourceLocation getFileLoc() const { return FileLoc; }
private:
/// Lex - Return the next token in the file. If this is the end of file, it
/// return the tok::eof token. This implicitly involves the preprocessor.
bool Lex(Token &Result);
private:
/// Called when the preprocessor is in 'dependency scanning lexing mode'.
bool LexDependencyDirectiveToken(Token &Result);

View File

@ -2829,12 +2829,20 @@ public:
}
void emitMacroExpansionWarnings(const Token &Identifier) const {
if (Identifier.getIdentifierInfo()->isDeprecatedMacro())
IdentifierInfo *Info = Identifier.getIdentifierInfo();
if (Info->isDeprecatedMacro())
emitMacroDeprecationWarning(Identifier);
if (Identifier.getIdentifierInfo()->isRestrictExpansion() &&
if (Info->isRestrictExpansion() &&
!SourceMgr.isInMainFile(Identifier.getLocation()))
emitRestrictExpansionWarning(Identifier);
if (Info->getName() == "INFINITY")
if (getLangOpts().NoHonorInfs)
emitRestrictInfNaNWarning(Identifier, 0);
if (Info->getName() == "NAN")
if (getLangOpts().NoHonorNaNs)
emitRestrictInfNaNWarning(Identifier, 1);
}
static void processPathForFileMacro(SmallVectorImpl<char> &Path,
@ -2850,6 +2858,8 @@ private:
void emitMacroDeprecationWarning(const Token &Identifier) const;
void emitRestrictExpansionWarning(const Token &Identifier) const;
void emitFinalMacroWarning(const Token &Identifier, bool IsUndef) const;
void emitRestrictInfNaNWarning(const Token &Identifier,
unsigned DiagSelection) const;
/// This boolean state keeps track if the current scanned token (by this PP)
/// is in an "-Wunsafe-buffer-usage" opt-out region. Assuming PP scans a

View File

@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/Preprocessor.h"
@ -3568,7 +3569,26 @@ private:
void ParseOpenACCCacheVarList();
/// Parses a single variable in a variable list for OpenACC.
bool ParseOpenACCVar();
/// Parses the variable list for the variety of clauses that take a var-list,
/// including the optional Special Token listed for some,based on clause type.
bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind);
/// Parses any parameters for an OpenACC Clause, including required/optional
/// parens.
bool ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
OpenACCClauseKind Kind);
/// Parses a single clause in a clause-list for OpenACC.
bool ParseOpenACCClause(OpenACCDirectiveKind DirKind);
/// Parses the clause-list for an OpenACC directive.
void ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
bool ParseOpenACCWaitArgument();
/// Parses the clause of the 'bind' argument, which can be a string literal or
/// an ID expression.
ExprResult ParseOpenACCBindClauseArgument();
/// Parses the clause kind of 'int-expr', which can be any integral
/// expression.
ExprResult ParseOpenACCIntExpr();
/// Parses the 'device-type-list', which is a list of identifiers.
bool ParseOpenACCDeviceTypeList();
private:
//===--------------------------------------------------------------------===//
@ -3644,6 +3664,18 @@ private:
ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd);
/// Parse the given string as a type.
///
/// This is a dangerous utility function currently employed only by API notes.
/// It is not a general entry-point for safely parsing types from strings.
///
/// \param TypeStr The string to be parsed as a type.
/// \param Context The name of the context in which this string is being
/// parsed, which will be used in diagnostics.
/// \param IncludeLoc The location at which this parse was triggered.
TypeResult ParseTypeFromString(StringRef TypeStr, StringRef Context,
SourceLocation IncludeLoc);
//===--------------------------------------------------------------------===//
// Modules
DeclGroupPtrTy ParseModuleDecl(Sema::ModuleImportState &ImportState);

View File

@ -66,7 +66,7 @@ namespace sema {
/// parsed.
class CompoundScopeInfo {
public:
/// Whether this compound stamement contains `for' or `while' loops
/// Whether this compound statement contains `for' or `while' loops
/// with empty bodies.
bool HasEmptyLoopBodies = false;
@ -168,7 +168,7 @@ public:
/// to build, the initial and final coroutine suspend points
bool NeedsCoroutineSuspends : 1;
/// An enumeration represeting the kind of the first coroutine statement
/// An enumeration representing the kind of the first coroutine statement
/// in the function. One of co_return, co_await, or co_yield.
unsigned char FirstCoroutineStmtKind : 2;
@ -220,7 +220,7 @@ public:
/// The initial and final coroutine suspend points.
std::pair<Stmt *, Stmt *> CoroutineSuspends;
/// The stack of currently active compound stamement scopes in the
/// The stack of currently active compound statement scopes in the
/// function.
SmallVector<CompoundScopeInfo, 4> CompoundScopes;

View File

@ -955,6 +955,10 @@ public:
OpaqueParser = P;
}
/// Callback to the parser to parse a type expressed as a string.
std::function<TypeResult(StringRef, StringRef, SourceLocation)>
ParseTypeFromStringCallback;
class DelayedDiagnostics;
class DelayedDiagnosticsState {
@ -2108,6 +2112,10 @@ public:
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
/// Check an argument list for placeholders that we won't try to
/// handle later.
bool CheckArgsForPlaceholders(MultiExprArg args);
/// Build a function type.
///
/// This routine checks the function type according to C++ rules and
@ -2153,7 +2161,7 @@ public:
SourceLocation Loc);
QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D);
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
/// Package the given type and TSI into a ParsedType.
@ -2194,7 +2202,7 @@ public:
SourceLocation TargetLoc, const FunctionProtoType *Source,
bool SkipSourceFirstParameter, SourceLocation SourceLoc);
TypeResult ActOnTypeName(Scope *S, Declarator &D);
TypeResult ActOnTypeName(Declarator &D);
/// The parser has parsed the context-sensitive type 'instancetype'
/// in an Objective-C message declaration. Return the appropriate type.
@ -3017,6 +3025,9 @@ public:
ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
QualType T);
QualType AdjustParameterTypeForObjCAutoRefCount(QualType T,
SourceLocation NameLoc,
TypeSourceInfo *TSInfo);
ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc,
SourceLocation NameLoc, IdentifierInfo *Name,
QualType T, TypeSourceInfo *TSInfo,
@ -4816,6 +4827,29 @@ public:
/// Valid types should not have multiple attributes with different CCs.
const AttributedType *getCallingConvAttributedType(QualType T) const;
/// Check whether a nullability type specifier can be added to the given
/// type through some means not written in source (e.g. API notes).
///
/// \param Type The type to which the nullability specifier will be
/// added. On success, this type will be updated appropriately.
///
/// \param Nullability The nullability specifier to add.
///
/// \param DiagLoc The location to use for diagnostics.
///
/// \param AllowArrayTypes Whether to accept nullability specifiers on an
/// array type (e.g., because it will decay to a pointer).
///
/// \param OverrideExisting Whether to override an existing, locally-specified
/// nullability specifier rather than complaining about the conflict.
///
/// \returns true if nullability cannot be applied, false otherwise.
bool CheckImplicitNullabilityTypeSpecifier(QualType &Type,
NullabilityKind Nullability,
SourceLocation DiagLoc,
bool AllowArrayTypes,
bool OverrideExisting);
/// Process the attributes before creating an attributed statement. Returns
/// the semantic attributes that have been processed.
void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs,
@ -7110,15 +7144,7 @@ public:
NestedNameSpecInfo &IdInfo,
bool EnteringContext);
/// The kind of conversion to check for. Either all attributes must match exactly,
/// or the converted type may add/drop '__arm_preserves_za'.
enum class AArch64SMECallConversionKind {
MatchExactly,
MayAddPreservesZA,
MayDropPreservesZA,
};
bool IsInvalidSMECallConversion(QualType FromType, QualType ToType,
AArch64SMECallConversionKind C);
bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
/// The parser has parsed a nested-name-specifier
/// 'template[opt] template-name < template-args >::'.
@ -8569,8 +8595,8 @@ public:
QualType ParamType,
SourceLocation Loc);
ExprResult
BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc);
BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc);
/// Enumeration describing how template parameter lists are compared
/// for equality.
@ -11223,6 +11249,11 @@ public:
VarDecl *buildCoroutinePromise(SourceLocation Loc);
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
// Heuristically tells if the function is `get_return_object` member of a
// coroutine promise_type by matching the function name.
static bool CanBeGetReturnObject(const FunctionDecl *FD);
static bool CanBeGetReturnTypeOnAllocFailure(const FunctionDecl *FD);
// As a clang extension, enforces that a non-coroutine function must be marked
// with [[clang::coro_wrapper]] if it returns a type marked with
// [[clang::coro_return_type]].
@ -13901,8 +13932,9 @@ private:
bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
unsigned BuiltinID);
bool SemaBuiltinComplex(CallExpr *TheCall);
bool SemaBuiltinVSX(CallExpr *TheCall);
bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
@ -14006,6 +14038,8 @@ private:
SourceRange range,
llvm::SmallBitVector &CheckedVarArgs);
void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
void CheckAbsoluteValueFunction(const CallExpr *Call,
const FunctionDecl *FDecl);

View File

@ -550,6 +550,10 @@ private:
/// declaration and the value is the deduced return type.
llvm::SmallMapVector<FunctionDecl *, QualType, 4> PendingDeducedTypeUpdates;
/// Functions has undededuced return type and we wish we can find the deduced
/// return type by iterating the redecls in other modules.
llvm::SmallVector<FunctionDecl *, 4> PendingUndeducedFunctionDecls;
/// Declarations that have been imported and have typedef names for
/// linkage purposes.
llvm::DenseMap<std::pair<DeclContext *, IdentifierInfo *>, NamedDecl *>

View File

@ -488,7 +488,7 @@ public:
enum RVVRequire : uint32_t {
RVV_REQ_None = 0,
RVV_REQ_RV64 = 1 << 0,
RVV_REQ_ZvfhminOrZvfh = 1 << 1,
RVV_REQ_Zvfhmin = 1 << 1,
RVV_REQ_Xsfvcp = 1 << 2,
RVV_REQ_Xsfvfnrclipxfqf = 1 << 3,
RVV_REQ_Xsfvfwmaccqqq = 1 << 4,

View File

@ -43,7 +43,7 @@ std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
assert(!outputDir.empty());
SmallString<128> InfoFile = outputDir;
llvm::sys::path::append(InfoFile, "remap");
return std::string(InfoFile.str());
return std::string(InfoFile);
}
bool FileRemapper::initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,

View File

@ -2201,7 +2201,7 @@ static std::string applyEditsToTemp(FileEntryRef FE,
TmpOut.write(NewText.data(), NewText.size());
TmpOut.close();
return std::string(TempPath.str());
return std::string(TempPath);
}
bool arcmt::getFileRemappingsFromFileList(

View File

@ -4484,10 +4484,11 @@ QualType ASTContext::getFunctionTypeInternal(
EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size());
size_t Size = FunctionProtoType::totalSizeToAlloc<
QualType, SourceLocation, FunctionType::FunctionTypeExtraBitfields,
FunctionType::ExceptionType, Expr *, FunctionDecl *,
FunctionProtoType::ExtParameterInfo, Qualifiers>(
FunctionType::FunctionTypeArmAttributes, FunctionType::ExceptionType,
Expr *, FunctionDecl *, FunctionProtoType::ExtParameterInfo, Qualifiers>(
NumArgs, EPI.Variadic, EPI.requiresFunctionProtoTypeExtraBitfields(),
ESH.NumExceptionType, ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
EPI.requiresFunctionProtoTypeArmAttributes(), ESH.NumExceptionType,
ESH.NumExprPtr, ESH.NumFunctionDeclPtr,
EPI.ExtParameterInfos ? NumArgs : 0,
EPI.TypeQuals.hasNonFastQualifiers() ? 1 : 0);
@ -6753,6 +6754,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
case TemplateArgument::Integral:
return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
case TemplateArgument::StructuralValue:
return TemplateArgument(*this,
getCanonicalType(Arg.getStructuralValueType()),
Arg.getAsStructuralValue());
case TemplateArgument::Type:
return TemplateArgument(getCanonicalType(Arg.getAsType()),
/*isNullPtr*/ false, Arg.getIsDefaulted());

View File

@ -823,6 +823,17 @@ ASTNodeImporter::import(const TemplateArgument &From) {
From.getIsDefaulted());
}
case TemplateArgument::StructuralValue: {
ExpectedType ToTypeOrErr = import(From.getStructuralValueType());
if (!ToTypeOrErr)
return ToTypeOrErr.takeError();
Expected<APValue> ToValueOrErr = import(From.getAsStructuralValue());
if (!ToValueOrErr)
return ToValueOrErr.takeError();
return TemplateArgument(Importer.getToContext(), *ToTypeOrErr,
*ToValueOrErr);
}
case TemplateArgument::Template: {
Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
if (!ToTemplateOrErr)
@ -3572,6 +3583,8 @@ private:
case TemplateArgument::NullPtr:
// FIXME: The type is not allowed to be in the function?
return CheckType(Arg.getNullPtrType());
case TemplateArgument::StructuralValue:
return CheckType(Arg.getStructuralValueType());
case TemplateArgument::Pack:
for (const auto &PackArg : Arg.getPackAsArray())
if (checkTemplateArgument(PackArg))
@ -3896,7 +3909,7 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
ToFunction->setLexicalDeclContext(LexicalDC);
ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
ToFunction->setTrivial(D->isTrivial());
ToFunction->setPure(D->isPure());
ToFunction->setIsPureVirtual(D->isPureVirtual());
ToFunction->setDefaulted(D->isDefaulted());
ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted());
ToFunction->setDeletedAsWritten(D->isDeletedAsWritten());
@ -6280,17 +6293,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
D->getTemplatedDecl()))
continue;
if (IsStructuralMatch(D, FoundTemplate)) {
// The Decl in the "From" context has a definition, but in the
// "To" context we already have a definition.
// FIXME Check for ODR error if the two definitions have
// different initializers?
VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate);
if (D->isThisDeclarationADefinition() && FoundDef)
// FIXME Check for ODR error if the two definitions have
// different initializers?
return Importer.MapImported(D, FoundDef);
if (FoundTemplate->getDeclContext()->isRecord() &&
D->getDeclContext()->isRecord())
return Importer.MapImported(D, FoundTemplate);
if (D->getDeclContext()->isRecord()) {
assert(FoundTemplate->getDeclContext()->isRecord() &&
"Member variable template imported as non-member, "
"inconsistent imported AST?");
if (FoundDef)
return Importer.MapImported(D, FoundDef);
if (!D->isThisDeclarationADefinition())
return Importer.MapImported(D, FoundTemplate);
} else {
if (FoundDef && D->isThisDeclarationADefinition())
return Importer.MapImported(D, FoundDef);
}
FoundByLookup = FoundTemplate;
break;
}

View File

@ -98,6 +98,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
QualType T1, QualType T2);
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Decl *D1, Decl *D2);
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const Stmt *S1, const Stmt *S2);
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const TemplateArgument &Arg1,
const TemplateArgument &Arg2);
@ -437,12 +439,67 @@ public:
};
} // namespace
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const UnaryOperator *E1,
const CXXOperatorCallExpr *E2) {
return UnaryOperator::getOverloadedOperator(E1->getOpcode()) ==
E2->getOperator() &&
IsStructurallyEquivalent(Context, E1->getSubExpr(), E2->getArg(0));
}
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const CXXOperatorCallExpr *E1,
const UnaryOperator *E2) {
return E1->getOperator() ==
UnaryOperator::getOverloadedOperator(E2->getOpcode()) &&
IsStructurallyEquivalent(Context, E1->getArg(0), E2->getSubExpr());
}
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const BinaryOperator *E1,
const CXXOperatorCallExpr *E2) {
return BinaryOperator::getOverloadedOperator(E1->getOpcode()) ==
E2->getOperator() &&
IsStructurallyEquivalent(Context, E1->getLHS(), E2->getArg(0)) &&
IsStructurallyEquivalent(Context, E1->getRHS(), E2->getArg(1));
}
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const CXXOperatorCallExpr *E1,
const BinaryOperator *E2) {
return E1->getOperator() ==
BinaryOperator::getOverloadedOperator(E2->getOpcode()) &&
IsStructurallyEquivalent(Context, E1->getArg(0), E2->getLHS()) &&
IsStructurallyEquivalent(Context, E1->getArg(1), E2->getRHS());
}
/// Determine structural equivalence of two statements.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const Stmt *S1, const Stmt *S2) {
if (!S1 || !S2)
return S1 == S2;
// Check for statements with similar syntax but different AST.
// A UnaryOperator node is more lightweight than a CXXOperatorCallExpr node.
// The more heavyweight node is only created if the definition-time name
// lookup had any results. The lookup results are stored CXXOperatorCallExpr
// only. The lookup results can be different in a "From" and "To" AST even if
// the compared structure is otherwise equivalent. For this reason we must
// treat a similar unary/binary operator node and CXXOperatorCall node as
// equivalent.
if (const auto *E2CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S2)) {
if (const auto *E1Unary = dyn_cast<UnaryOperator>(S1))
return IsStructurallyEquivalent(Context, E1Unary, E2CXXOperatorCall);
if (const auto *E1Binary = dyn_cast<BinaryOperator>(S1))
return IsStructurallyEquivalent(Context, E1Binary, E2CXXOperatorCall);
}
if (const auto *E1CXXOperatorCall = dyn_cast<CXXOperatorCallExpr>(S1)) {
if (const auto *E2Unary = dyn_cast<UnaryOperator>(S2))
return IsStructurallyEquivalent(Context, E1CXXOperatorCall, E2Unary);
if (const auto *E2Binary = dyn_cast<BinaryOperator>(S2))
return IsStructurallyEquivalent(Context, E1CXXOperatorCall, E2Binary);
}
// Compare the statements itself.
StmtComparer Comparer(Context);
if (!Comparer.IsEquivalent(S1, S2))
@ -628,6 +685,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
Arg2.getAsExpr());
case TemplateArgument::StructuralValue:
return Arg1.structurallyEquals(Arg2);
case TemplateArgument::Pack:
return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
Arg2.pack_elements());
@ -1410,7 +1470,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Method1->isConst() == Method2->isConst() &&
Method1->isVolatile() == Method2->isVolatile() &&
Method1->isVirtual() == Method2->isVirtual() &&
Method1->isPure() == Method2->isPure() &&
Method1->isPureVirtual() == Method2->isPureVirtual() &&
Method1->isDefaulted() == Method2->isDefaulted() &&
Method1->isDeleted() == Method2->isDeleted();
if (!PropertiesEqual)

View File

@ -343,6 +343,10 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
continue;
case TemplateArgument::StructuralValue:
LV.merge(getLVForValue(Arg.getAsStructuralValue(), computation));
continue;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (TemplateDecl *Template =
@ -3036,7 +3040,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.IsInline = isInlineSpecified;
FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
FunctionDeclBits.IsVirtualAsWritten = false;
FunctionDeclBits.IsPure = false;
FunctionDeclBits.IsPureVirtual = false;
FunctionDeclBits.HasInheritedPrototype = false;
FunctionDeclBits.HasWrittenPrototype = true;
FunctionDeclBits.IsDeleted = false;
@ -3203,8 +3207,8 @@ void FunctionDecl::setBody(Stmt *B) {
EndRangeLoc = B->getEndLoc();
}
void FunctionDecl::setPure(bool P) {
FunctionDeclBits.IsPure = P;
void FunctionDecl::setIsPureVirtual(bool P) {
FunctionDeclBits.IsPureVirtual = P;
if (P)
if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
Parent->markedVirtualFunctionPure();
@ -5369,16 +5373,23 @@ void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); }
void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); }
EnumConstantDecl::EnumConstantDecl(const ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *E, const llvm::APSInt &V)
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt *)E) {
setInitVal(C, V);
}
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
SourceLocation L,
IdentifierInfo *Id, QualType T,
Expr *E, const llvm::APSInt &V) {
return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V);
return new (C, CD) EnumConstantDecl(C, CD, L, Id, T, E, V);
}
EnumConstantDecl *
EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr,
return new (C, ID) EnumConstantDecl(C, nullptr, SourceLocation(), nullptr,
QualType(), nullptr, llvm::APSInt());
}

View File

@ -1383,6 +1383,31 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
}
bool CXXRecordDecl::isLiteral() const {
const LangOptions &LangOpts = getLangOpts();
if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
: hasTrivialDestructor()))
return false;
if (hasNonLiteralTypeFieldsOrBases()) {
// CWG2598
// is an aggregate union type that has either no variant
// members or at least one variant member of non-volatile literal type,
if (!isUnion())
return false;
bool HasAtLeastOneLiteralMember =
fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
return !D->getType().isVolatileQualified() &&
D->getType()->isLiteralType(getASTContext());
});
if (!HasAtLeastOneLiteralMember)
return false;
}
return isAggregate() || (isLambda() && LangOpts.CPlusPlus17) ||
hasConstexprNonCopyMoveConstructor() || hasTrivialDefaultConstructor();
}
void CXXRecordDecl::addedSelectedDestructor(CXXDestructorDecl *DD) {
DD->setIneligibleOrNotSelected(false);
addedEligibleSpecialMemberFunction(DD, SMF_Destructor);
@ -2054,7 +2079,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
// A class is abstract if it contains or inherits at least one
// pure virtual function for which the final overrider is pure
// virtual.
if (SO->second.front().Method->isPure()) {
if (SO->second.front().Method->isPureVirtual()) {
data().Abstract = true;
Done = true;
break;
@ -2273,7 +2298,7 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
// If the member function is marked 'final', we know that it can't be
// overridden and can therefore devirtualize it unless it's pure virtual.
if (hasAttr<FinalAttr>())
return isPure() ? nullptr : this;
return isPureVirtual() ? nullptr : this;
// If Base is unknown, we cannot devirtualize.
if (!Base)
@ -2302,7 +2327,7 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
// If that method is pure virtual, we can't devirtualize. If this code is
// reached, the result would be UB, not a direct call to the derived class
// function, and we can't assume the derived class function is defined.
if (DevirtualizedMethod->isPure())
if (DevirtualizedMethod->isPureVirtual())
return nullptr;
// If that method is marked final, we can devirtualize it.

View File

@ -871,7 +871,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
prettyPrintAttributes(D, Out, AttrPrintLoc::Right);
if (D->isPure())
if (D->isPureVirtual())
Out << " = 0";
else if (D->isDeletedAsWritten())
Out << " = delete";

View File

@ -690,7 +690,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
if (!Buffer.empty() && Buffer.front() == '\01')
return std::string(Buffer.substr(1));
return std::string(Buffer.str());
return std::string(Buffer);
}
return std::string(ND->getIdentifier()->getName());
}
@ -986,7 +986,7 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
SmallString<64> S;
FixedPointValueToString(
S, llvm::APSInt::getUnsigned(getValue().getZExtValue()), Scale);
return std::string(S.str());
return std::string(S);
}
void CharacterLiteral::print(unsigned Val, CharacterLiteralKind Kind,
@ -2219,7 +2219,10 @@ SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Kind,
: Expr(SourceLocExprClass, ResultTy, VK_PRValue, OK_Ordinary),
BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) {
SourceLocExprBits.Kind = llvm::to_underlying(Kind);
setDependence(ExprDependence::None);
// In dependent contexts, function names may change.
setDependence(MayBeDependent(Kind) && ParentContext->isDependentContext()
? ExprDependence::Value
: ExprDependence::None);
}
StringRef SourceLocExpr::getBuiltinStr() const {

View File

@ -194,14 +194,14 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
DirectInitRange(DirectInitRange) {
assert((Initializer != nullptr ||
InitializationStyle == CXXNewInitializationStyle::None ||
InitializationStyle == CXXNewInitializationStyle::Implicit) &&
"Only NoInit can have no initializer!");
InitializationStyle == CXXNewInitializationStyle::None) &&
"Only CXXNewInitializationStyle::None can have no initializer!");
CXXNewExprBits.IsGlobalNew = IsGlobalNew;
CXXNewExprBits.IsArray = ArraySize.has_value();
CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment;
CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize;
CXXNewExprBits.HasInitializer = Initializer != nullptr;
CXXNewExprBits.StoredInitializationStyle =
llvm::to_underlying(InitializationStyle);
bool IsParenTypeId = TypeIdParens.isValid();
@ -219,10 +219,10 @@ CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew,
getTrailingObjects<SourceRange>()[0] = TypeIdParens;
switch (getInitializationStyle()) {
case CXXNewInitializationStyle::Call:
case CXXNewInitializationStyle::Parens:
this->Range.setEnd(DirectInitRange.getEnd());
break;
case CXXNewInitializationStyle::List:
case CXXNewInitializationStyle::Braces:
this->Range.setEnd(getInitializer()->getSourceRange().getEnd());
break;
default:

View File

@ -5839,7 +5839,7 @@ static const CXXMethodDecl *HandleVirtualDispatch(
// C++2a [class.abstract]p6:
// the effect of making a virtual call to a pure virtual function [...] is
// undefined
if (Callee->isPure()) {
if (Callee->isPureVirtual()) {
Info.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << Callee;
Info.Note(Callee->getLocation(), diag::note_declared_at);
return nullptr;
@ -15439,11 +15439,13 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
if (Info.EnableNewConstInterp) {
if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result))
return false;
} else {
if (!::Evaluate(Result, Info, E))
return false;
return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result,
ConstantExprKind::Normal);
}
if (!::Evaluate(Result, Info, E))
return false;
// Implicit lvalue-to-rvalue cast.
if (E->isGLValue()) {
LValue LV;
@ -15671,6 +15673,13 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
EvalInfo Info(Ctx, Result, EM);
Info.InConstantContext = true;
if (Info.EnableNewConstInterp) {
if (!Info.Ctx.getInterpContext().evaluate(Info, this, Result.Val))
return false;
return CheckConstantExpression(Info, getExprLoc(),
getStorageType(Ctx, this), Result.Val, Kind);
}
// The type of the object we're initializing is 'const T' for a class NTTP.
QualType T = getType();
if (Kind == ConstantExprKind::ClassTemplateArgument)
@ -15746,18 +15755,36 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
Info.setEvaluatingDecl(VD, Value);
Info.InConstantContext = IsConstantInitialization;
SourceLocation DeclLoc = VD->getLocation();
QualType DeclTy = VD->getType();
if (Info.EnableNewConstInterp) {
auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext();
if (!InterpCtx.evaluateAsInitializer(Info, VD, Value))
return false;
return CheckConstantExpression(Info, DeclLoc, DeclTy, Value,
ConstantExprKind::Normal);
} else {
LValue LVal;
LVal.set(VD);
if (!EvaluateInPlace(Value, Info, LVal, this,
/*AllowNonLiteralTypes=*/true) ||
EStatus.HasSideEffects)
return false;
{
// C++23 [intro.execution]/p5
// A full-expression is ... an init-declarator ([dcl.decl]) or a
// mem-initializer.
// So we need to make sure temporary objects are destroyed after having
// evaluated the expression (per C++23 [class.temporary]/p4).
//
// FIXME: Otherwise this may break test/Modules/pr68702.cpp because the
// serialization code calls ParmVarDecl::getDefaultArg() which strips the
// outermost FullExpr, such as ExprWithCleanups.
FullExpressionRAII Scope(Info);
if (!EvaluateInPlace(Value, Info, LVal, this,
/*AllowNonLiteralTypes=*/true) ||
EStatus.HasSideEffects)
return false;
}
// At this point, any lifetime-extended temporaries are completely
// initialized.
@ -15767,8 +15794,6 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
llvm_unreachable("Unhandled cleanup; missing full expression marker?");
}
SourceLocation DeclLoc = VD->getLocation();
QualType DeclTy = VD->getType();
return CheckConstantExpression(Info, DeclLoc, DeclTy, Value,
ConstantExprKind::Normal) &&
CheckMemoryLeaks(Info);

View File

@ -20,8 +20,7 @@
using namespace clang;
using namespace clang::interp;
Expected<Function *>
ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
// Set up argument indices.
unsigned ParamOffset = 0;
SmallVector<PrimType, 8> ParamTypes;
@ -120,10 +119,6 @@ ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
// Compile the function body.
if (!IsEligibleForCompilation || !visitFunc(FuncDecl)) {
// Return a dummy function if compilation failed.
if (BailLocation)
return llvm::make_error<ByteCodeGenError>(*BailLocation);
Func->setIsFullyCompiled(true);
return Func;
}
@ -183,12 +178,6 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) {
return 0ull;
}
bool ByteCodeEmitter::bail(const SourceLocation &Loc) {
if (!BailLocation)
BailLocation = Loc;
return false;
}
/// Helper to write bytecode and bail out if 32-bit offsets become invalid.
/// Pointers will be automatically marshalled as 32-bit IDs.
template <typename T>

View File

@ -17,7 +17,6 @@
#include "PrimType.h"
#include "Program.h"
#include "Source.h"
#include "llvm/Support/Error.h"
namespace clang {
namespace interp {
@ -32,7 +31,7 @@ protected:
public:
/// Compiles the function into the module.
llvm::Expected<Function *> compileFunc(const FunctionDecl *FuncDecl);
Function *compileFunc(const FunctionDecl *FuncDecl);
protected:
ByteCodeEmitter(Context &Ctx, Program &P) : Ctx(Ctx), P(P) {}
@ -49,11 +48,6 @@ protected:
virtual bool visitExpr(const Expr *E) = 0;
virtual bool visitDecl(const VarDecl *E) = 0;
/// Bails out if a given node cannot be compiled.
bool bail(const Stmt *S) { return bail(S->getBeginLoc()); }
bool bail(const Decl *D) { return bail(D->getBeginLoc()); }
bool bail(const SourceLocation &Loc);
/// Emits jumps.
bool jumpTrue(const LabelTy &Label);
bool jumpFalse(const LabelTy &Label);
@ -81,8 +75,6 @@ private:
LabelTy NextLabel = 0;
/// Offset of the next local variable.
unsigned NextLocalOffset = 0;
/// Location of a failure.
std::optional<SourceLocation> BailLocation;
/// Label information for linker.
llvm::DenseMap<LabelTy, unsigned> LabelOffsets;
/// Location of label relocations.

View File

@ -287,6 +287,33 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return true;
}
case CK_IntegralComplexToReal:
case CK_FloatingComplexToReal:
return this->emitComplexReal(SubExpr);
case CK_IntegralRealToComplex:
case CK_FloatingRealToComplex: {
// We're creating a complex value here, so we need to
// allocate storage for it.
if (!Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(CE, /*IsExtended=*/true);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, CE))
return false;
}
// Init the complex value to {SubExpr, 0}.
if (!this->visitArrayElemInit(0, SubExpr))
return false;
// Zero-init the second element.
PrimType T = classifyPrim(SubExpr->getType());
if (!this->visitZeroInitializer(T, SubExpr->getType(), SubExpr))
return false;
return this->emitInitElem(T, 1, SubExpr);
}
case CK_ToVoid:
return discard(SubExpr);
@ -371,7 +398,7 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
}
if (!LT || !RT || !T)
return this->bail(BO);
return false;
// Pointer arithmetic special case.
if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
@ -451,7 +478,7 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
case BO_LAnd:
llvm_unreachable("Already handled earlier");
default:
return this->bail(BO);
return false;
}
llvm_unreachable("Unhandled binary op");
@ -504,7 +531,7 @@ bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
else if (Op == BO_Sub)
return this->emitSubOffset(OffsetType, E);
return this->bail(E);
return false;
}
template <class Emitter>
@ -842,6 +869,10 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
if (T->isAnyComplexType()) {
unsigned NumInits = E->getNumInits();
if (NumInits == 1)
return this->delegate(E->inits()[0]);
QualType ElemQT = E->getType()->getAs<ComplexType>()->getElementType();
PrimType ElemT = classifyPrim(ElemQT);
if (NumInits == 0) {
@ -2030,7 +2061,7 @@ bool ByteCodeExprGen<Emitter>::dereference(
}
if (LV->getType()->isAnyComplexType())
return visit(LV);
return this->delegate(LV);
return false;
}
@ -2337,7 +2368,7 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
auto GlobalIndex = P.getGlobal(VD);
assert(GlobalIndex); // visitVarDecl() didn't return false.
if (VarT) {
if (!this->emitGetGlobal(*VarT, *GlobalIndex, VD))
if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))
return false;
} else {
if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
@ -2358,7 +2389,9 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
// Return the value
if (VarT)
return this->emitRet(*VarT, VD);
return this->emitRetValue(VD);
// Return non-primitive values as pointers here.
return this->emitRet(PT_Ptr, VD);
}
template <class Emitter>
@ -2378,7 +2411,7 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
if (!GlobalIndex)
return this->bail(VD);
return false;
assert(Init);
{
@ -2767,23 +2800,16 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
if (!this->visit(SubExpr))
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
case UO_Real: { // __real x
assert(!T);
if (!this->visit(SubExpr))
return false;
if (!this->emitConstUint8(0, E))
return false;
if (!this->emitArrayElemPtrPopUint8(E))
return false;
// Since our _Complex implementation does not map to a primitive type,
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
if (!SubExpr->isLValue())
return this->emitLoadPop(classifyPrim(E->getType()), E);
return true;
}
case UO_Real: // __real x
if (T)
return this->delegate(SubExpr);
return this->emitComplexReal(SubExpr);
case UO_Imag: { // __imag x
assert(!T);
if (T) {
if (!this->discard(SubExpr))
return false;
return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
}
if (!this->visit(SubExpr))
return false;
if (!this->emitConstUint8(1, E))
@ -2948,10 +2974,32 @@ bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
return false;
}
/// Emits __real(SubExpr)
template <class Emitter>
bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
assert(SubExpr->getType()->isAnyComplexType());
if (DiscardResult)
return this->discard(SubExpr);
if (!this->visit(SubExpr))
return false;
if (!this->emitConstUint8(0, SubExpr))
return false;
if (!this->emitArrayElemPtrPopUint8(SubExpr))
return false;
// Since our _Complex implementation does not map to a primitive type,
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
if (!SubExpr->isLValue())
return this->emitLoadPop(*classifyComplexElementType(SubExpr->getType()),
SubExpr);
return true;
}
/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
/// FIXME: Handle virtual destructors.
template <class Emitter>
bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) {
assert(Desc);

View File

@ -191,10 +191,6 @@ protected:
if (!visitInitializer(Init))
return false;
if ((Init->getType()->isArrayType() || Init->getType()->isRecordType()) &&
!this->emitCheckGlobalCtor(Init))
return false;
return this->emitPopPtr(Init);
}
@ -294,6 +290,8 @@ private:
return this->classify(ElemType);
}
bool emitComplexReal(const Expr *SubExpr);
bool emitRecordDestruction(const Descriptor *Desc);
unsigned collectBaseOffset(const RecordType *BaseType,
const RecordType *DerivedType);

View File

@ -142,6 +142,27 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
// Classify the return type.
ReturnType = this->classify(F->getReturnType());
auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
const Expr *InitExpr) -> bool {
if (std::optional<PrimType> T = this->classify(InitExpr)) {
if (!this->visit(InitExpr))
return false;
if (F->isBitField())
return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
return this->emitInitThisField(*T, FieldOffset, InitExpr);
}
// Non-primitive case. Get a pointer to the field-to-initialize
// on the stack and call visitInitialzer() for it.
if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
return false;
if (!this->visitInitializer(InitExpr))
return false;
return this->emitPopPtr(InitExpr);
};
// Emit custom code if this is a lambda static invoker.
if (const auto *MD = dyn_cast<CXXMethodDecl>(F);
MD && MD->isLambdaStaticInvoker())
@ -162,29 +183,8 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
if (const FieldDecl *Member = Init->getMember()) {
const Record::Field *F = R->getField(Member);
if (std::optional<PrimType> T = this->classify(InitExpr)) {
if (!this->visit(InitExpr))
return false;
if (F->isBitField()) {
if (!this->emitInitThisBitField(*T, F, InitExpr))
return false;
} else {
if (!this->emitInitThisField(*T, F->Offset, InitExpr))
return false;
}
} else {
// Non-primitive case. Get a pointer to the field-to-initialize
// on the stack and call visitInitialzer() for it.
if (!this->emitGetPtrThisField(F->Offset, InitExpr))
return false;
if (!this->visitInitializer(InitExpr))
return false;
if (!this->emitPopPtr(InitExpr))
return false;
}
if (!emitFieldInitializer(F, F->Offset, InitExpr))
return false;
} else if (const Type *Base = Init->getBaseClass()) {
// Base class initializer.
// Get This Base and call initializer on it.
@ -198,6 +198,26 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
return false;
if (!this->emitInitPtrPop(InitExpr))
return false;
} else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
assert(IFD->getChainingSize() >= 2);
unsigned NestedFieldOffset = 0;
const Record::Field *NestedField = nullptr;
for (const NamedDecl *ND : IFD->chain()) {
const auto *FD = cast<FieldDecl>(ND);
const Record *FieldRecord =
this->P.getOrCreateRecord(FD->getParent());
assert(FieldRecord);
NestedField = FieldRecord->getField(FD);
assert(NestedField);
NestedFieldOffset += NestedField->Offset;
}
assert(NestedField);
if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
return false;
} else {
assert(Init->isDelegatingInitializer());
if (!this->emitThis(InitExpr))
@ -262,7 +282,7 @@ bool ByteCodeStmtGen<Emitter>::visitStmt(const Stmt *S) {
default: {
if (auto *Exp = dyn_cast<Expr>(S))
return this->discard(Exp);
return this->bail(S);
return false;
}
}
}

View File

@ -30,18 +30,8 @@ Context::~Context() {}
bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
assert(Stk.empty());
Function *Func = P->getFunction(FD);
if (!Func || !Func->hasBody()) {
if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD)) {
Func = *R;
} else {
handleAllErrors(R.takeError(), [&Parent](ByteCodeGenError &Err) {
Parent.FFDiag(Err.getRange().getBegin(),
diag::err_experimental_clang_interp_failed)
<< Err.getRange();
});
return false;
}
}
if (!Func || !Func->hasBody())
Func = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD);
APValue DummyResult;
if (!Run(Parent, Func, DummyResult)) {
@ -54,36 +44,90 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
assert(Stk.empty());
ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
if (Check(Parent, C.interpretExpr(E))) {
assert(Stk.empty());
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
auto Res = C.interpretExpr(E);
if (Res.isInvalid()) {
Stk.clear();
#endif
return true;
return false;
}
assert(Stk.empty());
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
Stk.clear();
return false;
#endif
// Implicit lvalue-to-rvalue conversion.
if (E->isGLValue()) {
std::optional<APValue> RValueResult = Res.toRValue();
if (!RValueResult) {
return false;
}
Result = *RValueResult;
} else {
Result = Res.toAPValue();
}
return true;
}
bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
assert(Stk.empty());
ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
auto Res = C.interpretExpr(E);
if (Res.isInvalid()) {
Stk.clear();
return false;
}
assert(Stk.empty());
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
Stk.clear();
#endif
Result = Res.toAPValue();
return true;
}
bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
APValue &Result) {
assert(Stk.empty());
ByteCodeExprGen<EvalEmitter> C(*this, *P, Parent, Stk, Result);
if (Check(Parent, C.interpretDecl(VD))) {
assert(Stk.empty());
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
auto Res = C.interpretDecl(VD);
if (Res.isInvalid()) {
Stk.clear();
#endif
return true;
return false;
}
assert(Stk.empty());
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
Stk.clear();
return false;
#endif
// Ensure global variables are fully initialized.
if (shouldBeGloballyIndexed(VD) && !Res.isInvalid() &&
(VD->getType()->isRecordType() || VD->getType()->isArrayType())) {
assert(Res.isLValue());
if (!Res.checkFullyInitialized(C.getState()))
return false;
// lvalue-to-rvalue conversion.
std::optional<APValue> RValueResult = Res.toRValue();
if (!RValueResult)
return false;
Result = *RValueResult;
} else
Result = Res.toAPValue();
return true;
}
const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
@ -234,12 +278,8 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
return Func;
if (!Func || WasNotDefined) {
if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = *R;
else {
llvm::consumeError(R.takeError());
return nullptr;
}
if (auto F = ByteCodeStmtGen<ByteCodeEmitter>(*this, *P).compileFunc(FD))
Func = F;
}
return Func;

View File

@ -51,6 +51,9 @@ public:
/// Evaluates a toplevel expression as an rvalue.
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
/// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
bool evaluate(State &Parent, const Expr *E, APValue &Result);
/// Evaluates a toplevel initializer.
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);

View File

@ -19,7 +19,7 @@ using namespace clang::interp;
EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
InterpStack &Stk, APValue &Result)
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), Result(Result) {
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx) {
// Create a dummy frame for the interpreter which does not have locals.
S.Current =
new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr, CodePtr());
@ -33,20 +33,22 @@ EvalEmitter::~EvalEmitter() {
}
}
llvm::Expected<bool> EvalEmitter::interpretExpr(const Expr *E) {
if (this->visitExpr(E))
return true;
if (BailLocation)
return llvm::make_error<ByteCodeGenError>(*BailLocation);
return false;
EvaluationResult EvalEmitter::interpretExpr(const Expr *E) {
EvalResult.setSource(E);
if (!this->visitExpr(E))
EvalResult.setInvalid();
return std::move(this->EvalResult);
}
llvm::Expected<bool> EvalEmitter::interpretDecl(const VarDecl *VD) {
if (this->visitDecl(VD))
return true;
if (BailLocation)
return llvm::make_error<ByteCodeGenError>(*BailLocation);
return false;
EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD) {
EvalResult.setSource(VD);
if (!this->visitDecl(VD))
EvalResult.setInvalid();
return std::move(this->EvalResult);
}
void EvalEmitter::emitLabel(LabelTy Label) {
@ -77,12 +79,6 @@ Scope::Local EvalEmitter::createLocal(Descriptor *D) {
return {Off, D};
}
bool EvalEmitter::bail(const SourceLocation &Loc) {
if (!BailLocation)
BailLocation = Loc;
return false;
}
bool EvalEmitter::jumpTrue(const LabelTy &Label) {
if (isActive()) {
if (S.Stk.pop<bool>())
@ -116,125 +112,37 @@ template <PrimType OpType> bool EvalEmitter::emitRet(const SourceInfo &Info) {
if (!isActive())
return true;
using T = typename PrimConv<OpType>::T;
return ReturnValue<T>(S.Stk.pop<T>(), Result);
EvalResult.setValue(S.Stk.pop<T>().toAPValue());
return true;
}
bool EvalEmitter::emitRetVoid(const SourceInfo &Info) { return true; }
template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
if (!isActive())
return true;
EvalResult.setPointer(S.Stk.pop<Pointer>());
return true;
}
template <> bool EvalEmitter::emitRet<PT_FnPtr>(const SourceInfo &Info) {
if (!isActive())
return true;
EvalResult.setFunctionPointer(S.Stk.pop<FunctionPointer>());
return true;
}
bool EvalEmitter::emitRetVoid(const SourceInfo &Info) {
EvalResult.setValid();
return true;
}
bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
// Method to recursively traverse composites.
std::function<bool(QualType, const Pointer &, APValue &)> Composite;
Composite = [this, &Composite](QualType Ty, const Pointer &Ptr, APValue &R) {
if (const auto *AT = Ty->getAs<AtomicType>())
Ty = AT->getValueType();
if (const auto *RT = Ty->getAs<RecordType>()) {
const auto *Record = Ptr.getRecord();
assert(Record && "Missing record descriptor");
bool Ok = true;
if (RT->getDecl()->isUnion()) {
const FieldDecl *ActiveField = nullptr;
APValue Value;
for (const auto &F : Record->fields()) {
const Pointer &FP = Ptr.atField(F.Offset);
QualType FieldTy = F.Decl->getType();
if (FP.isActive()) {
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
} else {
Ok &= Composite(FieldTy, FP, Value);
}
break;
}
}
R = APValue(ActiveField, Value);
} else {
unsigned NF = Record->getNumFields();
unsigned NB = Record->getNumBases();
unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases();
R = APValue(APValue::UninitStruct(), NB, NF);
for (unsigned I = 0; I < NF; ++I) {
const Record::Field *FD = Record->getField(I);
QualType FieldTy = FD->Decl->getType();
const Pointer &FP = Ptr.atField(FD->Offset);
APValue &Value = R.getStructField(I);
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
} else {
Ok &= Composite(FieldTy, FP, Value);
}
}
for (unsigned I = 0; I < NB; ++I) {
const Record::Base *BD = Record->getBase(I);
QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
const Pointer &BP = Ptr.atField(BD->Offset);
Ok &= Composite(BaseTy, BP, R.getStructBase(I));
}
for (unsigned I = 0; I < NV; ++I) {
const Record::Base *VD = Record->getVirtualBase(I);
QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
const Pointer &VP = Ptr.atField(VD->Offset);
Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
}
}
return Ok;
}
if (Ty->isIncompleteArrayType()) {
R = APValue(APValue::UninitArray(), 0, 0);
return true;
}
if (const auto *AT = Ty->getAsArrayTypeUnsafe()) {
const size_t NumElems = Ptr.getNumElems();
QualType ElemTy = AT->getElementType();
R = APValue(APValue::UninitArray{}, NumElems, NumElems);
bool Ok = true;
for (unsigned I = 0; I < NumElems; ++I) {
APValue &Slot = R.getArrayInitializedElt(I);
const Pointer &EP = Ptr.atIndex(I);
if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
TYPE_SWITCH(*T, Ok &= ReturnValue<T>(EP.deref<T>(), Slot));
} else {
Ok &= Composite(ElemTy, EP.narrow(), Slot);
}
}
return Ok;
}
// Complex types.
if (const auto *CT = Ty->getAs<ComplexType>()) {
QualType ElemTy = CT->getElementType();
std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
assert(ElemT);
if (ElemTy->isIntegerType()) {
INT_TYPE_SWITCH(*ElemT, {
auto V1 = Ptr.atIndex(0).deref<T>();
auto V2 = Ptr.atIndex(1).deref<T>();
Result = APValue(V1.toAPSInt(), V2.toAPSInt());
return true;
});
} else if (ElemTy->isFloatingType()) {
Result = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
Ptr.atIndex(1).deref<Floating>().getAPFloat());
return true;
}
return false;
}
llvm_unreachable("invalid value to return");
};
// Return the composite type.
const auto &Ptr = S.Stk.pop<Pointer>();
return Composite(Ptr.getType(), Ptr, Result);
if (std::optional<APValue> APV = Ptr.toRValue(S.getCtx())) {
EvalResult.setValue(*APV);
return true;
}
EvalResult.setInvalid();
return false;
}
bool EvalEmitter::emitGetPtrLocal(uint32_t I, const SourceInfo &Info) {

View File

@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H
#define LLVM_CLANG_AST_INTERP_EVALEMITTER_H
#include "EvaluationResult.h"
#include "InterpState.h"
#include "PrimType.h"
#include "Source.h"
@ -33,8 +34,10 @@ public:
using AddrTy = uintptr_t;
using Local = Scope::Local;
llvm::Expected<bool> interpretExpr(const Expr *E);
llvm::Expected<bool> interpretDecl(const VarDecl *VD);
EvaluationResult interpretExpr(const Expr *E);
EvaluationResult interpretDecl(const VarDecl *VD);
InterpState &getState() { return S; }
protected:
EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
@ -51,10 +54,6 @@ protected:
virtual bool visitExpr(const Expr *E) = 0;
virtual bool visitDecl(const VarDecl *VD) = 0;
bool bail(const Stmt *S) { return bail(S->getBeginLoc()); }
bool bail(const Decl *D) { return bail(D->getBeginLoc()); }
bool bail(const SourceLocation &Loc);
/// Emits jumps.
bool jumpTrue(const LabelTy &Label);
bool jumpFalse(const LabelTy &Label);
@ -86,7 +85,7 @@ private:
/// Callee evaluation state.
InterpState S;
/// Location to write the result to.
APValue &Result;
EvaluationResult EvalResult;
/// Temporaries which require storage.
llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals;
@ -100,8 +99,6 @@ private:
// The emitter always tracks the current instruction and sets OpPC to a token
// value which is mapped to the location of the opcode being evaluated.
CodePtr OpPC;
/// Location of a failure.
std::optional<SourceLocation> BailLocation;
/// Location of the current instruction.
SourceInfo CurrentSource;

View File

@ -0,0 +1,196 @@
//===----- EvaluationResult.cpp - Result class for the VM ------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "EvaluationResult.h"
#include "Context.h"
#include "InterpState.h"
#include "Record.h"
#include "clang/AST/ExprCXX.h"
namespace clang {
namespace interp {
APValue EvaluationResult::toAPValue() const {
assert(!empty());
switch (Kind) {
case LValue:
// Either a pointer or a function pointer.
if (const auto *P = std::get_if<Pointer>(&Value))
return P->toAPValue();
else if (const auto *FP = std::get_if<FunctionPointer>(&Value))
return FP->toAPValue();
else
llvm_unreachable("Unhandled LValue type");
break;
case RValue:
return std::get<APValue>(Value);
case Valid:
return APValue();
default:
llvm_unreachable("Unhandled result kind?");
}
}
std::optional<APValue> EvaluationResult::toRValue() const {
if (Kind == RValue)
return toAPValue();
assert(Kind == LValue);
// We have a pointer and want an RValue.
if (const auto *P = std::get_if<Pointer>(&Value))
return P->toRValue(*Ctx);
else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
return FP->toAPValue();
llvm_unreachable("Unhandled lvalue kind");
}
static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc,
const FieldDecl *SubObjDecl) {
assert(SubObjDecl && "Subobject declaration does not exist");
S.FFDiag(Loc, diag::note_constexpr_uninitialized)
<< /*(name)*/ 1 << SubObjDecl;
S.Note(SubObjDecl->getLocation(),
diag::note_constexpr_subobject_declared_here);
}
static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
const Pointer &BasePtr, const Record *R);
static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc,
const Pointer &BasePtr,
const ConstantArrayType *CAT) {
bool Result = true;
size_t NumElems = CAT->getSize().getZExtValue();
QualType ElemType = CAT->getElementType();
if (ElemType->isRecordType()) {
const Record *R = BasePtr.getElemRecord();
for (size_t I = 0; I != NumElems; ++I) {
Pointer ElemPtr = BasePtr.atIndex(I).narrow();
Result &= CheckFieldsInitialized(S, Loc, ElemPtr, R);
}
} else if (const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
for (size_t I = 0; I != NumElems; ++I) {
Pointer ElemPtr = BasePtr.atIndex(I).narrow();
Result &= CheckArrayInitialized(S, Loc, ElemPtr, ElemCAT);
}
} else {
for (size_t I = 0; I != NumElems; ++I) {
if (!BasePtr.atIndex(I).isInitialized()) {
DiagnoseUninitializedSubobject(S, Loc, BasePtr.getField());
Result = false;
}
}
}
return Result;
}
static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
const Pointer &BasePtr, const Record *R) {
assert(R);
bool Result = true;
// Check all fields of this record are initialized.
for (const Record::Field &F : R->fields()) {
Pointer FieldPtr = BasePtr.atField(F.Offset);
QualType FieldType = F.Decl->getType();
if (FieldType->isRecordType()) {
Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord());
} else if (FieldType->isIncompleteArrayType()) {
// Nothing to do here.
} else if (FieldType->isArrayType()) {
const auto *CAT =
cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
Result &= CheckArrayInitialized(S, Loc, FieldPtr, CAT);
} else if (!FieldPtr.isInitialized()) {
DiagnoseUninitializedSubobject(S, Loc, F.Decl);
Result = false;
}
}
// Check Fields in all bases
for (const Record::Base &B : R->bases()) {
Pointer P = BasePtr.atField(B.Offset);
if (!P.isInitialized()) {
S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(),
diag::note_constexpr_uninitialized_base)
<< B.Desc->getType();
return false;
}
Result &= CheckFieldsInitialized(S, Loc, P, B.R);
}
// TODO: Virtual bases
return Result;
}
bool EvaluationResult::checkFullyInitialized(InterpState &S) const {
assert(Source);
assert(isLValue());
// Our Source must be a VarDecl.
const Decl *SourceDecl = Source.dyn_cast<const Decl *>();
assert(SourceDecl);
const auto *VD = cast<VarDecl>(SourceDecl);
assert(VD->getType()->isRecordType() || VD->getType()->isArrayType());
SourceLocation InitLoc = VD->getAnyInitializer()->getExprLoc();
const Pointer &Ptr = *std::get_if<Pointer>(&Value);
assert(!Ptr.isZero());
if (const Record *R = Ptr.getRecord())
return CheckFieldsInitialized(S, InitLoc, Ptr, R);
const auto *CAT =
cast<ConstantArrayType>(Ptr.getType()->getAsArrayTypeUnsafe());
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);
return true;
}
void EvaluationResult::dump() const {
assert(Ctx);
auto &OS = llvm::errs();
const ASTContext &ASTCtx = Ctx->getASTContext();
switch (Kind) {
case Empty:
OS << "Empty\n";
break;
case RValue:
OS << "RValue: ";
std::get<APValue>(Value).dump(OS, ASTCtx);
break;
case LValue: {
assert(Source);
QualType SourceType;
if (const auto *D = Source.dyn_cast<const Decl *>()) {
if (const auto *VD = dyn_cast<ValueDecl>(D))
SourceType = VD->getType();
} else if (const auto *E = Source.dyn_cast<const Expr *>()) {
SourceType = E->getType();
}
OS << "LValue: ";
if (const auto *P = std::get_if<Pointer>(&Value))
P->toAPValue().printPretty(OS, ASTCtx, SourceType);
else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
FP->toAPValue().printPretty(OS, ASTCtx, SourceType);
OS << "\n";
break;
}
default:
llvm_unreachable("Can't print that.");
}
}
} // namespace interp
} // namespace clang

View File

@ -0,0 +1,111 @@
//===------ EvaluationResult.h - Result class for the VM -------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H
#define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H
#include "FunctionPointer.h"
#include "Pointer.h"
#include "clang/AST/APValue.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include <optional>
#include <variant>
namespace clang {
namespace interp {
class EvalEmitter;
class Context;
/// Defines the result of an evaluation.
///
/// The result might be in different forms--one of the pointer types,
/// an APValue, or nothing.
///
/// We use this class to inspect and diagnose the result, as well as
/// convert it to the requested form.
class EvaluationResult final {
public:
enum ResultKind {
Empty, // Initial state.
LValue, // Result is an lvalue/pointer.
RValue, // Result is an rvalue.
Invalid, // Result is invalid.
Valid, // Result is valid and empty.
};
using DeclTy = llvm::PointerUnion<const Decl *, const Expr *>;
private:
const Context *Ctx = nullptr;
std::variant<std::monostate, Pointer, FunctionPointer, APValue> Value;
ResultKind Kind = Empty;
DeclTy Source = nullptr; // Currently only needed for dump().
EvaluationResult(ResultKind Kind) : Kind(Kind) {
// Leave everything empty. Can be used as an
// error marker or for void return values.
assert(Kind == Valid || Kind == Invalid);
}
void setSource(DeclTy D) { Source = D; }
void setValue(const APValue &V) {
assert(empty());
assert(!V.isLValue());
Value = std::move(V);
Kind = RValue;
}
void setPointer(const Pointer P) {
assert(empty());
Value = P;
Kind = LValue;
}
void setFunctionPointer(const FunctionPointer &P) {
assert(empty());
Value = P;
Kind = LValue;
}
void setInvalid() {
assert(empty());
Kind = Invalid;
}
void setValid() {
assert(empty());
Kind = Valid;
}
public:
EvaluationResult(const Context *Ctx) : Ctx(Ctx) {}
bool empty() const { return Kind == Empty; }
bool isInvalid() const { return Kind == Invalid; }
bool isLValue() const { return Kind == LValue; }
bool isRValue() const { return Kind == RValue; }
/// Returns an APValue for the evaluation result. The returned
/// APValue might be an LValue or RValue.
APValue toAPValue() const;
/// If the result is an LValue, convert that to an RValue
/// and return it. This may fail, e.g. if the result is an
/// LValue and we can't read from it.
std::optional<APValue> toRValue() const;
bool checkFullyInitialized(InterpState &S) const;
/// Dump to stderr.
void dump() const;
friend class EvalEmitter;
};
} // namespace interp
} // namespace clang
#endif

View File

@ -204,14 +204,18 @@ public:
}
static bool rem(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
// FIXME: Implement.
assert(false);
if constexpr (Signed)
*R = IntegralAP(A.V.srem(B.V));
else
*R = IntegralAP(A.V.urem(B.V));
return false;
}
static bool div(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
// FIXME: Implement.
assert(false);
if constexpr (Signed)
*R = IntegralAP(A.V.sdiv(B.V));
else
*R = IntegralAP(A.V.udiv(B.V));
return false;
}

View File

@ -53,6 +53,25 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
return true;
}
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD) {
if (!S.getLangOpts().CPlusPlus)
return;
const SourceInfo &Loc = S.Current->getSource(OpPC);
if (VD->getType()->isIntegralOrEnumerationType())
S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
else
S.FFDiag(Loc,
S.getLangOpts().CPlusPlus11
? diag::note_constexpr_ltor_non_constexpr
: diag::note_constexpr_ltor_non_integral,
1)
<< VD << VD->getType();
S.Note(VD->getLocation(), diag::note_declared_at);
}
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (Ptr.isActive())
@ -171,9 +190,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at);
diagnoseNonConstVariable(S, OpPC, VD);
}
return false;
}
@ -216,6 +233,44 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return true;
}
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
assert(Desc);
auto IsConstType = [&S](const VarDecl *VD) -> bool {
if (VD->isConstexpr())
return true;
if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11)
return false;
QualType T = VD->getType();
if (T.isConstQualified())
return true;
if (const auto *RT = T->getAs<ReferenceType>())
return RT->getPointeeType().isConstQualified();
if (const auto *PT = T->getAs<PointerType>())
return PT->getPointeeType().isConstQualified();
return false;
};
if (const auto *D = Desc->asValueDecl()) {
if (const auto *VD = dyn_cast<VarDecl>(D);
VD && VD->hasGlobalStorage() && !IsConstType(VD)) {
diagnoseNonConstVariable(S, OpPC, VD);
return S.inConstantContext();
}
}
return true;
}
static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return CheckConstant(S, OpPC, Ptr.getDeclDesc());
}
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return !Ptr.isZero() && !Ptr.isDummy();
}
@ -304,6 +359,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckConstant(S, OpPC, Ptr))
return false;
if (!CheckDummy(S, OpPC, Ptr))
return false;
if (!CheckExtern(S, OpPC, Ptr))
@ -432,7 +490,7 @@ bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This) {
}
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
if (!MD->isPure())
if (!MD->isPureVirtual())
return true;
const SourceInfo &E = S.Current->getSource(OpPC);
S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
@ -440,98 +498,6 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) {
return false;
}
static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI,
const FieldDecl *SubObjDecl) {
assert(SubObjDecl && "Subobject declaration does not exist");
S.FFDiag(SI, diag::note_constexpr_uninitialized)
<< /*(name)*/ 1 << SubObjDecl;
S.Note(SubObjDecl->getLocation(),
diag::note_constexpr_subobject_declared_here);
}
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
const Pointer &BasePtr, const Record *R);
static bool CheckArrayInitialized(InterpState &S, CodePtr OpPC,
const Pointer &BasePtr,
const ConstantArrayType *CAT) {
bool Result = true;
size_t NumElems = CAT->getSize().getZExtValue();
QualType ElemType = CAT->getElementType();
if (ElemType->isRecordType()) {
const Record *R = BasePtr.getElemRecord();
for (size_t I = 0; I != NumElems; ++I) {
Pointer ElemPtr = BasePtr.atIndex(I).narrow();
Result &= CheckFieldsInitialized(S, OpPC, ElemPtr, R);
}
} else if (const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
for (size_t I = 0; I != NumElems; ++I) {
Pointer ElemPtr = BasePtr.atIndex(I).narrow();
Result &= CheckArrayInitialized(S, OpPC, ElemPtr, ElemCAT);
}
} else {
for (size_t I = 0; I != NumElems; ++I) {
if (!BasePtr.atIndex(I).isInitialized()) {
DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC),
BasePtr.getField());
Result = false;
}
}
}
return Result;
}
static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC,
const Pointer &BasePtr, const Record *R) {
assert(R);
bool Result = true;
// Check all fields of this record are initialized.
for (const Record::Field &F : R->fields()) {
Pointer FieldPtr = BasePtr.atField(F.Offset);
QualType FieldType = F.Decl->getType();
if (FieldType->isRecordType()) {
Result &= CheckFieldsInitialized(S, OpPC, FieldPtr, FieldPtr.getRecord());
} else if (FieldType->isIncompleteArrayType()) {
// Nothing to do here.
} else if (FieldType->isArrayType()) {
const auto *CAT =
cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe());
Result &= CheckArrayInitialized(S, OpPC, FieldPtr, CAT);
} else if (!FieldPtr.isInitialized()) {
DiagnoseUninitializedSubobject(S, S.Current->getSource(OpPC), F.Decl);
Result = false;
}
}
// Check Fields in all bases
for (const Record::Base &B : R->bases()) {
Pointer P = BasePtr.atField(B.Offset);
if (!P.isInitialized()) {
S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(),
diag::note_constexpr_uninitialized_base)
<< B.Desc->getType();
return false;
}
Result &= CheckFieldsInitialized(S, OpPC, P, B.R);
}
// TODO: Virtual bases
return Result;
}
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) {
assert(!This.isZero());
if (const Record *R = This.getRecord())
return CheckFieldsInitialized(S, OpPC, This, R);
const auto *CAT =
cast<ConstantArrayType>(This.getType()->getAsArrayTypeUnsafe());
return CheckArrayInitialized(S, OpPC, This, CAT);
}
bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr) {
if (!S.inConstantContext())
@ -605,13 +571,7 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
}
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (!VD->getType().isConstQualified()) {
S.FFDiag(E,
VD->getType()->isIntegralOrEnumerationType()
? diag::note_constexpr_ltor_non_const_int
: diag::note_constexpr_ltor_non_constexpr,
1)
<< VD;
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
diagnoseNonConstVariable(S, OpPC, VD);
return false;
}

View File

@ -77,6 +77,9 @@ bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
/// Checks if a pointer points to const storage.
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
/// Checks if the Descriptor is of a constexpr or const global variable.
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc);
/// Checks if a pointer points to a mutable field.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@ -108,9 +111,6 @@ bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);
/// Checks if a method is pure virtual.
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
/// Checks that all fields are initialized after a constructor call.
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This);
/// Checks if reinterpret casts are legal in the current context.
bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);
@ -1004,12 +1004,23 @@ bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
const Block *B = S.P.getGlobal(I);
if (!CheckConstant(S, OpPC, B->getDescriptor()))
return false;
if (B->isExtern())
return false;
S.Stk.push<T>(B->deref<T>());
return true;
}
/// Same as GetGlobal, but without the checks.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
auto *B = S.P.getGlobal(I);
S.Stk.push<T>(B->deref<T>());
return true;
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
// TODO: emit warning.
@ -1047,8 +1058,12 @@ inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
const Pointer &P = S.Stk.peek<Pointer>();
APValue *Cached = Temp->getOrCreateValue(true);
*Cached = P.toRValue(S.getCtx());
return true;
if (std::optional<APValue> APV = P.toRValue(S.getCtx())) {
*Cached = *APV;
return true;
}
return false;
}
template <PrimType Name, class T = typename PrimConv<Name>::T>
@ -1064,15 +1079,18 @@ bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
return true;
}
// FIXME: The Field pointer here is too much IMO and we could instead just
// pass an Offset + BitWidth pair.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
uint32_t FieldOffset) {
assert(F->isBitField());
if (S.checkingPotentialConstantExpression())
return false;
const Pointer &This = S.Current->getThis();
if (!CheckThis(S, OpPC, This))
return false;
const Pointer &Field = This.atField(F->Offset);
const Pointer &Field = This.atField(FieldOffset);
const auto &Value = S.Stk.pop<T>();
Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue(S.getCtx()));
Field.initialize();
@ -1846,11 +1864,6 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
return NarrowPtr(S, OpPC);
}
inline bool CheckGlobalCtor(InterpState &S, CodePtr OpPC) {
const Pointer &Obj = S.Stk.peek<Pointer>();
return CheckCtorCall(S, OpPC, Obj);
}
inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func) {
if (Func->hasThisPointer()) {
size_t ThisOffset =

View File

@ -375,10 +375,9 @@ def GetLocal : AccessOpcode { let HasCustomEval = 1; }
// [] -> [Pointer]
def SetLocal : AccessOpcode { let HasCustomEval = 1; }
def CheckGlobalCtor : Opcode {}
// [] -> [Value]
def GetGlobal : AccessOpcode;
def GetGlobalUnchecked : AccessOpcode;
// [Value] -> []
def InitGlobal : AccessOpcode;
// [Value] -> []
@ -416,7 +415,11 @@ def InitThisField : AccessOpcode;
// [Value] -> []
def InitThisFieldActive : AccessOpcode;
// [Value] -> []
def InitThisBitField : BitFieldOpcode;
def InitThisBitField : Opcode {
let Types = [AluTypeClass];
let Args = [ArgRecordField, ArgUint32];
let HasGroup = 1;
}
// [Pointer, Value] -> []
def InitField : AccessOpcode;
// [Pointer, Value] -> []

View File

@ -231,33 +231,143 @@ bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
return hasSameBase(A, B) && A.Base == B.Base && A.getFieldDesc()->IsArray;
}
APValue Pointer::toRValue(const Context &Ctx) const {
// Primitives.
if (getFieldDesc()->isPrimitive()) {
PrimType PT = *Ctx.classify(getType());
TYPE_SWITCH(PT, return deref<T>().toAPValue());
llvm_unreachable("Unhandled PrimType?");
}
std::optional<APValue> Pointer::toRValue(const Context &Ctx) const {
// Method to recursively traverse composites.
std::function<bool(QualType, const Pointer &, APValue &)> Composite;
Composite = [&Composite, &Ctx](QualType Ty, const Pointer &Ptr, APValue &R) {
if (const auto *AT = Ty->getAs<AtomicType>())
Ty = AT->getValueType();
// Invalid pointers.
if (Ptr.isDummy() || !Ptr.isLive() ||
(!Ptr.isUnknownSizeArray() && Ptr.isOnePastEnd()))
return false;
// Primitive values.
if (std::optional<PrimType> T = Ctx.classify(Ty)) {
if (T == PT_Ptr || T == PT_FnPtr) {
R = Ptr.toAPValue();
} else {
TYPE_SWITCH(*T, R = Ptr.deref<T>().toAPValue());
}
return true;
}
if (const auto *RT = Ty->getAs<RecordType>()) {
const auto *Record = Ptr.getRecord();
assert(Record && "Missing record descriptor");
bool Ok = true;
if (RT->getDecl()->isUnion()) {
const FieldDecl *ActiveField = nullptr;
APValue Value;
for (const auto &F : Record->fields()) {
const Pointer &FP = Ptr.atField(F.Offset);
QualType FieldTy = F.Decl->getType();
if (FP.isActive()) {
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue());
} else {
Ok &= Composite(FieldTy, FP, Value);
}
break;
}
}
R = APValue(ActiveField, Value);
} else {
unsigned NF = Record->getNumFields();
unsigned NB = Record->getNumBases();
unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases();
R = APValue(APValue::UninitStruct(), NB, NF);
for (unsigned I = 0; I < NF; ++I) {
const Record::Field *FD = Record->getField(I);
QualType FieldTy = FD->Decl->getType();
const Pointer &FP = Ptr.atField(FD->Offset);
APValue &Value = R.getStructField(I);
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue());
} else {
Ok &= Composite(FieldTy, FP, Value);
}
}
for (unsigned I = 0; I < NB; ++I) {
const Record::Base *BD = Record->getBase(I);
QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
const Pointer &BP = Ptr.atField(BD->Offset);
Ok &= Composite(BaseTy, BP, R.getStructBase(I));
}
for (unsigned I = 0; I < NV; ++I) {
const Record::Base *VD = Record->getVirtualBase(I);
QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
const Pointer &VP = Ptr.atField(VD->Offset);
Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
}
}
return Ok;
}
if (Ty->isIncompleteArrayType()) {
R = APValue(APValue::UninitArray(), 0, 0);
return true;
}
if (const auto *AT = Ty->getAsArrayTypeUnsafe()) {
const size_t NumElems = Ptr.getNumElems();
QualType ElemTy = AT->getElementType();
R = APValue(APValue::UninitArray{}, NumElems, NumElems);
bool Ok = true;
for (unsigned I = 0; I < NumElems; ++I) {
APValue &Slot = R.getArrayInitializedElt(I);
const Pointer &EP = Ptr.atIndex(I);
if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
TYPE_SWITCH(*T, Slot = EP.deref<T>().toAPValue());
} else {
Ok &= Composite(ElemTy, EP.narrow(), Slot);
}
}
return Ok;
}
// Complex types.
if (const auto *CT = Ty->getAs<ComplexType>()) {
QualType ElemTy = CT->getElementType();
std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
assert(ElemT);
if (ElemTy->isIntegerType()) {
INT_TYPE_SWITCH(*ElemT, {
auto V1 = Ptr.atIndex(0).deref<T>();
auto V2 = Ptr.atIndex(1).deref<T>();
R = APValue(V1.toAPSInt(), V2.toAPSInt());
return true;
});
} else if (ElemTy->isFloatingType()) {
R = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
Ptr.atIndex(1).deref<Floating>().getAPFloat());
return true;
}
return false;
}
llvm_unreachable("invalid value to return");
};
if (isZero())
return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {}, false,
true);
if (isDummy() || !isLive())
return std::nullopt;
// Return the composite type.
APValue Result;
// Records.
if (getFieldDesc()->isRecord()) {
const Record *R = getRecord();
Result =
APValue(APValue::UninitStruct(), R->getNumBases(), R->getNumFields());
for (unsigned I = 0; I != R->getNumFields(); ++I) {
const Pointer &FieldPtr = this->atField(R->getField(I)->Offset);
Result.getStructField(I) = FieldPtr.toRValue(Ctx);
}
for (unsigned I = 0; I != R->getNumBases(); ++I) {
const Pointer &BasePtr = this->atField(R->getBase(I)->Offset);
Result.getStructBase(I) = BasePtr.toRValue(Ctx);
}
}
// TODO: Arrays
if (!Composite(getType(), *this, Result))
return std::nullopt;
return Result;
}

View File

@ -98,7 +98,7 @@ public:
}
/// Converts the pointer to an APValue that is an rvalue.
APValue toRValue(const Context &Ctx) const;
std::optional<APValue> toRValue(const Context &Ctx) const;
/// Offsets a pointer inside an array.
[[nodiscard]] Pointer atIndex(unsigned Idx) const {
@ -379,6 +379,7 @@ public:
return *reinterpret_cast<T *>(Pointee->rawData() + Base +
sizeof(InitMapPtr));
assert(Offset + sizeof(T) <= Pointee->getDescriptor()->getAllocSize());
return *reinterpret_cast<T *>(Pointee->rawData() + Offset);
}

View File

@ -4833,9 +4833,23 @@ recurse:
E = cast<CXXStdInitializerListExpr>(E)->getSubExpr();
goto recurse;
case Expr::SubstNonTypeTemplateParmExprClass:
case Expr::SubstNonTypeTemplateParmExprClass: {
// Mangle a substituted parameter the same way we mangle the template
// argument.
auto *SNTTPE = cast<SubstNonTypeTemplateParmExpr>(E);
if (auto *CE = dyn_cast<ConstantExpr>(SNTTPE->getReplacement())) {
// Pull out the constant value and mangle it as a template argument.
QualType ParamType = SNTTPE->getParameterType(Context.getASTContext());
assert(CE->hasAPValueResult() && "expected the NTTP to have an APValue");
mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false,
/*NeedExactType=*/true);
break;
}
// The remaining cases all happen to be substituted with expressions that
// mangle the same as a corresponding template argument anyway.
E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
goto recurse;
}
case Expr::UserDefinedLiteralClass:
// We follow g++'s approach of mangling a UDL as a call to the literal
@ -4883,7 +4897,7 @@ recurse:
Out << '_';
mangleType(New->getAllocatedType());
if (New->hasInitializer()) {
if (New->getInitializationStyle() == CXXNewInitializationStyle::List)
if (New->getInitializationStyle() == CXXNewInitializationStyle::Braces)
Out << "il";
else
Out << "pi";
@ -4898,7 +4912,7 @@ recurse:
for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
mangleExpression(PLE->getExpr(i));
} else if (New->getInitializationStyle() ==
CXXNewInitializationStyle::List &&
CXXNewInitializationStyle::Braces &&
isa<InitListExpr>(Init)) {
// Only take InitListExprs apart for list-initialization.
mangleInitListElements(cast<InitListExpr>(Init));
@ -6064,6 +6078,11 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
mangleNullPointer(A.getNullPtrType());
break;
}
case TemplateArgument::StructuralValue:
mangleValueInTemplateArg(A.getStructuralValueType(),
A.getAsStructuralValue(),
/*TopLevel=*/true, NeedExactType);
break;
case TemplateArgument::Pack: {
// <template-arg> ::= J <template-arg>* E
Out << 'J';
@ -6472,7 +6491,20 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
Out << "plcvPcad";
Kind = Offset;
} else {
if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
// Clang 11 and before mangled an array subject to array-to-pointer decay
// as if it were the declaration itself.
bool IsArrayToPointerDecayMangledAsDecl = false;
if (TopLevel && Ctx.getLangOpts().getClangABICompat() <=
LangOptions::ClangABI::Ver11) {
QualType BType = B.getType();
IsArrayToPointerDecayMangledAsDecl =
BType->isArrayType() && V.getLValuePath().size() == 1 &&
V.getLValuePath()[0].getAsArrayIndex() == 0 &&
Ctx.hasSimilarType(T, Ctx.getDecayedType(BType));
}
if ((!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) &&
!IsArrayToPointerDecayMangledAsDecl) {
NotPrimaryExpr();
// A final conversion to the template parameter's type is usually
// folded into the 'so' mangling, but we can't do that for 'void*'

View File

@ -930,7 +930,7 @@ void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC));
attributeOnlyIfTrue("inline", FD->isInlineSpecified());
attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten());
attributeOnlyIfTrue("pure", FD->isPure());
attributeOnlyIfTrue("pure", FD->isPureVirtual());
attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten());
attributeOnlyIfTrue("constexpr", FD->isConstexpr());
attributeOnlyIfTrue("variadic", FD->isVariadic());
@ -1356,12 +1356,11 @@ void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) {
attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0);
switch (NE->getInitializationStyle()) {
case CXXNewInitializationStyle::None:
case CXXNewInitializationStyle::Implicit:
break;
case CXXNewInitializationStyle::Call:
case CXXNewInitializationStyle::Parens:
JOS.attribute("initStyle", "call");
break;
case CXXNewInitializationStyle::List:
case CXXNewInitializationStyle::Braces:
JOS.attribute("initStyle", "list");
break;
}

View File

@ -464,7 +464,7 @@ public:
SmallString<40> Mangled;
auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
return std::string(Mangled.str());
return std::string(Mangled);
};
return {

View File

@ -337,6 +337,7 @@ class MicrosoftCXXNameMangler {
public:
enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
enum class TplArgKind { ClassNTTP, StructuralValue };
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
: Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
@ -453,7 +454,7 @@ private:
const TemplateArgumentList &TemplateArgs);
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
const NamedDecl *Parm);
void mangleTemplateArgValue(QualType T, const APValue &V,
void mangleTemplateArgValue(QualType T, const APValue &V, TplArgKind,
bool WithScalarType = false);
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
@ -1088,7 +1089,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
Out << "?__N";
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
TPO->getValue());
TPO->getValue(), TplArgKind::ClassNTTP);
break;
}
@ -1604,6 +1605,22 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
}
}
/// If value V (with type T) represents a decayed pointer to the first element
/// of an array, return that array.
static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) {
// Must be a pointer...
if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() ||
!V.getLValueBase())
return nullptr;
// ... to element 0 of an array.
QualType BaseT = V.getLValueBase().getType();
if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 ||
V.getLValuePath()[0].getAsArrayIndex() != 0)
return nullptr;
return const_cast<ValueDecl *>(
V.getLValueBase().dyn_cast<const ValueDecl *>());
}
void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
const TemplateArgument &TA,
const NamedDecl *Parm) {
@ -1669,7 +1686,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
Out << "$";
auto *TPO = cast<TemplateParamObjectDecl>(ND);
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
TPO->getValue());
TPO->getValue(), TplArgKind::ClassNTTP);
} else {
mangle(ND, "$1?");
}
@ -1712,6 +1729,27 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
cast<NonTypeTemplateParmDecl>(Parm), T);
break;
}
case TemplateArgument::StructuralValue:
if (ValueDecl *D = getAsArrayToPointerDecayedDecl(
TA.getStructuralValueType(), TA.getAsStructuralValue())) {
// Mangle the result of array-to-pointer decay as if it were a reference
// to the original declaration, to match MSVC's behavior. This can result
// in mangling collisions in some cases!
return mangleTemplateArg(
TD, TemplateArgument(D, TA.getStructuralValueType()), Parm);
}
Out << "$";
if (cast<NonTypeTemplateParmDecl>(Parm)
->getType()
->getContainedDeducedType()) {
Out << "M";
mangleType(TA.getNonTypeTemplateArgumentType(), SourceRange(), QMM_Drop);
}
mangleTemplateArgValue(TA.getStructuralValueType(),
TA.getAsStructuralValue(),
TplArgKind::StructuralValue,
/*WithScalarType=*/false);
break;
case TemplateArgument::Expression:
mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm));
break;
@ -1754,6 +1792,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const APValue &V,
TplArgKind TAK,
bool WithScalarType) {
switch (V.getKind()) {
case APValue::None:
@ -1806,7 +1845,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
break;
}
} else {
if (T->isPointerType())
if (TAK == TplArgKind::ClassNTTP && T->isPointerType())
Out << "5";
SmallVector<char, 2> EntryTypes;
@ -1850,12 +1889,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
auto *VD = Base.dyn_cast<const ValueDecl*>();
if (!VD)
break;
Out << "E";
Out << (TAK == TplArgKind::ClassNTTP ? 'E' : '1');
mangle(VD);
for (const std::function<void()> &Mangler : EntryManglers)
Mangler();
if (T->isPointerType())
if (TAK == TplArgKind::ClassNTTP && T->isPointerType())
Out << '@';
}
@ -1869,11 +1908,18 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const CXXRecordDecl *RD =
T->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
const ValueDecl *D = V.getMemberPointerDecl();
if (T->isMemberDataPointerType())
mangleMemberDataPointerInClassNTTP(RD, D);
else
mangleMemberFunctionPointerInClassNTTP(RD,
cast_or_null<CXXMethodDecl>(D));
if (TAK == TplArgKind::ClassNTTP) {
if (T->isMemberDataPointerType())
mangleMemberDataPointerInClassNTTP(RD, D);
else
mangleMemberFunctionPointerInClassNTTP(RD,
cast_or_null<CXXMethodDecl>(D));
} else {
if (T->isMemberDataPointerType())
mangleMemberDataPointer(RD, D, "");
else
mangleMemberFunctionPointer(RD, cast_or_null<CXXMethodDecl>(D), "");
}
return;
}
@ -1885,11 +1931,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
unsigned BaseIndex = 0;
for (const CXXBaseSpecifier &B : RD->bases())
mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++));
mangleTemplateArgValue(B.getType(), V.getStructBase(BaseIndex++), TAK);
for (const FieldDecl *FD : RD->fields())
if (!FD->isUnnamedBitfield())
mangleTemplateArgValue(FD->getType(),
V.getStructField(FD->getFieldIndex()),
V.getStructField(FD->getFieldIndex()), TAK,
/*WithScalarType*/ true);
Out << '@';
return;
@ -1900,7 +1946,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleType(T, SourceRange(), QMM_Escape);
if (const FieldDecl *FD = V.getUnionField()) {
mangleUnqualifiedName(FD);
mangleTemplateArgValue(FD->getType(), V.getUnionValue());
mangleTemplateArgValue(FD->getType(), V.getUnionValue(), TAK);
}
Out << '@';
return;
@ -1932,7 +1978,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
const APValue &ElemV = I < V.getArrayInitializedElts()
? V.getArrayInitializedElt(I)
: V.getArrayFiller();
mangleTemplateArgValue(ElemT, ElemV);
mangleTemplateArgValue(ElemT, ElemV, TAK);
Out << '@';
}
Out << '@';
@ -1949,7 +1995,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleType(ElemT, SourceRange(), QMM_Escape);
for (unsigned I = 0, N = V.getVectorLength(); I != N; ++I) {
const APValue &ElemV = V.getVectorElt(I);
mangleTemplateArgValue(ElemT, ElemV);
mangleTemplateArgValue(ElemT, ElemV, TAK);
Out << '@';
}
Out << "@@";

Some files were not shown because too many files have changed in this diff Show More