Skip to content

Commit a311992

Browse files
committed
add type trait
1 parent 3acf856 commit a311992

File tree

10 files changed

+189
-2
lines changed

10 files changed

+189
-2
lines changed

clang/include/clang/AST/CXXRecordDeclDefinitionBits.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,9 @@ FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
253253
/// type that is intangible). HLSL only.
254254
FIELD(IsHLSLIntangible, 1, NO_MERGE)
255255

256+
/// Whether the record type is line vector layout compatible (that is,
257+
/// it has at most 4 elements, does not exceed 16 bytes, is homogenous,
258+
/// and does not contain any bool or enum types)
259+
FIELD(IsHLSLLineVectorLayoutCompatible, 1, NO_MERGE)
260+
256261
#undef FIELD

clang/include/clang/AST/DeclCXX.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,11 @@ class CXXRecordDecl : public RecordDecl {
15511551
/// a field or in base class.
15521552
bool isHLSLIntangible() const { return data().IsHLSLIntangible; }
15531553

1554+
/// Returns true if the class is line vector layout compatible
1555+
bool isHLSLLineVectorLayoutCompatible() const {
1556+
return data().IsHLSLLineVectorLayoutCompatible;
1557+
}
1558+
15541559
/// If the class is a local class [class.local], returns
15551560
/// the enclosing function declaration.
15561561
const FunctionDecl *isLocalClass() const {

clang/include/clang/AST/Type.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2665,7 +2665,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
26652665
bool isHLSLAttributedResourceType() const;
26662666
bool isHLSLIntangibleType()
26672667
const; // Any HLSL intangible type (builtin, array, class)
2668-
2668+
bool isHLSLLineVectorLayoutCompatibleType()
2669+
const; // Any HLSL line vector layout compatible type
26692670
/// Determines if this type, which must satisfy
26702671
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
26712672
/// than implicitly __strong.
@@ -8459,6 +8460,12 @@ inline bool Type::isHLSLBuiltinIntangibleType() const {
84598460
false;
84608461
}
84618462

8463+
inline bool Type::isHLSLLineVectorLayoutCompatibleType() const {
8464+
#define HLSL_LINE_VECTOR_LAYOUT_COMPATIBLE_TYPE(Name, Id, SingletonId) \
8465+
is##Id##Type() ||
8466+
return isHLSLAttributedResourceType();
8467+
}
8468+
84628469
inline bool Type::isHLSLSpecificType() const {
84638470
return isHLSLBuiltinIntangibleType() || isHLSLAttributedResourceType();
84648471
}

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ KEYWORD(out , KEYHLSL)
662662
// HLSL Type traits
663663
TYPE_TRAIT_2(__builtin_hlsl_is_scalarized_layout_compatible, IsScalarizedLayoutCompatible, KEYHLSL)
664664
TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL)
665+
TYPE_TRAIT_1(__builtin_hlsl_is_line_vector_layout_compatible, IsLineVectorLayoutCompatibleType, KEYHLSL)
665666

666667
// OpenMP Type Traits
667668
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class SemaHLSL : public SemaBase {
132132

133133
// HLSL Type trait implementations
134134
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
135+
bool IsLineVectorLayoutCompatibleType(QualType T1);
135136

136137
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);
137138

clang/lib/AST/DeclCXX.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
109109
ImplicitCopyAssignmentHasConstParam(true),
110110
HasDeclaredCopyConstructorWithConstParam(false),
111111
HasDeclaredCopyAssignmentWithConstParam(false),
112-
IsAnyDestructorNoReturn(false), IsHLSLIntangible(false), IsLambda(false),
112+
IsAnyDestructorNoReturn(false), IsHLSLIntangible(false),
113+
IsHLSLLineVectorLayoutCompatible(false), IsLambda(false),
113114
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
114115
HasODRHash(false), Definition(D) {}
115116

@@ -434,6 +435,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
434435
if (BaseClassDecl->isHLSLIntangible())
435436
data().IsHLSLIntangible = true;
436437

438+
if (BaseClassDecl->isHLSLLineVectorLayoutCompatible())
439+
data().IsHLSLLineVectorLayoutCompatible = true;
440+
437441
// C++11 [class.copy]p18:
438442
// The implicitly-declared copy assignment operator for a class X will
439443
// have the form 'X& X::operator=(const X&)' if each direct base class B

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5032,6 +5032,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
50325032
case UTT_IsScalar:
50335033
case UTT_IsCompound:
50345034
case UTT_IsMemberPointer:
5035+
case UTT_IsLineVectorLayoutCompatibleType:
50355036
// Fall-through
50365037

50375038
// These traits are modeled on type predicates in C++0x [meta.unary.prop]
@@ -5714,6 +5715,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
57145715
tok::kw___builtin_hlsl_is_intangible))
57155716
return false;
57165717
return T->isHLSLIntangibleType();
5718+
5719+
case UTT_IsLineVectorLayoutCompatibleType:
5720+
assert(Self.getLangOpts().HLSL &&
5721+
"line vector layout compatible types are HLSL-only feature");
5722+
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
5723+
diag::err_incomplete_type))
5724+
return false;
5725+
5726+
return Self.HLSL().IsLineVectorLayoutCompatibleType(T);
57175727
}
57185728
}
57195729

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,6 +2163,49 @@ static void BuildFlattenedTypeList(QualType BaseTy,
21632163
}
21642164
}
21652165

