forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[HLSL] Add __builtin_hlsl_is_scalarized_layout_compatible (llvm#102227)
HLSL tends to rely pretty aggressively on scalarization occuring in the complier, which allows for some relaxed language behaviors when types are fully sclarized to equivalent scalar representations. This change adds a new queryable trait builtin for scalarized layout compatability. Resolves llvm#100614 --------- Co-authored-by: Aaron Ballman <[email protected]>
- Loading branch information
Showing
6 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
clang/test/SemaHLSL/Types/Traits/ScalarizedLayoutCompatible.hlsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s | ||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s | ||
// expected-no-diagnostics | ||
|
||
// Case 1: How many ways can I come up with to represent three float values? | ||
struct ThreeFloats1 { | ||
float X, Y, Z; | ||
}; | ||
|
||
struct ThreeFloats2 { | ||
float X[3]; | ||
}; | ||
|
||
struct ThreeFloats3 { | ||
float3 V; | ||
}; | ||
|
||
struct ThreeFloats4 { | ||
float2 V; | ||
float F; | ||
}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(float3, float[3]), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(float3, ThreeFloats1), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(float3, ThreeFloats2), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(float3, ThreeFloats3), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(float3, ThreeFloats4), ""); | ||
|
||
// Case 2: structs and base classes and arrays, oh my! | ||
struct Dog { | ||
int Leg[4]; | ||
bool Tail; | ||
float Fur; | ||
}; | ||
|
||
struct Shiba { | ||
int4 StubbyLegs; | ||
bool CurlyTail; | ||
struct Coating { | ||
float Fur; | ||
} F; | ||
}; | ||
|
||
struct FourLegged { | ||
int FR, FL, BR, BL; | ||
}; | ||
|
||
struct Doggo : FourLegged { | ||
bool WaggyBit; | ||
float Fuzz; | ||
}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Dog, Shiba), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Dog, Doggo), ""); | ||
|
||
// Case 3: Arrays of structs inside structs | ||
|
||
struct Cat { | ||
struct Leg { | ||
int L; | ||
} Legs[4]; | ||
struct Other { | ||
bool Tail; | ||
float Furs; | ||
} Bits; | ||
}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Dog, Cat), ""); | ||
|
||
// case 4: Arrays of structs inside arrays of structs. | ||
struct Pets { | ||
Dog Puppers[6]; | ||
Cat Kitties[4]; | ||
}; | ||
|
||
struct Animals { | ||
Dog Puppers[2]; | ||
Cat Kitties[8]; | ||
}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Pets, Animals), ""); | ||
|
||
// Case 5: Turtles all the way down... | ||
|
||
typedef int Turtle; | ||
|
||
enum Ninja : Turtle { | ||
Leonardo, | ||
Donatello, | ||
Michelangelo, | ||
Raphael, | ||
}; | ||
|
||
enum NotNinja : Turtle { | ||
Fred, | ||
Mikey, | ||
}; | ||
|
||
enum Mammals : uint { | ||
Dog, | ||
Cat, | ||
}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Ninja, NotNinja), ""); | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(Ninja, Mammals), ""); | ||
|
||
// Case 6: Some basic types. | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(int, int32_t), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(uint, uint32_t), ""); | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(int, uint), ""); | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(int, float), ""); | ||
|
||
// Even though half and float may be the same size we don't want them to be | ||
// layout compatible since they are different types. | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(half, float), ""); | ||
|
||
// Case 6: Empty classes... because they're fun. | ||
|
||
struct NotEmpty { int X; }; | ||
struct Empty {}; | ||
struct AlsoEmpty {}; | ||
|
||
struct DerivedEmpty : Empty {}; | ||
|
||
struct DerivedNotEmpty : Empty { int X; }; | ||
struct DerivedEmptyNotEmptyBase : NotEmpty {}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Empty, AlsoEmpty), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Empty, DerivedEmpty), ""); | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(NotEmpty, DerivedNotEmpty), ""); | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(NotEmpty, DerivedEmptyNotEmptyBase), ""); |
64 changes: 64 additions & 0 deletions
64
clang/test/SemaHLSL/Types/Traits/ScalarizedLayoutCompatibleErrors.hlsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s | ||
|
||
// Some things that don't work! | ||
|
||
// Case 1: Both types must be complete! | ||
struct Defined { | ||
int X; | ||
}; | ||
|
||
|
||
struct Undefined; // expected-note {{forward declaration of 'Undefined'}} | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Undefined, Defined), ""); // expected-error{{incomplete type 'Undefined' where a complete type is required}} | ||
|
||
// Case 2: No variable length arrays! | ||
|
||
void fn(int X) { | ||
// expected-error@#vla {{variable length arrays are not supported for the current target}} | ||
// expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_scalarized_layout_compatible'}} | ||
// expected-error@#vla {{static assertion failed due to requirement '__builtin_hlsl_is_scalarized_layout_compatible(int[4], int[X])'}} | ||
// expected-warning@#vla {{variable length arrays in C++ are a Clang extension}} | ||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(int[4], int[X]), ""); // #vla | ||
} | ||
|
||
// Case 3: Make this always fail for unions. | ||
// HLSL doesn't really support unions, and the places where scalarized layouts | ||
// are valid is probably going to be really confusing for unions, so we should | ||
// just make sure unions are never scalarized compatible with anything other | ||
// than themselves. | ||
|
||
union Wah { | ||
int OhNo; | ||
float NotAgain; | ||
}; | ||
|
||
struct OneInt { | ||
int I; | ||
}; | ||
|
||
struct OneFloat { | ||
float F; | ||
}; | ||
|
||
struct HasUnion { | ||
int I; | ||
Wah W; | ||
}; | ||
|
||
struct HasUnionSame { | ||
int I; | ||
Wah W; | ||
}; | ||
|
||
struct HasUnionDifferent { | ||
Wah W; | ||
int I; | ||
}; | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(Wah, Wah), "Identical types are always compatible"); | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(Wah, OneInt), "Unions are not compatible with anything else"); | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(Wah, OneFloat), "Unions are not compatible with anything else"); | ||
|
||
_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(HasUnion, HasUnionSame), ""); | ||
_Static_assert(!__builtin_hlsl_is_scalarized_layout_compatible(HasUnion, HasUnionDifferent), ""); |