Skip to content

Commit 8890209

Browse files
authored
[HLSL] Default and Relaxed Availability Diagnostics (#92704)
Implements HLSL availability diagnostics' default and relaxed mode. HLSL availability diagnostics emits errors or warning when unavailable shader APIs are used. Unavailable shader APIs are APIs that are exposed in HLSL code but are not available in the target shader stage or shader model version. In the default mode the compiler emits an error when an unavailable API is found in a code that is reachable from the shader entry point function. In the future this check will also extended to exported library functions (#92073). The relaxed diagnostic mode is the same except the compiler emits a warning. This mode is enabled by ``-Wno-error=hlsl-availability``. See HLSL Availability Diagnostics design doc [here](https://github.com/llvm/llvm-project/blob/main/clang/docs/HLSL/AvailabilityDiagnostics.rst) for more details. Fixes #90095
1 parent 02c6845 commit 8890209

17 files changed

+941
-51
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,18 +1060,10 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
10601060
.Case("ShaderModel", "shadermodel")
10611061
.Default(Platform);
10621062
}
1063-
static llvm::StringRef getPrettyEnviromentName(llvm::StringRef Environment) {
1064-
return llvm::StringSwitch<llvm::StringRef>(Environment)
1065-
.Case("pixel", "pixel shader")
1066-
.Case("vertex", "vertex shader")
1067-
.Case("geometry", "geometry shader")
1068-
.Case("hull", "hull shader")
1069-
.Case("domain", "domain shader")
1070-
.Case("compute", "compute shader")
1071-
.Case("mesh", "mesh shader")
1072-
.Case("amplification", "amplification shader")
1073-
.Case("library", "shader library")
1074-
.Default(Environment);
1063+
static llvm::StringRef getPrettyEnviromentName(llvm::Triple::EnvironmentType EnvironmentType) {
1064+
if (EnvironmentType >= llvm::Triple::Pixel && EnvironmentType <= llvm::Triple::Amplification)
1065+
return llvm::Triple::getEnvironmentTypeName(EnvironmentType);
1066+
return "";
10751067
}
10761068
static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environment) {
10771069
return llvm::StringSwitch<llvm::Triple::EnvironmentType>(Environment)
@@ -1081,6 +1073,12 @@ static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environm
10811073
.Case("hull", llvm::Triple::Hull)
10821074
.Case("domain", llvm::Triple::Domain)
10831075
.Case("compute", llvm::Triple::Compute)
1076+
.Case("raygeneration", llvm::Triple::RayGeneration)
1077+
.Case("intersection", llvm::Triple::Intersection)
1078+
.Case("anyhit", llvm::Triple::AnyHit)
1079+
.Case("closesthit", llvm::Triple::ClosestHit)
1080+
.Case("miss", llvm::Triple::Miss)
1081+
.Case("callable", llvm::Triple::Callable)
10841082
.Case("mesh", llvm::Triple::Mesh)
10851083
.Case("amplification", llvm::Triple::Amplification)
10861084
.Case("library", llvm::Triple::Library)
@@ -4480,6 +4478,29 @@ def HLSLShader : InheritableAttr {
44804478
"Miss", "Callable", "Mesh", "Amplification"]>
44814479
];
44824480
let Documentation = [HLSLSV_ShaderTypeAttrDocs];
4481+
let AdditionalMembers =
4482+
[{
4483+
static const unsigned ShaderTypeMaxValue = (unsigned)HLSLShaderAttr::Amplification;
4484+
4485+
static llvm::Triple::EnvironmentType getTypeAsEnvironment(HLSLShaderAttr::ShaderType ShaderType) {
4486+
switch (ShaderType) {
4487+
case HLSLShaderAttr::Pixel: return llvm::Triple::Pixel;
4488+
case HLSLShaderAttr::Vertex: return llvm::Triple::Vertex;
4489+
case HLSLShaderAttr::Geometry: return llvm::Triple::Geometry;
4490+
case HLSLShaderAttr::Hull: return llvm::Triple::Hull;
4491+
case HLSLShaderAttr::Domain: return llvm::Triple::Domain;
4492+
case HLSLShaderAttr::Compute: return llvm::Triple::Compute;
4493+
case HLSLShaderAttr::RayGeneration: return llvm::Triple::RayGeneration;
4494+
case HLSLShaderAttr::Intersection: return llvm::Triple::Intersection;
4495+
case HLSLShaderAttr::AnyHit: return llvm::Triple::AnyHit;
4496+
case HLSLShaderAttr::ClosestHit: return llvm::Triple::ClosestHit;
4497+
case HLSLShaderAttr::Miss: return llvm::Triple::Miss;
4498+
case HLSLShaderAttr::Callable: return llvm::Triple::Callable;
4499+
case HLSLShaderAttr::Mesh: return llvm::Triple::Mesh;
4500+
case HLSLShaderAttr::Amplification: return llvm::Triple::Amplification;
4501+
}
4502+
}
4503+
}];
44834504
}
44844505

