summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2025-07-31 15:23:13 +0800
committerGitHub <noreply@github.com>2025-07-31 07:23:13 +0000
commit66301ab9068c5705e5a2bcbf2eaadfb28e8bb084 (patch)
tree3682e0224df6706bcf70f58e37873c1d078c785c /source/slang/slang-check-decl.cpp
parentdb59c22cfb774e984a207a074f13870b78ec0071 (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.cpp49
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