Skip to content

Commit 3d2a58d

Browse files
committed
[spirv] Limit firstbithigh/low to 32-bit args
Becuase the underlying GLSL.std.450 instructions FindSMsb, FindUMsb and FindILsB are currently limited to 32-bit width components, we should emit an explicit error messages when these instructions would be generated incorrectly in the SPIR-V backend. Closes microsoft#4702
1 parent 969ff6e commit 3d2a58d

File tree

4 files changed

+51
-22
lines changed

4 files changed

+51
-22
lines changed

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8287,25 +8287,6 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
82878287
srcLoc, srcRange); \
82888288
} break
82898289

8290-
#define INTRINSIC_OP_CASE_SINT_UINT(intrinsicOp, glslSintOp, glslUintOp, \
8291-
doEachVec) \
8292-
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
8293-
glslOpcode = isSintType ? GLSLstd450::GLSLstd450##glslSintOp \
8294-
: GLSLstd450::GLSLstd450##glslUintOp; \
8295-
retVal = processIntrinsicUsingGLSLInst(callExpr, glslOpcode, doEachVec, \
8296-
srcLoc, srcRange); \
8297-
} break
8298-
8299-
#define INTRINSIC_OP_CASE_SINT_UINT_FLOAT(intrinsicOp, glslSintOp, glslUintOp, \
8300-
glslFloatOp, doEachVec) \
8301-
case hlsl::IntrinsicOp::IOP_##intrinsicOp: { \
8302-
glslOpcode = isFloatType ? GLSLstd450::GLSLstd450##glslFloatOp \
8303-
: isSintType ? GLSLstd450::GLSLstd450##glslSintOp \
8304-
: GLSLstd450::GLSLstd450##glslUintOp; \
8305-
retVal = processIntrinsicUsingGLSLInst(callExpr, glslOpcode, doEachVec, \
8306-
srcLoc, srcRange); \
8307-
} break
8308-
83098290
switch (const auto hlslOpcode = static_cast<hlsl::IntrinsicOp>(opcode)) {
83108291
case hlsl::IntrinsicOp::IOP_InterlockedAdd:
83118292
case hlsl::IntrinsicOp::IOP_InterlockedAnd:
@@ -8713,6 +8694,35 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
87138694
srcRange);
87148695
break;
87158696
}
8697+
case hlsl::IntrinsicOp::IOP_ufirstbithigh:
8698+
case hlsl::IntrinsicOp::IOP_firstbithigh: {
8699+
const QualType argType = callExpr->getArg(0)->getType();
8700+
if (astContext.getTypeSize(argType) == 64) {
8701+
emitError("%0 is currently limited to 32-bit width components when "
8702+
"targetting SPIR-V",
8703+
srcLoc)
8704+
<< getFunctionOrOperatorName(callee, true);
8705+
return 0;
8706+
}
8707+
8708+
glslOpcode = isSintType ? GLSLstd450::GLSLstd450FindSMsb
8709+
: GLSLstd450::GLSLstd450FindUMsb;
8710+
retVal = processIntrinsicUsingGLSLInst(callExpr, glslOpcode, false, srcLoc,
8711+
srcRange);
8712+
} break;
8713+
case hlsl::IntrinsicOp::IOP_firstbitlow: {
8714+
const QualType argType = callExpr->getArg(0)->getType();
8715+
if (astContext.getTypeSize(argType) == 64) {
8716+
emitError("%0 is currently limited to 32-bit width components when "
8717+
"targetting SPIR-V",
8718+
srcLoc)
8719+
<< getFunctionOrOperatorName(callee, true);
8720+
return 0;
8721+
}
8722+
glslOpcode = GLSLstd450::GLSLstd450FindILsb;
8723+
retVal = processIntrinsicUsingGLSLInst(callExpr, glslOpcode, false, srcLoc,
8724+
srcRange);
8725+
} break;
87168726
INTRINSIC_SPIRV_OP_CASE(ddx, DPdx, true);
87178727
INTRINSIC_SPIRV_OP_CASE(ddx_coarse, DPdxCoarse, false);
87188728
INTRINSIC_SPIRV_OP_CASE(ddx_fine, DPdxFine, false);
@@ -8743,10 +8753,7 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
87438753
INTRINSIC_OP_CASE(determinant, Determinant, false);
87448754
INTRINSIC_OP_CASE(exp, Exp, true);
87458755
INTRINSIC_OP_CASE(exp2, Exp2, true);
8746-
INTRINSIC_OP_CASE_SINT_UINT(firstbithigh, FindSMsb, FindUMsb, false);
8747-
INTRINSIC_OP_CASE_SINT_UINT(ufirstbithigh, FindSMsb, FindUMsb, false);
87488756
INTRINSIC_OP_CASE(faceforward, FaceForward, false);
8749-
INTRINSIC_OP_CASE(firstbitlow, FindILsb, false);
87508757
INTRINSIC_OP_CASE(floor, Floor, true);
87518758
INTRINSIC_OP_CASE(fma, Fma, true);
87528759
INTRINSIC_OP_CASE(frac, Fract, true);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %dxc -T ps_6_0 -E main
2+
3+
void main() {
4+
uint64_t uint_1;
5+
uint64_t fbh = firstbithigh(uint_1);
6+
}
7+
8+
// CHECK: error: firstbithigh is currently limited to 32-bit width components when targetting SPIR-V
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %dxc -T ps_6_0 -E main
2+
3+
void main() {
4+
uint64_t uint_1;
5+
uint64_t fbl = firstbitlow(uint_1);
6+
}
7+
8+
// CHECK: error: firstbitlow is currently limited to 32-bit width components when targetting SPIR-V

tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,9 +1274,15 @@ TEST_F(FileTest, IntrinsicsFaceForward) {
12741274
TEST_F(FileTest, IntrinsicsFirstBitHigh) {
12751275
runFileTest("intrinsics.firstbithigh.hlsl");
12761276
}
1277+
TEST_F(FileTest, IntrinsicsFirstBitHigh64bit) {
1278+
runFileTest("intrinsics.firstbithigh.64bit.hlsl", Expect::Failure);
1279+
}
12771280
TEST_F(FileTest, IntrinsicsFirstBitLow) {
12781281
runFileTest("intrinsics.firstbitlow.hlsl");
12791282
}
1283+
TEST_F(FileTest, IntrinsicsFirstBitLow64bit) {
1284+
runFileTest("intrinsics.firstbitlow.64bit.hlsl", Expect::Failure);
1285+
}
12801286
TEST_F(FileTest, IntrinsicsPrintf) { runFileTest("intrinsics.printf.hlsl"); }
12811287
TEST_F(FileTest, IntrinsicsFloor) { runFileTest("intrinsics.floor.hlsl"); }
12821288
TEST_F(FileTest, IntrinsicsFmod) { runFileTest("intrinsics.fmod.hlsl"); }

0 commit comments

Comments
 (0)