Skip to content

Commit bd74d7d

Browse files
committed
[HLSL] Pass arrays by value
HLSL constant sized array function parameters do not decay to pointers. Instead constant sized array types are preserved as unique types for overload resolution, template instantiation and name mangling. This implements the change by adding a new `ArrayParameterType` which represents a non-decaying `ConstantArrayType`. The new type behaves the same as `ConstantArrayType` except that it does not decay to a pointer. Values of `ConstantArrayType` in HLSL decay during overload resolution via a new `HLSLArrayRValue` cast to `ArrayParameterType`. `ArrayParamterType` values are passed indirectly by-value to functions in IR generation resulting in callee generated memcpy instructions.
1 parent 880eb33 commit bd74d7d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+609
-27
lines changed

clang/docs/HLSL/FunctionCalls.rst

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -157,22 +157,24 @@ Clang Implementation
157157
of the changes in the prototype implementation are restoring Clang-3.7 code
158158
that was previously modified to its original state.
159159

160-
The implementation in clang depends on two new AST nodes and minor extensions to
161-
Clang's existing support for Objective-C write-back arguments. The goal of this
162-
design is to capture the semantic details of HLSL function calls in the AST, and
163-
minimize the amount of magic that needs to occur during IR generation.
164-
165-
The two new AST nodes are ``HLSLArrayTemporaryExpr`` and ``HLSLOutParamExpr``,
166-
which respectively represent the temporaries used for passing arrays by value
167-
and the temporaries created for function outputs.
160+
The implementation in clang adds a new non-decaying array type, a new AST node
161+
to represent output parameters, and minor extensions to Clang's existing support
162+
for Objective-C write-back arguments. The goal of this design is to capture the
163+
semantic details of HLSL function calls in the AST, and minimize the amount of
164+
magic that needs to occur during IR generation.
168165

169166
Array Temporaries
170167
-----------------
171168

