diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2025-07-31 15:23:13 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-31 07:23:13 +0000 |
| commit | 66301ab9068c5705e5a2bcbf2eaadfb28e8bb084 (patch) | |
| tree | 3682e0224df6706bcf70f58e37873c1d078c785c /source/slang/slang-check-decl.cpp | |
| parent | db59c22cfb774e984a207a074f13870b78ec0071 (diff) | |
msvc style bitfield packing (#7963)
Closes https://github.com/shader-slang/slang/issues/3646
New tests rather than just adding another TEST line to existing tests so
that we get the msvc- prefix in the output of slang-test
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 02f404d88..98cdb9e61 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -14020,6 +14020,10 @@ void SemanticsDeclAttributesVisitor::visitStructDecl(StructDecl* structDecl) checkRayPayloadStructFields(structDecl); } + // Check if we should use MSVC-style bitfield packing + const bool useMSVCPacking = + getOptionSet().getBoolOption(CompilerOptionName::UseMSVCStyleBitfieldPacking); + int backingWidth = 0; [[maybe_unused]] int totalWidth = 0; struct BitFieldInfo @@ -14055,15 +14059,32 @@ void SemanticsDeclAttributesVisitor::visitStructDecl(StructDecl* structDecl) backingMember->parentDecl = structDecl; const auto backingMemberDeclRef = DeclRef<VarDecl>(backingMember->getDefaultDeclRef()); - int bottomOfMember = 0; - for (const auto m : groupInfo) + if (useMSVCPacking) { - SLANG_ASSERT(bottomOfMember <= backingWidth); + // MSVC packs from MSB to LSB + int currentBitPosition = backingWidth; + for (const auto& m : groupInfo) + { + currentBitPosition -= m.bitWidth; + SLANG_ASSERT(currentBitPosition >= 0); - m.bitFieldModifier->backingDeclRef = backingMemberDeclRef; - m.bitFieldModifier->offset = bottomOfMember; + m.bitFieldModifier->backingDeclRef = backingMemberDeclRef; + m.bitFieldModifier->offset = currentBitPosition; + } + } + else + { + // GCC/Clang pack from LSB to MSB + int bottomOfMember = 0; + for (const auto& m : groupInfo) + { + SLANG_ASSERT(bottomOfMember <= backingWidth); - bottomOfMember += m.bitWidth; + m.bitFieldModifier->backingDeclRef = backingMemberDeclRef; + m.bitFieldModifier->offset = bottomOfMember; + + bottomOfMember += m.bitWidth; + } } const auto backingMemberIndex = groupInfo[0].memberIndex; @@ -14080,6 +14101,9 @@ void SemanticsDeclAttributesVisitor::visitStructDecl(StructDecl* structDecl) totalWidth = 0; groupInfo.clear(); }; + + int previousFieldTypeWidth = 0; // Track the type width of the previous bitfield for MSVC mode + for (; memberIndex < structDecl->getDirectMemberDeclCount(); ++memberIndex) { const auto& m = structDecl->getDirectMemberDecl(memberIndex); @@ -14141,7 +14165,17 @@ void SemanticsDeclAttributesVisitor::visitStructDecl(StructDecl* structDecl) // If there's a 0 width type, dispatch the current group if (thisFieldWidth == 0) + { dispatchSomeBitPackedMembers(); + previousFieldTypeWidth = 0; + } + + // MSVC-specific behavior: start a new backing field if the type size changes + if (useMSVCPacking && groupInfo.getCount() > 0 && + thisFieldTypeWidth != previousFieldTypeWidth) + { + dispatchSomeBitPackedMembers(); + } // If this member wouldn't fit into the current group, dispatch // everything so far; @@ -14154,6 +14188,9 @@ void SemanticsDeclAttributesVisitor::visitStructDecl(StructDecl* structDecl) // Grow the total width totalWidth += int(thisFieldWidth); groupInfo.add({memberIndex, int(thisFieldWidth), t, bfm}); + + // Track the type width for MSVC mode + previousFieldTypeWidth = thisFieldTypeWidth; } // If the struct ended with a bitpacked member, then make sure we don't forget the last // group |
