Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ line upon naming the release. Refer to previous for appropriate section names.

#### Other Changes
- Fixed mesh shader semantics that were incorrectly case sensitive.
- DXIL validation now rejects non-standard integer bit widths (e.g. `i25`) in instructions.

### Version 1.9.2602

Expand Down
26 changes: 22 additions & 4 deletions lib/DxilValidation/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2659,6 +2659,19 @@ static bool IsDxilBuiltinStructType(StructType *ST, hlsl::OP *HlslOP) {
}
}

static bool IsValidIntBitWidth(unsigned Width) {
switch (Width) {
case 1:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

// outer type may be: [ptr to][1 dim array of]( UDT struct | scalar )
// inner type (UDT struct member) may be: [N dim array of]( UDT struct | scalar
// ) scalar type may be: ( float(16|32|64) | int(16|32|64) )
Expand Down Expand Up @@ -2717,8 +2730,7 @@ static bool ValidateType(Type *Ty, ValidationContext &ValCtx,
return true;
}
if (Ty->isIntegerTy()) {
unsigned Width = Ty->getIntegerBitWidth();
if (Width != 1 && Width != 8 && Width != 16 && Width != 32 && Width != 64) {
if (!IsValidIntBitWidth(Ty->getIntegerBitWidth())) {
ValCtx.EmitTypeError(Ty, ValidationRule::TypesIntWidth);
return false;
}
Expand Down Expand Up @@ -3388,10 +3400,13 @@ static void ValidateFunctionBody(Function *F, ValidationContext &ValCtx) {
}
}
if (IntegerType *IT = dyn_cast<IntegerType>(op->getType())) {
if (IT->getBitWidth() == 8) {
unsigned BW = IT->getBitWidth();
if (BW == 8) {
// We always fail if we see i8 as operand type of a non-lifetime
// instruction.
ValCtx.EmitInstrError(&I, ValidationRule::TypesI8);
} else {
ValidateType(IT, ValCtx);
}
}
}
Expand All @@ -3402,12 +3417,15 @@ static void ValidateFunctionBody(Function *F, ValidationContext &ValCtx) {
while (isa<ArrayType>(Ty))
Ty = Ty->getArrayElementType();
if (IntegerType *IT = dyn_cast<IntegerType>(Ty)) {
if (IT->getBitWidth() == 8) {
unsigned BW = IT->getBitWidth();
if (BW == 8) {
// Allow i8* cast for llvm.lifetime.* intrinsics.
if (!SupportsLifetimeIntrinsics || !isa<BitCastInst>(I) ||
!onlyUsedByLifetimeMarkers(&I)) {
ValCtx.EmitInstrError(&I, ValidationRule::TypesI8);
}
} else {
ValidateType(IT, ValCtx);
}
}

Expand Down
35 changes: 35 additions & 0 deletions tools/clang/test/LitDXILValidation/int-width-validation.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
; RUN: not %dxv %s 2>&1 | FileCheck %s

target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
target triple = "dxil-ms-dx"

; CHECK: Int type 'i25' has an invalid width.
; CHECK: Int type 'i25' has an invalid width.
; CHECK: Validation failed.

define void @main() {
; Test invalid int width in operand and result types.
%1 = add i25 0, 1
; Test invalid int width inside array result type.
%2 = select i1 true, [2 x i25] zeroinitializer, [2 x i25] zeroinitializer
call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float 0.000000e+00)
ret void
}

declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #0

attributes #0 = { nounwind }

!dx.version = !{!0}
!dx.valver = !{!0}
!dx.shaderModel = !{!1}
!dx.entryPoints = !{!2}

!0 = !{i32 1, i32 0}
!1 = !{!"ps", i32 6, i32 0}
!2 = !{void ()* @main, !"main", !3, null, null}
!3 = !{null, !4, null}
!4 = !{!5}
!5 = !{i32 0, !"SV_Target", i8 9, i8 16, !6, i8 0, i32 1, i8 1, i32 0, i8 0, !7}
!6 = !{i32 0}
!7 = !{i32 3, i32 1}