diff options
| author | Yong He <yonghe@outlook.com> | 2025-03-19 11:44:04 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-19 11:44:04 -0700 |
| commit | 4eb7a27ac4532a49b9d383d2b0d80bc0ec317b4c (patch) | |
| tree | 3219e185674c04423e3306437e2a31223fadeb49 | |
| parent | eee974d74617944ca2b6f6ac424e98a12a51b82c (diff) | |
Fix reinterpret and bitcast and generic arg parsing. (#6627)
* Fix reinterpret and bitcast.
* Fix warning.
* Fix.
* Fix.
---------
Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com>
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-ir-extract-value-from-type.cpp | 13 | ||||
| -rw-r--r-- | source/slang/slang-ir-layout.cpp | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-bit-cast.cpp | 28 | ||||
| -rw-r--r-- | source/slang/slang-ir-lower-reinterpret.cpp | 13 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 25 | ||||
| -rw-r--r-- | tests/language-feature/bit-cast/struct-bit-cast-2.slang | 49 | ||||
| -rw-r--r-- | tests/language-feature/bit-cast/struct-reinterpret.slang | 47 | ||||
| -rw-r--r-- | tests/language-feature/reinterpret/narrowing-reinterpret-warning.slang | 12 | ||||
| -rw-r--r-- | tests/language-feature/reinterpret/widening-reinterpret-warning.slang | 12 |
10 files changed, 138 insertions, 68 deletions
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 981ed8439..e9fa72bce 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -2311,12 +2311,6 @@ DIAGNOSTIC( notEqualBitCastSize, "invalid to bit_cast differently sized types: '$0' with size '$1' casted into '$2' with size " "'$3'") -DIAGNOSTIC( - 41203, - Warning, - notEqualReinterpretCastSize, - "reinterpret<> into not equally sized types: '$0' with size '$1' casted into '$2' with size " - "'$3'") DIAGNOSTIC( 41300, diff --git a/source/slang/slang-ir-extract-value-from-type.cpp b/source/slang/slang-ir-extract-value-from-type.cpp index 919274863..acb17068f 100644 --- a/source/slang/slang-ir-extract-value-from-type.cpp +++ b/source/slang/slang-ir-extract-value-from-type.cpp @@ -231,6 +231,7 @@ IRInst* extractMultiByteValueAtOffset( { // The request value is fully contained in the found leaf element. // We can proceed to extract the requested bits from the element. + resultValue = builder.emitBitCast(uintType, leaf.leafValue); uint32_t shift = leaf.offsetInValue * 8; if (shift > 0) resultValue = @@ -242,7 +243,7 @@ IRInst* extractMultiByteValueAtOffset( bitMask = 0xFF; break; case 2: - bitMask = 0xFFFFF; + bitMask = 0xFFFF; break; case 3: bitMask = 0xFFFFFF; @@ -264,23 +265,25 @@ IRInst* extractMultiByteValueAtOffset( { // The requested value crosses the boundaries of different fields. // We need to extract first and second half separately, and combine them together. + auto firstHalfSize = leaf.valueSize - leaf.offsetInValue; auto firstHalf = extractMultiByteValueAtOffset( builder, targetProgram, dataType, layout, src, - size / 2, + firstHalfSize, offset); + auto restSize = size - firstHalfSize; auto secondHalf = extractMultiByteValueAtOffset( builder, targetProgram, dataType, layout, src, - size / 2, - offset + size / 2); - uint32_t shift = (size / 2) * 8; + restSize, + offset + firstHalfSize); + uint32_t shift = firstHalfSize * 8; resultValue = builder.emitAdd( builder.getUIntType(), firstHalf, diff --git a/source/slang/slang-ir-layout.cpp b/source/slang/slang-ir-layout.cpp index c60b39248..ec5389f56 100644 --- a/source/slang/slang-ir-layout.cpp +++ b/source/slang/slang-ir-layout.cpp @@ -341,6 +341,7 @@ static Result _calcSizeAndAlignment( case kIROp_ComPtrType: case kIROp_NativeStringType: case kIROp_RaytracingAccelerationStructureType: + case kIROp_FuncType: { *outSizeAndAlignment = IRSizeAndAlignment(kPointerSize, kPointerSize); return SLANG_OK; diff --git a/source/slang/slang-ir-lower-bit-cast.cpp b/source/slang/slang-ir-lower-bit-cast.cpp index 450ad8ac9..47fd01c49 100644 --- a/source/slang/slang-ir-lower-bit-cast.cpp +++ b/source/slang/slang-ir-lower-bit-cast.cpp @@ -171,6 +171,7 @@ struct BitCastLoweringContext case kIROp_UInt16Type: { auto object = extractValueAtOffset(builder, targetProgram, src, offset, 2); + object = builder.emitCast(builder.getUInt16Type(), object); return builder.emitBitCast(type, object); } break; @@ -184,6 +185,7 @@ struct BitCastLoweringContext #endif { auto object = extractValueAtOffset(builder, targetProgram, src, offset, 4); + object = builder.emitCast(builder.getUIntType(), object); return builder.emitBitCast(type, object); } break; @@ -195,25 +197,19 @@ struct BitCastLoweringContext case kIROp_UIntPtrType: #endif case kIROp_RawPointerType: + case kIROp_PtrType: + case kIROp_FuncType: { - auto low = extractValueAtOffset(builder, targetProgram, src, offset, 4); - auto high = extractValueAtOffset(builder, targetProgram, src, offset + 4, 4); - auto combined = builder.emitAdd( - builder.getUInt64Type(), - low, - builder.emitShl( - builder.getUInt64Type(), - high, - builder.getIntValue(builder.getUIntType(), 32))); - if (type->getOp() == kIROp_UInt64Type) - return combined; - return builder.emitBitCast(type, combined); + auto object = extractValueAtOffset(builder, targetProgram, src, offset, 8); + object = builder.emitCast(builder.getUInt64Type(), object); + return builder.emitBitCast(type, object); } break; case kIROp_UInt8Type: case kIROp_Int8Type: { auto object = extractValueAtOffset(builder, targetProgram, src, offset, 1); + object = builder.emitCast(builder.getUInt8Type(), object); return builder.emitBitCast(type, object); } break; @@ -250,14 +246,6 @@ struct BitCastLoweringContext return; } // Ignore cases we cannot handle yet. - if (as<IRPtrType>(fromType) || as<IRPtrType>(toType)) - { - return; - } - if (as<IRRawPointerType>(fromType) || as<IRRawPointerType>(toType)) - { - return; - } if (as<IRResourceTypeBase>(fromType) || as<IRResourceTypeBase>(toType)) { return; diff --git a/source/slang/slang-ir-lower-reinterpret.cpp b/source/slang/slang-ir-lower-reinterpret.cpp index 88c288f28..6624b5f1a 100644 --- a/source/slang/slang-ir-lower-reinterpret.cpp +++ b/source/slang/slang-ir-lower-reinterpret.cpp @@ -61,10 +61,8 @@ struct ReinterpretLoweringContext auto fromType = operand->getDataType(); auto toType = inst->getDataType(); SlangInt fromTypeSize = getAnyValueSize(fromType); - bool cantPack = false; if (fromTypeSize < 0) { - cantPack = true; sink->diagnose( inst->sourceLoc, Slang::Diagnostics::typeCannotBePackedIntoAnyValue, @@ -73,22 +71,11 @@ struct ReinterpretLoweringContext SlangInt toTypeSize = getAnyValueSize(toType); if (toTypeSize < 0) { - cantPack = true; sink->diagnose( inst->sourceLoc, Slang::Diagnostics::typeCannotBePackedIntoAnyValue, toType); } - if (fromTypeSize != toTypeSize && !cantPack && !as<IRExtractExistentialType>(fromType)) - { - sink->diagnose( - inst->sourceLoc, - Slang::Diagnostics::notEqualReinterpretCastSize, - fromType, - fromTypeSize, - toType, - toTypeSize); - } SlangInt anyValueSize = Math::Max(fromTypeSize, toTypeSize); IRBuilder builder(module); diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index aec3b4e90..6bf26b014 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -7721,6 +7721,31 @@ static Expr* parsePostfixExpr(Parser* parser) expr = memberExpr; } break; + case TokenType::OpMul: + { + // We may have a pointer type expr, e.g. T*, or the `*` is a mul operator. + // We can easily disambiguate by looking ahead of `*`, if the token after it + // is `,`, `>`, `)` or `>>`, then it must be a type postfix. + auto lookahead = peekTokenType(parser, 1); + switch (lookahead) + { + case TokenType::Comma: + case TokenType::RParent: + case TokenType::OpGreater: + case TokenType::OpRsh: + case TokenType::Colon: + case TokenType::Semicolon: + case TokenType::LBracket: + case TokenType::OpMul: + case TokenType::Dot: + case TokenType::Scope: + expr = parsePostfixTypeSuffix(parser, expr); + break; + default: + return expr; + } + } + break; } } } diff --git a/tests/language-feature/bit-cast/struct-bit-cast-2.slang b/tests/language-feature/bit-cast/struct-bit-cast-2.slang new file mode 100644 index 000000000..edf91e00b --- /dev/null +++ b/tests/language-feature/bit-cast/struct-bit-cast-2.slang @@ -0,0 +1,49 @@ +// struct-bit-cast-2.slang +// Test bit casts for read across boundaries of scalar types. + +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -vk -shaderobj +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -cpu -shaderobj +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -cuda -shaderobj + +// Test that bit_cast works for bit-reinterpreting one struct type as another. + +struct Foo +{ + uint16_t a; + uint16_t b; + uint32_t c; +} + +struct Bar +{ + uint64_t d; +} + + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer<int> outputBuffer; + +[numthreads(1, 1, 1)] +void computeMain(int3 dispatchThreadID : SV_DispatchThreadID) +{ + Bar b = { 0x1122334455667788 }; + + Foo f = bit_cast<Foo>(b); + // CHECK: 7788 + outputBuffer[0] = f.a; + // CHECK: 5566 + outputBuffer[1] = f.b; + // CHECK: 11223344 + outputBuffer[2] = f.c; + + uint8_t4 v = {0x10, 0x20, 0x30, 0x40}; + uint32_t u = bit_cast<uint32_t>(v); + + // CHECK: 40302010 + outputBuffer[3] = u; + + int* ptr = bit_cast<int*>(b.d); + Foo f1 = bit_cast<Foo>(ptr); + // CHECK: 11223344 + outputBuffer[4] = f1.c; +} diff --git a/tests/language-feature/bit-cast/struct-reinterpret.slang b/tests/language-feature/bit-cast/struct-reinterpret.slang new file mode 100644 index 000000000..6be359d79 --- /dev/null +++ b/tests/language-feature/bit-cast/struct-reinterpret.slang @@ -0,0 +1,47 @@ +// struct-bit-cast-2.slang +// Test bit casts for read across boundaries of scalar types. + +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -vk -shaderobj +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -cpu -shaderobj +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -cuda -shaderobj + +// Test that bit_cast works for bit-reinterpreting one struct type as another. + +struct Foo +{ + uint16_t a; + uint16_t b; + uint32_t c; +} + +struct Bar +{ + uint64_t d; +} + + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer<int> outputBuffer; + +[numthreads(1, 1, 1)] +void computeMain(int3 dispatchThreadID : SV_DispatchThreadID) +{ + Bar b = { 0x1122334455667788 }; + Foo f = reinterpret<Foo>(b); + // CHECK: 7788 + outputBuffer[0] = f.a; + // CHECK: 5566 + outputBuffer[1] = f.b; + // CHECK: 11223344 + outputBuffer[2] = f.c; + + uint8_t4 v = {0x10, 0x20, 0x30, 0x40}; + uint32_t u = reinterpret<uint32_t>(v); + + // CHECK: 40302010 + outputBuffer[3] = u; + int* ptr = reinterpret<int*>(b.d); + Foo f1 = reinterpret<Foo>(ptr); + // CHECK: 11223344 + outputBuffer[4] = f1.c; +} diff --git a/tests/language-feature/reinterpret/narrowing-reinterpret-warning.slang b/tests/language-feature/reinterpret/narrowing-reinterpret-warning.slang deleted file mode 100644 index 98ed71165..000000000 --- a/tests/language-feature/reinterpret/narrowing-reinterpret-warning.slang +++ /dev/null @@ -1,12 +0,0 @@ -//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -stage compute -entry computeMain - -uniform StructuredBuffer<uint32_t[2]> in; -uniform RWStructuredBuffer<uint32_t> out; - -// CHECK: warning 41203{{.*}}8{{.*}}4 - -[numthreads(4, 1, 1)] -[shader("compute")] -void computeMain() { - out[0] = reinterpret<uint32_t>(in[0]); -}
\ No newline at end of file diff --git a/tests/language-feature/reinterpret/widening-reinterpret-warning.slang b/tests/language-feature/reinterpret/widening-reinterpret-warning.slang deleted file mode 100644 index 2f643cc3f..000000000 --- a/tests/language-feature/reinterpret/widening-reinterpret-warning.slang +++ /dev/null @@ -1,12 +0,0 @@ -//TEST:SIMPLE(filecheck=CHECK): -target spirv -emit-spirv-directly -stage compute -entry computeMain - -uniform StructuredBuffer<uint32_t> in; -uniform RWStructuredBuffer<uint32_t[2]> out; - -//CHECK: warning 41203{{.*}}4{{.*}}8 - -[numthreads(4, 1, 1)] -[shader("compute")] -void computeMain() { - out[0] = reinterpret<uint32_t[2]>(in[0]); -}
\ No newline at end of file |
