Skip to content

Commit

Permalink
[LibraryImportGenerator] Basic stateless value marshaller support (#7…
Browse files Browse the repository at this point in the history
…1116)

- Separate out previous custom marshalling support into _V1 classes
- Add basic support for new stateless marshaller shape for values

This only adds really basic support for stateless value marshalling. It doesn't deal with support for caller-allocated buffer, pinning, guaranteed unmarshal, or linear collection marshalling.
  • Loading branch information
elinor-fung committed Jun 22, 2022
1 parent 315e931 commit f4cf69e
Show file tree
Hide file tree
Showing 41 changed files with 1,729 additions and 565 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ private static void AnalyzeManagedTypeMarshallingInfo(SymbolAnalysisContext cont
type.ToDisplayString()));
}

(bool hasCustomTypeMarshallerAttribute, ITypeSymbol? marshallerManagedType, _) = ManualTypeMarshallingHelper.GetMarshallerShapeInfo(marshallerType);
(bool hasCustomTypeMarshallerAttribute, ITypeSymbol? marshallerManagedType, _) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(marshallerType);

marshallerManagedType = ManualTypeMarshallingHelper.ResolveManagedType(marshallerManagedType, marshallerType, context.Compilation);

Expand Down Expand Up @@ -534,7 +534,7 @@ private static bool TypeSymbolsConstructedFromEqualTypes(ITypeSymbol left, IType
public void AnalyzeMarshallerType(SymbolAnalysisContext context)
{
INamedTypeSymbol marshallerType = (INamedTypeSymbol)context.Symbol;
(bool hasCustomTypeMarshallerAttribute, ITypeSymbol? type, CustomTypeMarshallerData? marshallerDataMaybe) = ManualTypeMarshallingHelper.GetMarshallerShapeInfo(marshallerType);
(bool hasCustomTypeMarshallerAttribute, ITypeSymbol? type, CustomTypeMarshallerData_V1? marshallerDataMaybe) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(marshallerType);
type = ManualTypeMarshallingHelper.ResolveManagedType(type, marshallerType, context.Compilation);

if (!hasCustomTypeMarshallerAttribute)
Expand Down Expand Up @@ -583,12 +583,12 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
continue;
}

if (inConstructor is null && ManualTypeMarshallingHelper.IsManagedToNativeConstructor(ctor, type, marshallerData.Kind))
if (inConstructor is null && ManualTypeMarshallingHelper_V1.IsManagedToNativeConstructor(ctor, type, marshallerData.Kind))
{
inConstructor = ctor;
}

if (callerAllocatedSpanConstructor is null && ManualTypeMarshallingHelper.IsCallerAllocatedSpanConstructor(ctor, type, _spanOfT, marshallerData.Kind, out _))
if (callerAllocatedSpanConstructor is null && ManualTypeMarshallingHelper_V1.IsCallerAllocatedSpanConstructor(ctor, type, _spanOfT, marshallerData.Kind, out _))
{
callerAllocatedSpanConstructor = ctor;
}
Expand Down Expand Up @@ -653,30 +653,30 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
}
}

if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && !ManualTypeMarshallingHelper.HasToManagedMethod(marshallerType, type))
if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && !ManualTypeMarshallingHelper_V1.HasToManagedMethod(marshallerType, type))
{
context.ReportDiagnostic(
marshallerType.CreateDiagnostic(
OutRequiresToManagedRule,
ImmutableDictionary<string, string>.Empty.Add(
MissingMemberNames.Key,
ShapeMemberNames.Value.ToManaged),
ShapeMemberNames_V1.Value.ToManaged),
marshallerType.ToDisplayString()));
}

