Skip to content

Commit 0c45099

Browse files
llvm-beanzdamyanp
andauthored
[202x] Implementaiton of conforming literals (#6572)
This change implements the conforming literals proposal as documented in proposal 0017: https://github.com/microsoft/hlsl-specs/blob/main/proposals/0017-conform ing-literals.md Fixes #6537 --------- Co-authored-by: Damyan Pepper <[email protected]>
1 parent 00cd823 commit 0c45099

8 files changed

Lines changed: 343 additions & 11 deletions

File tree

tools/clang/include/clang/AST/HlslTypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ clang::QualType GetElementTypeOrType(clang::QualType type);
457457
bool HasHLSLMatOrientation(clang::QualType type, bool *pIsRowMajor = nullptr);
458458
bool IsHLSLMatRowMajor(clang::QualType type, bool defaultValue);
459459
bool IsHLSLUnsigned(clang::QualType type);
460+
bool IsHLSLMinPrecision(clang::QualType type);
460461
bool HasHLSLUNormSNorm(clang::QualType type, bool *pIsSNorm = nullptr);
461462
bool HasHLSLGloballyCoherent(clang::QualType type);
462463
bool IsHLSLInputPatchType(clang::QualType type);

tools/clang/lib/AST/HlslTypes.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,22 @@ bool IsHLSLUnsigned(clang::QualType type) {
224224
return type->isUnsignedIntegerType();
225225
}
226226

227+
bool IsHLSLMinPrecision(clang::QualType Ty) {
228+
Ty = Ty.getCanonicalType().getNonReferenceType();
229+
if (auto BT = Ty->getAs<clang::BuiltinType>()) {
230+
switch (BT->getKind()) {
231+
case clang::BuiltinType::Min12Int:
232+
case clang::BuiltinType::Min16Int:
233+
case clang::BuiltinType::Min16UInt:
234+
case clang::BuiltinType::Min16Float:
235+
case clang::BuiltinType::Min10Float:
236+
return true;
237+
}
238+
}
239+
240+
return false;
241+
}
242+
227243
bool HasHLSLUNormSNorm(clang::QualType type, bool *pIsSNorm) {
228244
// snorm/unorm can be on outer vector/matrix as well as element type
229245
// in the template form. Outer-most type attribute wins.

tools/clang/lib/Basic/TargetInfo.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,29 @@ void TargetInfo::adjust(const LangOptions &Opts) {
278278
if (Opts.ShortWChar)
279279
WCharType = UnsignedShort;
280280

281+
// HLSL Change Begin
282+
// We should have always set these values for HLSL, but instead we hacked
283+
// ASTContext::getTypeInfoImpl to override some of the uses (but not all).
284+
// With 202x relying more on Clang's C/C++ support we need to correctly set
285+
// the TargetInfo at least for this subset of types. This change probably
286+
// shouldn't be dependent on the language version, but I made it this way to
287+
// reduce any unforseen risk.
288+
if (Opts.HLSL) {
289+
// DXILTargetInfo in Tergets.cpp sets base values that aren't dependent on
290+
// language options. The values here adjust the base values once the
291+
// language options are initialized.
292+
if (Opts.HLSLVersion >= hlsl::LangStd::v202x) {
293+
IntWidth = IntAlign = 32;
294+
LongLongWidth = LongLongAlign = 64;
295+
if (!Opts.UseMinPrecision)
296+
HalfWidth = HalfAlign = 16;
297+
else
298+
HalfWidth = HalfAlign = 32;
299+
FloatWidth = FloatAlign = 32;
300+
}
301+
}
302+
// HLSL Change End
303+
281304
if (Opts.OpenCL) {
282305
// OpenCL C requires specific widths for types, irrespective of
283306
// what these normally are for the target.

tools/clang/lib/Frontend/InitPreprocessor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,10 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
376376
// HLSL Version
377377
Builder.defineMacro("__HLSL_VERSION",
378378
Twine((unsigned int)LangOpts.HLSLVersion));
379+
// This define is enabled in Clang and allows conditionally compiling code
380+
// based on whether or not native 16-bit types are supported.
381+
if (!LangOpts.UseMinPrecision)
382+
Builder.defineMacro("__HLSL_ENABLE_16_BIT", "1");
379383
// Shader target information
380384
// "enums" for shader stages
381385
Builder.defineMacro("__SHADER_STAGE_VERTEX", Twine((unsigned)hlsl::DXIL::ShaderKind::Vertex));

tools/clang/lib/Sema/SemaExpr.cpp

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3257,7 +3257,7 @@ ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {
32573257
unsigned IntSize = Context.getTargetInfo().getIntWidth();
32583258
// HLSL Change Starts - HLSL literal int
32593259
QualType Ty;
3260-
if (getLangOpts().HLSL) {
3260+
if (getLangOpts().HLSL && getLangOpts().HLSLVersion < hlsl::LangStd::v202x) {
32613261
IntSize = 64;
32623262
Ty = Context.LitIntTy;
32633263
} else
@@ -3451,13 +3451,21 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
34513451

34523452
Ty = Context.FloatTy;
34533453
// HLSL Change Starts
3454-
else if (getLangOpts().HLSL && !Literal.isLong && !Literal.isHalf)
3454+
else if (getLangOpts().HLSL &&
3455+
getLangOpts().HLSLVersion < hlsl::LangStd::v202x &&
3456+
!Literal.isLong && !Literal.isHalf)
34553457
Ty = Context.LitFloatTy;
3456-
else if (getLangOpts().HLSL && Literal.isLong)
3458+
else if (Literal.isLong)
34573459
Ty = Context.DoubleTy;
3458-
else if (getLangOpts().HLSL && Literal.isHalf) {
3459-
Ty = getLangOpts().UseMinPrecision ? Context.FloatTy : Context.HalfTy;
3460-
}
3460+
else if (Literal.isHalf) {
3461+
if (getLangOpts().HLSL &&
3462+
getLangOpts().HLSLVersion < hlsl::LangStd::v202x)
3463+
Ty = getLangOpts().UseMinPrecision ? Context.FloatTy : Context.HalfTy;
3464+
else
3465+
Ty = getLangOpts().UseMinPrecision ? Context.HalfFloatTy
3466+
: Context.HalfTy;
3467+
} else if (getLangOpts().HLSL)
3468+
Ty = Context.FloatTy;
34613469
// HLSL Change Ends
34623470
else if (!Literal.isLong)
34633471
Ty = Context.DoubleTy;
@@ -3480,7 +3488,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
34803488
return ExprError();
34813489

34823490
// HLSL Change Starts
3483-
} else if (getLangOpts().HLSL) {
3491+
} else if (getLangOpts().HLSL &&
3492+
getLangOpts().HLSLVersion < hlsl::LangStd::v202x) {
34843493
QualType Ty;
34853494
unsigned Width = 64;
34863495
llvm::APInt ResultVal(Width, 0);
@@ -3519,8 +3528,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
35193528
} else {
35203529
QualType Ty;
35213530

3531+
// HLSL Change: disable the warning below.
35223532
// 'long long' is a C99 or C++11 feature.
3523-
if (!getLangOpts().C99 && Literal.isLongLong) {
3533+
if (!getLangOpts().HLSL && !getLangOpts().C99 && Literal.isLongLong) {
35243534
if (getLangOpts().CPlusPlus)
35253535
Diag(Tok.getLocation(),
35263536
getLangOpts().CPlusPlus11 ?
@@ -3590,6 +3600,17 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
35903600
}
35913601
}
35923602

3603+
// HLSL Change Begin - Treat `long` literal as `long long`
3604+
// This is a bit hacky. HLSL doesn't really have a `long` or `long long`
3605+
// type so the specification has simplified the suffices. Unfortunately,
3606+
// rather than just treating `ll` as `l` we need to do the inverse. This
3607+
// is because we rely on the MSVC mangling which follows LLP64 (l being
3608+
// 32-bit and ll 64-bit). We should find a better solution to this in
3609+
// Clang.
3610+
if (getLangOpts().HLSL && !Literal.isLongLong)
3611+
Literal.isLongLong = Literal.isLong;
3612+
// HLSL Change End
3613+
35933614
// Are long/unsigned long possibilities?
35943615
if (Ty.isNull() && !Literal.isLongLong) {
35953616
unsigned LongSize = Context.getTargetInfo().getLongWidth();
@@ -3603,7 +3624,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
36033624
Ty = Context.UnsignedLongTy;
36043625
// Check according to the rules of C90 6.1.3.2p5. C++03 [lex.icon]p2
36053626
// is compatible.
3606-
else if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) {
3627+
// HLSL Change: HLSL will promote to the next signed integer type.
3628+
else if (!getLangOpts().HLSL && !getLangOpts().C99 &&
3629+
!getLangOpts().CPlusPlus11) {
36073630
const unsigned LongLongSize =
36083631
Context.getTargetInfo().getLongLongWidth();
36093632
Diag(Tok.getLocation(),
@@ -6319,8 +6342,17 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
63196342

63206343
// HLSL Change Starts: HLSL supports a vector condition and is
63216344
// sufficiently different to merit its own checker.
6322-
if (getLangOpts().HLSL)
6323-
return hlsl::CheckVectorConditional(this, Cond, LHS, RHS, QuestionLoc);
6345+
if (getLangOpts().HLSL) {
6346+
// For HLSL 202x+ in a ternary operator we follow C++ rules unless both the
6347+
// right and left are minimum precision types, or either type is not a
6348+
// builtin scalar integer or float (e.g. vector, matrix, UDT).
6349+
QualType LHSTy = LHS.get()->getType();
6350+
QualType RHSTy = RHS.get()->getType();
6351+
if (getLangOpts().HLSLVersion < hlsl::LangStd::v202x ||
6352+
!LHSTy->isBuiltinType() || !RHSTy->isBuiltinType() ||
6353+
(hlsl::IsHLSLMinPrecision(LHSTy) && hlsl::IsHLSLMinPrecision(RHSTy)))
6354+
return hlsl::CheckVectorConditional(this, Cond, LHS, RHS, QuestionLoc);
6355+
}
63246356
// HLSL Change Ends
63256357

63266358
// C++ is sufficiently different to merit its own checker.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %dxc -T lib_6_3 -HV 202x -verify -enable-16bit-types %s
2+
3+
void fn() {
4+
half H = asfloat16(1.0);
5+
// expected-error@-1{{no matching function for call to 'asfloat16'}}
6+
// expected-note@-2{{candidate function not viable: no known conversion from 'float' to 'half' for 1st argument}}
7+
}

0 commit comments

Comments
 (0)