Skip to content
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

[Sema] Not report error when invalid intrinsic call is not used. #6140

Merged
merged 18 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions include/dxc/DXIL/DxilShaderModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class ShaderModel {
}
bool IsSM50Plus() const { return IsSMAtLeast(5, 0); }
bool IsSM51Plus() const { return IsSMAtLeast(5, 1); }
bool AllowDerivatives(DXIL::ShaderKind sk) const;
// clang-format off
// Python lines need to be not formatted.
/* <py::lines('VALRULE-TEXT')>hctdb_instrhelp.get_is_shader_model_plus()</py>*/
Expand Down
14 changes: 14 additions & 0 deletions lib/DXIL/DxilShaderModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,20 @@ const llvm::StringRef ShaderModel::FullNameFromKind(DXIL::ShaderKind sk) {
}
}

bool ShaderModel::AllowDerivatives(DXIL::ShaderKind sk) const {
switch (sk) {
case DXIL::ShaderKind::Pixel:
case DXIL::ShaderKind::Library:
case DXIL::ShaderKind::Node:
return true;
case DXIL::ShaderKind::Compute:
case DXIL::ShaderKind::Amplification:
case DXIL::ShaderKind::Mesh:
return IsSM66Plus();
}
return false;
}

typedef ShaderModel SM;
typedef Semantic SE;
const ShaderModel ShaderModel::ms_ShaderModels[kNumShaderModels] = {
Expand Down
1 change: 1 addition & 0 deletions tools/clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -800,4 +800,5 @@ def HLSLPayloadAccessQualifer: DiagGroup<"payload-access-qualifier", [
def HLSLSemanticIdentifierCollision : DiagGroup<"semantic-identifier-collision">;
def HLSLStructurizeExitsLifetimeMarkersConflict: DiagGroup<"structurize-exits-lifetime-markers-conflict">;
def HLSLParameterUsage : DiagGroup<"parameter-usage">;
def HLSLIntrinsicCall : DiagGroup<"intrinsic-call">;
// HLSL Change Ends
8 changes: 6 additions & 2 deletions tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7771,8 +7771,12 @@ def err_hlsl_unsupported_for_version_lower : Error<
"%0 is only allowed for HLSL %1 and lower.">;
def err_hlsl_unsupported_keyword_for_min_precision : Error<
"%0 is only supported with -enable-16bit-types option">;
def err_hlsl_intrinsic_overload_in_wrong_shader_model : Error<
"overload of intrinsic %0 requires shader model %1 or greater">;
def warn_hlsl_derivatives_intrinsic_in_wrong_shader_kind : Warning<
"Derivatives intrinsic %0 only works in ps and cs_6.6+/as_6.6+/ms_6.6+/node">,
DefaultError, InGroup<HLSLIntrinsicCall>;
def warn_hlsl_intrinsic_overload_in_wrong_shader_model : Warning<
"overload of intrinsic %0 requires shader model %1 or greater">,
DefaultError, InGroup<HLSLIntrinsicCall>;
def err_hlsl_intrinsic_template_arg_unsupported: Error<
"Explicit template arguments on intrinsic %0 are not supported">;
def err_hlsl_intrinsic_template_arg_requires_2018: Error<
Expand Down
4 changes: 4 additions & 0 deletions tools/clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

namespace hlsl {
struct UnusualAnnotation;
class ShaderModel;
}
// HLSL Change Ends

Expand Down Expand Up @@ -3807,6 +3808,9 @@ class Sema {
QualType TargetType,
SourceLocation Loc);
bool DiagnoseHLSLMethodCall(const CXXMethodDecl *MD, SourceLocation Loc);
void DiagnoseUsedHLSLMethodCall(const CXXMethodDecl *MD, SourceLocation Loc,
const hlsl::ShaderModel *SM,
hlsl::DXIL::ShaderKind EntrySK);
// HLSL Change Ends

bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
Expand Down
39 changes: 28 additions & 11 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11119,10 +11119,10 @@ void hlsl::DiagnoseRegisterType(clang::Sema *self, clang::SourceLocation loc,
// Check HLSL member call constraints
bool Sema::DiagnoseHLSLMethodCall(const CXXMethodDecl *MD, SourceLocation Loc) {
if (MD->hasAttr<HLSLIntrinsicAttr>()) {
// If this is a call to FinishedCrossGroupSharing then the Input record
// must have the NodeTrackRWInputSharing attribute
hlsl::IntrinsicOp opCode =
(IntrinsicOp)MD->getAttr<HLSLIntrinsicAttr>()->getOpcode();
// If this is a call to FinishedCrossGroupSharing then the Input record
// must have the NodeTrackRWInputSharing attribute
if (opCode == hlsl::IntrinsicOp::MOP_FinishedCrossGroupSharing) {
const CXXRecordDecl *NodeRecDecl = MD->getParent();
// Node I/O records are templateTypes
Expand All @@ -11138,25 +11138,42 @@ bool Sema::DiagnoseHLSLMethodCall(const CXXMethodDecl *MD, SourceLocation Loc) {
Diags.Report(Loc, diag::err_hlsl_wg_nodetrackrwinputsharing_missing);
return true;
}
} else if (opCode == hlsl::IntrinsicOp::MOP_CalculateLevelOfDetail ||
opCode ==
hlsl::IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped) {
const auto *shaderModel =
hlsl::ShaderModel::GetByName(getLangOpts().HLSLProfile.c_str());
if (!shaderModel->IsSM68Plus()) {
}
}
return false;
}

// Check HLSL member call constraints for used functions.
void Sema::DiagnoseUsedHLSLMethodCall(const CXXMethodDecl *MD,
SourceLocation Loc,
const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK) {
if (MD->hasAttr<HLSLIntrinsicAttr>()) {
hlsl::IntrinsicOp opCode =
(IntrinsicOp)MD->getAttr<HLSLIntrinsicAttr>()->getOpcode();
switch (opCode) {
case hlsl::IntrinsicOp::MOP_CalculateLevelOfDetail:
case hlsl::IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped: {
if (!SM->IsSM68Plus()) {
QualType SamplerComparisonTy =
HLSLExternalSource::FromSema(this)->GetBasicKindType(
AR_OBJECT_SAMPLERCOMPARISON);
if (MD->getParamDecl(0)->getType() == SamplerComparisonTy) {
Diags.Report(Loc,
diag::err_hlsl_intrinsic_overload_in_wrong_shader_model)
diag::warn_hlsl_intrinsic_overload_in_wrong_shader_model)
<< MD->getNameAsString() << "6.8";
return true;
}
}
if (!SM->AllowDerivatives(EntrySK)) {
Diags.Report(Loc,
diag::warn_hlsl_derivatives_intrinsic_in_wrong_shader_kind)
<< MD->getNameAsString();
}
} break;
default:
break;
}
}
return false;
}

bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc,
Expand Down
45 changes: 44 additions & 1 deletion tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@
///////////////////////////////////////////////////////////////////////////////

#include "dxc/DXIL/DxilShaderModel.h"
#include "dxc/HlslIntrinsicOp.h"
#include "dxc/Support/Global.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/SemaHLSL.h"
#include "llvm/Support/Debug.h"

using namespace clang;
using namespace llvm;
using namespace hlsl;

//
Expand Down Expand Up @@ -175,6 +179,8 @@ class CallGraphWithRecurseGuard {

const CallNodes &GetCallGraph() { return m_callNodes; }

const FunctionSet GetVisitedFunctions() { return m_visitedFunctions; }

void dump() const {
llvm::dbgs() << "Call Nodes:\n";
for (auto &node : m_callNodes) {
Expand Down Expand Up @@ -295,6 +301,25 @@ clang::FunctionDecl *ValidateNoRecursion(CallGraphWithRecurseGuard &callGraph,
return nullptr;
}

class HLSLMethodCallDiagnoseVisitor
: public RecursiveASTVisitor<HLSLMethodCallDiagnoseVisitor> {
public:
explicit HLSLMethodCallDiagnoseVisitor(Sema *S, const hlsl::ShaderModel *SM,
DXIL::ShaderKind EntrySK)
: sema(S), SM(SM), EntrySK(EntrySK) {}

bool VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
sema->DiagnoseUsedHLSLMethodCall(CE->getMethodDecl(), CE->getExprLoc(), SM,
EntrySK);
return true;
}

private:
clang::Sema *sema;
const hlsl::ShaderModel *SM;
DXIL::ShaderKind EntrySK;
};

} // namespace

void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
Expand Down Expand Up @@ -354,10 +379,14 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
}
}

CallGraphWithRecurseGuard callGraph;
const auto *shaderModel =
hlsl::ShaderModel::GetByName(self->getLangOpts().HLSLProfile.c_str());
DXIL::ShaderKind shaderKind = shaderModel->GetKind();

std::set<FunctionDecl *> DiagnosedDecls;
// for each FDecl, check for recursion
for (FunctionDecl *FDecl : FDeclsToCheck) {
CallGraphWithRecurseGuard callGraph;
FunctionDecl *result = ValidateNoRecursion(callGraph, FDecl);

if (result) {
Expand Down Expand Up @@ -422,5 +451,19 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
}
}
}

DXIL::ShaderKind EntrySK = shaderKind;
if (EntrySK == DXIL::ShaderKind::Library) {
// For library, check if the exported function is entry with shader
// attribute.
if (const auto *Attr = FDecl->getAttr<clang::HLSLShaderAttr>())
EntrySK = ShaderModel::KindFromFullName(Attr->getStage());
}
// Visit all visited functions in call graph to collect illegal intrinsic
// calls.
for (FunctionDecl *FD : callGraph.GetVisitedFunctions()) {
HLSLMethodCallDiagnoseVisitor Visitor(self, shaderModel, EntrySK);
Visitor.TraverseDecl(FD);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// RUN: %dxc -DSTAGE=1 -T cs_6_6 %s | FileCheck %s
// RUN: %dxc -DSTAGE=2 -T as_6_6 %s | FileCheck %s -check-prefixes=CHECK,ASMSCHECK
// RUN: %dxc -DSTAGE=3 -T ms_6_6 %s | FileCheck %s -check-prefixes=CHECK,ASMSCHECK
// RUN: %dxilver 1.6 | %dxc -DSTAGE=1 -T cs_6_5 %s | FileCheck %s -check-prefix=ERRCHECK
// RUN: %dxilver 1.6 | %dxc -DSTAGE=2 -T as_6_5 %s | FileCheck %s -check-prefix=ERRCHECK
// RUN: %dxilver 1.6 | %dxc -DSTAGE=3 -T ms_6_5 %s | FileCheck %s -check-prefix=ERRCHECK
// RUN: %dxilver 1.6 | %dxc -DSTAGE=1 -T cs_6_5 -Wno-intrinsic-call %s | FileCheck %s -check-prefix=ERRCHECK
// RUN: %dxilver 1.6 | %dxc -DSTAGE=2 -T as_6_5 -Wno-intrinsic-call %s | FileCheck %s -check-prefix=ERRCHECK
// RUN: %dxilver 1.6 | %dxc -DSTAGE=3 -T ms_6_5 -Wno-intrinsic-call %s | FileCheck %s -check-prefix=ERRCHECK

#define CS 1
#define AS 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,42 @@
SamplerComparisonState s;
Texture1D t;

// Make sure direct call to CalculateLevelOfDetail and CalculateLevelOfDetailUnclamped get error.
export
float foo(float a) {
return t.CalculateLevelOfDetail(s, a) + // expected-error {{overload of intrinsic CalculateLevelOfDetail requires shader model 6.8 or greater}}
t.CalculateLevelOfDetailUnclamped(s, a); // expected-error {{overload of intrinsic CalculateLevelOfDetailUnclamped requires shader model 6.8 or greater}}
}

// Make sure unused function call to CalculateLevelOfDetail and CalculateLevelOfDetailUnclamped don't get error.
float bar(float a) {
return t.CalculateLevelOfDetail(s, a) +
t.CalculateLevelOfDetailUnclamped(s, a);
}

// Make sure nested call to CalculateLevelOfDetail and CalculateLevelOfDetailUnclamped get error.
float foo2(float a) {
return t.CalculateLevelOfDetail(s, a) + // expected-error {{overload of intrinsic CalculateLevelOfDetail requires shader model 6.8 or greater}}
t.CalculateLevelOfDetailUnclamped(s, a); // expected-error {{overload of intrinsic CalculateLevelOfDetailUnclamped requires shader model 6.8 or greater}}
}

export
float bar2(float a) {
return foo2(a);
}

// Make sure report error when derivatives not supported.

[shader("pixel")]
float ps(float a:A) : SV_Target {
return t.CalculateLevelOfDetail(s, a) + // expected-error {{overload of intrinsic CalculateLevelOfDetail requires shader model 6.8 or greater}}
t.CalculateLevelOfDetailUnclamped(s, a); // expected-error {{overload of intrinsic CalculateLevelOfDetailUnclamped requires shader model 6.8 or greater}}
}

[shader("vertex")]
float4 vs(float a:A) : SV_Position {
// expected-error@+1 {{Derivatives intrinsic CalculateLevelOfDetail only works in ps and cs_6.6+/as_6.6+/ms_6.6+/node}}
return t.CalculateLevelOfDetail(s, a) + // expected-error {{overload of intrinsic CalculateLevelOfDetail requires shader model 6.8 or greater}}
// expected-error@+1 {{Derivatives intrinsic CalculateLevelOfDetailUnclamped only works in ps and cs_6.6+/as_6.6+/ms_6.6+/node}}
t.CalculateLevelOfDetailUnclamped(s, a); // expected-error {{overload of intrinsic CalculateLevelOfDetailUnclamped requires shader model 6.8 or greater}}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// RUN: dxc -Tlib_6_7 -Wno-intrinsic-call %s -verify

SamplerComparisonState s;
Texture1D t;

// Make sure -Wno-intrinsic-call suppresses the error.
// expected-no-diagnostics

export
float foo(float a) {
return t.CalculateLevelOfDetail(s, a) +
t.CalculateLevelOfDetailUnclamped(s, a);
}

float bar(float a) {
return t.CalculateLevelOfDetail(s, a) +
t.CalculateLevelOfDetailUnclamped(s, a);
}

float foo2(float a) {
return t.CalculateLevelOfDetail(s, a) +
t.CalculateLevelOfDetailUnclamped(s, a);
}

export
float bar2(float a) {
return foo2(a);
}

[shader("pixel")]
float ps(float a:A) : SV_Target {
return t.CalculateLevelOfDetail(s, a) +
t.CalculateLevelOfDetailUnclamped(s, a);
}

[shader("vertex")]
float4 vs(float a:A) : SV_Position {
return t.CalculateLevelOfDetail(s, a) +
t.CalculateLevelOfDetailUnclamped(s, a);
}