if (marshallerData.Kind == CustomTypeMarshallerKind.LinearCollection)
{
IMethodSymbol? getManagedValuesSourceMethod = ManualTypeMarshallingHelper.FindGetManagedValuesSourceMethod(marshallerType, _readOnlySpanOfT);
IMethodSymbol? getManagedValuesDestinationMethod = ManualTypeMarshallingHelper.FindGetManagedValuesDestinationMethod(marshallerType, _spanOfT);
IMethodSymbol? getNativeValuesSourceMethod = ManualTypeMarshallingHelper.FindGetNativeValuesSourceMethod(marshallerType, _readOnlySpanOfByte);
IMethodSymbol? getNativeValuesDestinationMethod = ManualTypeMarshallingHelper.FindGetNativeValuesDestinationMethod(marshallerType, _spanOfByte);
IMethodSymbol? getManagedValuesSourceMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesSourceMethod(marshallerType, _readOnlySpanOfT);
IMethodSymbol? getManagedValuesDestinationMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesDestinationMethod(marshallerType, _spanOfT);
IMethodSymbol? getNativeValuesSourceMethod = ManualTypeMarshallingHelper_V1.FindGetNativeValuesSourceMethod(marshallerType, _readOnlySpanOfByte);
IMethodSymbol? getNativeValuesDestinationMethod = ManualTypeMarshallingHelper_V1.FindGetNativeValuesDestinationMethod(marshallerType, _spanOfByte);
if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.In) && (getManagedValuesSourceMethod is null || getNativeValuesDestinationMethod is null))
{
var missingMembers = (getManagedValuesSourceMethod, getNativeValuesDestinationMethod) switch
{
(null, not null) => ShapeMemberNames.LinearCollection.GetManagedValuesSource,
(not null, null) => ShapeMemberNames.LinearCollection.GetNativeValuesDestination,
(null, null) => $"{ShapeMemberNames.LinearCollection.GetManagedValuesSource}{MissingMemberNames.Delimiter}{ShapeMemberNames.LinearCollection.GetNativeValuesDestination}",
(null, not null) => ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource,
(not null, null) => ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination,
(null, null) => $"{ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource}{MissingMemberNames.Delimiter}{ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination}",
(not null, not null) => string.Empty
};
context.ReportDiagnostic(
Expand All @@ -692,9 +692,9 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
{
var missingMembers = (getNativeValuesSourceMethod, getManagedValuesDestinationMethod) switch
{
(not null, null) => ShapeMemberNames.LinearCollection.GetNativeValuesSource,
(null, not null) => ShapeMemberNames.LinearCollection.GetManagedValuesDestination,
(null, null) => $"{ShapeMemberNames.LinearCollection.GetNativeValuesSource}{MissingMemberNames.Delimiter}{ShapeMemberNames.LinearCollection.GetManagedValuesDestination}",
(not null, null) => ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource,
(null, not null) => ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination,
(null, null) => $"{ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource}{MissingMemberNames.Delimiter}{ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination}",
(not null, not null) => string.Empty
};
context.ReportDiagnostic(
Expand Down Expand Up @@ -736,18 +736,18 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
marshallerType.ToDisplayString()));
}

if (marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.UnmanagedResources) && !ManualTypeMarshallingHelper.HasFreeNativeMethod(marshallerType))
if (marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.UnmanagedResources) && !ManualTypeMarshallingHelper_V1.HasFreeNativeMethod(marshallerType))
{
context.ReportDiagnostic(
marshallerType.CreateDiagnostic(
UnmanagedResourcesRequiresFreeNativeRule,
ImmutableDictionary<string, string>.Empty.Add(
MissingMemberNames.Key,
ShapeMemberNames.Value.FreeNative),
ShapeMemberNames_V1.Value.FreeNative),
marshallerType.ToDisplayString(),
type.ToDisplayString()));
}
else if (!marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.UnmanagedResources) && ManualTypeMarshallingHelper.HasFreeNativeMethod(marshallerType))
else if (!marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.UnmanagedResources) && ManualTypeMarshallingHelper_V1.HasFreeNativeMethod(marshallerType))
{
context.ReportDiagnostic(
marshallerType.CreateDiagnostic(
Expand All @@ -758,8 +758,8 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
marshallerType.ToDisplayString()));
}

IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper.FindToNativeValueMethod(marshallerType);
IMethodSymbol? fromNativeValueMethod = ManualTypeMarshallingHelper.FindFromNativeValueMethod(marshallerType);
IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(marshallerType);
IMethodSymbol? fromNativeValueMethod = ManualTypeMarshallingHelper_V1.FindFromNativeValueMethod(marshallerType);
bool toNativeValueMethodIsRefReturn = toNativeValueMethod is { ReturnsByRef: true } or { ReturnsByRefReadonly: true };
ITypeSymbol nativeType = marshallerType;

