-
Notifications
You must be signed in to change notification settings - Fork 204
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
[SwiftBindings] Added post processing step to compute struct frozenness #2912
base: feature/swift-bindings
Are you sure you want to change the base?
[SwiftBindings] Added post processing step to compute struct frozenness #2912
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love to see the tests in place. This is a good start, but there are some things that need to be addressed. If it's not practical to resolve them, open issues and keep going.
ProcessStructFields(structDecl); | ||
|
||
// TODO: Remove loading dylib | ||
IntPtr metadataPtr = DynamicLibraryLoader.invoke(_dylibPath, $"{structDecl.MangledName}Ma"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed, we shouldn't do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. This will be the next step. Here is a tracking issue #2914. Should also cover the comments about blittability and size, stride, alignment.
/// <returns>True if blittable, false otherwise.</returns> | ||
private unsafe bool EvaluateBlittability(SwiftTypeInfo swiftTypeInfo) | ||
{ | ||
// TODO: Replace with a manual approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Is there an issue for this?
{ | ||
_typeDatabase.Registrar.RegisterType(namedTypeSpec.Module, | ||
namedTypeSpec.NameWithoutModule, | ||
new TypeRecord |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a separate issue, but we will need the size, stride, and alignment as well.
/// <param name="structDecl">The struct declaration.</param> | ||
private void ProcessStruct(NamedTypeSpec namedTypeSpec, StructDecl structDecl) | ||
{ | ||
// Ensure all fields are processed or known in the database. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All nominal types can have inner types. Because fields in the structure may depend on them, we should process any inner types before we process fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are processed during ABI parsing so we have full information. Added test for that and patched some logic.
namedTypeSpec.NameWithoutModule, | ||
new TypeRecord | ||
{ | ||
Namespace = namedTypeSpec.Module, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see a separate type for holding a type name. Something like:
public class /* or record or struct */ TypeName {
public string Namespace { get; init; }
public string Name { get; init; }
public string FullName { get; } => Namespace + "." + Name;
// if not a record, make ToString, Equals, etc
}
This will make it easier to set up import
statements in Swift and using
statements in C#.
@@ -146,7 +146,7 @@ public ModuleDecl GetModuleDecl() | |||
|
|||
moduleDecl.Fields = decls.OfType<FieldDecl>().ToList(); | |||
moduleDecl.Methods = decls.OfType<MethodDecl>().ToList(); | |||
moduleDecl.Declarations = decls.Where(d => !(d is MethodDecl) && !(d is FieldDecl)).ToList(); | |||
moduleDecl.Types = decls.OfType<TypeDecl>().ToDictionary(d => new NamedTypeSpec(d.FullyQualifiedName), d => d); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that we will run into right here is that the *Decl
types are already C# and that type may not be the same as the Swift from which it came. For example, if we get a Swift type that is unpronounceable in C# (eg, contains emoji) then we've just created an incorrect NamedTypesSpec.
typeRecord.IsProcessed = true; | ||
|
||
if (node.Children != null && decl != null) | ||
if (decl != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
favor is not null
over != null
to avoid possible issues that arise from operator implementations.
@@ -0,0 +1,223 @@ | |||
using Swift.Runtime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using Swift.Runtime; | |
// Copyright (c) Microsoft Corporation. | |
// Licensed under the MIT License. | |
using Swift.Runtime; |
/// Calculates properties on types which are not directly available from the ABI. | ||
/// Generates type database entries for structs, enums, and classes. | ||
/// </summary> | ||
internal class ModuleProcessor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of having a processor/marshaller that based on ABI and dylib inputs, registers types in the database. For that, we need to wire up a Mach-O reader and a demangler.
// Register the module and set the filter | ||
var moduleRecord = typeDatabase.Registrar.RegisterModule(moduleName); | ||
moduleRecord.Path = dylibPath; | ||
|
||
// Parse the Swift ABI file and generate declarations | ||
var decl = swiftParser.GetModuleDecl(); | ||
|
||
var moduleProcessor = new ModuleProcessor(moduleName, dylibPath, decl.Types, typeDatabase); | ||
moduleProcessor.FinalizeTypeProcessing(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ModuleProcessor
is exclusively creating a type registrar, should it be returned here?
break; | ||
|
||
default: | ||
throw new NotSupportedException($"Unknown or unsupported type declaration '{typeDecl.GetType().Name}'."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should gracefully handle unknown types to generate partial bindings.
Implements #2886
Initialises a post ABI parsing step which calculates information about types and populates type database.
Follow-ups: