Skip to content

[HLSL] Implement array temporary support #79382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions clang/docs/HLSL/FunctionCalls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,23 @@ Clang Implementation
of the changes in the prototype implementation are restoring Clang-3.7 code
that was previously modified to its original state.

The implementation in clang depends on two new AST nodes and minor extensions to
Clang's existing support for Objective-C write-back arguments. The goal of this
design is to capture the semantic details of HLSL function calls in the AST, and
minimize the amount of magic that needs to occur during IR generation.

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

Array Temporaries
-----------------

The ``HLSLArrayTemporaryExpr`` represents temporary values for input
constant-sized array arguments. This applies for all constant-sized array
arguments regardless of whether or not the parameter is constant-sized or
unsized.
The new ``ArrayParameterType`` is a sub-class of ``ConstantArrayType``
inheriting all the behaviors and methods of the parent except that it does not
decay to a pointer during overload resolution or template type deduction.

An argument of ``ConstantArrayType`` can be implicitly converted to an
equivalent non-decayed ``ArrayParameterType`` if the underlying canonical
``ConstantArrayType`` is the same. This occurs during overload resolution
instead of array to pointer decay.

.. code-block:: c++

Expand All @@ -193,7 +194,7 @@ In the example above, the following AST is generated for the call to
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(float [4])' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (float [4])' lvalue Function 'SizedArray' 'void (float [4])'
`-HLSLArrayTemporaryExpr 'float [4]'
`-ImplicitCastExpr 'float [4]' <HLSLArrayRValue>
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'

In the example above, the following AST is generated for the call to
Expand All @@ -204,7 +205,7 @@ In the example above, the following AST is generated for the call to
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(float [])' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])'
`-HLSLArrayTemporaryExpr 'float [4]'
`-ImplicitCastExpr 'float [4]' <HLSLArrayRValue>
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'

In both of these cases the argument expression is of known array size so we can
Expand Down Expand Up @@ -236,7 +237,7 @@ An expected AST should be something like:
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(float [])' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])'
`-HLSLArrayTemporaryExpr 'float [4]'
`-ImplicitCastExpr 'float [4]' <HLSLArrayRValue>
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'

Out Parameter Temporaries
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
ASTContext&>
SubstTemplateTemplateParmPacks;

mutable llvm::ContextualFoldingSet<ArrayParameterType, ASTContext &>
ArrayParameterTypes;

/// The set of nested name specifiers.
///
/// This set is managed by the NestedNameSpecifier class.
Expand Down Expand Up @@ -1367,6 +1370,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// type to the decayed type.
QualType getDecayedType(QualType Orig, QualType Decayed) const;

/// Return the uniqued reference to a specified array parameter type from the
/// original array type.
QualType getArrayParameterType(QualType Ty) const;

/// Return the uniqued reference to the atomic type for the specified
/// type.
QualType getAtomicType(QualType T) const;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/OperationKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ CAST_OPERATION(IntToOCLSampler)
// Truncate a vector type by dropping elements from the end (HLSL only).
CAST_OPERATION(HLSLVectorTruncation)

// Non-decaying array RValue cast (HLSL only).
CAST_OPERATION(HLSLArrayRValue)

//===- Binary Operations -------------------------------------------------===//
// Operators listed in order of precedence.
// Note that additions to this should also update the StmtVisitor class,
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(ConstantArrayType, {
TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
})

DEF_TRAVERSE_TYPE(ArrayParameterType, {
TRY_TO(TraverseType(T->getElementType()));
if (T->getSizeExpr())
TRY_TO(TraverseStmt(const_cast<Expr *>(T->getSizeExpr())));
})

DEF_TRAVERSE_TYPE(IncompleteArrayType,
{ TRY_TO(TraverseType(T->getElementType())); })

Expand Down Expand Up @@ -1260,6 +1266,11 @@ DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
TRY_TO(TraverseArrayTypeLocHelper(TL));
})

DEF_TRAVERSE_TYPELOC(ArrayParameterType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
TRY_TO(TraverseArrayTypeLocHelper(TL));
})

DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
TRY_TO(TraverseArrayTypeLocHelper(TL));
Expand Down
45 changes: 40 additions & 5 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2300,6 +2300,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isConstantArrayType() const;
bool isIncompleteArrayType() const;
bool isVariableArrayType() const;
bool isArrayParameterType() const;
bool isDependentSizedArrayType() const;
bool isRecordType() const;
bool isClassType() const;
Expand Down Expand Up @@ -3334,14 +3335,15 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
return T->getTypeClass() == ConstantArray ||
T->getTypeClass() == VariableArray ||
T->getTypeClass() == IncompleteArray ||
T->getTypeClass() == DependentSizedArray;
T->getTypeClass() == DependentSizedArray ||
T->getTypeClass() == ArrayParameter;
}
};

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