44854506
def HLSLResource : InheritableAttr {

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,9 @@ def HLSLMixPackOffset : DiagGroup<"mix-packoffset">;
15171517
// Warnings for DXIL validation
15181518
def DXILValidation : DiagGroup<"dxil-validation">;
15191519

1520+
// Warning for HLSL API availability
1521+
def HLSLAvailability : DiagGroup<"hlsl-availability">;
1522+
15201523
// Warnings and notes related to const_var_decl_type attribute checks
15211524
def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">;
15221525

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12239,6 +12239,13 @@ def err_hlsl_param_qualifier_mismatch :
1223912239
def warn_hlsl_impcast_vector_truncation : Warning<
1224012240
"implicit conversion truncates vector: %0 to %1">, InGroup<Conversion>;
1224112241

12242+
def warn_hlsl_availability : Warning<
12243+
"%0 is only available %select{|in %4 environment }3on %1 %2 or newer">,
12244+
InGroup<HLSLAvailability>, DefaultError;
12245+
def warn_hlsl_availability_unavailable :
12246+
Warning<err_unavailable.Summary>,
12247+
InGroup<HLSLAvailability>, DefaultError;
12248+
1224212249
// Layout randomization diagnostics.
1224312250
def err_non_designated_init_used : Error<
1224412251
"a randomized struct can only be initialized with a designated initializer">;

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class SemaHLSL : public SemaBase {
4949
void DiagnoseAttrStageMismatch(
5050
const Attr *A, HLSLShaderAttr::ShaderType Stage,
5151
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
52+
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
5253
};
5354

5455
} // namespace clang

clang/lib/AST/DeclBase.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,8 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
669669
IdentifierInfo *IIEnv = A->getEnvironment();
670670
StringRef TargetEnv =
671671
Context.getTargetInfo().getTriple().getEnvironmentName();
672-
StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(TargetEnv);
672+
StringRef EnvName = AvailabilityAttr::getPrettyEnviromentName(
673+
Context.getTargetInfo().getTriple().getEnvironment());
673674
// Matching environment or no environment on attribute
674675
if (!IIEnv || (!TargetEnv.empty() && IIEnv->getName() == TargetEnv)) {
675676
if (Message) {

clang/lib/Sema/Sema.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,10 @@ void Sema::ActOnEndOfTranslationUnit() {
13571357
Consumer.CompleteExternalDeclaration(D);
13581358
}
13591359

1360+
if (LangOpts.HLSL)
1361+
HLSL().DiagnoseAvailabilityViolations(
1362+
getASTContext().getTranslationUnitDecl());
1363+
13601364
// If there were errors, disable 'unused' warnings since they will mostly be
13611365
// noise. Don't warn for a use from a module: either we should warn on all
13621366
// file-scope declarations in modules or not at all, but whether the

clang/lib/Sema/SemaAvailability.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/AST/RecursiveASTVisitor.h"
1616
#include "clang/Basic/DiagnosticSema.h"
1717
#include "clang/Basic/IdentifierTable.h"
18+
#include "clang/Basic/LangOptions.h"
1819
#include "clang/Basic/TargetInfo.h"
1920
#include "clang/Lex/Preprocessor.h"
2021
#include "clang/Sema/DelayedDiagnostic.h"
@@ -228,8 +229,9 @@ shouldDiagnoseAvailabilityByDefault(const ASTContext &Context,
228229
ForceAvailabilityFromVersion = VersionTuple(/*Major=*/10, /*Minor=*/13);
229230
break;
230231
case llvm::Triple::ShaderModel:
231-
// Always enable availability diagnostics for shader models.
232-
return true;
232+
// FIXME: This will be updated when HLSL strict diagnostic mode
233+
// is implemented (issue #90096)
234+
return false;
233235
default:
234236
// New targets should always warn about availability.
235237
return Triple.getVendor() == llvm::Triple::Apple;
@@ -409,10 +411,11 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
409411
std::string PlatformName(
410412
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
411413
llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
412-
TI.getTriple().getEnvironmentName()));
414+
TI.getTriple().getEnvironment()));
413415
llvm::StringRef AttrEnvironment =
414416
AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName(
415-
AA->getEnvironment()->getName())
417+
AvailabilityAttr::getEnvironmentType(
418+
AA->getEnvironment()->getName()))
416419
: "";
417420
bool UseEnvironment =
418421
(!AttrEnvironment.empty() && !TargetEnvironment.empty());
@@ -438,6 +441,10 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
438441
<< S.Context.getTargetInfo().getPlatformMinVersion().getAsString()
439442
<< UseEnvironment << AttrEnvironment << TargetEnvironment;
440443

444+
// Do not offer to silence the warning or fixits for HLSL
445+
if (S.getLangOpts().HLSL)
446+
return;
447+
441448
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
442449
if (const auto *TD = dyn_cast<TagDecl>(Enclosing))
443450
if (TD->getDeclName().isEmpty()) {
@@ -839,10 +846,11 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
839846
std::string PlatformName(
840847
AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));
841848
llvm::StringRef TargetEnvironment(AvailabilityAttr::getPrettyEnviromentName(
842-
TI.getTriple().getEnvironmentName()));
849+
TI.getTriple().getEnvironment()));
843850
llvm::StringRef AttrEnvironment =
844851
AA->getEnvironment() ? AvailabilityAttr::getPrettyEnviromentName(
845-
AA->getEnvironment()->getName())
852+
AvailabilityAttr::getEnvironmentType(
853+
AA->getEnvironment()->getName()))
846854
: "";
847855
bool UseEnvironment =
848856
(!AttrEnvironment.empty() && !TargetEnvironment.empty());
@@ -865,6 +873,10 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
865873
<< SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()
866874
<< UseEnvironment << AttrEnvironment << TargetEnvironment;
867875

876+
// Do not offer to silence the warning or fixits for HLSL
877+
if (SemaRef.getLangOpts().HLSL)
878+
return;
879+
868880
auto FixitDiag =
869881
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
870882
<< Range << D

0 commit comments

Comments
 (0)