Skip to content

Add support for --with-packing #405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions sources/ClangSharp.PInvokeGenerator/Abstractions/StructDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,12 @@ public StructLayoutAttribute? LayoutAttribute
{
Debug.Assert(layout.Kind == LayoutKind.Explicit);

var attribute = new StructLayoutAttribute(layout.Kind);

if (layout.Pack != 0)
{
attribute.Pack = (int)layout.Pack;
}

return attribute;
return new StructLayoutAttribute(layout.Kind);
}

if (layout.Pack != 0)
if (layout.Pack is not null)
{
return new StructLayoutAttribute(layout.Kind) {
Pack = (int)layout.Pack
};
return new StructLayoutAttribute(layout.Kind);
}

return null;
Expand All @@ -110,7 +101,7 @@ public struct LayoutDesc
public long Alignment64 { get; set; }
public long Size32 { get; set; }
public long Size64 { get; set; }
public long Pack { get; set; }
public string? Pack { get; set; }
public long MaxFieldAlignment { get; set; }
public LayoutKind Kind { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,10 +746,10 @@ public void BeginStruct(in StructDesc desc)
WriteIndented("[StructLayout(LayoutKind.");
Write(desc.LayoutAttribute.Value);

if (desc.LayoutAttribute.Pack != 0)
if (desc.Layout.Pack is not null)
{
Write(", Pack = ");
Write(desc.LayoutAttribute.Pack);
Write(desc.Layout.Pack);
}

WriteLine(")]");
Expand Down
16 changes: 13 additions & 3 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,11 @@ private void VisitRecordDecl(RecordDecl recordDecl)
baseTypeNames = baseTypeNamesBuilder.ToArray();
}

if (!TryGetRemappedValue(recordDecl, _config.WithPackings, out var pack))
{
pack = alignment < maxAlignm ? alignment.ToString(CultureInfo.InvariantCulture) : null;
}

var desc = new StructDesc {
AccessSpecifier = GetAccessSpecifier(recordDecl, matchStar: true),
EscapedName = escapedName,
Expand All @@ -1478,7 +1483,7 @@ private void VisitRecordDecl(RecordDecl recordDecl)
Alignment64 = alignment64,
Size32 = size32,
Size64 = size64,
Pack = alignment < maxAlignm ? alignment : 0,
Pack = pack,
MaxFieldAlignment = maxAlignm,
Kind = layoutKind
},
Expand Down Expand Up @@ -1515,7 +1520,7 @@ private void VisitRecordDecl(RecordDecl recordDecl)

if (desc.LayoutAttribute is not null)
{
withAttributes.Add($"StructLayout(LayoutKind.{desc.LayoutAttribute.Value}{((desc.LayoutAttribute.Pack != 0) ? $", Pack = {desc.LayoutAttribute.Pack}" : "")})");
withAttributes.Add($"StructLayout(LayoutKind.{desc.LayoutAttribute.Value}{((desc.Layout.Pack is not null) ? $", Pack = {desc.Layout.Pack}" : "")})");
_ = withUsings.Add("System.Runtime.InteropServices");
}

Expand Down Expand Up @@ -2817,6 +2822,11 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
AddDiagnostic(DiagnosticLevel.Info, $"{escapedName} (constant array field) has a size of 0", constantOrIncompleteArray);
}

if (!TryGetRemappedValue(recordDecl, _config.WithPackings, out var pack))
{
pack = alignment < maxAlignm ? alignment.ToString(CultureInfo.InvariantCulture) : null;
}

var desc = new StructDesc {
AccessSpecifier = accessSpecifier,
EscapedName = escapedName,
Expand All @@ -2826,7 +2836,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co
Alignment64 = alignment64,
Size32 = size32,
Size64 = size64,
Pack = alignment < maxAlignm ? alignment : 0,
Pack = pack,
MaxFieldAlignment = maxAlignm,
Kind = LayoutKind.Sequential
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public sealed class PInvokeGeneratorConfiguration
private readonly SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)> _withTransparentStructs;
private readonly SortedDictionary<string, string> _withTypes;
private readonly SortedDictionary<string, IReadOnlyList<string>> _withUsings;
private readonly SortedDictionary<string, string> _withPackings;

private PInvokeGeneratorConfigurationOptions _options;

Expand Down Expand Up @@ -94,6 +95,7 @@ public PInvokeGeneratorConfiguration(string defaultNamespace, string outputLocat
_withTransparentStructs = new SortedDictionary<string, (string, PInvokeGeneratorTransparentStructKind)>();
_withTypes = new SortedDictionary<string, string>();
_withUsings = new SortedDictionary<string, IReadOnlyList<string>>();
_withPackings = new SortedDictionary<string, string>();

if ((outputMode == PInvokeGeneratorOutputMode.Xml) && !options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) && (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsNUnit) || options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateTestsXUnit)))
{
Expand Down Expand Up @@ -528,6 +530,20 @@ public IReadOnlyDictionary<string, IReadOnlyList<string>> WithUsings
}
}

