Skip to content

Commit

Permalink
Split identifier calculation from code context and bind marshallers t…
Browse files Browse the repository at this point in the history
…o the code context (dotnet#106846)
  • Loading branch information
jkoritzinsky authored Aug 30, 2024
1 parent c2efebf commit c87cbf6
Show file tree
Hide file tree
Showing 68 changed files with 1,530 additions and 1,681 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal sealed class JSExportCodeGenerator : JSCodeGenerator
{
private readonly BoundGenerators _marshallers;

private readonly StubCodeContext _context;
private readonly StubIdentifierContext _context;
private readonly JSExportData _jsExportData;
private readonly JSSignatureContext _signatureContext;

Expand All @@ -29,21 +29,24 @@ public JSExportCodeGenerator(
{
_signatureContext = signatureContext;
_jsExportData = attributeData;
_context = new NativeToManagedStubCodeContext(ReturnIdentifier, ReturnIdentifier)
{
CodeEmitOptions = new(SkipInit: true)
};

_marshallers = BoundGenerators.Create(argTypes, generatorResolver, _context, new EmptyJSGenerator(), out var bindingFailures);
_marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultNativeToManagedStub, new EmptyJSGenerator(), out var bindingFailures);

diagnosticsBag.ReportGeneratorDiagnostics(bindingFailures);

if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier(_context))
if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier)
{
// If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code.
_context = new NativeToManagedStubCodeContext(ReturnIdentifier, ReturnNativeIdentifier)
_context = new DefaultIdentifierContext(ReturnIdentifier, ReturnNativeIdentifier, MarshalDirection.UnmanagedToManaged)
{
CodeEmitOptions = new(SkipInit: true),
};
}
else
{
_context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.UnmanagedToManaged)
{
CodeEmitOptions = new(SkipInit: true)
CodeEmitOptions = new(SkipInit: true),
};
}

Expand All @@ -53,7 +56,7 @@ public JSExportCodeGenerator(
IBoundMarshallingGenerator spanArg = _marshallers.SignatureMarshallers.FirstOrDefault(m => m.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo));
if (spanArg != default)
{
diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo, _context)
diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo)
{
NotSupportedDetails = SR.SpanAndTaskNotSupported
});
Expand Down Expand Up @@ -160,9 +163,9 @@ public StatementSyntax GenerateJSExportRegistration()

private ArgumentSyntax CreateSignaturesSyntax()
{
IEnumerable<ExpressionSyntax> types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind(_context) : [];
IEnumerable<ExpressionSyntax> types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind() : [];
types = types
.Concat(_marshallers.NativeParameterMarshallers.OfType<IJSMarshallingGenerator>().SelectMany(p => p.GenerateBind(_context)));
.Concat(_marshallers.NativeParameterMarshallers.OfType<IJSMarshallingGenerator>().SelectMany(p => p.GenerateBind()));

return Argument(ArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerTypeGlobal))
.WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList<ExpressionSyntax>(OmittedArraySizeExpression())))))
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ namespace Microsoft.Interop.JavaScript
internal abstract class JSCodeGenerator
{
public const string ReturnIdentifier = "__retVal";
public const string ReturnNativeIdentifier = $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}";
public const string ReturnNativeIdentifier = $"{ReturnIdentifier}{StubIdentifierContext.GeneratedNativeIdentifierSuffix}";
public const string InvokeSucceededIdentifier = "__invokeSucceeded";
}

internal sealed class JSImportCodeGenerator : JSCodeGenerator
{
private readonly BoundGenerators _marshallers;

private readonly StubCodeContext _context;
private readonly StubIdentifierContext _context;
private readonly JSImportData _jsImportData;
private readonly JSSignatureContext _signatureContext;

Expand All @@ -36,18 +36,22 @@ public JSImportCodeGenerator(
{
_jsImportData = attributeData;
_signatureContext = signatureContext;
_context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnIdentifier)
{
CodeEmitOptions = new(SkipInit: true)
};
_marshallers = BoundGenerators.Create(argTypes, generatorResolver, _context, new EmptyJSGenerator(), out var bindingFailures);

_marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultManagedToNativeStub, new EmptyJSGenerator(), out var bindingFailures);

diagnosticsBag.ReportGeneratorDiagnostics(bindingFailures);

if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier(_context))
if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier)
{
// If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code.
_context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnNativeIdentifier)
_context = new DefaultIdentifierContext(ReturnIdentifier, ReturnNativeIdentifier, MarshalDirection.ManagedToUnmanaged)
{
CodeEmitOptions = new(SkipInit: true)
};
}
else
{
_context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.ManagedToUnmanaged)
{
CodeEmitOptions = new(SkipInit: true)
};
Expand All @@ -59,7 +63,7 @@ public JSImportCodeGenerator(
IBoundMarshallingGenerator spanArg = _marshallers.SignatureMarshallers.FirstOrDefault(m => m.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo));
if (spanArg != default)
{
diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo, _context)
diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo)
{
NotSupportedDetails = SR.SpanAndTaskNotSupported
});
Expand Down Expand Up @@ -151,9 +155,9 @@ private void BindSyntax(List<StatementSyntax> statementsToUpdate)

