@@ -995,7 +995,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
995995 var isIndirectPointerField = IsTypePointerOrReference ( indirectFieldDecl , type ) && ( typeName != "IntPtr" ) && ( typeName != "UIntPtr" ) ;
996996
997997 _outputBuilder . BeginBody ( ) ;
998- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
998+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : fieldDecl . IsBitField && ! Config . GenerateCompatibleCode ) ;
999999 var code = _outputBuilder . BeginCSharpCode ( ) ;
10001000
10011001 if ( fieldDecl . IsBitField )
@@ -2439,7 +2439,8 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
24392439 bitfieldName += index . ToString ( ) ;
24402440 }
24412441
2442- typeBacking = ( index > 0 ) ? bitfieldDescs [ index - 1 ] . TypeBacking : bitfieldDescs [ 0 ] . TypeBacking ;
2442+ var bitfieldDesc = ( index > 0 ) ? bitfieldDescs [ index - 1 ] : bitfieldDescs [ 0 ] ;
2443+ typeBacking = bitfieldDesc . TypeBacking ;
24432444 typeNameBacking = GetRemappedTypeName ( fieldDecl , context : null , typeBacking , out _ ) ;
24442445 }
24452446
@@ -2452,6 +2453,8 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
24522453 return ;
24532454 }
24542455
2456+ var isTypeBackingSigned = false ;
2457+
24552458 switch ( builtinTypeBacking . Kind )
24562459 {
24572460 case CXType_Char_U :
@@ -2489,21 +2492,25 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
24892492 case CXType_Short :
24902493 case CXType_Int :
24912494 {
2495+ isTypeBackingSigned = true ;
24922496 break ;
24932497 }
24942498
24952499 case CXType_Long :
24962500 {
2501+ isTypeBackingSigned = true ;
2502+
24972503 if ( _config . GenerateUnixTypes )
24982504 {
24992505 goto default ;
25002506 }
2501-
2502- goto case CXType_Int ;
2507+ break ;
25032508 }
25042509
25052510 case CXType_LongLong :
25062511 {
2512+ isTypeBackingSigned = true ;
2513+
25072514 if ( typeNameBacking == "nint" )
25082515 {
25092516 goto case CXType_Int ;
@@ -2545,6 +2552,8 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
25452552 return ;
25462553 }
25472554
2555+ var isTypeSigned = false ;
2556+
25482557 switch ( builtinType . Kind )
25492558 {
25502559 case CXType_Char_U :
@@ -2582,21 +2591,25 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
25822591 case CXType_Short :
25832592 case CXType_Int :
25842593 {
2594+ isTypeSigned = true ;
25852595 break ;
25862596 }
25872597
25882598 case CXType_Long :
25892599 {
2600+ isTypeSigned = true ;
2601+
25902602 if ( _config . GenerateUnixTypes )
25912603 {
25922604 goto default ;
25932605 }
2594-
2595- goto case CXType_Int ;
2606+ break ;
25962607 }
25972608
25982609 case CXType_LongLong :
25992610 {
2611+ isTypeSigned = true ;
2612+
26002613 if ( typeNameBacking == "nint" )
26012614 {
26022615 goto case CXType_Int ;
@@ -2639,15 +2652,30 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
26392652 _outputBuilder . BeginField ( in desc ) ;
26402653 _outputBuilder . WriteRegularField ( typeName , escapedName ) ;
26412654 _outputBuilder . BeginBody ( ) ;
2642- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
2655+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : ! Config . GenerateCompatibleCode ) ;
26432656 var code = _outputBuilder . BeginCSharpCode ( ) ;
26442657
26452658 code . WriteIndented ( "return " ) ;
26462659
26472660 var recordDeclName = GetCursorName ( recordDecl ) ;
26482661
2662+ var isSmallType = currentSize < 4 ;
26492663 var isRemappedToSelf = _config . RemappedNames . TryGetValue ( typeName , out var remappedTypeName ) && typeName . Equals ( remappedTypeName ) ;
2650- var needsCast = ( currentSize < 4 ) || ( type != builtinTypeBacking ) || isRemappedToSelf ;
2664+ var isTypeMismatch = type != builtinTypeBacking ;
2665+ var isUnsignedToSigned = ! isTypeBackingSigned && isTypeSigned ;
2666+
2667+ var needsCast = isSmallType || isRemappedToSelf || isTypeMismatch || isUnsignedToSigned ;
2668+ var needsParenFirst = ! isSmallType && isUnsignedToSigned ;
2669+ var needsParenSecond = ! needsParenFirst || isRemappedToSelf ;
2670+
2671+ // backing int, current int (value << cns) >> cns
2672+ // backing int, current uint (uint)((value >> cns) & msk)
2673+
2674+ // backing uint, current int ((int)value << cns) >> cns
2675+ // backing uint, current uint (value >> cns) & msk
2676+
2677+ // backing uint, current byte (byte)((value >> cns) & msk)
2678+ // backing uint, current sbyte (sbyte)((value << cns) >> cns)
26512679
26522680 if ( needsCast )
26532681 {
@@ -2658,7 +2686,7 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
26582686 code . Write ( ")(" ) ;
26592687 }
26602688
2661- if ( bitfieldOffset != 0 )
2689+ if ( ( ! needsParenFirst && ( bitfieldOffset != 0 ) ) || ( ! needsCast && isTypeSigned ) )
26622690 {
26632691 code . Write ( '(' ) ;
26642692 }
@@ -2675,21 +2703,37 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
26752703 code . Write ( bitfieldName ) ;
26762704 code . EndMarker ( "bitfieldName" ) ;
26772705
2678- if ( bitfieldOffset != 0 )
2706+ if ( isTypeSigned )
26792707 {
2680- code . Write ( " >> " ) ;
2681- code . BeginMarker ( "bitfieldOffset " ) ;
2682- code . Write ( bitfieldOffset ) ;
2683- code . EndMarker ( "bitfieldOffset " ) ;
2708+ code . Write ( " << " ) ;
2709+ code . BeginMarker ( "remainingBitsMinusBitWidth " ) ;
2710+ code . Write ( remainingBits - fieldDecl . BitWidthValue ) ;
2711+ code . EndMarker ( "remainingBitsMinusBitWidth " ) ;
26842712 code . Write ( ')' ) ;
2713+
2714+ code . Write ( " >> " ) ;
2715+ code . BeginMarker ( "currentSizeMinusBitWidth" ) ;
2716+ code . Write ( ( currentSize * 8 ) - fieldDecl . BitWidthValue ) ;
2717+ code . EndMarker ( "currentSizeMinusBitWidth" ) ;
26852718 }
2719+ else
2720+ {
2721+ if ( bitfieldOffset != 0 )
2722+ {
2723+ code . Write ( " >> " ) ;
2724+ code . BeginMarker ( "bitfieldOffset" ) ;
2725+ code . Write ( bitfieldOffset ) ;
2726+ code . EndMarker ( "bitfieldOffset" ) ;
2727+ code . Write ( ')' ) ;
2728+ }
26862729
2687- code . Write ( " & 0x" ) ;
2688- code . BeginMarker ( "bitwidthHexStringBacking" ) ;
2689- code . Write ( bitwidthHexStringBacking ) ;
2690- code . EndMarker ( "bitwidthHexStringBacking" ) ;
2730+ code . Write ( " & 0x" ) ;
2731+ code . BeginMarker ( "bitwidthHexStringBacking" ) ;
2732+ code . Write ( bitwidthHexStringBacking ) ;
2733+ code . EndMarker ( "bitwidthHexStringBacking" ) ;
2734+ }
26912735
2692- if ( needsCast )
2736+ if ( needsCast && needsParenSecond )
26932737 {
26942738 code . Write ( ')' ) ;
26952739 }
@@ -2868,6 +2912,11 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
28682912 AddDiagnostic ( DiagnosticLevel . Info , $ "{ escapedName } (constant array field) has a size of 0", constantOrIncompleteArray ) ;
28692913 }
28702914
2915+ if ( ! _config . GeneratePreviewCode || ( totalSize <= 1 ) || isUnsafeElementType )
2916+ {
2917+ totalSizeString = null ;
2918+ }
2919+
28712920 var desc = new StructDesc {
28722921 AccessSpecifier = accessSpecifier ,
28732922 EscapedName = escapedName ,
@@ -2884,18 +2933,23 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
28842933 Location = constantOrIncompleteArray . Location ,
28852934 IsNested = true ,
28862935 WriteCustomAttrs = static context => {
2887- ( var fieldDecl , var outputBuilder , var generator , var totalSizeString ) = ( ( FieldDecl , IOutputBuilder , PInvokeGenerator , string ) ) context ;
2936+ ( var fieldDecl , var outputBuilder , var generator , var totalSizeString ) = ( ( FieldDecl , IOutputBuilder , PInvokeGenerator , string ? ) ) context ;
28882937
28892938 generator . WithAttributes ( fieldDecl ) ;
28902939 generator . WithUsings ( fieldDecl ) ;
2940+
2941+ if ( totalSizeString is not null )
2942+ {
2943+ outputBuilder . WriteCustomAttribute ( $ "InlineArray({ totalSizeString } )") ;
2944+ }
28912945 } ,
28922946 CustomAttrGeneratorData = ( constantOrIncompleteArray , _outputBuilder , this , totalSizeString ) ,
28932947 } ;
28942948
28952949 _outputBuilder . BeginStruct ( in desc ) ;
28962950
28972951 var firstFieldName = "" ;
2898- var numFieldsToEmit = totalSize ;
2952+ var numFieldsToEmit = ( totalSizeString is not null ) ? Math . Min ( totalSize , 1 ) : totalSize ;
28992953
29002954 for ( long i = 0 ; i < numFieldsToEmit ; i ++ )
29012955 {
@@ -2963,7 +3017,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
29633017 _outputBuilder . EndIndexerParameters ( ) ;
29643018 _outputBuilder . BeginBody ( ) ;
29653019
2966- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
3020+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : false ) ;
29673021 var code = _outputBuilder . BeginCSharpCode ( ) ;
29683022
29693023 code . WriteIndented ( "fixed (" ) ;
@@ -2982,7 +3036,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
29823036 _outputBuilder . EndBody ( ) ;
29833037 _outputBuilder . EndIndexer ( ) ;
29843038 }
2985- else
3039+ else if ( totalSizeString is null )
29863040 {
29873041 _outputBuilder . BeginIndexer ( AccessSpecifier . Public , isUnsafe : false , needsUnscopedRef : _config . GenerateLatestCode ) ;
29883042 _outputBuilder . WriteIndexer ( $ "ref { arrayTypeName } ") ;
@@ -2996,7 +3050,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
29963050 _outputBuilder . EndIndexerParameters ( ) ;
29973051 _outputBuilder . BeginBody ( ) ;
29983052
2999- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
3053+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : false ) ;
30003054 var code = _outputBuilder . BeginCSharpCode ( ) ;
30013055 code . AddUsingDirective ( "System" ) ;
30023056 code . AddUsingDirective ( "System.Runtime.InteropServices" ) ;
0 commit comments