2166+
bool SemaHLSL::IsLineVectorLayoutCompatibleType(clang::QualType QT) {
2167+
if (QT.isNull())
2168+
return false;
2169+
2170+
llvm::SmallVector<QualType, 16> QTTypes;
2171+
BuildFlattenedTypeList(QT, QTTypes);
2172+
2173+
QualType FirstQT = QTTypes[0];
2174+
2175+
// element count cannot exceed 4
2176+
if (QTTypes.size() > 4)
2177+
return false;
2178+
2179+
// check if the outer type was an array type
2180+
if (llvm::isa<clang::ArrayType>(QT.getTypePtr()))
2181+
return false;
2182+
2183+
for (QualType TempQT : QTTypes) {
2184+
// ensure homogeneity
2185+
if (TempQT != FirstQT)
2186+
return false;
2187+
2188+
if (const BuiltinType *BT = TempQT->getAs<BuiltinType>()) {
2189+
if (BT->getKind() == BuiltinType::Bool ||
2190+
BT->getKind() == BuiltinType::Enum)
2191+
return false;
2192+
2193+
// Check if it is an array type.
2194+
if (llvm::isa<clang::ArrayType>(TempQT.getTypePtr()))
2195+
return false;
2196+
}
2197+
}
2198+
2199+
// if the loop above completes without returning, then
2200+
// we've guaranteed homogeneity
2201+
int TotalSizeInBytes =
2202+
(SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size();
2203+
if (TotalSizeInBytes > 16)
2204+
return false;
2205+
2206+
return true;
2207+
}
2208+
21662209
bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
21672210
if (T1.isNull() || T2.isNull())
21682211
return false;
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
2+
// expected-no-diagnostics
3+
4+
struct oneInt {
5+
int i;
6+
};
7+
8+
struct twoInt {
9+
int aa;
10+
int ab;
11+
};
12+
13+
struct threeInts {
14+
oneInt o;
15+
twoInt t;
16+
};
17+
18+
struct oneFloat {
19+
float f;
20+
};
21+
struct depthDiff {
22+
int i;
23+
oneInt o;
24+
oneFloat f;
25+
};
26+
27+
struct notHomogenous{
28+
int i;
29+
float f;
30+
};
31+
32+
struct EightElements {
33+
twoInt x[2];
34+
twoInt y[2];
35+
};
36+
37+
struct EightHalves {
38+
half x[8];
39+
};
40+
41+
struct intVec {
42+
int2 i;
43+
};
44+
45+
struct oneIntWithVec {
46+
int i;
47+
oneInt i2;
48+
int2 i3;
49+
};
50+
51+
struct weirdStruct {
52+
int i;
53+
intVec iv;
54+
};
55+
56+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(int), "");
57+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(float), "");
58+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(float4), "");
59+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(double2), "");
60+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(oneInt), "");
61+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(oneFloat), "");
62+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(twoInt), "");
63+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(threeInts), "");
64+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(notHomogenous), "");
65+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(depthDiff), "");
66+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(EightElements), "");
67+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(EightHalves), "");
68+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(oneIntWithVec), "");
69+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(weirdStruct), "");
70+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(RWBuffer<int>), "");
71+
72+
73+
// arrays not allowed
74+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(half[4]), "");
75+
76+
template<typename T> struct TemplatedBuffer {
77+
T a;
78+
__hlsl_resource_t h;
79+
};
80+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(TemplatedBuffer<int>), "");
81+
82+
struct MyStruct1 : TemplatedBuffer<float> {
83+
float x;
84+
};
85+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(MyStruct1), "");
86+
87+
struct MyStruct2 {
88+
const TemplatedBuffer<float> TB[10];
89+
};
90+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(MyStruct2), "");
91+
92+
template<typename T> struct SimpleTemplate {
93+
T a;
94+
};
95+
96+
// though the element type is incomplete, the type trait should still technically return true
97+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(SimpleTemplate<__hlsl_resource_t>), "");
98+
99+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(SimpleTemplate<float>), "");
100+
101+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
2+
3+
// expected-note@+1{{forward declaration of 'notComplete'}}
4+
struct notComplete;
5+
// expected-error@+1{{incomplete type 'notComplete' where a complete type is required}}
6+
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(notComplete), "");
7+
8+
9+
// types must be complete
10+
_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(__hlsl_resource_t), "");

0 commit comments

Comments
 (0)