private ArgumentSyntax CreateSignaturesSyntax()
{
IEnumerable<ExpressionSyntax> types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind(_context) : [];
IEnumerable<ExpressionSyntax> types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind() : [];
types = types
.Concat(_marshallers.NativeParameterMarshallers.OfType<IJSMarshallingGenerator>().SelectMany(p => p.GenerateBind(_context)));
.Concat(_marshallers.NativeParameterMarshallers.OfType<IJSMarshallingGenerator>().SelectMany(p => p.GenerateBind()));

return Argument(ArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerTypeGlobal))
.WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList<ExpressionSyntax>(OmittedArraySizeExpression())))))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@ internal sealed class ArrayJSGenerator : PrimitiveJSGenerator
{
private readonly MarshalerType _elementMarshalerType;

public ArrayJSGenerator(TypePositionInfo info, MarshalerType elementMarshalerType)
: base(info, MarshalerType.Array)
public ArrayJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType)
: base(info, context, MarshalerType.Array)
{
_elementMarshalerType = elementMarshalerType;
}

public override IEnumerable<ExpressionSyntax> GenerateBind(StubCodeContext context)
public override IEnumerable<ExpressionSyntax> GenerateBind()
{
yield return InvocationExpression(MarshalerTypeName(Type),
ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType)))));
}

public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new ArrayJSGenerator(info, _elementMarshalerType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ internal sealed class ArraySegmentJSGenerator : PrimitiveJSGenerator
{
private readonly MarshalerType _elementMarshalerType;

public ArraySegmentJSGenerator(TypePositionInfo info, MarshalerType elementMarshalerType)
: base(info, MarshalerType.ArraySegment)
public ArraySegmentJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType)
: base(info, context, MarshalerType.ArraySegment)
{
_elementMarshalerType = elementMarshalerType;
}

public override IEnumerable<ExpressionSyntax> GenerateBind(StubCodeContext context)
public override IEnumerable<ExpressionSyntax> GenerateBind()
{
yield return InvocationExpression(MarshalerTypeName(Type),
ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType)))));
}

public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new ArraySegmentJSGenerator(info, _elementMarshalerType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,29 @@ protected BaseJSGenerator(MarshalerType marshalerType, IBoundMarshallingGenerato

public TypePositionInfo TypeInfo => _inner.TypeInfo;

public StubCodeContext CodeContext => _inner.CodeContext;

public ManagedTypeInfo NativeType => _inner.NativeType;

public SignatureBehavior NativeSignatureBehavior => _inner.NativeSignatureBehavior;

public ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context) => _inner.GetValueBoundaryBehavior(context);
public ValueBoundaryBehavior ValueBoundaryBehavior => _inner.ValueBoundaryBehavior;

public virtual bool UsesNativeIdentifier(StubCodeContext context) => _inner.UsesNativeIdentifier(context);
public virtual bool UsesNativeIdentifier => _inner.UsesNativeIdentifier;

public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic)
=> _inner.SupportsByValueMarshalKind(marshalKind, context, out diagnostic);
public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic)
=> _inner.SupportsByValueMarshalKind(marshalKind, out diagnostic);

public virtual IEnumerable<ExpressionSyntax> GenerateBind(StubCodeContext context)
public virtual IEnumerable<ExpressionSyntax> GenerateBind()
{
yield return MarshalerTypeName(Type);
}

