@@ -995,7 +995,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
995
995
var isIndirectPointerField = IsTypePointerOrReference ( indirectFieldDecl , type ) && ( typeName != "IntPtr" ) && ( typeName != "UIntPtr" ) ;
996
996
997
997
_outputBuilder . BeginBody ( ) ;
998
- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
998
+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : fieldDecl . IsBitField && ! Config . GenerateCompatibleCode ) ;
999
999
var code = _outputBuilder . BeginCSharpCode ( ) ;
1000
1000
1001
1001
if ( fieldDecl . IsBitField )
@@ -2439,7 +2439,8 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2439
2439
bitfieldName += index . ToString ( ) ;
2440
2440
}
2441
2441
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 ;
2443
2444
typeNameBacking = GetRemappedTypeName ( fieldDecl , context : null , typeBacking , out _ ) ;
2444
2445
}
2445
2446
@@ -2452,6 +2453,8 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2452
2453
return ;
2453
2454
}
2454
2455
2456
+ var isTypeBackingSigned = false ;
2457
+
2455
2458
switch ( builtinTypeBacking . Kind )
2456
2459
{
2457
2460
case CXType_Char_U :
@@ -2489,21 +2492,25 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2489
2492
case CXType_Short :
2490
2493
case CXType_Int :
2491
2494
{
2495
+ isTypeBackingSigned = true ;
2492
2496
break ;
2493
2497
}
2494
2498
2495
2499
case CXType_Long :
2496
2500
{
2501
+ isTypeBackingSigned = true ;
2502
+
2497
2503
if ( _config . GenerateUnixTypes )
2498
2504
{
2499
2505
goto default ;
2500
2506
}
2501
-
2502
- goto case CXType_Int ;
2507
+ break ;
2503
2508
}
2504
2509
2505
2510
case CXType_LongLong :
2506
2511
{
2512
+ isTypeBackingSigned = true ;
2513
+
2507
2514
if ( typeNameBacking == "nint" )
2508
2515
{
2509
2516
goto case CXType_Int ;
@@ -2545,6 +2552,8 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2545
2552
return ;
2546
2553
}
2547
2554
2555
+ var isTypeSigned = false ;
2556
+
2548
2557
switch ( builtinType . Kind )
2549
2558
{
2550
2559
case CXType_Char_U :
@@ -2582,21 +2591,25 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2582
2591
case CXType_Short :
2583
2592
case CXType_Int :
2584
2593
{
2594
+ isTypeSigned = true ;
2585
2595
break ;
2586
2596
}
2587
2597
2588
2598
case CXType_Long :
2589
2599
{
2600
+ isTypeSigned = true ;
2601
+
2590
2602
if ( _config . GenerateUnixTypes )
2591
2603
{
2592
2604
goto default ;
2593
2605
}
2594
-
2595
- goto case CXType_Int ;
2606
+ break ;
2596
2607
}
2597
2608
2598
2609
case CXType_LongLong :
2599
2610
{
2611
+ isTypeSigned = true ;
2612
+
2600
2613
if ( typeNameBacking == "nint" )
2601
2614
{
2602
2615
goto case CXType_Int ;
@@ -2639,15 +2652,30 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2639
2652
_outputBuilder . BeginField ( in desc ) ;
2640
2653
_outputBuilder . WriteRegularField ( typeName , escapedName ) ;
2641
2654
_outputBuilder . BeginBody ( ) ;
2642
- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
2655
+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : ! Config . GenerateCompatibleCode ) ;
2643
2656
var code = _outputBuilder . BeginCSharpCode ( ) ;
2644
2657
2645
2658
code . WriteIndented ( "return " ) ;
2646
2659
2647
2660
var recordDeclName = GetCursorName ( recordDecl ) ;
2648
2661
2662
+ var isSmallType = currentSize < 4 ;
2649
2663
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)
2651
2679
2652
2680
if ( needsCast )
2653
2681
{
@@ -2658,7 +2686,7 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2658
2686
code . Write ( ")(" ) ;
2659
2687
}
2660
2688
2661
- if ( bitfieldOffset != 0 )
2689
+ if ( ( ! needsParenFirst && ( bitfieldOffset != 0 ) ) || ( ! needsCast && isTypeSigned ) )
2662
2690
{
2663
2691
code . Write ( '(' ) ;
2664
2692
}
@@ -2675,21 +2703,37 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record
2675
2703
code . Write ( bitfieldName ) ;
2676
2704
code . EndMarker ( "bitfieldName" ) ;
2677
2705
2678
- if ( bitfieldOffset != 0 )
2706
+ if ( isTypeSigned )
2679
2707
{
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 " ) ;
2684
2712
code . Write ( ')' ) ;
2713
+
2714
+ code . Write ( " >> " ) ;
2715
+ code . BeginMarker ( "currentSizeMinusBitWidth" ) ;
2716
+ code . Write ( ( currentSize * 8 ) - fieldDecl . BitWidthValue ) ;
2717
+ code . EndMarker ( "currentSizeMinusBitWidth" ) ;
2685
2718
}
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
+ }
2686
2729
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
+ }
2691
2735
2692
- if ( needsCast )
2736
+ if ( needsCast && needsParenSecond )
2693
2737
{
2694
2738
code . Write ( ')' ) ;
2695
2739
}
@@ -2868,6 +2912,11 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
2868
2912
AddDiagnostic ( DiagnosticLevel . Info , $ "{ escapedName } (constant array field) has a size of 0", constantOrIncompleteArray ) ;
2869
2913
}
2870
2914
2915
+ if ( ! _config . GeneratePreviewCode || ( totalSize <= 1 ) || isUnsafeElementType )
2916
+ {
2917
+ totalSizeString = null ;
2918
+ }
2919
+
2871
2920
var desc = new StructDesc {
2872
2921
AccessSpecifier = accessSpecifier ,
2873
2922
EscapedName = escapedName ,
@@ -2884,18 +2933,23 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
2884
2933
Location = constantOrIncompleteArray . Location ,
2885
2934
IsNested = true ,
2886
2935
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 ;
2888
2937
2889
2938
generator . WithAttributes ( fieldDecl ) ;
2890
2939
generator . WithUsings ( fieldDecl ) ;
2940
+
2941
+ if ( totalSizeString is not null )
2942
+ {
2943
+ outputBuilder . WriteCustomAttribute ( $ "InlineArray({ totalSizeString } )") ;
2944
+ }
2891
2945
} ,
2892
2946
CustomAttrGeneratorData = ( constantOrIncompleteArray , _outputBuilder , this , totalSizeString ) ,
2893
2947
} ;
2894
2948
2895
2949
_outputBuilder . BeginStruct ( in desc ) ;
2896
2950
2897
2951
var firstFieldName = "" ;
2898
- var numFieldsToEmit = totalSize ;
2952
+ var numFieldsToEmit = ( totalSizeString is not null ) ? Math . Min ( totalSize , 1 ) : totalSize ;
2899
2953
2900
2954
for ( long i = 0 ; i < numFieldsToEmit ; i ++ )
2901
2955
{
@@ -2963,7 +3017,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
2963
3017
_outputBuilder . EndIndexerParameters ( ) ;
2964
3018
_outputBuilder . BeginBody ( ) ;
2965
3019
2966
- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
3020
+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : false ) ;
2967
3021
var code = _outputBuilder . BeginCSharpCode ( ) ;
2968
3022
2969
3023
code . WriteIndented ( "fixed (" ) ;
@@ -2982,7 +3036,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
2982
3036
_outputBuilder . EndBody ( ) ;
2983
3037
_outputBuilder . EndIndexer ( ) ;
2984
3038
}
2985
- else
3039
+ else if ( totalSizeString is null )
2986
3040
{
2987
3041
_outputBuilder . BeginIndexer ( AccessSpecifier . Public , isUnsafe : false , needsUnscopedRef : _config . GenerateLatestCode ) ;
2988
3042
_outputBuilder . WriteIndexer ( $ "ref { arrayTypeName } ") ;
@@ -2996,7 +3050,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
2996
3050
_outputBuilder . EndIndexerParameters ( ) ;
2997
3051
_outputBuilder . BeginBody ( ) ;
2998
3052
2999
- _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining ) ;
3053
+ _outputBuilder . BeginGetter ( _config . GenerateAggressiveInlining , isReadOnly : false ) ;
3000
3054
var code = _outputBuilder . BeginCSharpCode ( ) ;
3001
3055
code . AddUsingDirective ( "System" ) ;
3002
3056
code . AddUsingDirective ( "System.Runtime.InteropServices" ) ;
0 commit comments