Browse Source

Fix assert from considering initialized cbuffer int an ICE (#1509)

- cbuffer globals are marked 'const', but when initialized are not
  actually known values, since their initializer is ignored in HLSL.
Tex Riddell 7 years ago
parent
commit
cb9fd11fa6

+ 5 - 0
tools/clang/lib/AST/Decl.cpp

@@ -2068,6 +2068,11 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const {
   const LangOptions &Lang = C.getLangOpts();
   (void)(Lang); // HLSL Change - this object is only accessed through static consts
 
+  // HLSL Change: non-static globals are constant buffer variables that look
+  // like const globals, but cannot be used in constant expressions.
+  if (Lang.HLSL && hasGlobalStorage() && getStorageClass() != SC_Static)
+    return false;
+
   if (!Lang.CPlusPlus)
     return false;
 

+ 7 - 0
tools/clang/lib/AST/ExprConstant.cpp

@@ -9064,6 +9064,13 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
         if (!Dcl->getType()->isIntegralOrEnumerationType())
           return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
 
+        // HLSL Change: cbuffer vars with init are not really constant in this way
+        if (Ctx.getLangOpts().HLSL &&
+            Dcl->hasGlobalStorage() &&
+            Dcl->getStorageClass() != SC_Static) {
+          return ICEDiag(IK_NotICE, cast<DeclRefExpr>(E)->getLocation());
+        }
+
         const VarDecl *VD;
         // Look for a declaration of this variable that has an initializer, and
         // check whether it is an ICE.

+ 8 - 0
tools/clang/lib/Sema/SemaChecking.cpp

@@ -32,6 +32,7 @@
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaHLSL.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallString.h"
@@ -7085,6 +7086,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
   if (auto VecTy = dyn_cast<VectorType>(Target))
     Target = VecTy->getElementType().getTypePtr();
 
+  // HLSL Change Begins: Vector/matrix implicit conversions already diagnosed
+  if (hlsl::IsVectorType(&S, QualType(Source, 0)) || hlsl::IsMatrixType(&S, QualType(Source, 0)) ||
+      hlsl::IsVectorType(&S, QualType(Target, 0)) || hlsl::IsMatrixType(&S, QualType(Target, 0))) {
+    return;
+  }
+  // HLSL Change Ends
+
   // Strip complex types.
   if (isa<ComplexType>(Source)) {
     if (!isa<ComplexType>(Target)) {

+ 5 - 1
tools/clang/lib/Sema/SemaDecl.cpp

@@ -9818,7 +9818,11 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
       ActiveTemplateInstantiations.empty()) {
     PragmaStack<StringLiteral *> *Stack = nullptr;
     int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read;
-    if (var->getType().isConstQualified())
+    if (var->getType().isConstQualified()
+      // HLSL Change: for HLSL, const initialized isn't the same, unless static
+        && (!getLangOpts().HLSL ||
+            var->getTLSKind() == VarDecl::TLS_Static)
+        )
       Stack = &ConstSegStack;
     else if (!var->getInit()) {
       Stack = &BSSSegStack;

+ 27 - 0
tools/clang/test/CodeGenHLSL/quick-test/cbufer_init_not_ice.hlsl

@@ -0,0 +1,27 @@
+// RUN: %dxc -E main -T vs_6_0  %s 2>&1 | FileCheck %s
+
+// Make sure it compiles, and make sure cbuffer load isn't optimized away
+// CHECK: call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %{{.*}}, i32 0)
+
+// The following is const by default for cbuffer, but not the way clang normally
+// interprets a const initialized global, since the initializer will be thrown away.
+uint CB_One = 1;
+
+// Simplified repro:
+int2 main() : OUTPUT {
+  const uint ConstVal = CB_One;
+  return int(ConstVal);
+}
+
+int2 main2(int2 input : INPUT) : OUTPUT {
+  const uint ConstFactor = CB_One;
+  int2 result = input;
+  [unroll]
+  for (uint LoopIdx = 0; LoopIdx < 2; LoopIdx++)
+  {
+    const int2 Offset = (LoopIdx == 0 ? 1 : -1) * (int(ConstFactor) * result);
+    result += Offset;
+  }
+  return result;
+}
+