Browse Source

Restrict parameters to Interlocked* Intrinsics (#3057)

Because the defined types of Interlocked* Parameters do not restrict
type casting, they can result in late errors that cause crashes due to
reference params with casts that aren't actually respected by dxil
generation.

By constraining the parameters as they should be, instead of crashes, we
get errors.

Fixes #2077
Fixes #2483
Greg Roth 5 years ago
parent
commit
6971d25e1e

+ 2 - 1
include/dxc/dxcapi.internal.h

@@ -90,7 +90,8 @@ enum LEGAL_INTRINSIC_COMPTYPES {
   LICOMPTYPE_TEXTURE2D = 33,
   LICOMPTYPE_TEXTURE2D = 33,
   LICOMPTYPE_TEXTURE2DARRAY = 34,
   LICOMPTYPE_TEXTURE2DARRAY = 34,
   LICOMPTYPE_RESOURCE = 35,
   LICOMPTYPE_RESOURCE = 35,
-  LICOMPTYPE_COUNT = 36
+  LICOMPTYPE_INT32_ONLY = 36,
+  LICOMPTYPE_COUNT = 37
 };
 };
 
 
 static const BYTE IA_SPECIAL_BASE = 0xf0;
 static const BYTE IA_SPECIAL_BASE = 0xf0;

+ 10 - 0
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -1198,6 +1198,15 @@ static const ArBasicKind g_Numeric16OnlyCT[] =
   AR_BASIC_UNKNOWN
   AR_BASIC_UNKNOWN
 };
 };
 
 
+static const ArBasicKind g_Int32OnlyCT[] =
+{
+  AR_BASIC_INT32,
+  AR_BASIC_UINT32,
+  AR_BASIC_LITERAL_INT,
+  AR_BASIC_NOCAST,
+  AR_BASIC_UNKNOWN
+};
+
 // Basic kinds, indexed by a LEGAL_INTRINSIC_COMPTYPES value.
 // Basic kinds, indexed by a LEGAL_INTRINSIC_COMPTYPES value.
 const ArBasicKind* g_LegalIntrinsicCompTypes[] =
 const ArBasicKind* g_LegalIntrinsicCompTypes[] =
 {
 {
@@ -1237,6 +1246,7 @@ const ArBasicKind* g_LegalIntrinsicCompTypes[] =
   g_Texture2DCT,        // LICOMPTYPE_TEXTURE2D
   g_Texture2DCT,        // LICOMPTYPE_TEXTURE2D
   g_Texture2DArrayCT,   // LICOMPTYPE_TEXTURE2DARRAY
   g_Texture2DArrayCT,   // LICOMPTYPE_TEXTURE2DARRAY
   g_ResourceCT,         // LICOMPTYPE_RESOURCE
   g_ResourceCT,         // LICOMPTYPE_RESOURCE
+  g_Int32OnlyCT,        // LICOMPTYPE_INT32_ONLY
 };
 };
 static_assert(ARRAYSIZE(g_LegalIntrinsicCompTypes) == LICOMPTYPE_COUNT,
 static_assert(ARRAYSIZE(g_LegalIntrinsicCompTypes) == LICOMPTYPE_COUNT,
   "Intrinsic comp type table must be updated when new enumerants are added.");
   "Intrinsic comp type table must be updated when new enumerants are added.");

+ 19 - 19
tools/clang/lib/Sema/gen_intrin_main_tables_15.h

