[Lldb-commits] [clang] [lldb] [llvm] [HLSL] Pack Intrinsics and related types (PR #224277)
Alexander Johnston via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 22 05:23:49 PDT 2026
https://github.com/Alexander-Johnston updated https://github.com/llvm/llvm-project/pull/224277
>From 4b85318bf69c6e78fa29b72494fe9dba1b591aa7 Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Thu, 17 Sep 2026 12:32:44 +0100
Subject: [PATCH 1/3] [HLSL] Introduce HLSL packed types used by pack_ and
unpack_
This introduces the HLSL types int8_t4_packe and uint8_t4_packed.
These types are implicitly converted to uint as described by the
DirectX specs, but have not been given the full breadth of
functionality DXC provides them (such as increment operations).
---
clang/include/clang/AST/ASTContext.h | 2 +
clang/include/clang/AST/TypeBase.h | 21 +++++++++-
clang/include/clang/AST/TypeProperties.td | 4 ++
clang/include/clang/Basic/HLSLIntrinsics.td | 2 +
clang/include/clang/Basic/HLSLPackedTypes.def | 31 +++++++++++++++
clang/include/clang/Basic/Specifiers.h | 3 ++
clang/include/clang/Basic/TokenKinds.def | 3 ++
clang/include/clang/Sema/DeclSpec.h | 3 ++
clang/include/clang/Sema/Overload.h | 3 ++
clang/include/clang/Sema/SemaHLSL.h | 1 +
.../include/clang/Serialization/ASTBitCodes.h | 5 ++-
clang/lib/AST/ASTContext.cpp | 15 +++++++
clang/lib/AST/ASTImporter.cpp | 4 ++
clang/lib/AST/ExprConstant.cpp | 2 +
clang/lib/AST/ItaniumMangle.cpp | 5 +++
clang/lib/AST/MicrosoftMangle.cpp | 6 +++
clang/lib/AST/NSAPI.cpp | 2 +
clang/lib/AST/PrintfFormatString.cpp | 3 ++
clang/lib/AST/Type.cpp | 8 ++++
clang/lib/AST/TypeLoc.cpp | 2 +
clang/lib/CodeGen/CGDebugInfo.cpp | 4 ++
clang/lib/CodeGen/CGDebugInfo.h | 3 ++
clang/lib/CodeGen/CodeGenTypes.cpp | 4 ++
clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 +
clang/lib/CodeGen/QualTypeMapper.cpp | 4 ++
clang/lib/Parse/ParseDecl.cpp | 13 +++++++
clang/lib/Parse/ParseExpr.cpp | 2 +
clang/lib/Parse/ParseExprCXX.cpp | 5 +++
clang/lib/Parse/ParseTentative.cpp | 4 ++
clang/lib/Sema/DeclSpec.cpp | 6 +++
clang/lib/Sema/SemaCast.cpp | 9 +++++
clang/lib/Sema/SemaExpr.cpp | 4 ++
clang/lib/Sema/SemaExprCXX.cpp | 13 ++++++-
clang/lib/Sema/SemaHLSL.cpp | 9 +++++
clang/lib/Sema/SemaOverload.cpp | 39 +++++++++++++++++++
clang/lib/Sema/SemaTemplateVariadic.cpp | 2 +
clang/lib/Sema/SemaType.cpp | 6 +++
clang/lib/Serialization/ASTCommon.cpp | 5 +++
clang/lib/Serialization/ASTReader.cpp | 5 +++
.../UnifiedSymbolResolution/USRGeneration.cpp | 5 +++
clang/test/AST/HLSL/int8_t4_packed.hlsl | 8 ++++
clang/test/AST/HLSL/uint8_t4_packed.hlsl | 8 ++++
.../test/SemaHLSL/BuiltIns/packed-types.hlsl | 20 ++++++++++
.../SemaHLSL/Types/int8_t4_packed-size.hlsl | 5 +++
.../SemaHLSL/Types/uint8_t4_packed-size.hlsl | 5 +++
clang/tools/libclang/CIndex.cpp | 2 +
46 files changed, 314 insertions(+), 3 deletions(-)
create mode 100644 clang/include/clang/Basic/HLSLPackedTypes.def
create mode 100644 clang/test/AST/HLSL/int8_t4_packed.hlsl
create mode 100644 clang/test/AST/HLSL/uint8_t4_packed.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/packed-types.hlsl
create mode 100644 clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl
create mode 100644 clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 2f7d39599c477..d686b0ae9f95e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1422,6 +1422,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
#include "clang/Basic/SPIRVTypes.def"
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index 424a2afee84da..040e593cd8ba0 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -2796,8 +2796,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) bool is##Id##Type() const;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) bool is##Id##Type() const;
+#include "clang/Basic/HLSLPackedTypes.def"
bool isHLSLSpecificType() const; // Any HLSL specific type
bool isHLSLBuiltinIntangibleType() const; // Any HLSL builtin intangible type
+ bool isHLSLBuiltinPackedType() const;
bool isHLSLAttributedResourceType() const;
bool isHLSLInlineSpirvType() const;
bool isHLSLResourceRecord() const;
@@ -3265,6 +3268,9 @@ class BuiltinType : public Type {
// HLSL intangible Types
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) Id,
#include "clang/Basic/HLSLIntangibleTypes.def"
+// HLSL intangible Types
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) Id,
+#include "clang/Basic/HLSLPackedTypes.def"
// SPIRV types
#define SPIRV_TYPE(Name, Id, SingletonId) Id,
#include "clang/Basic/SPIRVTypes.def"
@@ -8960,6 +8966,12 @@ inline bool Type::isOpenCLSpecificType() const {
}
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ inline bool Type::is##Id##Type() const { \
+ return isSpecificBuiltinType(BuiltinType::Id); \
+ }
+#include "clang/Basic/HLSLPackedTypes.def"
+
#define SPIRV_TYPE(Name, Id, SingletonId) \
inline bool Type::is##Id##Type() const { \
return isSpecificBuiltinType(BuiltinType::Id); \
@@ -8973,9 +8985,16 @@ inline bool Type::isHLSLBuiltinIntangibleType() const {
false;
}
+inline bool Type::isHLSLBuiltinPackedType() const {
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) is##Id##Type() ||
+ return
+#include "clang/Basic/HLSLPackedTypes.def"
+ false;
+}
+
inline bool Type::isHLSLSpecificType() const {
return isHLSLBuiltinIntangibleType() || isHLSLAttributedResourceType() ||
- isHLSLInlineSpirvType();
+ isHLSLInlineSpirvType() || isHLSLBuiltinPackedType();
}
inline bool Type::isHLSLAttributedResourceType() const {
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index dc2a45ec85729..c6e494ddb75c1 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -885,6 +885,10 @@ let Class = BuiltinType in {
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(NAME, ID, SINGLETON_ID) \
+ case BuiltinType::ID: return ctx.SINGLETON_ID;
+#include "clang/Basic/HLSLPackedTypes.def"
+
#define SPIRV_TYPE(NAME, ID, SINGLETON_ID) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/SPIRVTypes.def"
diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td
index 21c0960b6fa23..163a51dd9497e 100644
--- a/clang/include/clang/Basic/HLSLIntrinsics.td
+++ b/clang/include/clang/Basic/HLSLIntrinsics.td
@@ -65,6 +65,8 @@ def IntTy : HLSLType<"int">;
def UIntTy : HLSLType<"uint">;
def Int64Ty : HLSLType<"int64_t">;
def UInt64Ty : HLSLType<"uint64_t">;
+def Int8PackedTy : HLSLType<"int8_t4_packed">;
+def UInt8PackedTy : HLSLType<"uint8_t4_packed">;
//===----------------------------------------------------------------------===//
// Element type groups
diff --git a/clang/include/clang/Basic/HLSLPackedTypes.def b/clang/include/clang/Basic/HLSLPackedTypes.def
new file mode 100644
index 0000000000000..763267bb779eb
--- /dev/null
+++ b/clang/include/clang/Basic/HLSLPackedTypes.def
@@ -0,0 +1,31 @@
+//===-- HLSLPackedTypes.def - HLSL packed scalar types ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines HLSL SM 6.6 packed types.
+//
+// The macro is:
+//
+// HLSL_PACKED_TYPE(Spelling, Id, SingletonId)
+//
+// where:
+//
+// - Spelling is the HLSL type name (e.g. int8_t4_packed).
+//
+// - BuiltinType::Id is the enumerator defining the type.
+//
+// - Context.SingletonId is the global singleton of this type.
+//
+// To include this file, define HLSL_PACKED_TYPE.
+// The macro will be undefined after inclusion.
+//
+//===----------------------------------------------------------------------===//
+
+HLSL_PACKED_TYPE(int8_t4_packed, Int8_4Packed, Int8_4PackedTy)
+HLSL_PACKED_TYPE(uint8_t4_packed, UInt8_4Packed, UInt8_4PackedTy)
+
+#undef HLSL_PACKED_TYPE
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index c1b7198565f07..67742038bb6a8 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -102,6 +102,9 @@ namespace clang {
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
TST_##Name, // HLSL Intangible Types
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ TST_##Name, // HLSL Packed Types
+#include "clang/Basic/HLSLPackedTypes.def"
TST_error // erroneous type
};
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index dc9c7d8109467..97e5915bcd0d5 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -552,6 +552,9 @@ KEYWORD(column_major , KEYHLSL)
// HLSL Intangible Types
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL)
#include "clang/Basic/HLSLIntangibleTypes.def"
+// HLSL Packed Types
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL)
+#include "clang/Basic/HLSLPackedTypes.def"
// Borland Extensions.
KEYWORD(__pascal , KEYALL)
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index e6dc6831d893f..66a6098a75ae9 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -298,6 +298,9 @@ class DeclSpec {
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
static const TST TST_##Name = clang::TST_##Name;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ static const TST TST_##Name = clang::TST_##Name;
+#include "clang/Basic/HLSLPackedTypes.def"
static const TST TST_error = clang::TST_error;
// type-qualifiers
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index 3abc0013d8f69..af3335f5b53ee 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -210,6 +210,9 @@ class Sema;
/// HLSL matrix splat from scalar or boolean type.
ICK_HLSL_Matrix_Splat,
+ /// HLSL packed type conversion to uint
+ ICK_HLSL_Packed_Type_Conversion,
+
/// The number of conversion kinds
ICK_Num_Conversion_Kinds,
};
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 6c0e5b52f7cb3..6096f24b25069 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -239,6 +239,7 @@ class SemaHLSL : public SemaBase {
bool CanPerformScalarCast(QualType SrcTy, QualType DestTy);
bool CanPerformElementwiseCast(Expr *Src, QualType DestType);
bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType);
+ bool CanPerformPackedToUintCast(Expr *SrcTy, QualType DestTy);
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg);
QualType getInoutParameterType(QualType Ty);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 6a52a9e4fa780..5dd6f38d64f37 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1154,6 +1154,9 @@ enum PredefinedTypeIDs {
// \brief HLSL intangible types with auto numeration
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
#include "clang/Basic/HLSLIntangibleTypes.def"
+// \brief HLSL packed types with auto numeration
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
+#include "clang/Basic/HLSLPackedTypes.def"
// \brief SPIR-V types with auto numeration
#define SPIRV_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID,
#include "clang/Basic/SPIRVTypes.def"
@@ -1169,7 +1172,7 @@ enum PredefinedTypeIDs {
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
-const unsigned NUM_PREDEF_TYPE_IDS = 530;
+const unsigned NUM_PREDEF_TYPE_IDS = 532;
// Ensure we do not overrun the predefined types we reserved
// in the enum PredefinedTypeIDs above.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index ef3e6e87ec1fe..6533c82c1c12f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1448,6 +1448,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
InitBuiltinType(SingletonId, BuiltinType::Id);
#include "clang/Basic/HLSLIntangibleTypes.def"
+
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ InitBuiltinType(SingletonId, BuiltinType::Id);
+#include "clang/Basic/HLSLPackedTypes.def"
}
if (Target.hasAArch64ACLETypes() ||
@@ -2452,6 +2456,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getPointerWidth(LangAS::Default);
Align = Target->getPointerAlign(LangAS::Default);
break;
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
+ Width = 32;
+ Align = 32;
+ break;
#define SPIRV_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
Width = Target->getPointerWidth(LangAS::Default); \
@@ -3604,6 +3613,10 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
case BuiltinType::Id: \
return;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ return;
+#include "clang/Basic/HLSLPackedTypes.def"
case BuiltinType::Dependent:
llvm_unreachable("should never get here");
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
@@ -9274,6 +9287,8 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C,
#include "clang/Basic/PPCTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define BUILTIN_TYPE(KIND, ID)
#define PLACEHOLDER_TYPE(KIND, ID) \
case BuiltinType::KIND:
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 22c3af47f451f..7871ff717fe99 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1370,6 +1370,10 @@ ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
case BuiltinType::Id: \
return Importer.getToContext().SingletonId;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ return Importer.getToContext().SingletonId;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
return Importer.getToContext().SingletonId;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9242491832841..2b6b087c7652c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16384,6 +16384,8 @@ GCCTypeClass EvaluateBuiltinClassifyType(QualType T,
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
return GCCTypeClass::None;
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 780fe3a321200..e25a61dc1e69a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3564,6 +3564,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
mangleVendorType(#Name); \
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ mangleVendorType(#Name); \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
mangleVendorType(Name); \
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index cc7bf2279b72e..983306e422485 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -2833,6 +2833,12 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ mangleArtificialTagType(TagTypeKind::Struct, #Name); \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
+
case BuiltinType::SveBool:
Out << "$_CA";
break;
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index 7142ded5a551d..54c0b03b14848 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -457,6 +457,8 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
case BuiltinType::BoundMember:
diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp
index e0cff04069d59..d09ed5e02dc02 100644
--- a/clang/lib/AST/PrintfFormatString.cpp
+++ b/clang/lib/AST/PrintfFormatString.cpp
@@ -957,6 +957,9 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
+
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index cbacca1c44d91..9059272056809 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2507,6 +2507,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const {
return STK_Floating;
if (BT->isFixedPointType())
return STK_FixedPoint;
+ if (BT->isHLSLBuiltinPackedType())
+ return STK_Integral;
llvm_unreachable("unknown scalar builtin type");
} else if (isa<PointerType>(T)) {
return STK_CPointer;
@@ -3708,6 +3710,10 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
case Id: \
return #Name;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case Id: \
+ return #Name;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) \
case Id: \
return Name;
@@ -5281,6 +5287,8 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
case BuiltinType::BuiltinFn:
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 682ce9ffacc30..da7e130f6d813 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -421,6 +421,8 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
case BuiltinType::BuiltinFn:
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 02864621d60a3..e3f68c058838d 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -979,6 +979,10 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Id: \
return getOrCreateStructPtrType(#Name, SingletonId);
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ return DBuilder.createBasicType(#Name, 32, llvm::dwarf::DW_ATE_unsigned);
+#include "clang/Basic/HLSLPackedTypes.def"
#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/AArch64ACLETypes.def"
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 8a46e3f0e60bb..37520394812b4 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -97,6 +97,9 @@ class CGDebugInfo {
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) \
llvm::DIType *SingletonId = nullptr;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ llvm::DIType *SingletonId = nullptr;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) llvm::DIType *SingletonId = nullptr;
#include "clang/Basic/SPIRVTypes.def"
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 99ead1295bc58..facd551f9a604 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -590,6 +590,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
#include "clang/Basic/HLSLIntangibleTypes.def"
ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty);
break;
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
+ ResultType = llvm::IntegerType::get(getLLVMContext(), 32);
+ break;
#define SPIRV_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
return llvm::TargetExtType::get(getLLVMContext(), "spirv.Event");
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index c17813140b10f..b4b5fb5d7fd20 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -3787,6 +3787,8 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
case BuiltinType::ShortAccum:
diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp
index a6e96c63446f6..dd8dd6a571891 100644
--- a/clang/lib/CodeGen/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -311,6 +311,10 @@ QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
#include "clang/Basic/HLSLIntangibleTypes.def"
llvm::reportFatalInternalError(
"HLSL intangible types not yet Supported in ABI lowering library");
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
+ llvm::reportFatalInternalError(
+ "HLSL packed types not yet Supported in ABI lowering library");
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
llvm::reportFatalInternalError(
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index a4bdec00ca80a..0d0a193e7bd88 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4672,6 +4672,13 @@ void Parser::ParseDeclarationSpecifiers(
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case tok::kw_##Name: \
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_##Name, Loc, PrevSpec, \
+ DiagID, Policy); \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
+
case tok::less:
// GCC ObjC supports types like "<SomeProtocol>" as a synonym for
// "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
@@ -5612,6 +5619,8 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
@@ -5702,6 +5711,8 @@ bool Parser::isTypeSpecifierQualifier(const Token &Tok) {
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
@@ -6048,6 +6059,8 @@ bool Parser::isDeclarationSpecifier(
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
case tok::kw___funcref:
case tok::kw_groupshared:
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index ef89b77d0a997..05cb680faa215 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1354,6 +1354,8 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand,
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
{
if (!getLangOpts().CPlusPlus) {
Diag(Tok, diag::err_expected_expression);
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 860c069e18fca..6542fc10e23d9 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2218,6 +2218,11 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
DS.SetTypeSpecType(DeclSpec::TST_##Name, Loc, PrevSpec, DiagID, Policy); \
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case tok::kw_##Name: \
+ DS.SetTypeSpecType(DeclSpec::TST_##Name, Loc, PrevSpec, DiagID, Policy); \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
case tok::annot_decltype:
case tok::kw_decltype:
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index c71ce09267f8a..efbb1ecd5abb4 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1527,6 +1527,8 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
if (NextToken().is(tok::l_paren))
return TPResult::Ambiguous;
@@ -1657,6 +1659,8 @@ bool Parser::isCXXDeclarationSpecifierAType() {
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case tok::kw_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
return true;
case tok::kw_auto:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index c13d5c8345604..1bc3bb45dc897 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -350,6 +350,8 @@ bool Declarator::isDeclarationOfFunction() const {
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case TST_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case TST_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
return false;
case TST_decltype_auto:
@@ -585,6 +587,10 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_##Name: \
return #Name;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case DeclSpec::TST_##Name: \
+ return #Name;
+#include "clang/Basic/HLSLPackedTypes.def"
case DeclSpec::TST_error: return "(error)";
}
llvm_unreachable("Unknown typespec!");
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index cc76411135d23..f2dc0f79c6e95 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -2977,6 +2977,15 @@ bool CastOperation::CheckHLSLCStyleCast(CheckedConversionKind CCK) {
return true;
}
+ // HLSL includes packed data types that can be converted directly to uint
+ if (Self.HLSL().CanPerformPackedToUintCast(SrcExpr.get(), DestType)) {
+ SrcExpr = Self.ImpCastExprToType(
+ SrcExpr.get(), SrcExpr.get()->getType(), CK_IntegralCast,
+ SrcExpr.get()->getValueKind(), nullptr, CCK);
+ Kind = CK_IntegralCast;
+ return true;
+ }
+
// If the destination is an array, we've exhausted the valid HLSL casts, so we
// should emit a dignostic and stop processing.
if (DestType->isArrayType()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 7444fe0e71fd8..e7103f8c98a96 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6514,6 +6514,8 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
@@ -22255,6 +22257,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
#define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id:
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index deb7bdd09fdc7..242d78a4ef9c3 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5007,6 +5007,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
llvm_unreachable("Improper first standard conversion");
}
+ // HLSL Packed Types are a special case which need to be converted to uint
+ // before the second conversions are applied.
+ if (SCS.Dimension == ICK_HLSL_Packed_Type_Conversion) {
+ From = ImpCastExprToType(From, Context.UnsignedIntTy, CK_IntegralCast,
+ From->getValueKind(), nullptr, CCK)
+ .get();
+ FromType = Context.UnsignedIntTy;
+ }
+
// Perform the second implicit conversion
switch (SCS.Second) {
case ICK_Identity:
@@ -5411,10 +5420,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_HLSL_Matrix_Truncation:
case ICK_HLSL_Vector_Splat:
case ICK_HLSL_Matrix_Splat:
+ case ICK_HLSL_Packed_Type_Conversion:
llvm_unreachable("Improper second standard conversion");
}
- if (SCS.Dimension != ICK_Identity) {
+ if (SCS.Dimension != ICK_Identity &&
+ SCS.Dimension != ICK_HLSL_Packed_Type_Conversion) {
// If SCS.Element is not ICK_Identity the To and From types must be HLSL
// vectors or matrices.
assert(
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 461bb8fb96678..f0e71297cf4b2 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -5184,6 +5184,15 @@ bool SemaHLSL::CanPerformElementwiseCast(Expr *Src, QualType DestTy) {
return true;
}
+bool SemaHLSL::CanPerformPackedToUintCast(Expr *Src, QualType DestTy) {
+ QualType SrcTy = Src->getType();
+ if (SrcTy->isHLSLBuiltinPackedType()) {
+ if (DestTy->isScalarType() || DestTy->isHLSLBuiltinPackedType())
+ return true;
+ }
+ return false;
+}
+
ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg) {
assert(Param->hasAttr<HLSLParamModifierAttr>() &&
"We should not get here without a parameter modifier expression");
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 963f0e93bd651..ebd8e4630323a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -196,6 +196,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
ICR_Conversion,
ICR_HLSL_Scalar_Widening,
ICR_HLSL_Scalar_Widening,
+ ICR_HLSL_Dimension_Reduction,
};
static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds);
return Rank[(int)Kind];
@@ -260,6 +261,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) {
"Non-decaying array conversion",
"HLSL vector splat",
"HLSL matrix splat",
+ "HLSL packed type conversion",
};
static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds);
return Name[Kind];
@@ -2345,6 +2347,37 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
return false;
}
+static bool IsHLSLPackedTypeConversion(Sema &S, QualType FromType,
+ QualType ToType,
+ ImplicitConversionKind &ICK,
+ ImplicitConversionKind &DimensionICK,
+ Expr *From) {
+ if (!S.getLangOpts().HLSL || !FromType->isHLSLBuiltinPackedType())
+ return false;
+ if (S.Context.hasSameUnqualifiedType(FromType, ToType))
+ return false;
+
+ if (ToType->isHLSLBuiltinPackedType()) {
+ ICK = ICK_Integral_Conversion;
+ DimensionICK = ICK_Identity;
+ return true;
+ }
+
+ if (!ToType->isScalarType())
+ return false;
+
+ QualType UIntTy = S.Context.UnsignedIntTy;
+ DimensionICK = ICK_HLSL_Packed_Type_Conversion;
+
+ // Already converting to uint, don't need to do anything else
+ if (S.Context.hasSameUnqualifiedType(UIntTy, ToType))
+ return true;
+
+ // We can reuse IsVectorOrMatrixElementConversion to handle uint to
+ // float/integral/boolean conversion and promotion
+ return IsVectorOrMatrixElementConversion(S, UIntTy, ToType, ICK, From);
+}
+
static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
@@ -2612,6 +2645,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
SCS.Second = SecondICK;
SCS.Dimension = DimensionICK;
FromType = ToType.getUnqualifiedType();
+ } else if (IsHLSLPackedTypeConversion(S, FromType, ToType, SecondICK,
+ DimensionICK, From)) {
+ SCS.Second = SecondICK;
+ SCS.Dimension = DimensionICK;
+ FromType = ToType.getUnqualifiedType();
} else if (!S.getLangOpts().CPlusPlus &&
S.Context.typesAreCompatible(ToType, FromType)) {
// Compatible conversions (Clang extension for C function overloading)
@@ -6497,6 +6535,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
case ICK_HLSL_Array_RValue:
+ case ICK_HLSL_Packed_Type_Conversion:
llvm_unreachable("found a first conversion kind in Second");
case ICK_Function_Conversion:
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 0f5c4d41c3295..7f6cd7f6e7ce6 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1210,6 +1210,8 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
#include "clang/Basic/OpenCLImageTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case TST_##Name:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case TST_##Name:
+#include "clang/Basic/HLSLPackedTypes.def"
case TST_unknown_anytype:
case TST_error:
break;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 483f9ab088799..9b2b6c9f64641 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1394,6 +1394,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case DeclSpec::TST_##Name: \
+ Result = Context.SingletonId; \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index ca7993adb7d2c..6b107fae054f2 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -268,6 +268,11 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
ID = PREDEF_TYPE_##Id##_ID; \
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ ID = PREDEF_TYPE_##Id##_ID; \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
ID = PREDEF_TYPE_##Id##_ID; \
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index a9c230d767c50..2b9950c7f4cbb 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -8171,6 +8171,11 @@ QualType ASTReader::GetType(TypeID ID) {
T = Context.SingletonId; \
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case PREDEF_TYPE_##Id##_ID: \
+ T = Context.SingletonId; \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) \
case PREDEF_TYPE_##Id##_ID: \
T = Context.SingletonId; \
diff --git a/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp b/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp
index 19f3fa19efb27..cab4520dc57e4 100644
--- a/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp
+++ b/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp
@@ -858,6 +858,11 @@ void USRGenerator::VisitType(QualType T) {
Out << "@BT@" << #Name; \
break;
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ Out << "@BT@" << #Name; \
+ break;
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id: \
Out << "@BT@" << Name; \
diff --git a/clang/test/AST/HLSL/int8_t4_packed.hlsl b/clang/test/AST/HLSL/int8_t4_packed.hlsl
new file mode 100644
index 0000000000000..16c33d71086f4
--- /dev/null
+++ b/clang/test/AST/HLSL/int8_t4_packed.hlsl
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -x hlsl -ast-dump -disable-llvm-passes -o - 2>&1 %s | FileCheck %s
+
+struct MyBuffer {
+ int8_t4_packed val;
+};
+
+// CHECK:CXXRecordDecl 0x{{[0-9a-z]+}} <{{.*}}> line:3:8 struct MyBuffer definition
+// CHECK:FieldDecl 0x{{[0-9a-z]+}} <line:4:3, col:18> col:18 val 'int8_t4_packed'
diff --git a/clang/test/AST/HLSL/uint8_t4_packed.hlsl b/clang/test/AST/HLSL/uint8_t4_packed.hlsl
new file mode 100644
index 0000000000000..3b18bf6bb9d52
--- /dev/null
+++ b/clang/test/AST/HLSL/uint8_t4_packed.hlsl
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -x hlsl -ast-dump -disable-llvm-passes -o - 2>&1 %s | FileCheck %s
+
+struct MyBuffer {
+ uint8_t4_packed val;
+};
+
+// CHECK:CXXRecordDecl 0x{{[0-9a-z]+}} <{{.*}}> line:3:8 struct MyBuffer definition
+// CHECK:FieldDecl 0x{{[0-9a-z]+}} <line:4:3, col:19> col:19 val 'uint8_t4_packed'
diff --git a/clang/test/SemaHLSL/BuiltIns/packed-types.hlsl b/clang/test/SemaHLSL/BuiltIns/packed-types.hlsl
new file mode 100644
index 0000000000000..9bfecc5c8c17c
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/packed-types.hlsl
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -finclude-default-header -fsyntax-only -verify -triple dxil-unknown-shadermodel6.6-library %s
+
+typedef float int8_t4_packed; // expected-error {{cannot combine with previous 'float' declaration specifier}} expected-warning {{typedef requires a name}}
+typedef float uint8_t4_packed; // expected-error {{cannot combine with previous 'float' declaration specifier}} expected-warning {{typedef requires a name}}
+
+void f(int8_t4_packed s_arg, uint8_t4_packed u_arg) {
+ int8_t4_packed s1;
+ int8_t4_packed s2[10];
+ uint8_t4_packed u1;
+ uint8_t4_packed u2[10];
+
+ uint32_t b = s_arg;
+ uint32_t d = u_arg;
+ int a = s_arg;
+ int c = u_arg;
+ int8_t4_packed u_to_s = u_arg;
+ uint8_t4_packed s_to_u = s_arg;
+ float f1 = s_arg;
+ float f2 = u_arg;
+}
diff --git a/clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl b/clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl
new file mode 100644
index 0000000000000..9dcc5411394fd
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/int8_t4_packed-size.hlsl
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -verify -fnative-half-type -fnative-int16-type %s
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -verify -fnative-half-type -fnative-int16-type %s
+
+// expected-no-diagnostics
+_Static_assert(sizeof(int8_t4_packed) == 4, "int8_t4_packed is 4 bytes");
diff --git a/clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl b/clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl
new file mode 100644
index 0000000000000..fe18cc72f1110
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/uint8_t4_packed-size.hlsl
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -verify -fnative-half-type -fnative-int16-type %s
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -verify -fnative-half-type -fnative-int16-type %s
+
+// expected-no-diagnostics
+_Static_assert(sizeof(uint8_t4_packed) == 4, "uint8_t4_packed is 4 bytes");
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 39e9e89b1ff00..0fe36e8878dda 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1597,6 +1597,8 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/HLSLIntangibleTypes.def"
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/SPIRVTypes.def"
#define BUILTIN_TYPE(Id, SingletonId)
>From 7feaf88c7c40c5de863880871ef2766badcc830e Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Thu, 17 Sep 2026 12:37:13 +0100
Subject: [PATCH 2/3] [HLSL] Add pack_ intrinsics.
Adds the pack_u8/s8 and pack_clamp_u8/s8 operations for DirectX and SPIRV.
---
clang/include/clang/Basic/Builtins.td | 24 ++++++
clang/include/clang/Basic/HLSLIntrinsics.td | 36 +++++++++
clang/lib/CodeGen/CGHLSLBuiltins.cpp | 24 ++++++
clang/lib/CodeGen/CGHLSLRuntime.h | 4 +
clang/lib/Sema/SemaHLSL.cpp | 73 +++++++++++++++++++
.../CodeGenHLSL/builtins/pack_clamp_s8.hlsl | 16 ++++
.../CodeGenHLSL/builtins/pack_clamp_u8.hlsl | 16 ++++
clang/test/CodeGenHLSL/builtins/pack_s8.hlsl | 16 ++++
clang/test/CodeGenHLSL/builtins/pack_u8.hlsl | 16 ++++
.../test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl | 61 ++++++++++++++++
.../test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl | 61 ++++++++++++++++
clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl | 61 ++++++++++++++++
clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl | 61 ++++++++++++++++
llvm/include/llvm/IR/IntrinsicsDirectX.td | 6 ++
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 4 +
llvm/lib/Target/DirectX/DXIL.td | 9 +++
llvm/lib/Target/DirectX/DXILOpLowering.cpp | 34 +++++++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 55 ++++++++++++++
llvm/test/CodeGen/DirectX/pack_clamp_s8.ll | 26 +++++++
llvm/test/CodeGen/DirectX/pack_clamp_u8.ll | 26 +++++++
llvm/test/CodeGen/DirectX/pack_s8.ll | 26 +++++++
llvm/test/CodeGen/DirectX/pack_u8.ll | 26 +++++++
.../SPIRV/hlsl-intrinsics/pack_clamp_s8.ll | 44 +++++++++++
.../SPIRV/hlsl-intrinsics/pack_clamp_u8.ll | 42 +++++++++++
.../CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll | 28 +++++++
.../CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll | 28 +++++++
26 files changed, 823 insertions(+)
create mode 100644 clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl
create mode 100644 clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl
create mode 100644 clang/test/CodeGenHLSL/builtins/pack_s8.hlsl
create mode 100644 clang/test/CodeGenHLSL/builtins/pack_u8.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl
create mode 100644 llvm/test/CodeGen/DirectX/pack_clamp_s8.ll
create mode 100644 llvm/test/CodeGen/DirectX/pack_clamp_u8.ll
create mode 100644 llvm/test/CodeGen/DirectX/pack_s8.ll
create mode 100644 llvm/test/CodeGen/DirectX/pack_u8.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 90340ad7f812c..d5d8ffd79659f 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5878,6 +5878,30 @@ def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLPackU8 : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_pack_u8"];
+ let Attributes = [NoThrow, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLPackS8 : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_pack_s8"];
+ let Attributes = [NoThrow, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLPackClampU8 : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_pack_clamp_u8"];
+ let Attributes = [NoThrow, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLPackClampS8 : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_pack_clamp_s8"];
+ let Attributes = [NoThrow, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td
index 163a51dd9497e..6a61d15773675 100644
--- a/clang/include/clang/Basic/HLSLIntrinsics.td
+++ b/clang/include/clang/Basic/HLSLIntrinsics.td
@@ -1924,3 +1924,39 @@ the specified wave.
let Availability = SM6_0;
let VaryingMatDims = [];
}
+
+def hlsl_pack_u8 : HLSLOneArgBuiltin<"pack_u8", "__builtin_hlsl_pack_u8"> {
+ let VaryingTypes = [UInt16Ty, UIntTy];
+ let VaryingScalar = 0;
+ let VaryingVecSizes = [4];
+ let VaryingMatDims = [];
+ let ReturnType = UInt8PackedTy;
+ let Availability = SM6_6;
+}
+
+def hlsl_pack_s8 : HLSLOneArgBuiltin<"pack_s8", "__builtin_hlsl_pack_s8"> {
+ let VaryingTypes = [Int16Ty, IntTy];
+ let VaryingScalar = 0;
+ let VaryingVecSizes = [4];
+ let VaryingMatDims = [];
+ let ReturnType = Int8PackedTy;
+ let Availability = SM6_6;
+}
+
+def hlsl_pack_clamp_u8 : HLSLOneArgBuiltin<"pack_clamp_u8", "__builtin_hlsl_pack_clamp_u8"> {
+ let VaryingTypes = [Int16Ty, IntTy];
+ let VaryingScalar = 0;
+ let VaryingVecSizes = [4];
+ let VaryingMatDims = [];
+ let ReturnType = UInt8PackedTy;
+ let Availability = SM6_6;
+}
+
+def hlsl_pack_clamp_s8 : HLSLOneArgBuiltin<"pack_clamp_s8", "__builtin_hlsl_pack_clamp_s8"> {
+ let VaryingTypes = [Int16Ty, IntTy];
+ let VaryingScalar = 0;
+ let VaryingVecSizes = [4];
+ let VaryingMatDims = [];
+ let ReturnType = Int8PackedTy;
+ let Availability = SM6_6;
+}
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index b1ec72ae46242..014373b7d2563 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -1705,6 +1705,30 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
ArrayRef<Value *>{Op0}, nullptr,
"hlsl.ddy.fine");
}
+ case Builtin::BI__builtin_hlsl_pack_u8: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getPackU8Intrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID,
+ {Op0}, nullptr, "hlsl.pack.u8");
+ }
+ case Builtin::BI__builtin_hlsl_pack_s8: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getPackS8Intrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID,
+ {Op0}, nullptr, "hlsl.pack.s8");
+ }
+ case Builtin::BI__builtin_hlsl_pack_clamp_u8: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getPackClampU8Intrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID,
+ {Op0}, nullptr, "hlsl.pack.clamp.u8");
+ }
+ case Builtin::BI__builtin_hlsl_pack_clamp_s8: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getPackClampS8Intrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Builder.getInt32Ty(), ID,
+ {Op0}, nullptr, "hlsl.pack.clamp.s8");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index f551bb006ea2c..0600f368ca4d8 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -211,6 +211,10 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(PackS8, pack_s8)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(PackU8, pack_u8)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(PackClampS8, pack_clamp_s8)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(PackClampU8, pack_clamp_u8)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f0e71297cf4b2..6f6f420e67cbc 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -4860,6 +4860,79 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
getASTContext().UnsignedIntTy);
break;
}
+ case Builtin::BI__builtin_hlsl_pack_u8: {
+ if (SemaRef.checkArgCount(TheCall, 1))
+ return true;
+ const auto *VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
+ if (!VecTy) {
+ SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector of */ 4 << /* unsigned integer */ 3 << /* no fp */ 0
+ << TheCall->getArg(0)->getType();
+ return true;
+ }
+ QualType ElementTy = VecTy->getElementType();
+ if (!ElementTy->isUnsignedIntegerType() ||
+ SemaRef.Context.getTypeSize(ElementTy) == 64 ||
+ VecTy->getNumElements() != 4) {
+ SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector of */ 4 << /* unsigned integer */ 3 << /* no fp */ 0
+ << TheCall->getArg(0)->getType();
+ return true;
+ }
+ TheCall->setType(getASTContext().UInt8_4PackedTy);
+ break;
+ }
+ case Builtin::BI__builtin_hlsl_pack_clamp_u8: {
+ if (SemaRef.checkArgCount(TheCall, 1))
+ return true;
+ const auto *VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
+ if (!VecTy) {
+ SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0
+ << TheCall->getArg(0)->getType();
+ return true;
+ }
+ QualType ElementTy = VecTy->getElementType();
+ if (!ElementTy->isSignedIntegerType() ||
+ SemaRef.Context.getTypeSize(ElementTy) == 64 ||
+ VecTy->getNumElements() != 4) {
+ SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0
+ << TheCall->getArg(0)->getType();
+ return true;
+ }
+ TheCall->setType(getASTContext().UInt8_4PackedTy);
+ break;
+ }
+ case Builtin::BI__builtin_hlsl_pack_s8:
+ case Builtin::BI__builtin_hlsl_pack_clamp_s8: {
+ if (SemaRef.checkArgCount(TheCall, 1))
+ return true;
+ const auto *VecTy = TheCall->getArg(0)->getType()->getAs<VectorType>();
+ if (!VecTy) {
+ SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0
+ << TheCall->getArg(0)->getType();
+ return true;
+ }
+ QualType ElementTy = VecTy->getElementType();
+ if (!ElementTy->isSignedIntegerType() ||
+ SemaRef.Context.getTypeSize(ElementTy) == 64 ||
+ VecTy->getNumElements() != 4) {
+ SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector of */ 4 << /* signed integer */ 2 << /* no fp */ 0
+ << TheCall->getArg(0)->getType();
+ return true;
+ }
+ TheCall->setType(getASTContext().Int8_4PackedTy);
+ break;
+ }
}
return false;
}
diff --git a/clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl
new file mode 100644
index 0000000000000..80db19d467f10
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/pack_clamp_s8.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=dx
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=spv
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_u16Dv4_s
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.s8.v4i16(<4 x i16> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+int8_t4_packed test_u16(int16_t4 val) { return pack_clamp_s8(val); }
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_u32Dv4_i
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.s8.v4i32(<4 x i32> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+int8_t4_packed test_u32(int4 val) { return pack_clamp_s8(val); }
diff --git a/clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl
new file mode 100644
index 0000000000000..99beb20843ea8
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/pack_clamp_u8.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=dx
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=spv
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_u16Dv4_s
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.u8.v4i16(<4 x i16> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+uint8_t4_packed test_u16(int16_t4 val) { return pack_clamp_u8(val); }
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_u32Dv4_i
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.clamp.u8.v4i32(<4 x i32> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+uint8_t4_packed test_u32(int4 val) { return pack_clamp_u8(val); }
diff --git a/clang/test/CodeGenHLSL/builtins/pack_s8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_s8.hlsl
new file mode 100644
index 0000000000000..4b90a2890a54b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/pack_s8.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=dx
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=spv
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_s16Dv4_s
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.s8.v4i16(<4 x i16> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+int8_t4_packed test_s16(int16_t4 val) { return pack_s8(val); }
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_s32Dv4_i
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.s8.v4i32(<4 x i32> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+int8_t4_packed test_s32(int4 val) { return pack_s8(val); }
diff --git a/clang/test/CodeGenHLSL/builtins/pack_u8.hlsl b/clang/test/CodeGenHLSL/builtins/pack_u8.hlsl
new file mode 100644
index 0000000000000..b4ea9e78b12b4
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/pack_u8.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.6-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=dx
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-int16-type -fnative-half-type -o - | \
+// RUN: FileCheck %s -DCALL=spv
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_u16Dv4_t
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.u8.v4i16(<4 x i16> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+uint8_t4_packed test_u16(uint16_t4 val) { return pack_u8(val); }
+
+// CHECK-LABEL: define {{.*}} i32 @_Z8test_u32Dv4_j
+// CHECK: [[VAR:%.*]] = call i32 @llvm.[[CALL]].pack.u8.v4i32(<4 x i32> %{{.*}})
+// CHECK-NEXT: ret i32 [[VAR]]
+uint8_t4_packed test_u32(uint4 val) { return pack_u8(val); }
diff --git a/clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl
new file mode 100644
index 0000000000000..2a87693b47fbf
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/pack_clamp_s8.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
+
+void test_no_args() {
+ pack_clamp_s8();
+ // expected-error at -1 {{no matching function for call to 'pack_clamp_s8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}}
+}
+
+int8_t4_packed test_extra_args(int32_t4 p0) {
+ return pack_clamp_s8(p0, p0);
+ // expected-error at -1 {{no matching function for call to 'pack_clamp_s8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+}
+
+int8_t4_packed test_64bit_arg(int64_t4 p0) {
+ return pack_clamp_s8(p0);
+ // expected-error at -1 {{call to 'pack_clamp_s8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+int8_t4_packed test_float_vec_arg(float32_t4 p0) {
+ return pack_clamp_s8(p0);
+ // expected-error at -1 {{call to 'pack_clamp_s8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+int8_t4_packed test_wrong_vec_elems(int32_t3 p0) {
+ return pack_clamp_s8(p0);
+ // expected-error at -1 {{no matching function for call to 'pack_clamp_s8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}}
+}
+
+void test_builtin_no_args() {
+ __builtin_hlsl_pack_clamp_s8();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+int8_t4_packed test_builtin_extra_args(int32_t4 p0) {
+ return __builtin_hlsl_pack_clamp_s8(p0, p0);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+int8_t4_packed test_builtin_64bit_arg(int64_t4 p0) {
+ return __builtin_hlsl_pack_clamp_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int64_t4' (aka 'vector<int64_t, 4>'))}}
+}
+
+int8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) {
+ return __builtin_hlsl_pack_clamp_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}}
+}
+
+int8_t4_packed test_builtin_wrong_vec_elems(int32_t3 p0) {
+ return __builtin_hlsl_pack_clamp_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int32_t3' (aka 'vector<int32_t, 3>'))}}
+}
+
+int8_t4_packed test_builtin_scalar_arg(int p0) {
+ return __builtin_hlsl_pack_clamp_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl
new file mode 100644
index 0000000000000..f4f1c50943916
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/pack_clamp_u8.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
+
+void test_no_args() {
+ pack_clamp_u8();
+ // expected-error at -1 {{no matching function for call to 'pack_clamp_u8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}}
+}
+
+uint8_t4_packed test_extra_args(int32_t4 p0) {
+ return pack_clamp_u8(p0, p0);
+ // expected-error at -1 {{no matching function for call to 'pack_clamp_u8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+}
+
+uint8_t4_packed test_64bit_arg(int64_t4 p0) {
+ return pack_clamp_u8(p0);
+ // expected-error at -1 {{call to 'pack_clamp_u8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+uint8_t4_packed test_float_vec_arg(float32_t4 p0) {
+ return pack_clamp_u8(p0);
+ // expected-error at -1 {{call to 'pack_clamp_u8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+uint8_t4_packed test_wrong_vec_elems(int32_t3 p0) {
+ return pack_clamp_u8(p0);
+ // expected-error at -1 {{no matching function for call to 'pack_clamp_u8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}}
+}
+
+void test_builtin_no_args() {
+ __builtin_hlsl_pack_clamp_u8();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+uint8_t4_packed test_builtin_extra_args(int32_t4 p0) {
+ return __builtin_hlsl_pack_clamp_u8(p0, p0);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+uint8_t4_packed test_builtin_64bit_arg(int64_t4 p0) {
+ return __builtin_hlsl_pack_clamp_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int64_t4' (aka 'vector<int64_t, 4>'))}}
+}
+
+uint8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) {
+ return __builtin_hlsl_pack_clamp_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}}
+}
+
+uint8_t4_packed test_builtin_wrong_vec_elems(int32_t3 p0) {
+ return __builtin_hlsl_pack_clamp_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int32_t3' (aka 'vector<int32_t, 3>'))}}
+}
+
+uint8_t4_packed test_builtin_scalar_arg(int p0) {
+ return __builtin_hlsl_pack_clamp_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl
new file mode 100644
index 0000000000000..6d9bcc615ef1f
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/pack_s8.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
+
+void test_no_args() {
+ pack_s8();
+ // expected-error at -1 {{no matching function for call to 'pack_s8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}}
+}
+
+int8_t4_packed test_extra_args(int32_t4 p0) {
+ return pack_s8(p0, p0);
+ // expected-error at -1 {{no matching function for call to 'pack_s8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+}
+
+int8_t4_packed test_64bit_arg(int64_t4 p0) {
+ return pack_s8(p0);
+ // expected-error at -1 {{call to 'pack_s8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+int8_t4_packed test_float_vec_arg(float32_t4 p0) {
+ return pack_s8(p0);
+ // expected-error at -1 {{call to 'pack_s8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+int8_t4_packed test_wrong_vec_elems(int32_t3 p0) {
+ return pack_s8(p0);
+ // expected-error at -1 {{no matching function for call to 'pack_s8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}}
+}
+
+void test_builtin_no_args() {
+ __builtin_hlsl_pack_s8();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+int8_t4_packed test_builtin_extra_args(int32_t4 p0) {
+ return __builtin_hlsl_pack_s8(p0, p0);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+int8_t4_packed test_builtin_64bit_arg(int64_t4 p0) {
+ return __builtin_hlsl_pack_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int64_t4' (aka 'vector<int64_t, 4>'))}}
+}
+
+int8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) {
+ return __builtin_hlsl_pack_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}}
+}
+
+int8_t4_packed test_builtin_wrong_vec_elems(int32_t3 p0) {
+ return __builtin_hlsl_pack_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int32_t3' (aka 'vector<int32_t, 3>'))}}
+}
+
+int8_t4_packed test_builtin_scalar_arg(int p0) {
+ return __builtin_hlsl_pack_s8(p0);
+ // expected-error at -1 {{1st argument must be a vector of signed integer types (was 'int')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl b/clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl
new file mode 100644
index 0000000000000..8fdc95bbed03c
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/pack_u8.hlsl
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -fnative-int16-type -emit-llvm-only -disable-llvm-passes -verify
+
+void test_no_args() {
+ pack_u8();
+ // expected-error at -1 {{no matching function for call to 'pack_u8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 0 were provided}}
+}
+
+uint8_t4_packed test_extra_args(uint32_t4 p0) {
+ return pack_u8(p0, p0);
+ // expected-error at -1 {{no matching function for call to 'pack_u8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+}
+
+uint8_t4_packed test_64bit_arg(uint64_t4 p0) {
+ return pack_u8(p0);
+ // expected-error at -1 {{call to 'pack_u8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+uint8_t4_packed test_float_vec_arg(float32_t4 p0) {
+ return pack_u8(p0);
+ // expected-error at -1 {{call to 'pack_u8' is ambiguous}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function}}
+}
+
+uint8_t4_packed test_wrong_vec_elems(uint32_t3 p0) {
+ return pack_u8(p0);
+ // expected-error at -1 {{no matching function for call to 'pack_u8'}}
+ // expected-note at hlsl/hlsl_alias_intrinsics_gen.inc:* 2 {{candidate function not viable: no known conversion from}}
+}
+
+void test_builtin_no_args() {
+ __builtin_hlsl_pack_u8();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+uint8_t4_packed test_builtin_extra_args(uint32_t4 p0) {
+ return __builtin_hlsl_pack_u8(p0, p0);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+uint8_t4_packed test_builtin_64bit_arg(uint64_t4 p0) {
+ return __builtin_hlsl_pack_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of unsigned integer types (was 'uint64_t4' (aka 'vector<uint64_t, 4>'))}}
+}
+
+uint8_t4_packed test_builtin_float_vec_arg(float32_t4 p0) {
+ return __builtin_hlsl_pack_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of unsigned integer types (was 'float32_t4' (aka 'vector<float32_t, 4>'))}}
+}
+
+uint8_t4_packed test_builtin_wrong_vec_elems(uint32_t3 p0) {
+ return __builtin_hlsl_pack_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of unsigned integer types (was 'uint32_t3' (aka 'vector<uint32_t, 3>'))}}
+}
+
+uint8_t4_packed test_builtin_scalar_arg(uint p0) {
+ return __builtin_hlsl_pack_u8(p0);
+ // expected-error at -1 {{1st argument must be a vector of unsigned integer types (was 'uint' (aka 'unsigned int'))}}
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index f90340c379386..0ab61b789c226 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -346,4 +346,10 @@ def int_dx_store_output
[llvm_i32_ty /*SigElementId*/, llvm_i32_ty /*RowIndex*/,
llvm_i8_ty /*ColIndex*/, llvm_any_ty /*Value*/],
[IntrConvergent]>;
+
+def int_dx_pack_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+def int_dx_pack_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+def int_dx_pack_clamp_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+def int_dx_pack_clamp_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+
}
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 86b49a8ee446a..7d4fac1226846 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -365,5 +365,9 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
def int_spv_unpackhalf2x16 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [llvm_i32_ty], [IntrNoMem]>;
def int_spv_packhalf2x16 : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty], [IntrNoMem]>;
+ def int_spv_pack_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+ def int_spv_pack_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+ def int_spv_pack_clamp_u8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
+ def int_spv_pack_clamp_s8 : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_vector_int_ty], [IntrNoMem]>;
}
diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td
index 4beafd0c619b0..2a18b7ee074be 100644
--- a/llvm/lib/Target/DirectX/DXIL.td
+++ b/llvm/lib/Target/DirectX/DXIL.td
@@ -1539,3 +1539,12 @@ def CreateHandleFromHeap : DXILOp<218, createHandleFromHeap> {
let stages = [Stages<DXIL1_6, [all_stages]>];
let attributes = [Attributes<DXIL1_0, [ReadNone]>];
}
+
+def Pack4x8 : DXILOp<220, pack4x8> {
+ let Doc = "pack 4 integer values into a single 32 bit value";
+ let arguments = [Int8Ty, OverloadTy, OverloadTy, OverloadTy, OverloadTy];
+ let overloads = [Overloads<DXIL1_6, [Int16Ty, Int32Ty]>];
+ let result = Int32Ty;
+ let stages = [Stages<DXIL1_6, [all_stages]>];
+ let attributes = [Attributes<DXIL1_6, [ReadNone]>];
+}
diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
index aa73629eee232..41a126b5749c0 100644
--- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp
+++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp
@@ -1319,6 +1319,30 @@ class OpLowerer {
});
}
+ [[nodiscard]] bool lowerPack(Function &F, uint32_t PackOpCode) {
+ IRBuilder<> &IRB = OpBuilder.getIRB();
+ Type *RetTy = IRB.getInt32Ty();
+ return replaceFunction(F, [&](CallInst *CI) -> Error {
+ IRB.SetInsertPoint(CI);
+ SmallVector<Value *, 5> Args;
+ Args.push_back(IRB.getInt8(PackOpCode));
+
+ // Disassemble the vector to fill args 1-5 of the pack op.
+ Value *VecArg = CI->getArgOperand(0);
+ for (int i = 1; i < 5; i++)
+ Args.push_back(IRB.CreateExtractElement(VecArg, i - 1));
+
+ Expected<CallInst *> OpCall =
+ OpBuilder.tryCreateOp(OpCode::Pack4x8, Args, CI->getName(), RetTy);
+ if (Error E = OpCall.takeError())
+ return E;
+
+ CI->replaceAllUsesWith(*OpCall);
+ CI->eraseFromParent();
+ return Error::success();
+ });
+ }
+
bool lowerIntrinsics() {
bool Updated = false;
bool HasErrors = false;
@@ -1439,6 +1463,16 @@ class OpLowerer {
case Intrinsic::is_fpclass:
HasErrors |= lowerIsFPClass(F);
break;
+ case Intrinsic::dx_pack_u8:
+ case Intrinsic::dx_pack_s8:
+ HasErrors |= lowerPack(F, 0);
+ break;
+ case Intrinsic::dx_pack_clamp_u8:
+ HasErrors |= lowerPack(F, 1);
+ break;
+ case Intrinsic::dx_pack_clamp_s8:
+ HasErrors |= lowerPack(F, 2);
+ break;
}
Updated = true;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 1d821c5aec993..c85f9016394f9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -485,6 +485,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
MachineInstr &I) const;
bool selectDerivativeInst(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I, const unsigned DPdOpCode) const;
+ bool selectPackInst(Register ResVReg, SPIRVTypeInst ResType, MachineInstr &I,
+ const bool Signed, const bool Clamp) const;
// Utilities
Register buildI32Constant(uint32_t Val, MachineInstr &I,
SPIRVTypeInst ResType = nullptr) const;
@@ -5254,6 +5256,51 @@ bool SPIRVInstructionSelector::selectDerivativeInst(
return true;
}
+bool SPIRVInstructionSelector::selectPackInst(Register ResVReg,
+ SPIRVTypeInst ResType,
+ MachineInstr &I,
+ const bool Signed,
+ const bool Clamp) const {
+ MachineIRBuilder MIRBuilder(I);
+ Register SrcReg = I.getOperand(2).getReg();
+ SPIRVTypeInst SrcType = GR.getSPIRVTypeForVReg(SrcReg);
+
+ // pack_clamp_ instructions require SClamp before performing SConvert
+ // limits are determined by if the pack_clamp is signed or not
+ if (Clamp) {
+ const unsigned ElemWidth = GR.getScalarOrVectorBitWidth(SrcType);
+ APInt Lower =
+ Signed ? APInt(ElemWidth, -128, true) : APInt::getZero(ElemWidth);
+ APInt Upper =
+ Signed ? APInt(ElemWidth, 127, true) : APInt(ElemWidth, 255, true);
+ bool ZeroAsNull = !STI.isShader();
+ Register LowerLimit =
+ GR.getOrCreateConstVector(Lower, I, SrcType, TII, ZeroAsNull);
+ Register UpperLimit =
+ GR.getOrCreateConstVector(Upper, I, SrcType, TII, ZeroAsNull);
+
+ Register ClampedReg = MRI->createVirtualRegister(GR.getRegClass(SrcType));
+ // Regardless of if we are using pack_clamp_u8 or pack_clamp_s8 we want to
+ // generate a signed clamp
+ if (!selectExtInst(ClampedReg, SrcType, I, CL::s_clamp, GL::SClamp,
+ /*setMIFlags=*/true, /*useMISrc=*/false,
+ {SrcReg, LowerLimit, UpperLimit}))
+ return false;
+ SrcReg = ClampedReg;
+ }
+
+ // Narrow to an i8 vector, then bitcast. Convert sign doesn't matter here
+ SPIRVTypeInst I8Type = GR.getOrCreateSPIRVIntegerType(8, MIRBuilder);
+ SPIRVTypeInst I8x4Type =
+ GR.getOrCreateSPIRVVectorType(I8Type, 4, MIRBuilder, true);
+ Register I8x4Reg = MRI->createVirtualRegister(GR.getRegClass(I8x4Type));
+ auto ConvertOpcode = Signed ? SPIRV::OpSConvert : SPIRV::OpUConvert;
+ if (!selectOpWithSrcs(I8x4Reg, I8x4Type, I, {SrcReg}, ConvertOpcode))
+ return false;
+
+ return selectOpWithSrcs(ResVReg, ResType, I, {I8x4Reg}, SPIRV::OpBitcast);
+}
+
bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
SPIRVTypeInst ResType,
MachineInstr &I) const {
@@ -5842,6 +5889,14 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
MIB.constrainAllUses(TII, TRI, RBI);
return true;
}
+ case Intrinsic::spv_pack_u8:
+ case Intrinsic::spv_pack_s8:
+ // For non-clamp packs the sign is meaningless
+ return selectPackInst(ResVReg, ResType, I, false, false);
+ case Intrinsic::spv_pack_clamp_u8:
+ return selectPackInst(ResVReg, ResType, I, false, true);
+ case Intrinsic::spv_pack_clamp_s8:
+ return selectPackInst(ResVReg, ResType, I, true, true);
default:
return diagnoseUnsupported(I, "intrinsic selection not implemented.");
}
diff --git a/llvm/test/CodeGen/DirectX/pack_clamp_s8.ll b/llvm/test/CodeGen/DirectX/pack_clamp_s8.ll
new file mode 100644
index 0000000000000..e8c9e5b4d2425
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/pack_clamp_s8.ll
@@ -0,0 +1,26 @@
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s
+
+define noundef i32 @pack_clamp_s8_16(<4 x i16> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 2, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.clamp.s8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_clamp_s8_32(<4 x i32> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 2, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.clamp.s8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.dx.pack.clamp.s8.v4i16(<4 x i16>)
+declare i32 @llvm.dx.pack.clamp.s8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/DirectX/pack_clamp_u8.ll b/llvm/test/CodeGen/DirectX/pack_clamp_u8.ll
new file mode 100644
index 0000000000000..ec854fff6a02f
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/pack_clamp_u8.ll
@@ -0,0 +1,26 @@
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s
+
+define noundef i32 @pack_clamp_u8_16(<4 x i16> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 1, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.clamp.u8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_clamp_u8_32(<4 x i32> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 1, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.clamp.u8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.dx.pack.clamp.u8.v4i16(<4 x i16>)
+declare i32 @llvm.dx.pack.clamp.u8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/DirectX/pack_s8.ll b/llvm/test/CodeGen/DirectX/pack_s8.ll
new file mode 100644
index 0000000000000..1920147ec3839
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/pack_s8.ll
@@ -0,0 +1,26 @@
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s
+
+define noundef i32 @pack_s8_16(<4 x i16> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 0, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.s8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_s8_32(<4 x i32> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 0, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.s8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.dx.pack.s8.v4i16(<4 x i16>)
+declare i32 @llvm.dx.pack.s8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/DirectX/pack_u8.ll b/llvm/test/CodeGen/DirectX/pack_u8.ll
new file mode 100644
index 0000000000000..38360f69e2d59
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/pack_u8.ll
@@ -0,0 +1,26 @@
+; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.6-library %s | FileCheck %s
+
+define noundef i32 @pack_u8_16(<4 x i16> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i16> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i16> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i16> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i16> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i16(i32 220, i8 0, i16 [[one]], i16 [[two]], i16 [[three]], i16 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.u8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_u8_32(<4 x i32> noundef %a) {
+; CHECK: [[one:%.*]] = extractelement <4 x i32> %a, i64 0
+; CHECK: [[two:%.*]] = extractelement <4 x i32> %a, i64 1
+; CHECK: [[three:%.*]] = extractelement <4 x i32> %a, i64 2
+; CHECK: [[four:%.*]] = extractelement <4 x i32> %a, i64 3
+; CHECK: [[packed:%.*]] = call i32 @dx.op.pack4x8.i32(i32 220, i8 0, i32 [[one]], i32 [[two]], i32 [[three]], i32 [[four]])
+; ret i32 [[packed]]
+ %packed = call i32 @llvm.dx.pack.u8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.dx.pack.u8.v4i16(<4 x i16>)
+declare i32 @llvm.dx.pack.u8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll
new file mode 100644
index 0000000000000..f6784e076265c
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_s8.ll
@@ -0,0 +1,44 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: [[import:%.*]] = OpExtInstImport "GLSL.std.450"
+
+; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0
+; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4
+; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0
+; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4
+; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0
+; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4
+
+; 65408 is -128 for SClamp
+; CHECK-DAG: [[int16_65408:%.*]] = OpConstant [[int16]] 65408
+; CHECK-DAG: [[int16_65408x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_65408]] [[int16_65408]] [[int16_65408]] [[int16_65408]]
+; CHECK-DAG: [[int16_127:%.*]] = OpConstant [[int16]] 127
+; CHECK-DAG: [[int16_127x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_127]] [[int16_127]] [[int16_127]] [[int16_127]]
+
+; 4294967168 is -128 for SClamp
+; CHECK-DAG: [[int32_4294967168:%.*]] = OpConstant [[int32]] 4294967168
+; CHECK-DAG: [[int32_4294967168x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_4294967168]] [[int32_4294967168]] [[int32_4294967168]] [[int32_4294967168]]
+; CHECK-DAG: [[int32_127:%.*]] = OpConstant [[int32]] 127
+; CHECK-DAG: [[int32_127x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_127]] [[int32_127]] [[int32_127]] [[int32_127]]
+
+define noundef i32 @pack_clamp_s8_16(<4 x i16> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]]
+; CHECK: [[clamped:%.*]] = OpExtInst [[int16x4]] [[import]] SClamp [[in]] [[int16_65408x4]] [[int16_127x4]]
+; CHECK: [[converted:%.*]] = OpSConvert [[int8x4]] [[clamped]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.clamp.s8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_clamp_s8_32(<4 x i32> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]]
+; CHECK: [[clamped:%.*]] = OpExtInst [[int32x4]] [[import]] SClamp [[in]] [[int32_4294967168x4]] [[int32_127x4]]
+; CHECK: [[converted:%.*]] = OpSConvert [[int8x4]] [[clamped]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.clamp.s8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.spv.pack.clamp.s8.v4i16(<4 x i16>)
+declare i32 @llvm.spv.pack.clamp.s8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll
new file mode 100644
index 0000000000000..c5234e3283fee
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_clamp_u8.ll
@@ -0,0 +1,42 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: [[import:%.*]] = OpExtInstImport "GLSL.std.450"
+
+; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0
+; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4
+; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0
+; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4
+; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0
+; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4
+
+; CHECK-DAG: [[int16_0:%.*]] = OpConstant [[int16]] 0
+; CHECK-DAG: [[int16_0x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_0]] [[int16_0]] [[int16_0]] [[int16_0]]
+; CHECK-DAG: [[int16_255:%.*]] = OpConstant [[int16]] 255
+; CHECK-DAG: [[int16_255x4:%.*]] = OpConstantComposite [[int16x4]] [[int16_255]] [[int16_255]] [[int16_255]] [[int16_255]]
+
+; CHECK-DAG: [[int32_0:%.*]] = OpConstant [[int32]] 0
+; CHECK-DAG: [[int32_0x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_0]] [[int32_0]] [[int32_0]] [[int32_0]]
+; CHECK-DAG: [[int32_255:%.*]] = OpConstant [[int32]] 255
+; CHECK-DAG: [[int32_255x4:%.*]] = OpConstantComposite [[int32x4]] [[int32_255]] [[int32_255]] [[int32_255]] [[int32_255]]
+
+define noundef i32 @pack_clamp_u8_16(<4 x i16> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]]
+; CHECK: [[clamped:%.*]] = OpExtInst [[int16x4]] [[import]] SClamp [[in]] [[int16_0x4]] [[int16_255x4]]
+; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[clamped]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.clamp.u8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_clamp_u8_32(<4 x i32> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]]
+; CHECK: [[clamped:%.*]] = OpExtInst [[int32x4]] [[import]] SClamp [[in]] [[int32_0x4]] [[int32_255x4]]
+; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[clamped]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.clamp.u8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.spv.pack.clamp.u8.v4i16(<4 x i16>)
+declare i32 @llvm.spv.pack.clamp.u8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll
new file mode 100644
index 0000000000000..d16cdaac17a31
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_s8.ll
@@ -0,0 +1,28 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0
+; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4
+; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0
+; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4
+; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0
+; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4
+
+define noundef i32 @pack_s8_16(<4 x i16> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]]
+; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.s8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_s8_32(<4 x i32> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]]
+; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.s8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.spv.pack.s8.v4i16(<4 x i16>)
+declare i32 @llvm.spv.pack.s8.v4i32(<4 x i32>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll
new file mode 100644
index 0000000000000..e87e57984d967
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pack_u8.ll
@@ -0,0 +1,28 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: [[int8:%.*]] = OpTypeInt 8 0
+; CHECK-DAG: [[int8x4:%.*]] = OpTypeVector [[int8]] 4
+; CHECK-DAG: [[int16:%.*]] = OpTypeInt 16 0
+; CHECK-DAG: [[int16x4:%.*]] = OpTypeVector [[int16]] 4
+; CHECK-DAG: [[int32:%.*]] = OpTypeInt 32 0
+; CHECK-DAG: [[int32x4:%.*]] = OpTypeVector [[int32]] 4
+
+define noundef i32 @pack_u8_16(<4 x i16> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int16x4]]
+; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.u8.v4i16(<4 x i16> %a)
+ ret i32 %packed
+}
+
+define noundef i32 @pack_u8_32(<4 x i32> noundef %a) {
+; CHECK: [[in:%.*]] = OpFunctionParameter [[int32x4]]
+; CHECK: [[converted:%.*]] = OpUConvert [[int8x4]] [[in]]
+; CHECK: [[cast:%.*]] = OpBitcast [[int32]] [[converted]]
+ %packed = call i32 @llvm.spv.pack.u8.v4i32(<4 x i32> %a)
+ ret i32 %packed
+}
+
+declare i32 @llvm.spv.pack.u8.v4i16(<4 x i16>)
+declare i32 @llvm.spv.pack.u8.v4i32(<4 x i32>)
>From b12322e01f986434cfdbbfe90cb1de399fbc8b42 Mon Sep 17 00:00:00 2001
From: Alexander Johnston <alexander.johnston at amd.com>
Date: Tue, 22 Sep 2026 13:23:08 +0100
Subject: [PATCH 3/3] Add missing cases in lldb
---
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 5255ec835c0a4..ff2e46c1b58e0 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -4925,6 +4925,11 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type) {
case clang::BuiltinType::NullPtr:
return lldb::eEncodingUint;
+ // HLSL -- Packed Types
+#define HLSL_PACKED_TYPE(Name, Id, SingletonId) case clang::BuiltinType::Id:
+#include "clang/Basic/HLSLPackedTypes.def"
+ return lldb::eEncodingUint;
+
case clang::BuiltinType::Kind::ARCUnbridgedCast:
case clang::BuiltinType::Kind::BoundMember:
case clang::BuiltinType::Kind::BuiltinFn:
More information about the lldb-commits
mailing list