Skip to content

Commit 62079b2

Browse files
committed
Use InlineArray instead of fixed when using latest codegen
1 parent e1690f3 commit 62079b2

30 files changed

+831
-242
lines changed

sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.Visit.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void WriteDivider(bool force = false)
7373

7474
public void WriteIid(string name, Guid value)
7575
{
76-
if (_config.GenerateUnmanagedConstants)
76+
if (_generator.Config.GenerateUnmanagedConstants)
7777
{
7878
AddUsingDirective("System");
7979
AddUsingDirective("System.Diagnostics");
@@ -89,7 +89,7 @@ public void WriteIid(string name, Guid value)
8989

9090
WriteIndented("ReadOnlySpan<byte> data = ");
9191

92-
if (_config.GenerateLatestCode)
92+
if (_generator.Config.GenerateLatestCode)
9393
{
9494
WriteLine('[');
9595
}
@@ -124,7 +124,7 @@ public void WriteIid(string name, Guid value)
124124
WriteNewline();
125125
DecreaseIndentation();
126126

127-
if (_config.GenerateLatestCode)
127+
if (_generator.Config.GenerateLatestCode)
128128
{
129129
WriteIndented(']');
130130
}

sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public void EndUnchecked()
3131

3232
public void BeginValue(in ValueDesc desc)
3333
{
34-
if (_config.GenerateDocIncludes && (desc.Kind == ValueKind.Enumerator))
34+
if (_generator.Config.GenerateDocIncludes && (desc.Kind == ValueKind.Enumerator))
3535
{
3636
WriteIndented("/// <include file='");
3737
Write(desc.ParentName);
@@ -63,7 +63,7 @@ public void BeginValue(in ValueDesc desc)
6363
}
6464
else if (desc.IsConstant)
6565
{
66-
if (_config.GenerateUnmanagedConstants && (desc.Kind != ValueKind.Enumerator))
66+
if (_generator.Config.GenerateUnmanagedConstants && (desc.Kind != ValueKind.Enumerator))
6767
{
6868
if (desc.IsCopy)
6969
{
@@ -88,7 +88,7 @@ public void BeginValue(in ValueDesc desc)
8888
{
8989
Write(" static ");
9090

91-
if (!_config.GenerateUnmanagedConstants)
91+
if (!_generator.Config.GenerateUnmanagedConstants)
9292
{
9393
Write("readonly ");
9494
}
@@ -111,7 +111,7 @@ public void BeginValue(in ValueDesc desc)
111111
Write(GetAccessSpecifierString(desc.AccessSpecifier, isNested: true));
112112
Write(" static ");
113113

114-
if (_config.GenerateUnmanagedConstants && desc.IsConstant)
114+
if (_generator.Config.GenerateUnmanagedConstants && desc.IsConstant)
115115
{
116116
if (desc.IsArray)
117117
{
@@ -177,7 +177,7 @@ public void BeginValue(in ValueDesc desc)
177177
{
178178
WriteNewline();
179179
WriteBlockStart();
180-
BeginGetter(desc.IsConstant && _config.GenerateAggressiveInlining, isReadOnly: false);
180+
BeginGetter(desc.IsConstant && _generator.Config.GenerateAggressiveInlining, isReadOnly: false);
181181
}
182182
else
183183
{
@@ -203,7 +203,7 @@ public void EndValue(in ValueDesc desc)
203203
{
204204
WriteLine(',');
205205

206-
if (_config.GenerateDocIncludes)
206+
if (_generator.Config.GenerateDocIncludes)
207207
{
208208
NeedsNewline = true;
209209
}
@@ -214,7 +214,7 @@ public void EndValue(in ValueDesc desc)
214214
{
215215
if (desc.IsConstant)
216216
{
217-
if (_config.GenerateUnmanagedConstants && !desc.IsCopy)
217+
if (_generator.Config.GenerateUnmanagedConstants && !desc.IsCopy)
218218
{
219219
EndGetter();
220220
WriteBlockEnd();
@@ -244,7 +244,7 @@ public void EndValue(in ValueDesc desc)
244244

245245
public void BeginEnum(in EnumDesc desc)
246246
{
247-
if (_config.GenerateDocIncludes)
247+
if (_generator.Config.GenerateDocIncludes)
248248
{
249249
WriteIndented("/// <include file='");
250250
Write(desc.EscapedName);
@@ -283,7 +283,7 @@ public void BeginEnum(in EnumDesc desc)
283283

284284
public void BeginField(in FieldDesc desc)
285285
{
286-
if (_config.GenerateDocIncludes && !string.IsNullOrWhiteSpace(desc.ParentName))
286+
if (_generator.Config.GenerateDocIncludes && !string.IsNullOrWhiteSpace(desc.ParentName))
287287
{
288288
WriteIndented("/// <include file='");
289289
Write(desc.ParentName);
@@ -327,7 +327,7 @@ public void BeginField(in FieldDesc desc)
327327

328328
public void WriteFixedCountField(string typeName, string escapedName, string fixedName, string count)
329329
{
330-
if (PInvokeGenerator.IsSupportedFixedSizedBufferType(typeName))
330+
if (_generator.IsSupportedFixedSizedBufferType(typeName))
331331
{
332332
Write("fixed ");
333333
Write(typeName);
@@ -364,7 +364,7 @@ public void EndField(in FieldDesc desc)
364364

365365
public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isMethodClassUnsafe)
366366
{
367-
if (_config.GenerateDocIncludes && !string.IsNullOrEmpty(desc.ParentName))
367+
if (_generator.Config.GenerateDocIncludes && !string.IsNullOrEmpty(desc.ParentName))
368368
{
369369
if (desc.IsInherited)
370370
{
@@ -430,7 +430,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM
430430

431431
Write("ExactSpelling = true");
432432

433-
if (desc.SetLastError && !_config.GenerateSetsLastSystemErrorAttribute)
433+
if (desc.SetLastError && !_generator.Config.GenerateSetsLastSystemErrorAttribute)
434434
{
435435
Write(", SetLastError = true");
436436
}
@@ -443,7 +443,7 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM
443443
WriteSourceLocation(location, false);
444444
}
445445

446-
if (desc.SetLastError && _config.GenerateSetsLastSystemErrorAttribute)
446+
if (desc.SetLastError && _generator.Config.GenerateSetsLastSystemErrorAttribute)
447447
{
448448
WriteIndentedLine("[SetsLastSystemError]");
449449
}
@@ -732,7 +732,7 @@ public void EndFunctionOrDelegate(in FunctionOrDelegateDesc desc)
732732

733733
public void BeginStruct(in StructDesc desc)
734734
{
735-
if (_config.GenerateDocIncludes)
735+
if (_generator.Config.GenerateDocIncludes)
736736
{
737737
WriteIndented("/// <include file='");
738738
Write(desc.EscapedName);
@@ -793,7 +793,7 @@ public void BeginStruct(in StructDesc desc)
793793
Write("partial struct ");
794794
Write(desc.EscapedName);
795795

796-
if (_config.GenerateMarkerInterfaces)
796+
if (_generator.Config.GenerateMarkerInterfaces)
797797
{
798798
if (desc.HasVtbl)
799799
{
@@ -802,7 +802,7 @@ public void BeginStruct(in StructDesc desc)
802802
Write(".Interface");
803803
}
804804

805-
if ((desc.Uuid is not null) && _config.GenerateGuidMember && _config.GenerateLatestCode)
805+
if ((desc.Uuid is not null) && _generator.Config.GenerateGuidMember && _generator.Config.GenerateLatestCode)
806806
{
807807
Write(desc.HasVtbl ? ", " : " : ");
808808
Write("INativeGuid");
@@ -840,7 +840,7 @@ public void BeginExplicitVtbl()
840840
{
841841
WriteIndented("public partial struct Vtbl");
842842

843-
if (_config.GenerateMarkerInterfaces && !_config.ExcludeFnptrCodegen)
843+
if (_generator.Config.GenerateMarkerInterfaces && !_generator.Config.ExcludeFnptrCodegen)
844844
{
845845
WriteLine("<TSelf>");
846846
IncreaseIndentation();

sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

99
namespace ClangSharp.CSharp;
1010

11-
internal sealed partial class CSharpOutputBuilder(string name, PInvokeGeneratorConfiguration config, string indentationString = CSharpOutputBuilder.DefaultIndentationString,
11+
internal sealed partial class CSharpOutputBuilder(string name, PInvokeGenerator generator, string indentationString = CSharpOutputBuilder.DefaultIndentationString,
1212
bool isTestOutput = false, MarkerMode markerMode = MarkerMode.None,
1313
bool writeSourceLocation = false)
1414
{
1515
public const string DefaultIndentationString = " ";
1616

1717
private readonly string _name = name;
18-
private readonly PInvokeGeneratorConfiguration _config = config;
18+
private readonly PInvokeGenerator _generator = generator;
1919
private readonly List<string> _contents = [];
2020
private readonly StringBuilder _currentLine = new StringBuilder();
2121
private readonly SortedSet<string> _usingDirectives = [];
@@ -301,7 +301,7 @@ private void AddVtblIndexAttribute(long vtblIndex, string? prefix = null, string
301301

302302
private void AddNativeTypeNameAttribute(string nativeTypeName, string? prefix = null, string? postfix = null, string? attributePrefix = null)
303303
{
304-
foreach (var entry in _config.NativeTypeNamesToStrip)
304+
foreach (var entry in _generator.Config.NativeTypeNamesToStrip)
305305
{
306306
nativeTypeName = nativeTypeName.Replace(entry, "", StringComparison.Ordinal);
307307
}

sources/ClangSharp.PInvokeGenerator/OutputBuilderFactory.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ namespace ClangSharp;
1111

1212
internal sealed class OutputBuilderFactory
1313
{
14-
private readonly PInvokeGeneratorConfiguration _config;
14+
private readonly PInvokeGenerator _generator;
1515
private readonly bool _writeSourceLocation;
1616
private readonly Dictionary<string, IOutputBuilder> _outputBuilders;
1717

18-
public OutputBuilderFactory(PInvokeGeneratorConfiguration config)
18+
public OutputBuilderFactory(PInvokeGenerator generator)
1919
{
20-
_config = config;
21-
_writeSourceLocation = config.GenerateSourceLocationAttribute;
20+
_generator = generator;
21+
_writeSourceLocation = generator.Config.GenerateSourceLocationAttribute;
2222
_outputBuilders = [];
2323
}
2424

@@ -33,10 +33,10 @@ public IOutputBuilder Create(string name)
3333
throw new ArgumentNullException(nameof(name));
3434
}
3535

36-
var outputBuilder = _config.OutputMode switch
36+
var outputBuilder = _generator.Config.OutputMode switch
3737
{
38-
PInvokeGeneratorOutputMode.CSharp => (IOutputBuilder) new CSharpOutputBuilder(name, _config, writeSourceLocation: _writeSourceLocation),
39-
PInvokeGeneratorOutputMode.Xml => new XmlOutputBuilder(name, _config),
38+
PInvokeGeneratorOutputMode.CSharp => (IOutputBuilder) new CSharpOutputBuilder(name, _generator, writeSourceLocation: _writeSourceLocation),
39+
PInvokeGeneratorOutputMode.Xml => new XmlOutputBuilder(name, _generator),
4040
_ => throw new InvalidOperationException()
4141
};
4242

@@ -51,7 +51,7 @@ public CSharpOutputBuilder CreateTests(string name)
5151
throw new ArgumentNullException(nameof(name));
5252
}
5353

54-
var outputBuilder = new CSharpOutputBuilder(name, _config, isTestOutput: true, writeSourceLocation: _writeSourceLocation);
54+
var outputBuilder = new CSharpOutputBuilder(name, _generator, isTestOutput: true, writeSourceLocation: _writeSourceLocation);
5555

5656
_outputBuilders.Add(name, outputBuilder);
5757
return outputBuilder;

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,19 +1087,18 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl)
10871087
{
10881088
code.Write("[0], ");
10891089
code.Write(Math.Max(IsType<ConstantArrayType>(indirectFieldDecl, type, out var constantArrayType) ? constantArrayType.Size : 0, 1));
1090+
code.Write(')');
10901091
}
1091-
else
1092+
else if (!_config.GenerateLatestCode)
10921093
{
1093-
code.Write(".AsSpan(");
1094+
code.Write(".AsSpan()");
10941095
}
10951096
}
10961097
else
10971098
{
1098-
code.Write(", 1)");
1099+
code.Write(", 1))");
10991100
}
11001101

1101-
code.Write(')');
1102-
11031102
if (isIndirectPointerField)
11041103
{
11051104
code.Write('.');
@@ -3046,14 +3045,17 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
30463045
code.AddUsingDirective("System");
30473046
code.AddUsingDirective("System.Runtime.InteropServices");
30483047

3049-
code.WriteIndented("return ref AsSpan(");
3048+
code.WriteIndented("return ref ");
30503049

30513050
if (arraySize == 1)
30523051
{
3053-
code.Write("int.MaxValue");
3052+
code.Write("Unsafe.Add(ref e0, index)");
3053+
}
3054+
else
3055+
{
3056+
code.Write("AsSpan()[index]");
30543057
}
30553058

3056-
code.Write(")[index]");
30573059
code.WriteSemicolon();
30583060
code.WriteNewline();
30593061
_outputBuilder.EndCSharpCode(code);

sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ public PInvokeGenerator(PInvokeGeneratorConfiguration config, Func<string, Strea
127127
throw new InvalidOperationException($"Invalid libClang version. Returned string '{clangSharpVersion}' does not contain '{ExpectedClangSharpVersion}'");
128128
}
129129

130+
_config = config;
130131
_index = CXIndex.Create();
131-
_outputBuilderFactory = new OutputBuilderFactory(config);
132+
_outputBuilderFactory = new OutputBuilderFactory(this);
132133
_outputStreamFactory = outputStreamFactory ?? ((path) => {
133134
var directoryPath = Path.GetDirectoryName(path) ?? "";
134135
_ = Directory.CreateDirectory(directoryPath);
@@ -138,7 +139,6 @@ public PInvokeGenerator(PInvokeGeneratorConfiguration config, Func<string, Strea
138139
_visitedFiles = [];
139140
_diagnostics = [];
140141
_context = new LinkedList<(Cursor, object?)>();
141-
_config = config;
142142
_uuidsToGenerate = [];
143143
_generatedUuids = [];
144144
_cursorNames = [];
@@ -3690,7 +3690,7 @@ private string GetTypeName(Cursor? cursor, Cursor? context, Type rootType, Type
36903690
case CXTemplateArgumentKind_Expression:
36913691
{
36923692
var oldOutputBuilder = _outputBuilder;
3693-
_outputBuilder = new CSharpOutputBuilder("ClangSharp_TemplateSpecializationType_AsExpr", _config);
3693+
_outputBuilder = new CSharpOutputBuilder("ClangSharp_TemplateSpecializationType_AsExpr", this);
36943694

36953695
Visit(arg.AsExpr);
36963696
typeName = _outputBuilder.ToString() ?? "";
@@ -5326,7 +5326,7 @@ private bool IsTypeVoid(Cursor? cursor, Type type)
53265326
=> IsType<BuiltinType>(cursor, type, out var builtinType)
53275327
&& (builtinType.Kind == CXType_Void);
53285328

5329-
internal static bool IsSupportedFixedSizedBufferType(string typeName)
5329+
internal bool IsSupportedFixedSizedBufferType(string typeName)
53305330
{
53315331
switch (typeName)
53325332
{
@@ -5343,7 +5343,8 @@ internal static bool IsSupportedFixedSizedBufferType(string typeName)
53435343
case "uint":
53445344
case "ulong":
53455345
{
5346-
return true;
5346+
// We want to prefer InlineArray in modern code, as it is safer and supports more features
5347+
return !Config.GenerateLatestCode;
53475348
}
53485349

53495350
default:

sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.VisitDecl.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ public void EmitSystemSupport()
307307
public CSharpOutputBuilder BeginCSharpCode()
308308
{
309309
_ = _sb.Append("<code>");
310-
return new CSharpOutputBuilder("__Internal", _config, markerMode: MarkerMode.Xml);
310+
return new CSharpOutputBuilder("__Internal", _generator, markerMode: MarkerMode.Xml);
311311
}
312312

313313
public void EndCSharpCode(CSharpOutputBuilder output)
@@ -396,7 +396,7 @@ private void AddNativeTypeNameAttribute(string? nativeTypeName)
396396
return;
397397
}
398398

399-
foreach (var entry in _config.NativeTypeNamesToStrip)
399+
foreach (var entry in _generator.Config.NativeTypeNamesToStrip)
400400
{
401401
nativeTypeName = nativeTypeName.Replace(entry, "", StringComparison.Ordinal);
402402
}

sources/ClangSharp.PInvokeGenerator/XML/XmlOutputBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
namespace ClangSharp.XML;
1010

11-
internal partial class XmlOutputBuilder(string name, PInvokeGeneratorConfiguration config) : IOutputBuilder
11+
internal partial class XmlOutputBuilder(string name, PInvokeGenerator generator) : IOutputBuilder
1212
{
13-
private readonly PInvokeGeneratorConfiguration _config = config;
13+
private readonly PInvokeGenerator _generator = generator;
1414

1515
public string Name { get; } = name;
1616
public string Extension { get; } = ".xml";

tests/ClangSharp.PInvokeGenerator.UnitTests/Base/StructDeclarationTest.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest
9292
[TestCase("unsigned short", "ushort")]
9393
[TestCase("unsigned int", "uint")]
9494
[TestCase("unsigned long long", "ulong")]
95-
[TestCase("bool", "byte")]
9695
public Task FixedSizedBufferPrimitiveTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveTestImpl(nativeType, expectedManagedType);
9796

9897
[TestCase("unsigned char", "byte")]
@@ -105,7 +104,6 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest
105104
[TestCase("unsigned short", "ushort")]
106105
[TestCase("unsigned int", "uint")]
107106
[TestCase("unsigned long long", "ulong")]
108-
[TestCase("bool", "byte")]
109107
public Task FixedSizedBufferPrimitiveMultidimensionalTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveMultidimensionalTestImpl(nativeType, expectedManagedType);
110108

111109
[TestCase("unsigned char", "byte")]
@@ -118,7 +116,6 @@ public abstract class StructDeclarationTest : PInvokeGeneratorTest
118116
[TestCase("unsigned short", "ushort")]
119117
[TestCase("unsigned int", "uint")]
120118
[TestCase("unsigned long long", "ulong")]
121-
[TestCase("bool", "byte")]
122119
public Task FixedSizedBufferPrimitiveTypedefTest(string nativeType, string expectedManagedType) => FixedSizedBufferPrimitiveTypedefTestImpl(nativeType, expectedManagedType);
123120

124121
[Test]

0 commit comments

Comments
 (0)