@@ -175,14 +175,14 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args26[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args27[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args27[] =
 {
 {
     {"InterlockedAdd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedAdd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args28[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args28[] =
 {
 {
     {"InterlockedAdd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedAdd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
@@ -190,14 +190,14 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args28[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args29[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args29[] =
 {
 {
     {"InterlockedAnd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedAnd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args30[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args30[] =
 {
 {
     {"InterlockedAnd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedAnd", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
@@ -205,7 +205,7 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args30[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args31[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args31[] =
 {
 {
     {"InterlockedCompareExchange", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedCompareExchange", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"compare", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"compare", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_UINT, 1, 1},
     {"original", AR_QUAL_OUT, 4, LITEMPLATE_SCALAR, 4, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 4, LITEMPLATE_SCALAR, 4, LICOMPTYPE_ANY_INT32, 1, 1},
@@ -214,7 +214,7 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args31[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args32[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args32[] =
 {
 {
     {"InterlockedCompareStore", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedCompareStore", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"compare", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"compare", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_UINT, 1, 1},
 };
 };
@@ -222,22 +222,22 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args32[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args33[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args33[] =
 {
 {
     {"InterlockedExchange", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedExchange", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_NUMERIC32, 1, 1},
-    {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_NUMERIC32, 1, 1},
-    {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_NUMERIC32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
+    {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
+    {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args34[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args34[] =
 {
 {
     {"InterlockedMax", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedMax", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args35[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args35[] =
 {
 {
     {"InterlockedMax", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedMax", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
@@ -245,14 +245,14 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args35[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args36[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args36[] =
 {
 {
     {"InterlockedMin", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedMin", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args37[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args37[] =
 {
 {
     {"InterlockedMin", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedMin", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
@@ -260,14 +260,14 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args37[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args38[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args38[] =
 {
 {
     {"InterlockedOr", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedOr", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args39[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args39[] =
 {
 {
     {"InterlockedOr", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedOr", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
@@ -275,14 +275,14 @@ static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args39[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args40[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args40[] =
 {
 {
     {"InterlockedXor", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedXor", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args41[] =
 static const HLSL_INTRINSIC_ARGUMENT g_Intrinsics_Args41[] =
 {
 {
     {"InterlockedXor", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedXor", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
-    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_ANY_INT32, 1, 1},
+    {"result", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_INT32_ONLY, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
     {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_ANY_INT32, 1, 1},
 };
 };
@@ -5538,8 +5538,8 @@ static const HLSL_INTRINSIC_ARGUMENT g_RWByteAddressBufferMethods_Args7[] =
 {
 {
     {"InterlockedExchange", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"InterlockedExchange", 0, 0, LITEMPLATE_VOID, 0, LICOMPTYPE_VOID, 0, 0},
     {"byteOffset", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_UINT, 1, 1},
     {"byteOffset", AR_QUAL_IN, 1, LITEMPLATE_SCALAR, 1, LICOMPTYPE_UINT, 1, 1},
-    {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_NUMERIC32, 1, 1},
-    {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_NUMERIC32, 1, 1},
+    {"value", AR_QUAL_IN, 2, LITEMPLATE_SCALAR, 2, LICOMPTYPE_UINT, 1, 1},
+    {"original", AR_QUAL_OUT, 3, LITEMPLATE_SCALAR, 3, LICOMPTYPE_UINT, 1, 1},
 };
 };
 
 
 static const HLSL_INTRINSIC_ARGUMENT g_RWByteAddressBufferMethods_Args8[] =
 static const HLSL_INTRINSIC_ARGUMENT g_RWByteAddressBufferMethods_Args8[] =

+ 3 - 3
tools/clang/test/CodeGenSPIRV/intrinsics.interlocked-methods.error.hlsl

@@ -14,6 +14,6 @@ void main()
   InterlockedXor(MySBuffer[2], 5);
   InterlockedXor(MySBuffer[2], 5);
 }
 }
 
 
-// CHECK:     :12:18: error: can only perform atomic operations on scalar integer values
-// CHECK:     :13:27: error: can only perform atomic operations on scalar integer values
-// CHECK-NOT:         error: can only perform atomic operations on scalar integer values
+// CHECK:     :12:3: error: no matching function for call to 'InterlockedAdd'
+// CHECK:     :13:3: error: no matching function for call to 'InterlockedCompareStore'
+// CHECK-NOT:        error: no matching function for call to

+ 2 - 2
tools/clang/test/HLSLFileCheck/hlsl/intrinsics/atomic/atomic_cast1.hlsl

@@ -8,6 +8,6 @@ RWBuffer<uint> buffer;
 [numthreads(1,1,1)]
 [numthreads(1,1,1)]
 void main()
 void main()
 {
 {
-	uint unused;
-	InterlockedOr((float)buffer[0], 1, unused);
+	float unused;
+	InterlockedOr((int)buffer[0], 1, unused);
 }
 }

+ 175 - 0
tools/clang/test/HLSLFileCheck/hlsl/intrinsics/atomic/atomic_overload.hlsl

@@ -0,0 +1,175 @@
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=double  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+// RUN: %dxc -no-warnings -T vs_6_2 -DTYPE=float16_t -enable-16bit-types  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+// RUN: %dxc -no-warnings -T vs_6_2 -DTYPE=int16_t -enable-16bit-types  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+// RUN: %dxc -no-warnings -T vs_6_2 -DTYPE=uint16_t -enable-16bit-types  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=bool  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=int64_t  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=uint64_t  %s | %FileCheck %s -check-prefixes=INTFAIL,FLTFAIL
+
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=float  %s | %FileCheck %s -check-prefixes=INTFAIL,
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=half  %s | %FileCheck %s -check-prefixes=INTFAIL
+
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=int  %s | %FileCheck %s -check-prefixes=INTCHK
+// RUN: %dxc -no-warnings -T vs_6_0 -DTYPE=uint  %s | %FileCheck %s -check-prefixes=INTCHK
+
+
+// Test various Interlocked ops using different memory types with invalid types
+
+RWBuffer<TYPE> rw_res;
+groupshared TYPE gs_res;
+RWByteAddressBuffer ba_res;
+
+float main() :OUT{
+  int val = 1;
+  TYPE comp = 1;
+  TYPE orig;
+
+  // add
+  // INTFAIL: error: no matching function for call to 'InterlockedAdd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedAdd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedAdd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedAdd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw add i32
+  // INTCHK: atomicrmw add i32
+  InterlockedAdd(rw_res[0], val);
+  InterlockedAdd(rw_res[0], val, orig);
+  InterlockedAdd(gs_res, val);
+  InterlockedAdd(gs_res, val, orig);
+
+  // min
+  // INTFAIL: error: no matching function for call to 'InterlockedMin'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedMin'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedMin'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedMin'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw {{u?}}min i32
+  // INTCHK: atomicrmw {{u?}}min i32
+  InterlockedMin(rw_res[0], val);
+  InterlockedMin(rw_res[0], val, orig);
+  InterlockedMin(gs_res, val);
+  InterlockedMin(gs_res, val, orig);
+
+  // max
+  // INTFAIL: error: no matching function for call to 'InterlockedMax'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedMax'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedMax'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedMax'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw {{u?}}max i32
+  // INTCHK: atomicrmw {{u?}}max i32
+  InterlockedMax(rw_res[0], val);
+  InterlockedMax(rw_res[0], val, orig);
+  InterlockedMax(gs_res, val);
+  InterlockedMax(gs_res, val, orig);
+
+  // and
+  // INTFAIL: error: no matching function for call to 'InterlockedAnd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedAnd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedAnd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedAnd'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw and i32
+  // INTCHK: atomicrmw and i32
+  InterlockedAnd(rw_res[0], val);
+  InterlockedAnd(rw_res[0], val, orig);
+  InterlockedAnd(gs_res, val);
+  InterlockedAnd(gs_res, val, orig);
+
+  // or
+  // INTFAIL: error: no matching function for call to 'InterlockedOr'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedOr'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedOr'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedOr'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw or i32
+  // INTCHK: atomicrmw or i32
+  InterlockedOr(rw_res[0], val);
+  InterlockedOr(rw_res[0], val, orig);
+  InterlockedOr(gs_res, val);
+  InterlockedOr(gs_res, val, orig);
+
+  // xor
+  // INTFAIL: error: no matching function for call to 'InterlockedXor'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedXor'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedXor'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedXor'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw xor i32
+  // INTCHK: atomicrmw xor i32
+  InterlockedXor(rw_res[0], val);
+  InterlockedXor(rw_res[0], val, orig);
+  InterlockedXor(gs_res, val);
+  InterlockedXor(gs_res, val, orig);
+
+  // compareStore
+  // INTFAIL: error: no matching function for call to 'InterlockedCompareStore'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedCompareStore'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicCompareExchange.i32
+  // INTCHK: cmpxchg i32
+  InterlockedCompareStore(rw_res[0], comp, val);
+  InterlockedCompareStore(gs_res, comp, val);
+
+  // exchange
+  // FLTFAIL: error: no matching function for call to 'InterlockedExchange'
+  // FLTFAIL: note: candidate function not viable: no known conversion from
+  // FLTFAIL: error: no matching function for call to 'InterlockedExchange'
+  // FLTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicBinOp.i32
+  // INTCHK: atomicrmw xchg i32
+  InterlockedExchange(rw_res[0], val, orig);
+  InterlockedExchange(gs_res, val, orig);
+
+  // compareExchange
+  // INTFAIL: error: no matching function for call to 'InterlockedCompareExchange'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+  // INTFAIL: error: no matching function for call to 'InterlockedCompareExchange'
+  // INTFAIL: note: candidate function not viable: no known conversion from
+
+  // INTCHK: call i32 @dx.op.atomicCompareExchange.i32
+  // INTCHK: cmpxchg i32
+  InterlockedCompareExchange(rw_res[0], comp, val, orig);
+  InterlockedCompareExchange(gs_res, comp, val, orig);
+
+  return (float)rw_res[0] + gs_res;
+}

+ 16 - 16
utils/hct/gen_intrin_main.txt

@@ -147,21 +147,21 @@ $type1 [[]] frexp(in float<> x, out $type1 exp);
 $type1 [[rn]] fwidth(in float_like<> x);
 $type1 [[rn]] fwidth(in float_like<> x);
 void [[]] GroupMemoryBarrier() : syncsharedmemory;
 void [[]] GroupMemoryBarrier() : syncsharedmemory;
 void [[]] GroupMemoryBarrierWithGroupSync() : syncgroupandsharedmemory;
 void [[]] GroupMemoryBarrierWithGroupSync() : syncgroupandsharedmemory;
-void [[]] InterlockedAdd(in any_int32 result, in uint value);
-void [[]] InterlockedAdd(in any_int32 result, in uint value, out any_int32 original) : interlockedadd_immediate;
-void [[unsigned_op=InterlockedUMin,overload=0]] InterlockedMin(in any_int32 result, in any_int32 value) : interlockedmin;
-void [[unsigned_op=InterlockedUMin,overload=0]] InterlockedMin(in any_int32 result, in any_int32 value, out any_int32 original) : interlockedmin_immediate;
-void [[unsigned_op=InterlockedUMax,overload=0]] InterlockedMax(in any_int32 result, in any_int32 value) : interlockedmax;
-void [[unsigned_op=InterlockedUMax,overload=0]] InterlockedMax(in any_int32 result, in any_int32 value, out any_int32  original) : interlockedmax_immediate;
-void [[]] InterlockedAnd(in any_int32 result, in uint value);
-void [[]] InterlockedAnd(in any_int32 result, in uint value, out any_int32 original) : interlockedand_immediate;
-void [[]] InterlockedOr(in any_int32 result, in uint value);
-void [[]] InterlockedOr(in any_int32 result, in uint value, out any_int32 original) : interlockedor_immediate;
-void [[]] InterlockedXor(in any_int32 result, in uint value);
-void [[]] InterlockedXor(in any_int32 result, in uint value, out any_int32 original) : interlockedxor_immediate;
-void [[]] InterlockedCompareStore(in any_int32 result, in uint compare, in uint value);
-void [[]] InterlockedExchange(in numeric32 result, in numeric32 value, out numeric32 original);
-void [[]] InterlockedCompareExchange(in any_int32 result, in uint compare, in uint value, out any_int32 original);
+void [[]] InterlockedAdd(in int32_only result, in uint value);
+void [[]] InterlockedAdd(in int32_only result, in uint value, out any_int32 original) : interlockedadd_immediate;
+void [[unsigned_op=InterlockedUMin,overload=0]] InterlockedMin(in int32_only result, in any_int32 value) : interlockedmin;
+void [[unsigned_op=InterlockedUMin,overload=0]] InterlockedMin(in int32_only result, in any_int32 value, out any_int32 original) : interlockedmin_immediate;
+void [[unsigned_op=InterlockedUMax,overload=0]] InterlockedMax(in int32_only result, in any_int32 value) : interlockedmax;
+void [[unsigned_op=InterlockedUMax,overload=0]] InterlockedMax(in int32_only result, in any_int32 value, out any_int32  original) : interlockedmax_immediate;
+void [[]] InterlockedAnd(in int32_only result, in uint value);
+void [[]] InterlockedAnd(in int32_only result, in uint value, out any_int32 original) : interlockedand_immediate;
+void [[]] InterlockedOr(in int32_only result, in uint value);
+void [[]] InterlockedOr(in int32_only result, in uint value, out any_int32 original) : interlockedor_immediate;
+void [[]] InterlockedXor(in int32_only result, in uint value);
+void [[]] InterlockedXor(in int32_only result, in uint value, out any_int32 original) : interlockedxor_immediate;
+void [[]] InterlockedCompareStore(in int32_only result, in uint compare, in uint value);
+void [[]] InterlockedExchange(in int32_only result, in uint value, out any_int32 original);
+void [[]] InterlockedCompareExchange(in int32_only result, in uint compare, in uint value, out any_int32 original);
 $match<1, 0> bool<> [[rn]] isfinite(in float<> x);
 $match<1, 0> bool<> [[rn]] isfinite(in float<> x);
 $match<1, 0> bool<> [[rn]] isinf(in float<> x);
 $match<1, 0> bool<> [[rn]] isinf(in float<> x);
 $match<1, 0> bool<> [[rn]] isnan(in float<> x);
 $match<1, 0> bool<> [[rn]] isnan(in float<> x);
@@ -811,7 +811,7 @@ void [[]] InterlockedOr(in uint byteOffset, in uint value, out uint original) :
 void [[]] InterlockedXor(in uint byteOffset, in uint value);
 void [[]] InterlockedXor(in uint byteOffset, in uint value);
 void [[]] InterlockedXor(in uint byteOffset, in uint value, out uint original) : interlockedxor_immediate;
 void [[]] InterlockedXor(in uint byteOffset, in uint value, out uint original) : interlockedxor_immediate;
 void [[]] InterlockedCompareStore(in uint byteOffset, in uint compare, in uint value);
 void [[]] InterlockedCompareStore(in uint byteOffset, in uint compare, in uint value);
-void [[]] InterlockedExchange(in uint byteOffset, in numeric32 value, out numeric32 original);
+void [[]] InterlockedExchange(in uint byteOffset, in uint value, out uint original);
 void [[]] InterlockedCompareExchange(in uint byteOffset, in uint compare, in uint value, out uint original);
 void [[]] InterlockedCompareExchange(in uint byteOffset, in uint compare, in uint value, out uint original);
 
 
 } namespace
 } namespace

+ 1 - 0
utils/hct/hctdb.py

@@ -2777,6 +2777,7 @@ class db_hlsl(object):
         self.base_types = {
         self.base_types = {
             "bool": "LICOMPTYPE_BOOL",
             "bool": "LICOMPTYPE_BOOL",
             "int": "LICOMPTYPE_INT",
             "int": "LICOMPTYPE_INT",
+            "int32_only": "LICOMPTYPE_INT32_ONLY",
             "int16_t": "LICOMPTYPE_INT16",
             "int16_t": "LICOMPTYPE_INT16",
             "uint": "LICOMPTYPE_UINT",
             "uint": "LICOMPTYPE_UINT",
             "uint16_t": "LICOMPTYPE_UINT16",
             "uint16_t": "LICOMPTYPE_UINT16",