struct ExternalSize {
Expand Down Expand Up @@ -3382,6 +3384,19 @@ class ConstantArrayType final : public ArrayType {
const Expr *SzExpr, ArraySizeModifier SzMod,
unsigned Qual);

protected:
ConstantArrayType(TypeClass Tc, const ConstantArrayType *ATy, QualType Can)
: ArrayType(Tc, ATy->getElementType(), Can, ATy->getSizeModifier(),
ATy->getIndexTypeQualifiers().getAsOpaqueValue(), nullptr) {
ConstantArrayTypeBits.HasExternalSize =
ATy->ConstantArrayTypeBits.HasExternalSize;
if (!ConstantArrayTypeBits.HasExternalSize) {
ConstantArrayTypeBits.SizeWidth = ATy->ConstantArrayTypeBits.SizeWidth;
Size = ATy->Size;
} else
SizePtr = ATy->SizePtr;
}

public:
/// Return the constant array size as an APInt.
llvm::APInt getSize() const {
Expand Down Expand Up @@ -3453,7 +3468,22 @@ class ConstantArrayType final : public ArrayType {
ArraySizeModifier SizeMod, unsigned TypeQuals);

static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray;
return T->getTypeClass() == ConstantArray ||
T->getTypeClass() == ArrayParameter;
}
};

/// Represents a constant array type that does not decay to a pointer when used
/// as a function parameter.
class ArrayParameterType : public ConstantArrayType {
friend class ASTContext; // ASTContext creates these.

ArrayParameterType(const ConstantArrayType *ATy, QualType CanTy)
: ConstantArrayType(ArrayParameter, ATy, CanTy) {}

public:
static bool classof(const Type *T) {
return T->getTypeClass() == ArrayParameter;
}
};

Expand Down Expand Up @@ -7185,7 +7215,8 @@ inline bool QualType::isCanonicalAsParam() const {
if (T->isVariablyModifiedType() && T->hasSizedVLAType())
return false;

return !isa<FunctionType>(T) && !isa<ArrayType>(T);
return !isa<FunctionType>(T) &&
(!isa<ArrayType>(T) || isa<ArrayParameterType>(T));
}

inline bool QualType::isConstQualified() const {
Expand Down Expand Up @@ -7450,6 +7481,10 @@ inline bool Type::isVariableArrayType() const {
return isa<VariableArrayType>(CanonicalType);
}

inline bool Type::isArrayParameterType() const {
return isa<ArrayParameterType>(CanonicalType);
}

inline bool Type::isDependentSizedArrayType() const {
return isa<DependentSizedArrayType>(CanonicalType);
}
Expand Down Expand Up @@ -7813,7 +7848,7 @@ inline bool Type::isTypedefNameType() const {

/// Determines whether this type can decay to a pointer type.
inline bool Type::canDecayToPointerType() const {
return isFunctionType() || isArrayType();
return isFunctionType() || (isArrayType() && !isArrayParameterType());
}

inline bool Type::hasPointerRepresentation() const {
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/TypeLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,11 @@ class ConstantArrayTypeLoc :
ConstantArrayType> {
};

/// Wrapper for source info for array parameter types.
class ArrayParameterTypeLoc
: public InheritingConcreteTypeLoc<
ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {};

class IncompleteArrayTypeLoc :
public InheritingConcreteTypeLoc<ArrayTypeLoc,
IncompleteArrayTypeLoc,
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ let Class = ConstantArrayType in {
}]>;
}

let Class = ArrayParameterType in {
def : Creator<[{ return ctx.getAdjustedParameterType(
ctx.getConstantArrayType(elementType,sizeValue,
size,sizeModifier,
indexQualifiers.getCVRQualifiers())); }]>;
}

let Class = IncompleteArrayType in {
def : Creator<[{
return ctx.getIncompleteArrayType(elementType, sizeModifier,
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TypeNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def ConstantArrayType : TypeNode<ArrayType>;
def IncompleteArrayType : TypeNode<ArrayType>;
def VariableArrayType : TypeNode<ArrayType>;
def DependentSizedArrayType : TypeNode<ArrayType>, AlwaysDependent;
def ArrayParameterType : TypeNode<ConstantArrayType>;
def DependentSizedExtVectorType : TypeNode<Type>, AlwaysDependent;
def DependentAddressSpaceType : TypeNode<Type>, AlwaysDependent;
def VectorType : TypeNode<Type>;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/Overload.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ class Sema;
/// HLSL vector truncation.
ICK_HLSL_Vector_Truncation,

/// HLSL non-decaying array rvalue cast.
ICK_HLSL_Array_RValue,

/// The number of conversion kinds
ICK_Num_Conversion_Kinds,
};
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Serialization/TypeBitCodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@ TYPE_BIT_CODE(Using, USING, 54)
TYPE_BIT_CODE(BTFTagAttributed, BTFTAG_ATTRIBUTED, 55)
TYPE_BIT_CODE(PackIndexing, PACK_INDEXING, 56)
TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57)
TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58)

#undef TYPE_BIT_CODE
Loading