2
0
Эх сурвалжийг харах

Turn modifier 'center' and friends into identifiers in more cases (#1423)

There are more cases in which the center/sample/etc modifier
should be treated as identifiers:

* Inside decoration groups
* In assignments
* Inside parentheses
* etc.

This commit adds a few more special handling cases that turns these
modifiers into identifiers, upon seeing the next token as punctuator.
Lei Zhang 7 жил өмнө
parent
commit
53576a601e

+ 12 - 0
tools/clang/include/clang/Basic/TokenKinds.h

@@ -100,6 +100,18 @@ inline bool isAnnotation(TokenKind K) {
   return false;
 }
 
+// HLSL Change Starts
+/// \brief Return true if this is a punctuator token.
+inline bool isPunctuator(TokenKind K) {
+#define PUNCTUATOR(NAME, SYMBOL) \
+  if (K == tok::NAME) \
+    return true;
+#include "clang/Basic/TokenKinds.def"
+#undef PUNCTUATOR
+  return false;
+}
+// HLSL Change Ends
+
 }  // end namespace tok
 }  // end namespace clang
 

+ 21 - 0
tools/clang/lib/Parse/ParseDecl.cpp

@@ -5965,6 +5965,27 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
       // the l_paren token.
     }
 
+    // HLSL Change Starts
+    // FXC compatiblity: these are keywords when used as modifiers, but in
+    // FXC they can also be used an identifiers. If the next token is a
+    // punctuator, then we are using them as identifers. Need to change
+    // the token type to tok::identifier and fall through to the next case.
+    // E.g., <type> left, center, right;
+    if (getLangOpts().HLSL) {
+      switch (Tok.getKind()) {
+      case tok::kw_center:
+      case tok::kw_globallycoherent:
+      case tok::kw_precise:
+      case tok::kw_sample:
+        if (tok::isPunctuator(NextToken().getKind()))
+          Tok.setKind(tok::identifier);
+        break;
+      default:
+        break;
+      }
+    }
+    // HLSL Change Ends
+
     if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
                     tok::tilde)) {
       // We found something that indicates the start of an unqualified-id.

+ 19 - 0
tools/clang/lib/Parse/ParseStmt.cpp

@@ -175,6 +175,25 @@ Retry:
     cutOffParsing();
     return StmtError();
 
+    // HLSL Change Starts
+  case tok::kw_precise:
+  case tok::kw_sample:
+  case tok::kw_globallycoherent:
+  case tok::kw_center: {
+    // FXC compatiblity: these are keywords when used as modifiers, but in
+    // FXC they can also be used an identifiers. If the next token is a
+    // punctuator, then we are using them as identifers. Need to change
+    // the token type to tok::identifier and fall through to the next case.
+    // E.g., center = <RHS>.
+    if (tok::isPunctuator(NextToken().getKind())) {
+      Tok.setKind(tok::identifier);
+      __fallthrough;
+    } else {
+      goto tok_default_case;
+    }
+  }
+    // HLSL Change Ends
+
   case tok::identifier: {
     Token Next = NextToken();
     if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement

+ 16 - 4
tools/clang/lib/Parse/ParseTentative.cpp

@@ -1271,6 +1271,22 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
     return TPResult::True;
 
   // HLSL Change Starts
+  case tok::kw_sample:
+  case tok::kw_precise:
+  case tok::kw_center:
+  case tok::kw_globallycoherent:
+    // FXC compatiblity: these are keywords when used as modifiers, but in
+    // FXC they can also be used an identifiers. If the next token is a
+    // punctuator, then we are using them as identifers. Need to change
+    // the token type to tok::identifier and return false.
+    // E.g., return (center);
+    if (tok::isPunctuator(NextToken().getKind())) {
+      Tok.setKind(tok::identifier);
+      return TPResult::False;
+    } else {
+      return TPResult::True;
+    }
+
   case tok::kw_in:
   case tok::kw_inout:
   case tok::kw_out:
@@ -1278,12 +1294,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
   case tok::kw_centroid:
   case tok::kw_nointerpolation:
   case tok::kw_noperspective:
-  case tok::kw_sample:
-  case tok::kw_precise:
-  case tok::kw_center:
   case tok::kw_shared:
   case tok::kw_groupshared:
-  case tok::kw_globallycoherent:
   case tok::kw_uniform:
   case tok::kw_row_major:
   case tok::kw_column_major:

+ 21 - 7
tools/clang/test/CodeGenHLSL/quick-test/sample_kwd.hlsl

@@ -1,19 +1,21 @@
 // RUN: %dxc -T ps_6_0 -Od -E main %s | FileCheck %s
 
 // CHECK: %precise = alloca float, align 4
-// CHECK: %globallycoherent = alloca float, align 4
+// CHECK: %globallycoherent = alloca i32, align 4
 // CHECK: %sample = alloca float, align 4
+// CHECK: %center = alloca float, align 4
 
 // CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 0)
 // CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 16)
 // CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 32)
 // CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 48)
 
-// Make sure 'precise', 'globallycoherent' and 'sample' can be used as identifiers (FXC back-compat)
+// Check function parameters are accepted
 float3 foo(float3 sample) {
     return sample;
 }
 
+// Check member fields are accepted
 struct S {
   float4 center;
   float4 precise;
@@ -23,13 +25,25 @@ struct S {
 
 RWStructuredBuffer<S> MyBuffer;
 
-float3 main(float4 input : SV_POSITION) : SV_TARGET
+float4 main(float4 input : SV_POSITION) : SV_TARGET
 {
+    // Check declarations are accepted
     float precise = 1.0f;
-    float globallycoherent = 1.0f;
-    float sample = 1.0f;
+    int globallycoherent = 1;
+    float sample;
 
-    return foo(float3(precise, globallycoherent, sample)) +
+    // Check assignments are accepted
+    sample = 1.0f;
+    globallycoherent += 10;
+
+    // Check declaration group is accepted
+    float left, center = 1.0, right;
+
+    // Check parentheses are accepted
+    // (they go through the path for type cast in frontend)
+    float w = (center).x;
+
+    return float4(foo(float3(precise, globallycoherent, sample)), w) +
            MyBuffer[0].center + MyBuffer[0].precise +
            MyBuffer[0].sample + MyBuffer[0].globallycoherent;
-}
+}