public virtual IEnumerable<StatementSyntax> Generate(StubCodeContext context)
public virtual IEnumerable<StatementSyntax> Generate(StubIdentifierContext context)
{
string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg");

if (context.CurrentStage == StubCodeContext.Stage.Setup)
if (context.CurrentStage == StubIdentifierContext.Stage.Setup)
{
if (!TypeInfo.IsManagedReturnPosition)
{
Expand Down Expand Up @@ -87,7 +89,5 @@ protected static IdentifierNameSyntax GetToJSMethod(MarshalerType marshalerType)
return IdentifierName(Constants.ToJSMethod);
}
}

public abstract IBoundMarshallingGenerator Rebind(TypePositionInfo info);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ namespace Microsoft.Interop.JavaScript
internal sealed class EmptyJSGenerator : IUnboundMarshallingGenerator
{
public ManagedTypeInfo AsNativeType(TypePositionInfo info) => info.ManagedType;
public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context) => Array.Empty<StatementSyntax>();
public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext identifierContext) => Array.Empty<StatementSyntax>();
public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.ManagedTypeAndAttributes;
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.ManagedIdentifier;
public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic)
=> ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic);
public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic)
=> ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic);
public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ internal sealed class FuncJSGenerator : BaseJSGenerator
private readonly bool _isAction;
private readonly MarshalerType[] _argumentMarshalerTypes;

public FuncJSGenerator(TypePositionInfo info, bool isAction, MarshalerType[] argumentMarshalerTypes)
: base(isAction ? MarshalerType.Action : MarshalerType.Function, new Forwarder().Bind(info))
public FuncJSGenerator(TypePositionInfo info, StubCodeContext context, bool isAction, MarshalerType[] argumentMarshalerTypes)
: base(isAction ? MarshalerType.Action : MarshalerType.Function, new Forwarder().Bind(info, context))
{
_isAction = isAction;
_argumentMarshalerTypes = argumentMarshalerTypes;
}

public override IEnumerable<ExpressionSyntax> GenerateBind(StubCodeContext context)
public override IEnumerable<ExpressionSyntax> GenerateBind()
{
var args = _argumentMarshalerTypes.Select(x => Argument(MarshalerTypeName(x))).ToList();
yield return InvocationExpression(MarshalerTypeName(Type), ArgumentList(SeparatedList(args)));
}

public override IEnumerable<StatementSyntax> Generate(StubCodeContext context)
public override IEnumerable<StatementSyntax> Generate(StubIdentifierContext context)
{
string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg");
var target = TypeInfo.IsManagedReturnPosition
Expand All @@ -45,12 +45,12 @@ public override IEnumerable<StatementSyntax> Generate(StubCodeContext context)
.Select(a => a.Syntax)
.ToArray();

if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition)
if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition)
{
yield return ToManagedMethod(target, source, jsty);
}

if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition)
if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition)
{
yield return ToJSMethod(target, source, jsty);
}
Expand All @@ -60,21 +60,20 @@ public override IEnumerable<StatementSyntax> Generate(StubCodeContext context)
yield return x;
}

if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition)
if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition)
{
yield return ToJSMethod(target, source, jsty);
}

if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition)
if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition)
{
yield return ToManagedMethod(target, source, jsty);
}
}

private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax source, JSFunctionTypeInfo info)
{
List<ArgumentSyntax> arguments = new List<ArgumentSyntax>();
arguments.Add(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)));
List<ArgumentSyntax> arguments = [source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))];
for (int i = 0; i < info.ArgsTypeInfo.Length; i++)
{
var sourceType = info.ArgsTypeInfo[i];
Expand All @@ -95,8 +94,7 @@ private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax

private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax source, JSFunctionTypeInfo info)
{
List<ArgumentSyntax> arguments = new List<ArgumentSyntax>();
arguments.Add(source);
List<ArgumentSyntax> arguments = [source];
for (int i = 0; i < info.ArgsTypeInfo.Length; i++)
{
var sourceType = info.ArgsTypeInfo[i];
Expand All @@ -115,9 +113,6 @@ private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax sourc
.WithArgumentList(ArgumentList(SeparatedList(arguments))));
}

public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new FuncJSGenerator(info, _isAction, _argumentMarshalerTypes);


private static ArgumentSyntax ArgToJS(int i, TypeSyntax sourceType, MarshalerType marshalerType) => Argument(ParenthesizedLambdaExpression()
.WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword)))
.WithParameterList(ParameterList(SeparatedList(new[]{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ namespace Microsoft.Interop.JavaScript
{
internal interface IJSMarshallingGenerator : IBoundMarshallingGenerator
{
IEnumerable<ExpressionSyntax> GenerateBind(StubCodeContext context);
IEnumerable<ExpressionSyntax> GenerateBind();
}
}
Loading

0 comments on commit c87cbf6

Please sign in to comment.