[AllowNull]
public IReadOnlyDictionary<string, string> WithPackings
{
get
{
return _withPackings;
}

init
{
AddRange(_withPackings, value);
}
}

public static AccessSpecifier ConvertStringToAccessSpecifier(string input)
{
if (input.Equals("internal", StringComparison.OrdinalIgnoreCase))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,10 @@ public void BeginStruct(in StructDesc info)
_ = _sb.Append(info.LayoutAttribute.Value);
_ = _sb.Append('"');

if (info.LayoutAttribute.Pack != 0)
if (info.Layout.Pack is not null)
{
_ = _sb.Append(" pack=\"");
_ = _sb.Append(info.LayoutAttribute.Pack);
_ = _sb.Append(info.Layout.Pack);
_ = _sb.Append('"');
}
}
Expand Down
19 changes: 18 additions & 1 deletion sources/ClangSharpPInvokeGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class Program
private static readonly Option<string[]> s_withTransparentStructNameValuePairs;
private static readonly Option<string[]> s_withTypeNameValuePairs;
private static readonly Option<string[]> s_withUsingNameValuePairs;
private static readonly Option<string[]> s_withPackingNameValuePairs;


private static readonly TwoColumnHelpRow[] s_configOptions = new TwoColumnHelpRow[]
Expand Down Expand Up @@ -161,6 +162,7 @@ static Program()
s_withTransparentStructNameValuePairs = GetWithTransparentStructOption();
s_withTypeNameValuePairs = GetWithTypeOption();
s_withUsingNameValuePairs = GetWithUsingOption();
s_withPackingNameValuePairs = GetWithPackingOption();

s_rootCommand = new RootCommand("ClangSharp P/Invoke Binding Generator")
{
Expand Down Expand Up @@ -198,7 +200,8 @@ static Program()
s_withSuppressGCTransitions,
s_withTransparentStructNameValuePairs,
s_withTypeNameValuePairs,
s_withUsingNameValuePairs
s_withUsingNameValuePairs,
s_withPackingNameValuePairs
};
Handler.SetHandler(s_rootCommand, (Action<InvocationContext>)Run);
}
Expand Down Expand Up @@ -255,6 +258,7 @@ public static void Run(InvocationContext context)
var withTransparentStructNameValuePairs = context.ParseResult.GetValueForOption(s_withTransparentStructNameValuePairs) ?? Array.Empty<string>();
var withTypeNameValuePairs = context.ParseResult.GetValueForOption(s_withTypeNameValuePairs) ?? Array.Empty<string>();
var withUsingNameValuePairs = context.ParseResult.GetValueForOption(s_withUsingNameValuePairs) ?? Array.Empty<string>();
var withPackingNameValuePairs = context.ParseResult.GetValueForOption(s_withPackingNameValuePairs) ?? Array.Empty<string>();

var versionResult = context.ParseResult.FindResultFor(s_versionOption);

Expand Down Expand Up @@ -295,6 +299,7 @@ public static void Run(InvocationContext context)
ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary<string, (string, PInvokeGeneratorTransparentStructKind)> withTransparentStructs);
ParseKeyValuePairs(withTypeNameValuePairs, errorList, out Dictionary<string, string> withTypes);
ParseKeyValuePairs(withUsingNameValuePairs, errorList, out Dictionary<string, IReadOnlyList<string>> withUsings);
ParseKeyValuePairs(withPackingNameValuePairs, errorList, out Dictionary<string, string> withPackings);

foreach (var key in withTransparentStructs.Keys)
{
Expand Down Expand Up @@ -681,6 +686,7 @@ public static void Run(InvocationContext context)
WithTransparentStructs = withTransparentStructs,
WithTypes = withTypes,
WithUsings = withUsings,
WithPackings = withPackings,
};

if (config.GenerateMacroBindings)
Expand Down Expand Up @@ -1288,4 +1294,15 @@ private static Option<string[]> GetWithUsingOption()
AllowMultipleArgumentsPerToken = true
};
}

private static Option<string[]> GetWithPackingOption()
{
return new Option<string[]>(
aliases: new string[] { "--with-packing", "-wp" },
description: "Overrides the StructLayoutAttribute.Pack property for the given type.",
getDefaultValue: Array.Empty<string>
) {
AllowMultipleArgumentsPerToken = true
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ private static async Task ValidateGeneratedBindingsAsync(string inputContents, s
WithTransparentStructs = withTransparentStructs,
WithTypes = withTypes,
WithUsings = withUsings,
WithPackings = null,
};

using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream))
Expand Down