llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-hlsl

<details>
<summary>Changes</summary>

HLSL supports vector swizzles on scalars by implicitly converting the scalar to 
a single-element vector. This syntax is a convienent way to initialize vectors 
based on filling a scalar value.

There are two parts of this change. The first part in the Lexer splits numeric 
constant tokens when a `.x` or `.r` suffix is encountered. This splitting is a 
bit hacky but allows the numeric constant to be parsed separately from the 
vector element expression. There is an ambiguity here with the `r` suffix used 
by fixed point types, however fixed point types aren't supported in HLSL so 
this should not cause any exposable problems (a separate issue has been filed 
to track validating language options for HLSL: #<!-- -->67689).

The second part of this change is in Sema::LookupMemberExpr. For HLSL, if the 
base type is a scalar, we implicit cast the scalar to a one-element vector then 
call back to perform the vector lookup.

Fixes #<!-- -->56658 and #<!-- -->67511

---
Full diff: https://github.com/llvm/llvm-project/pull/67700.diff


5 Files Affected:

- (modified) clang/lib/Lex/Lexer.cpp (+4) 
- (modified) clang/lib/Lex/LiteralSupport.cpp (+5-1) 
- (modified) clang/lib/Sema/SemaExprMember.cpp (+10) 
- (added) clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzleErrors.hlsl 
(+14) 
- (added) clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl (+78) 


``````````diff
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index 37c3e4175d4736e..65588191cfd8fdb 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -1950,6 +1950,10 @@ bool Lexer::LexNumericConstant(Token &Result, const char 
*CurPtr) {
   while (isPreprocessingNumberBody(C)) {
     CurPtr = ConsumeChar(CurPtr, Size, Result);
     PrevCh = C;
+    if (LangOpts.HLSL && C == '.' && (*CurPtr == 'x' || *CurPtr == 'r')) {
+      CurPtr--;
+      break;
+    }
     C = getCharAndSize(CurPtr, Size);
   }
 
diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp
index 2de307883b97ce7..0a78638f680511d 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -930,7 +930,11 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   // and FP constants (specifically, the 'pp-number' regex), and assumes that
   // the byte at "*end" is both valid and not part of the regex.  Because of
   // this, it doesn't have to check for 'overscan' in various places.
-  if (isPreprocessingNumberBody(*ThisTokEnd)) {
+  // Note: For HLSL, the end token is allowed to be '.' which would be in the
+  // 'pp-number' regex. This is required to support vector swizzles on numeric
+  // constants (i.e. 1.xx or 1.5f.rrr).
+  if (isPreprocessingNumberBody(*ThisTokEnd) &&
+      !(LangOpts.HLSL && *ThisTokEnd == '.')) {
     Diags.Report(TokLoc, diag::err_lexing_numeric);
     hadError = true;
     return;
diff --git a/clang/lib/Sema/SemaExprMember.cpp 
b/clang/lib/Sema/SemaExprMember.cpp
index fe92215ae46776f..2de5579df27153d 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1687,6 +1687,16 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult 
&R,
                             ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
   }
 
+  // HLSL supports implicit conversion of scalar types to single element vector
+  // rvalues in member expressions.
+  if (S.getLangOpts().HLSL && BaseType->isScalarType()) {
+    QualType VectorTy = S.Context.getExtVectorType(BaseType, 1);
+    BaseExpr = S.ImpCastExprToType(BaseExpr.get(), VectorTy, CK_VectorSplat,
+                                   BaseExpr.get()->getValueKind());
+    return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
+                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
+  }
+
   S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
     << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;
 
diff --git a/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzleErrors.hlsl 
b/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzleErrors.hlsl
new file mode 100644
index 000000000000000..56c6ab537261769
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzleErrors.hlsl
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library  -x hlsl 
-finclude-default-header -verify %s
+
+
+int2 ToTwoInts(int V) {
+  return V.xy; // expected-error{{vector component access exceeds type 'int 
__attribute__((ext_vector_type(1)))' (vector of 1 'int' value)}}
+}
+
+float2 ToTwoFloats(float V) {
+  return V.rg; // expected-error{{vector component access exceeds type 'float 
__attribute__((ext_vector_type(1)))' (vector of 1 'float' value)}}
+}
+
+int4 SomeNonsense(int V) {
+  return V.poop; // expected-error{{illegal vector component name 'p'}}
+}
diff --git a/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl 
b/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl
new file mode 100644
index 000000000000000..b25d73499fdba0f
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library  -x hlsl \
+// RUN:   -finclude-default-header -ast-dump %s | FileCheck %s
+
+
+// CHECK: ExtVectorElementExpr {{.*}} 'int 
__attribute__((ext_vector_type(2)))' xx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int 
__attribute__((ext_vector_type(1)))' lvalue <VectorSplat>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'V' 'int'
+
+int2 ToTwoInts(int V){
+  return V.xx;
+}
+
+// CHECK: ExtVectorElementExpr {{.*}} 'float 
__attribute__((ext_vector_type(4)))' rrrr
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float 
__attribute__((ext_vector_type(1)))' lvalue <VectorSplat>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'V' 'float'
+
+
+float4 ToThreeFloats(float V){
+  return V.rrrr;
+}
+
+// CHECK: ExtVectorElementExpr {{.*}} 'int 
__attribute__((ext_vector_type(2)))' xx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
+
+int2 FillOne(){
+  return 1.xx;
+}
+
+
+// CHECK: ExtVectorElementExpr {{.*}} 'unsigned int 
__attribute__((ext_vector_type(3)))' xxx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned int 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
+
+uint3 FillOneUnsigned(){
+  return 1u.xxx;
+}
+
+// CHECK: ExtVectorElementExpr {{.*}} 'unsigned long 
__attribute__((ext_vector_type(4)))' xxxx
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'unsigned long 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: IntegerLiteral {{.*}} 'unsigned long' 1
+
+vector<uint64_t,4> FillOneUnsignedLong(){
+  return 1ul.xxxx;
+}
+
+// CHECK: ExtVectorElementExpr {{.*}} 'double 
__attribute__((ext_vector_type(2)))' rr
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: FloatingLiteral {{.*}} 'double' 2.500000e+00
+
+double2 FillTwoPointFive(){
+  return 2.5.rr;
+}
+
+// CHECK: ExtVectorElementExpr {{.*}} 'double 
__attribute__((ext_vector_type(3)))' rrr
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: FloatingLiteral {{.*}} 'double' 5.000000e-01
+
+double3 FillOneHalf(){
+  return .5.rrr;
+}
+
+// CHECK: ExtVectorElementExpr {{.*}} 'float 
__attribute__((ext_vector_type(4)))' rrrr
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 2.500000e+00
+
+float4 FillTwoPointFiveFloat(){
+  return 2.5f.rrrr;
+}
+
+// CHECK: InitListExpr {{.*}} 'vector<float, 1>':'float 
__attribute__((ext_vector_type(1)))'
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float' r
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float 
__attribute__((ext_vector_type(1)))' <VectorSplat>
+// CHECK-NEXT: FloatingLiteral {{.*}} 'float' 5.000000e-01
+
+vector<float, 1> FillOneHalfFloat(){
+  return .5f.r;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/67700
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to