Expand All @@ -771,7 +771,7 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
InTwoStageMarshallingRequiresToNativeValueRule,
ImmutableDictionary<string, string>.Empty.Add(
MissingMemberNames.Key,
ShapeMemberNames.Value.ToNativeValue),
ShapeMemberNames_V1.Value.ToNativeValue),
marshallerType.ToDisplayString()));
}
if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && fromNativeValueMethod is null)
Expand All @@ -780,7 +780,7 @@ public void AnalyzeMarshallerType(SymbolAnalysisContext context)
OutTwoStageMarshallingRequiresFromNativeValueRule,
ImmutableDictionary<string, string>.Empty.Add(
MissingMemberNames.Key,
ShapeMemberNames.Value.FromNativeValue),
ShapeMemberNames_V1.Value.FromNativeValue),
marshallerType.ToDisplayString()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ private static SyntaxNode AddMissingFeatures(string attributeName, AttributeData

SyntaxNode featureAttributeArgument = gen.AttributeArgument("Features",
gen.GetEnumValueAsFlagsExpression(
customTypeMarshallerAttribute.AttributeClass.GetMembers(ManualTypeMarshallingHelper.CustomMarshallerAttributeFields.Features).OfType<IPropertySymbol>().First().Type,
customTypeMarshallerAttribute.AttributeClass.GetMembers(ManualTypeMarshallingHelper_V1.CustomMarshallerAttributeFields.Features).OfType<IPropertySymbol>().First().Type,
(int)newFeaturesValue,
includeZeroValueFlags: false));

Expand Down Expand Up @@ -251,12 +251,12 @@ private static SyntaxNode AddMissingMembers(SyntaxNode node, ITypeSymbol
SyntaxNode updatedDeclaration = node;


(_, ITypeSymbol managedType, _) = ManualTypeMarshallingHelper.GetMarshallerShapeInfo(marshallerType);
(_, ITypeSymbol managedType, _) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(marshallerType);

IMethodSymbol? fromNativeValueMethod = ManualTypeMarshallingHelper.FindFromNativeValueMethod(marshallerType);
IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper.FindToNativeValueMethod(marshallerType);
IMethodSymbol? getManagedValuesSourceMethod = ManualTypeMarshallingHelper.FindGetManagedValuesSourceMethod(marshallerType, readOnlySpanOfT);
IMethodSymbol? getManagedValuesDestinationMethod = ManualTypeMarshallingHelper.FindGetManagedValuesDestinationMethod(marshallerType, spanOfT);
IMethodSymbol? fromNativeValueMethod = ManualTypeMarshallingHelper_V1.FindFromNativeValueMethod(marshallerType);
IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(marshallerType);
IMethodSymbol? getManagedValuesSourceMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesSourceMethod(marshallerType, readOnlySpanOfT);
IMethodSymbol? getManagedValuesDestinationMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesDestinationMethod(marshallerType, spanOfT);

SyntaxNode[] throwNotImplementedStatements = new[]
{
Expand Down Expand Up @@ -321,21 +321,21 @@ private static SyntaxNode AddMissingMembers(SyntaxNode node, ITypeSymbol
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.Value.ToManaged:
case ShapeMemberNames_V1.Value.ToManaged:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.Value.ToManaged,
ShapeMemberNames_V1.Value.ToManaged,
returnType: gen.TypeExpression(managedType),
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.Value.FreeNative:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(ShapeMemberNames.Value.FreeNative,
case ShapeMemberNames_V1.Value.FreeNative:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(ShapeMemberNames_V1.Value.FreeNative,
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.Value.FromNativeValue:
case ShapeMemberNames_V1.Value.FromNativeValue:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.Value.FromNativeValue,
ShapeMemberNames_V1.Value.FromNativeValue,
parameters: new[]
{
gen.ParameterDeclaration("value",
Expand All @@ -344,33 +344,33 @@ private static SyntaxNode AddMissingMembers(SyntaxNode node, ITypeSymbol
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.Value.ToNativeValue:
case ShapeMemberNames_V1.Value.ToNativeValue:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.Value.ToNativeValue,
ShapeMemberNames_V1.Value.ToNativeValue,
returnType: gen.TypeExpression(fromNativeValueMethod?.Parameters[0].Type ?? @byte),
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.LinearCollection.GetManagedValuesSource:
case ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource:
INamedTypeSymbol? getManagedValuesDestinationReturnType = (INamedTypeSymbol?)getManagedValuesDestinationMethod?.ReturnType;
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.LinearCollection.GetManagedValuesSource,
ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource,
returnType: gen.TypeExpression(
readOnlySpanOfT.Construct(
getManagedValuesDestinationReturnType?.TypeArguments[0] ?? @object)),
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.LinearCollection.GetNativeValuesDestination:
case ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.LinearCollection.GetNativeValuesDestination,
ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination,
returnType: gen.TypeExpression(spanOfByte),
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.LinearCollection.GetNativeValuesSource:
case ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource:
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.LinearCollection.GetNativeValuesSource,
ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource,
parameters: new[]
{
gen.ParameterDeclaration("numElements", type: gen.TypeExpression(int32))
Expand All @@ -379,10 +379,10 @@ private static SyntaxNode AddMissingMembers(SyntaxNode node, ITypeSymbol
accessibility: Accessibility.Public,
statements: throwNotImplementedStatements));
break;
case ShapeMemberNames.LinearCollection.GetManagedValuesDestination:
case ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination:
INamedTypeSymbol? getManagedValuesSourceReturnType = (INamedTypeSymbol?)getManagedValuesSourceMethod?.ReturnType;
updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
ShapeMemberNames.LinearCollection.GetNativeValuesDestination,
ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination,
parameters: new[]
{
gen.ParameterDeclaration("numElements", type: gen.TypeExpression(int32))
Expand Down
Loading

0 comments on commit f4cf69e

Please sign in to comment.