172-
The ``HLSLArrayTemporaryExpr`` represents temporary values for input
173-
constant-sized array arguments. This applies for all constant-sized array
174-
arguments regardless of whether or not the parameter is constant-sized or
175-
unsized.
169+
The new ``ArrayParameterType`` is a non-array type which represents an array
170+
value. It is only applied to constant-sized array ``ParmVarDecl`` nodes. Much
171+
like a ``DecayedType`` it stores both the original ``ConstantArrayType`` and a
172+
decayed ``PointerType``, which is used during code generation.
173+
174+
An argument of ``ConstantArrayType`` can be implicitly converted to an
175+
equivalent non-decayed ``ArrayParameterType`` if the underlying canonical
176+
``ConstantArrayType``s are the same. This occurs during overload resolution
177+
instead of array to pointer decay.
176178
177179
.. code-block:: c++
178180
@@ -193,7 +195,7 @@ In the example above, the following AST is generated for the call to
193195
CallExpr 'void'
194196
|-ImplicitCastExpr 'void (*)(float [4])' <FunctionToPointerDecay>
195197
| `-DeclRefExpr 'void (float [4])' lvalue Function 'SizedArray' 'void (float [4])'
196-
`-HLSLArrayTemporaryExpr 'float [4]'
198+
`-ImplicitCastExpr 'float [4]' <HLSLArrayRValue>
197199
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'
198200
199201
In the example above, the following AST is generated for the call to
@@ -204,7 +206,7 @@ In the example above, the following AST is generated for the call to
204206
CallExpr 'void'
205207
|-ImplicitCastExpr 'void (*)(float [])' <FunctionToPointerDecay>
206208
| `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])'
207-
`-HLSLArrayTemporaryExpr 'float [4]'
209+
`-ImplicitCastExpr 'float [4]' <HLSLArrayRValue>
208210
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'
209211
210212
In both of these cases the argument expression is of known array size so we can
@@ -236,7 +238,7 @@ An expected AST should be something like:
236238
CallExpr 'void'
237239
|-ImplicitCastExpr 'void (*)(float [])' <FunctionToPointerDecay>
238240
| `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])'
239-
`-HLSLArrayTemporaryExpr 'float [4]'
241+
`-ImplicitCastExpr 'float [4]' <HLSLArrayRValue>
240242
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'
241243
242244
Out Parameter Temporaries

clang/include/clang/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
260260
ASTContext&>
261261
SubstTemplateTemplateParmPacks;
262262

263+
mutable llvm::ContextualFoldingSet<ArrayParameterType, ASTContext &>
264+
ArrayParameterTypes;
265+
263266
/// The set of nested name specifiers.
264267
///
265268
/// This set is managed by the NestedNameSpecifier class.
@@ -1367,6 +1370,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
13671370
/// type to the decayed type.
13681371
QualType getDecayedType(QualType Orig, QualType Decayed) const;
13691372

1373+
/// Return the uniqued reference to a specified array parameter type from the
1374+
/// original array type.
1375+
QualType getArrayParameterType(QualType Ty) const;
1376+
13701377
/// Return the uniqued reference to the atomic type for the specified
13711378
/// type.
13721379
QualType getAtomicType(QualType T) const;

clang/include/clang/AST/OperationKinds.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ CAST_OPERATION(IntToOCLSampler)
364364
// Truncate a vector type by dropping elements from the end (HLSL only).
365365
CAST_OPERATION(HLSLVectorTruncation)
366366

367+
// Non-decaying array RValue cast (HLSL only).
368+
CAST_OPERATION(HLSLArrayRValue)
369+
367370
//===- Binary Operations -------------------------------------------------===//
368371
// Operators listed in order of precedence.
369372
// Note that additions to this should also update the StmtVisitor class,

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(ConstantArrayType, {
993993
TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
994994
})
995995

996+
DEF_TRAVERSE_TYPE(ArrayParameterType, {
997+
TRY_TO(TraverseType(T->getElementType()));
998+
if (T->getSizeExpr())
999+
TRY_TO(TraverseStmt(const_cast<Expr *>(T->getSizeExpr())));
1000+
})
1001+
9961002
DEF_TRAVERSE_TYPE(IncompleteArrayType,
9971003
{ TRY_TO(TraverseType(T->getElementType())); })
9981004

@@ -1260,6 +1266,11 @@ DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
12601266
TRY_TO(TraverseArrayTypeLocHelper(TL));
12611267
})
12621268

1269+
DEF_TRAVERSE_TYPELOC(ArrayParameterType, {
1270+
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
1271+
TRY_TO(TraverseArrayTypeLocHelper(TL));
1272+
})
1273+
12631274
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
12641275
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
12651276
TRY_TO(TraverseArrayTypeLocHelper(TL));

clang/include/clang/AST/Type.h

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,6 +2300,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
23002300
bool isConstantArrayType() const;
23012301
bool isIncompleteArrayType() const;
23022302
bool isVariableArrayType() const;
2303+
bool isArrayParameterType() const;
23032304
bool isDependentSizedArrayType() const;
23042305
bool isRecordType() const;
23052306
bool isClassType() const;
@@ -3334,14 +3335,15 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
33343335
return T->getTypeClass() == ConstantArray ||
33353336
T->getTypeClass() == VariableArray ||
33363337
T->getTypeClass() == IncompleteArray ||
3337-
T->getTypeClass() == DependentSizedArray;
3338+
T->getTypeClass() == DependentSizedArray ||
3339+
T->getTypeClass() == ArrayParameter;
33383340
}
33393341
};
33403342

33413343
/// Represents the canonical version of C arrays with a specified constant size.
33423344
/// For example, the canonical type for 'int A[4 + 4*100]' is a
33433345
/// ConstantArrayType where the element type is 'int' and the size is 404.
3344-
class ConstantArrayType final : public ArrayType {
3346+
class ConstantArrayType : public ArrayType {
33453347
friend class ASTContext; // ASTContext creates these.
33463348

33473349
struct ExternalSize {
@@ -3381,6 +3383,18 @@ class ConstantArrayType final : public ArrayType {
33813383
QualType Can, const llvm::APInt &Sz,
33823384
const Expr *SzExpr, ArraySizeModifier SzMod,
33833385
unsigned Qual);
3386+
protected:
3387+
ConstantArrayType(TypeClass Tc, const ConstantArrayType *ATy, QualType Can)
3388+
: ArrayType(Tc, ATy->getElementType(), Can, ATy->getSizeModifier(),
3389+
ATy->getIndexTypeQualifiers().getAsOpaqueValue(), nullptr) {
3390+
ConstantArrayTypeBits.HasExternalSize =
3391+
ATy->ConstantArrayTypeBits.HasExternalSize;
3392+
if (ConstantArrayTypeBits.HasExternalSize) {
3393+
ConstantArrayTypeBits.SizeWidth = ATy->ConstantArrayTypeBits.SizeWidth;
3394+
Size = ATy->Size;
3395+
} else
3396+
SizePtr = ATy->SizePtr;
3397+
}
33843398

33853399
public:
33863400
/// Return the constant array size as an APInt.
@@ -3453,7 +3467,22 @@ class ConstantArrayType final : public ArrayType {
34533467
ArraySizeModifier SizeMod, unsigned TypeQuals);
34543468

34553469
static bool classof(const Type *T) {
3456-
return T->getTypeClass() == ConstantArray;
3470+
return T->getTypeClass() == ConstantArray ||
3471+
T->getTypeClass() == ArrayParameter;
3472+
}
3473+
};
3474+
3475+
/// Represents a constant array type that does not decay to a pointer when used
3476+
/// as a function parameter.
3477+
class ArrayParameterType : public ConstantArrayType {
3478+
friend class ASTContext; // ASTContext creates these.
3479+
3480+
ArrayParameterType(const ConstantArrayType *ATy, QualType CanTy)
3481+
: ConstantArrayType(ArrayParameter, ATy, CanTy) {}
3482+
3483+
public:
3484+
static bool classof(const Type *T) {
3485+
return T->getTypeClass() == ArrayParameter;
34573486
}
34583487
};
34593488

@@ -7185,7 +7214,8 @@ inline bool QualType::isCanonicalAsParam() const {
71857214
if (T->isVariablyModifiedType() && T->hasSizedVLAType())
71867215
return false;
71877216

7188-
return !isa<FunctionType>(T) && !isa<ArrayType>(T);
7217+
return !isa<FunctionType>(T) &&
7218+
(!isa<ArrayType>(T) || isa<ArrayParameterType>(T));
71897219
}
71907220

71917221
inline bool QualType::isConstQualified() const {
@@ -7450,6 +7480,10 @@ inline bool Type::isVariableArrayType() const {
74507480
return isa<VariableArrayType>(CanonicalType);
74517481
}
74527482

7483+
inline bool Type::isArrayParameterType() const {
7484+
return isa<ArrayParameterType>(CanonicalType);
7485+
}
7486+
74537487
inline bool Type::isDependentSizedArrayType() const {
74547488
return isa<DependentSizedArrayType>(CanonicalType);
74557489
}
@@ -7813,7 +7847,7 @@ inline bool Type::isTypedefNameType() const {
78137847

78147848
/// Determines whether this type can decay to a pointer type.
78157849
inline bool Type::canDecayToPointerType() const {
7816-
return isFunctionType() || isArrayType();
7850+
return isFunctionType() || (isArrayType() && !isArrayParameterType());
78177851
}
78187852

78197853
inline bool Type::hasPointerRepresentation() const {

clang/include/clang/AST/TypeLoc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,11 @@ class ConstantArrayTypeLoc :
16111611
ConstantArrayType> {
16121612
};
16131613

1614+
/// Wrapper for source info for array parameter types.
1615+
class ArrayParameterTypeLoc
1616+
: public InheritingConcreteTypeLoc<
1617+
ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {};
1618+
16141619
class IncompleteArrayTypeLoc :
16151620
public InheritingConcreteTypeLoc<ArrayTypeLoc,
16161621
IncompleteArrayTypeLoc,

clang/include/clang/AST/TypeProperties.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ let Class = ConstantArrayType in {
136136
}]>;
137137
}
138138

139+
let Class = ArrayParameterType in {
140+
def : Creator<[{ return ctx.getAdjustedParameterType(
141+
ctx.getConstantArrayType(elementType,sizeValue,
142+
size,sizeModifier,
143+
indexQualifiers.getCVRQualifiers())); }]>;
144+
}
145+
139146
let Class = IncompleteArrayType in {
140147
def : Creator<[{
141148
return ctx.getIncompleteArrayType(elementType, sizeModifier,

clang/include/clang/Basic/TypeNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def ConstantArrayType : TypeNode<ArrayType>;
6464
def IncompleteArrayType : TypeNode<ArrayType>;
6565
def VariableArrayType : TypeNode<ArrayType>;
6666
def DependentSizedArrayType : TypeNode<ArrayType>, AlwaysDependent;
67+
def ArrayParameterType : TypeNode<ConstantArrayType>;
6768
def DependentSizedExtVectorType : TypeNode<Type>, AlwaysDependent;
6869
def DependentAddressSpaceType : TypeNode<Type>, AlwaysDependent;
6970
def VectorType : TypeNode<Type>;

clang/include/clang/Sema/Overload.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ class Sema;
198198
/// HLSL vector truncation.
199199
ICK_HLSL_Vector_Truncation,
200200

201+
/// HLSL non-decaying array rvalue cast.
202+
ICK_HLSL_Array_RValue,
203+
201204
/// The number of conversion kinds
202205
ICK_Num_Conversion_Kinds,
203206
};

clang/include/clang/Serialization/TypeBitCodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,6 @@ TYPE_BIT_CODE(Using, USING, 54)
6666
TYPE_BIT_CODE(BTFTagAttributed, BTFTAG_ATTRIBUTED, 55)
6767
TYPE_BIT_CODE(PackIndexing, PACK_INDEXING, 56)
6868
TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57)
69+
TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58)
6970

7071
#undef TYPE_BIT_CODE

0 commit comments

Comments
 (0)