diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -3073,14 +3073,17 @@ void MicrosoftCXXNameMangler::mangleType(const VectorType *T, Qualifiers Quals, SourceRange Range) { - const BuiltinType *ET = T->getElementType()->getAs(); - assert(ET && "vectors with non-builtin elements are unsupported"); + QualType EltTy = T->getElementType(); + const BuiltinType *ET = EltTy->getAs(); + const BitIntType *BitIntTy = EltTy->getAs(); + assert((ET || BitIntTy) && + "vectors with non-builtin/_BitInt elements are unsupported"); uint64_t Width = getASTContext().getTypeSize(T); // Pattern match exactly the typedefs in our intrinsic headers. Anything that // doesn't match the Intel types uses a custom mangling below. size_t OutSizeBefore = Out.tell(); if (!isa(T)) { - if (getASTContext().getTargetInfo().getTriple().isX86()) { + if (getASTContext().getTargetInfo().getTriple().isX86() && ET) { if (Width == 64 && ET->getKind() == BuiltinType::LongLong) { mangleArtificialTagType(TTK_Union, "__m64"); } else if (Width >= 128) { @@ -3105,7 +3108,11 @@ MicrosoftCXXNameMangler Extra(Context, Stream); Stream << "?$"; Extra.mangleSourceName("__vector"); - Extra.mangleType(QualType(ET, 0), Range, QMM_Escape); + if (ET) + Extra.mangleType(QualType(ET, 0), Range, QMM_Escape); + else + Extra.mangleType(QualType(BitIntTy, 0), Range, QMM_Escape); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements())); mangleArtificialTagType(TTK_Union, TemplateMangling, {"__clang"}); diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h --- a/clang/lib/Basic/Targets/DirectX.h +++ b/clang/lib/Basic/Targets/DirectX.h @@ -63,6 +63,7 @@ void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; + bool hasBitIntType() const override { return true; } bool hasFeature(StringRef Feature) const override { return Feature == "directx"; } diff --git a/clang/lib/Headers/hlsl/hlsl_basic_types.h b/clang/lib/Headers/hlsl/hlsl_basic_types.h --- a/clang/lib/Headers/hlsl/hlsl_basic_types.h +++ b/clang/lib/Headers/hlsl/hlsl_basic_types.h @@ -13,8 +13,8 @@ #ifdef __HLSL_ENABLE_16_BIT // 16-bit integer. -typedef unsigned short uint16_t; -typedef short int16_t; +typedef unsigned _BitInt(16) uint16_t; +typedef _BitInt(16) int16_t; #endif // unsigned 32-bit integer. diff --git a/clang/test/CodeGenHLSL/int16_t_add.hlsl b/clang/test/CodeGenHLSL/int16_t_add.hlsl new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenHLSL/int16_t_add.hlsl @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -D__HLSL_ENABLE_16_BIT \ +// RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s + +// Make sure generate i16 add. +// CHECK: add nsw i16 % +int16_t add(int16_t a, int16_t b) { + return a + b; +} +// CHECK: define noundef <2 x i16> @ +// CHECK: add <2 x i16> +int16_t2 add(int16_t2 a, int16_t2 b) { + return a + b; +} +// CHECK: define noundef <3 x i16> @ +// CHECK: add <3 x i16> +int16_t3 add(int16_t3 a, int16_t3 b) { + return a + b; +} +// CHECK: define noundef <4 x i16> @ +// CHECK: add <4 x i16> +int16_t4 add(int16_t4 a, int16_t4 b) { + return a + b; +}