653 lines
30 KiB
C#
653 lines
30 KiB
C#
using System;
|
|
using System.Collections.Immutable;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.Emit;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal sealed class LoweredDynamicOperationFactory
|
|
{
|
|
[Flags]
|
|
private enum CSharpBinderFlags
|
|
{
|
|
None = 0,
|
|
CheckedContext = 1,
|
|
InvokeSimpleName = 2,
|
|
InvokeSpecialName = 4,
|
|
BinaryOperationLogical = 8,
|
|
ConvertExplicit = 0x10,
|
|
ConvertArrayIndex = 0x20,
|
|
ResultIndexed = 0x40,
|
|
ValueFromCompoundAssignment = 0x80,
|
|
ResultDiscarded = 0x100
|
|
}
|
|
|
|
[Flags]
|
|
private enum CSharpArgumentInfoFlags
|
|
{
|
|
None = 0,
|
|
UseCompileTimeType = 1,
|
|
Constant = 2,
|
|
NamedArgument = 4,
|
|
IsRef = 8,
|
|
IsOut = 0x10,
|
|
IsStaticType = 0x20
|
|
}
|
|
|
|
private readonly SyntheticBoundNodeFactory _factory;
|
|
|
|
private readonly int _methodOrdinal;
|
|
|
|
private readonly int _localFunctionOrdinal;
|
|
|
|
private NamedTypeSymbol? _currentDynamicCallSiteContainer;
|
|
|
|
private int _callSiteIdDispenser;
|
|
|
|
public int MethodOrdinal => _methodOrdinal;
|
|
|
|
internal LoweredDynamicOperationFactory(SyntheticBoundNodeFactory factory, int methodOrdinal, int localFunctionOrdinal = -1)
|
|
{
|
|
_factory = factory;
|
|
_methodOrdinal = methodOrdinal;
|
|
_localFunctionOrdinal = localFunctionOrdinal;
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicConversion(BoundExpression loweredOperand, bool isExplicit, bool isArrayIndex, bool isChecked, TypeSymbol resultType)
|
|
{
|
|
_factory.Syntax = loweredOperand.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (isChecked)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.CheckedContext;
|
|
}
|
|
if (isExplicit)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ConvertExplicit;
|
|
}
|
|
if (isArrayIndex)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ConvertArrayIndex;
|
|
}
|
|
ImmutableArray<BoundExpression> loweredArguments = ImmutableArray.Create(loweredOperand);
|
|
BoundExpression binderConstruction = MakeBinderConstruction((WellKnownMember)148, new BoundExpression[3]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.Typeof(resultType),
|
|
_factory.TypeofDynamicOperationContextType()
|
|
});
|
|
return MakeDynamicOperation(binderConstruction, null, (RefKind)0, loweredArguments, default(ImmutableArray<RefKind>), null, resultType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicUnaryOperator(UnaryOperatorKind operatorKind, BoundExpression loweredOperand, TypeSymbol resultType)
|
|
{
|
|
_factory.Syntax = loweredOperand.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (operatorKind.IsChecked())
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.CheckedContext;
|
|
}
|
|
ImmutableArray<BoundExpression> loweredArguments = ImmutableArray.Create(loweredOperand);
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)157, new BoundExpression[4]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.Literal((int)operatorKind.ToExpressionType()),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, default(ImmutableArray<string>), default(ImmutableArray<RefKind>), null, (RefKind)0)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, null, (RefKind)0, loweredArguments, default(ImmutableArray<RefKind>), null, resultType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicBinaryOperator(BinaryOperatorKind operatorKind, BoundExpression loweredLeft, BoundExpression loweredRight, bool isCompoundAssignment, TypeSymbol resultType)
|
|
{
|
|
_factory.Syntax = loweredLeft.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (operatorKind.IsChecked())
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.CheckedContext;
|
|
}
|
|
if (operatorKind.IsLogical())
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.BinaryOperationLogical;
|
|
}
|
|
ImmutableArray<BoundExpression> loweredArguments = ImmutableArray.Create(loweredLeft, loweredRight);
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)147, new BoundExpression[4]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.Literal((int)operatorKind.ToExpressionType(isCompoundAssignment)),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, default(ImmutableArray<string>), default(ImmutableArray<RefKind>), null, (RefKind)0)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, null, (RefKind)0, loweredArguments, default(ImmutableArray<RefKind>), null, resultType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicMemberInvocation(string name, BoundExpression loweredReceiver, ImmutableArray<TypeWithAnnotations> typeArgumentsWithAnnotations, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> refKinds, bool hasImplicitReceiver, bool resultDiscarded)
|
|
{
|
|
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (hasImplicitReceiver && _factory.TopLevelMethod.RequiresInstanceReceiver)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.InvokeSimpleName;
|
|
}
|
|
TypeSymbol resultType;
|
|
if (resultDiscarded)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ResultDiscarded;
|
|
resultType = _factory.SpecialType((SpecialType)6);
|
|
}
|
|
else
|
|
{
|
|
resultType = AssemblySymbol.DynamicType;
|
|
}
|
|
RefKind receiverRefKind;
|
|
bool receiverIsStaticType;
|
|
if (loweredReceiver.Kind == BoundKind.TypeExpression)
|
|
{
|
|
loweredReceiver = _factory.Typeof(((BoundTypeExpression)loweredReceiver).Type);
|
|
receiverRefKind = (RefKind)0;
|
|
receiverIsStaticType = true;
|
|
}
|
|
else
|
|
{
|
|
receiverRefKind = GetReceiverRefKind(loweredReceiver);
|
|
receiverIsStaticType = false;
|
|
}
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)153, new BoundExpression[5]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.Literal(name),
|
|
typeArgumentsWithAnnotations.IsDefaultOrEmpty ? _factory.Null(_factory.WellKnownArrayType((WellKnownType)61)) : _factory.ArrayOrEmpty(_factory.WellKnownType((WellKnownType)61), _factory.TypeOfs(typeArgumentsWithAnnotations)),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, argumentNames, refKinds, loweredReceiver, receiverRefKind, receiverIsStaticType)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, receiverRefKind, loweredArguments, refKinds, null, resultType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicEventAccessorInvocation(string accessorName, BoundExpression loweredReceiver, BoundExpression loweredHandler)
|
|
{
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
CSharpBinderFlags value = CSharpBinderFlags.InvokeSpecialName | CSharpBinderFlags.ResultDiscarded;
|
|
ImmutableArray<BoundExpression> empty = ImmutableArray<BoundExpression>.Empty;
|
|
TypeSymbol dynamicType = AssemblySymbol.DynamicType;
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
object obj;
|
|
if ((object)argumentInfoFactory == null)
|
|
{
|
|
obj = null;
|
|
}
|
|
else
|
|
{
|
|
BoundExpression[] obj2 = new BoundExpression[5]
|
|
{
|
|
_factory.Literal((int)value),
|
|
_factory.Literal(accessorName),
|
|
_factory.Null(_factory.WellKnownArrayType((WellKnownType)61)),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
null
|
|
};
|
|
obj2[4] = MakeCallSiteArgumentInfos(argumentInfoFactory, empty, default(ImmutableArray<string>), default(ImmutableArray<RefKind>), loweredReceiver, (RefKind)0, receiverIsStaticType: false, loweredHandler);
|
|
obj = MakeBinderConstruction((WellKnownMember)153, obj2);
|
|
}
|
|
BoundExpression binderConstruction = (BoundExpression)obj;
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, empty, default(ImmutableArray<RefKind>), loweredHandler, dynamicType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicInvocation(BoundExpression loweredReceiver, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> refKinds, bool resultDiscarded)
|
|
{
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
TypeSymbol resultType;
|
|
if (resultDiscarded)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ResultDiscarded;
|
|
resultType = _factory.SpecialType((SpecialType)6);
|
|
}
|
|
else
|
|
{
|
|
resultType = AssemblySymbol.DynamicType;
|
|
}
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)151, new BoundExpression[3]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, argumentNames, refKinds, loweredReceiver, (RefKind)0)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, loweredArguments, refKinds, null, resultType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicConstructorInvocation(SyntaxNode syntax, TypeSymbol type, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> refKinds)
|
|
{
|
|
_factory.Syntax = syntax;
|
|
BoundExpression loweredReceiver = _factory.Typeof(type);
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)152, new BoundExpression[3]
|
|
{
|
|
_factory.Literal(0),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, argumentNames, refKinds, loweredReceiver, (RefKind)0, receiverIsStaticType: true)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, loweredArguments, refKinds, null, type);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicGetMember(BoundExpression loweredReceiver, string name, bool resultIndexed)
|
|
{
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (resultIndexed)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ResultIndexed;
|
|
}
|
|
ImmutableArray<BoundExpression> empty = ImmutableArray<BoundExpression>.Empty;
|
|
DynamicTypeSymbol instance = DynamicTypeSymbol.Instance;
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
object obj;
|
|
if ((object)argumentInfoFactory == null)
|
|
{
|
|
obj = null;
|
|
}
|
|
else
|
|
{
|
|
BoundExpression[] obj2 = new BoundExpression[4]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.Literal(name),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
null
|
|
};
|
|
obj2[3] = MakeCallSiteArgumentInfos(argumentInfoFactory, empty, default(ImmutableArray<string>), default(ImmutableArray<RefKind>), loweredReceiver, (RefKind)0);
|
|
obj = MakeBinderConstruction((WellKnownMember)150, obj2);
|
|
}
|
|
BoundExpression binderConstruction = (BoundExpression)obj;
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, empty, default(ImmutableArray<RefKind>), null, instance);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicSetMember(BoundExpression loweredReceiver, string name, BoundExpression loweredRight, bool isCompoundAssignment = false, bool isChecked = false)
|
|
{
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (isCompoundAssignment)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ValueFromCompoundAssignment;
|
|
if (isChecked)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.CheckedContext;
|
|
}
|
|
}
|
|
ImmutableArray<BoundExpression> empty = ImmutableArray<BoundExpression>.Empty;
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
object obj;
|
|
if ((object)argumentInfoFactory == null)
|
|
{
|
|
obj = null;
|
|
}
|
|
else
|
|
{
|
|
BoundExpression[] obj2 = new BoundExpression[4]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.Literal(name),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
null
|
|
};
|
|
obj2[3] = MakeCallSiteArgumentInfos(argumentInfoFactory, empty, default(ImmutableArray<string>), default(ImmutableArray<RefKind>), loweredReceiver, (RefKind)0, receiverIsStaticType: false, loweredRight);
|
|
obj = MakeBinderConstruction((WellKnownMember)156, obj2);
|
|
}
|
|
BoundExpression binderConstruction = (BoundExpression)obj;
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, empty, default(ImmutableArray<RefKind>), loweredRight, AssemblySymbol.DynamicType);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicGetIndex(BoundExpression loweredReceiver, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> refKinds)
|
|
{
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
DynamicTypeSymbol instance = DynamicTypeSymbol.Instance;
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)149, new BoundExpression[3]
|
|
{
|
|
_factory.Literal(0),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, argumentNames, refKinds, loweredReceiver, (RefKind)0)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, loweredArguments, refKinds, null, instance);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicSetIndex(BoundExpression loweredReceiver, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> refKinds, BoundExpression loweredRight, bool isCompoundAssignment = false, bool isChecked = false)
|
|
{
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
|
|
CSharpBinderFlags cSharpBinderFlags = CSharpBinderFlags.None;
|
|
if (isCompoundAssignment)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.ValueFromCompoundAssignment;
|
|
if (isChecked)
|
|
{
|
|
cSharpBinderFlags |= CSharpBinderFlags.CheckedContext;
|
|
}
|
|
}
|
|
RefKind receiverRefKind = GetReceiverRefKind(loweredReceiver);
|
|
DynamicTypeSymbol instance = DynamicTypeSymbol.Instance;
|
|
MethodSymbol argumentInfoFactory = GetArgumentInfoFactory();
|
|
BoundExpression binderConstruction = (((object)argumentInfoFactory != null) ? MakeBinderConstruction((WellKnownMember)155, new BoundExpression[3]
|
|
{
|
|
_factory.Literal((int)cSharpBinderFlags),
|
|
_factory.TypeofDynamicOperationContextType(),
|
|
MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments, argumentNames, refKinds, loweredReceiver, receiverRefKind, receiverIsStaticType: false, loweredRight)
|
|
}) : null);
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, receiverRefKind, loweredArguments, refKinds, loweredRight, instance);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicIsEventTest(string name, BoundExpression loweredReceiver)
|
|
{
|
|
_factory.Syntax = loweredReceiver.Syntax;
|
|
NamedTypeSymbol resultType = _factory.SpecialType((SpecialType)7);
|
|
BoundExpression binderConstruction = MakeBinderConstruction((WellKnownMember)154, new BoundExpression[3]
|
|
{
|
|
_factory.Literal(0),
|
|
_factory.Literal(name),
|
|
_factory.TypeofDynamicOperationContextType()
|
|
});
|
|
return MakeDynamicOperation(binderConstruction, loweredReceiver, (RefKind)0, ImmutableArray<BoundExpression>.Empty, default(ImmutableArray<RefKind>), null, resultType);
|
|
}
|
|
|
|
private MethodSymbol GetArgumentInfoFactory()
|
|
{
|
|
return _factory.WellKnownMethod((WellKnownMember)158);
|
|
}
|
|
|
|
private BoundExpression? MakeBinderConstruction(WellKnownMember factoryMethod, BoundExpression[] args)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
Symbol symbol = _factory.WellKnownMember(factoryMethod);
|
|
if ((object)symbol == null)
|
|
{
|
|
return null;
|
|
}
|
|
return _factory.Call(null, (MethodSymbol)symbol, ImmutableArrayExtensions.AsImmutableOrNull<BoundExpression>(args));
|
|
}
|
|
|
|
internal static RefKind GetReceiverRefKind(BoundExpression loweredReceiver)
|
|
{
|
|
if (!loweredReceiver.Type.IsValueType)
|
|
{
|
|
return (RefKind)0;
|
|
}
|
|
switch (loweredReceiver.Kind)
|
|
{
|
|
case BoundKind.PointerIndirectionOperator:
|
|
case BoundKind.PointerElementAccess:
|
|
case BoundKind.RefValueOperator:
|
|
case BoundKind.ArrayAccess:
|
|
case BoundKind.ThisReference:
|
|
case BoundKind.Local:
|
|
case BoundKind.Parameter:
|
|
return (RefKind)1;
|
|
case BoundKind.TypeExpression:
|
|
case BoundKind.BaseReference:
|
|
throw ExceptionUtilities.UnexpectedValue((object)loweredReceiver.Kind);
|
|
default:
|
|
return (RefKind)0;
|
|
}
|
|
}
|
|
|
|
internal BoundExpression MakeCallSiteArgumentInfos(MethodSymbol argumentInfoFactory, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<string> argumentNames = default(ImmutableArray<string>), ImmutableArray<RefKind> refKinds = default(ImmutableArray<RefKind>), BoundExpression? loweredReceiver = null, RefKind receiverRefKind = (RefKind)0, bool receiverIsStaticType = false, BoundExpression? loweredRight = null)
|
|
{
|
|
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
|
|
BoundExpression[] array = new BoundExpression[((loweredReceiver != null) ? 1 : 0) + loweredArguments.Length + ((loweredRight != null) ? 1 : 0)];
|
|
int num = 0;
|
|
if (loweredReceiver != null)
|
|
{
|
|
array[num++] = GetArgumentInfo(argumentInfoFactory, loweredReceiver, null, receiverRefKind, receiverIsStaticType);
|
|
}
|
|
for (int i = 0; i < loweredArguments.Length; i++)
|
|
{
|
|
array[num++] = GetArgumentInfo(argumentInfoFactory, loweredArguments[i], argumentNames.IsDefaultOrEmpty ? null : argumentNames[i], (RefKind)((!refKinds.IsDefault) ? ((int)refKinds[i]) : 0), isStaticType: false);
|
|
}
|
|
if (loweredRight != null)
|
|
{
|
|
array[num++] = GetArgumentInfo(argumentInfoFactory, loweredRight, null, (RefKind)0, isStaticType: false);
|
|
}
|
|
return _factory.ArrayOrEmpty(argumentInfoFactory.ContainingType, array);
|
|
}
|
|
|
|
internal LoweredDynamicOperation MakeDynamicOperation(BoundExpression? binderConstruction, BoundExpression? loweredReceiver, RefKind receiverRefKind, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<RefKind> refKinds, BoundExpression? loweredRight, TypeSymbol resultType)
|
|
{
|
|
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
|
NamedTypeSymbol delegateType = GetDelegateType(loweredReceiver, receiverRefKind, loweredArguments, refKinds, loweredRight, resultType);
|
|
NamedTypeSymbol namedTypeSymbol = _factory.WellKnownType((WellKnownType)183);
|
|
MethodSymbol methodSymbol = _factory.WellKnownMethod((WellKnownMember)121);
|
|
FieldSymbol fieldSymbol = (FieldSymbol)_factory.WellKnownMember((WellKnownMember)122);
|
|
MethodSymbol delegateInvokeMethod;
|
|
if (binderConstruction == null || (object)delegateType == null || delegateType.IsErrorType() || (object)(delegateInvokeMethod = delegateType.DelegateInvokeMethod) == null || namedTypeSymbol.IsErrorType() || (object)methodSymbol == null || (object)fieldSymbol == null)
|
|
{
|
|
_factory.Diagnostics.Add(ErrorCode.ERR_DynamicRequiredTypesMissing, NoLocation.Singleton);
|
|
return LoweredDynamicOperation.Bad(loweredReceiver, loweredArguments, loweredRight, resultType);
|
|
}
|
|
if ((object)_currentDynamicCallSiteContainer == null)
|
|
{
|
|
_currentDynamicCallSiteContainer = CreateCallSiteContainer(_factory, _methodOrdinal, _localFunctionOrdinal);
|
|
}
|
|
SynthesizedContainer synthesizedContainer = (SynthesizedContainer)_currentDynamicCallSiteContainer.OriginalDefinition;
|
|
TypeMap typeMap = synthesizedContainer.TypeMap;
|
|
ImmutableArray<LocalSymbol> temps = MakeTempsForDiscardArguments(ref loweredArguments);
|
|
TypeSymbol[] typeArguments = new NamedTypeSymbol[1] { delegateType };
|
|
NamedTypeSymbol newOwner = namedTypeSymbol.Construct(typeArguments);
|
|
MethodSymbol method = methodSymbol.AsMember(newOwner);
|
|
FieldSymbol f = fieldSymbol.AsMember(newOwner);
|
|
FieldSymbol fieldSymbol2 = DefineCallSiteStorageSymbol(synthesizedContainer, delegateType, typeMap);
|
|
BoundFieldAccess boundFieldAccess = _factory.Field(null, fieldSymbol2);
|
|
ImmutableArray<BoundExpression> callSiteArguments = GetCallSiteArguments(boundFieldAccess, loweredReceiver, loweredArguments, loweredRight);
|
|
BoundExpression boundExpression = _factory.Null(fieldSymbol2.Type);
|
|
BoundExpression siteInitialization = _factory.Conditional(_factory.ObjectEqual(boundFieldAccess, boundExpression), _factory.AssignmentExpression(boundFieldAccess, _factory.Call(null, method, binderConstruction)), boundExpression, fieldSymbol2.Type);
|
|
BoundCall siteInvocation = _factory.Call(_factory.Field(boundFieldAccess, f), delegateInvokeMethod, callSiteArguments);
|
|
return new LoweredDynamicOperation(_factory, siteInitialization, siteInvocation, resultType, temps);
|
|
}
|
|
|
|
private ImmutableArray<LocalSymbol> MakeTempsForDiscardArguments(ref ImmutableArray<BoundExpression> loweredArguments)
|
|
{
|
|
int num = ImmutableArrayExtensions.Count<BoundExpression>(loweredArguments, (Func<BoundExpression, bool>)((BoundExpression a) => a.Kind == BoundKind.DiscardExpression));
|
|
if (num == 0)
|
|
{
|
|
return ImmutableArray<LocalSymbol>.Empty;
|
|
}
|
|
ArrayBuilder<LocalSymbol> instance = ArrayBuilder<LocalSymbol>.GetInstance(num);
|
|
loweredArguments = _factory.MakeTempsForDiscardArguments(loweredArguments, instance);
|
|
return instance.ToImmutableAndFree();
|
|
}
|
|
|
|
private static NamedTypeSymbol CreateCallSiteContainer(SyntheticBoundNodeFactory factory, int methodOrdinal, int localFunctionOrdinal)
|
|
{
|
|
int currentGenerationOrdinal = ((CommonPEModuleBuilder)factory.CompilationState.ModuleBuilderOpt).CurrentGenerationOrdinal;
|
|
DynamicSiteContainer dynamicSiteContainer = new DynamicSiteContainer(GeneratedNames.MakeDynamicCallSiteContainerName(methodOrdinal, localFunctionOrdinal, currentGenerationOrdinal), factory.TopLevelMethod, factory.CurrentFunction);
|
|
factory.AddNestedType(dynamicSiteContainer);
|
|
if (!dynamicSiteContainer.TypeParameters.IsEmpty)
|
|
{
|
|
return dynamicSiteContainer.Construct(ImmutableArrayExtensions.Cast<TypeParameterSymbol, TypeSymbol>(dynamicSiteContainer.ConstructedFromTypeParameters));
|
|
}
|
|
return dynamicSiteContainer;
|
|
}
|
|
|
|
internal FieldSymbol DefineCallSiteStorageSymbol(NamedTypeSymbol containerDefinition, NamedTypeSymbol delegateTypeOverMethodTypeParameters, TypeMap methodToContainerTypeParametersMap)
|
|
{
|
|
string name = GeneratedNames.MakeDynamicCallSiteFieldName(_callSiteIdDispenser++);
|
|
NamedTypeSymbol namedTypeSymbol = methodToContainerTypeParametersMap.SubstituteNamedType(delegateTypeOverMethodTypeParameters);
|
|
NamedTypeSymbol wellKnownType = _factory.Compilation.GetWellKnownType((WellKnownType)183);
|
|
_factory.Diagnostics.ReportUseSite(wellKnownType, _factory.Syntax);
|
|
NamedTypeSymbol namedTypeSymbol2 = wellKnownType;
|
|
TypeSymbol[] typeArguments = new NamedTypeSymbol[1] { namedTypeSymbol };
|
|
wellKnownType = namedTypeSymbol2.Construct(typeArguments);
|
|
SynthesizedFieldSymbol synthesizedFieldSymbol = new SynthesizedFieldSymbol(containerDefinition, wellKnownType, name, isPublic: true, isReadOnly: false, isStatic: true);
|
|
_factory.AddField(containerDefinition, synthesizedFieldSymbol);
|
|
if (!_currentDynamicCallSiteContainer.IsGenericType)
|
|
{
|
|
return synthesizedFieldSymbol;
|
|
}
|
|
return synthesizedFieldSymbol.AsMember(_currentDynamicCallSiteContainer);
|
|
}
|
|
|
|
internal NamedTypeSymbol? GetDelegateType(BoundExpression? loweredReceiver, RefKind receiverRefKind, ImmutableArray<BoundExpression> loweredArguments, ImmutableArray<RefKind> refKinds, BoundExpression? loweredRight, TypeSymbol resultType)
|
|
{
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
|
|
NamedTypeSymbol namedTypeSymbol = _factory.WellKnownType((WellKnownType)182);
|
|
if (namedTypeSymbol.IsErrorType())
|
|
{
|
|
return null;
|
|
}
|
|
TypeSymbol[] array = MakeCallSiteDelegateSignature(namedTypeSymbol, loweredReceiver, loweredArguments, loweredRight, resultType);
|
|
bool flag = resultType.IsVoidType();
|
|
bool flag2 = (int)receiverRefKind != 0 || !refKinds.IsDefaultOrEmpty;
|
|
if (!flag2)
|
|
{
|
|
WellKnownType val = (flag ? WellKnownTypes.GetWellKnownActionDelegate(array.Length) : WellKnownTypes.GetWellKnownFunctionDelegate(array.Length - 1));
|
|
if ((int)val != 0)
|
|
{
|
|
NamedTypeSymbol wellKnownType = _factory.Compilation.GetWellKnownType(val);
|
|
if (!wellKnownType.HasUseSiteError)
|
|
{
|
|
_factory.Diagnostics.AddDependencies(wellKnownType);
|
|
return wellKnownType.Construct(array);
|
|
}
|
|
}
|
|
}
|
|
RefKindVector refKinds2;
|
|
if (flag2)
|
|
{
|
|
refKinds2 = RefKindVector.Create(1 + ((loweredReceiver != null) ? 1 : 0) + loweredArguments.Length + ((loweredRight != null) ? 1 : 0) + ((!flag) ? 1 : 0));
|
|
int num = 1;
|
|
if (loweredReceiver != null)
|
|
{
|
|
refKinds2[num++] = getRefKind(receiverRefKind);
|
|
}
|
|
if (!refKinds.IsDefault)
|
|
{
|
|
int num2 = 0;
|
|
while (num2 < refKinds.Length)
|
|
{
|
|
refKinds2[num] = getRefKind(refKinds[num2]);
|
|
num2++;
|
|
num++;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
refKinds2[num++] = (RefKind)0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
refKinds2 = default(RefKindVector);
|
|
}
|
|
int parameterCount = array.Length - ((!flag) ? 1 : 0);
|
|
int currentGenerationOrdinal = ((CommonPEModuleBuilder)_factory.CompilationState.ModuleBuilderOpt).CurrentGenerationOrdinal;
|
|
return _factory.Compilation.AnonymousTypeManager.SynthesizeDelegate(parameterCount, refKinds2, flag, currentGenerationOrdinal).Construct(array);
|
|
static RefKind getRefKind(RefKind refKind)
|
|
{
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
|
if ((int)refKind == 0)
|
|
{
|
|
return (RefKind)0;
|
|
}
|
|
return (RefKind)1;
|
|
}
|
|
}
|
|
|
|
private BoundExpression GetArgumentInfo(MethodSymbol argumentInfoFactory, BoundExpression boundArgument, string? name, RefKind refKind, bool isStaticType)
|
|
{
|
|
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0015: Invalid comparison between Unknown and I4
|
|
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Invalid comparison between Unknown and I4
|
|
CSharpArgumentInfoFlags cSharpArgumentInfoFlags = CSharpArgumentInfoFlags.None;
|
|
if (isStaticType)
|
|
{
|
|
cSharpArgumentInfoFlags |= CSharpArgumentInfoFlags.IsStaticType;
|
|
}
|
|
if (name != null)
|
|
{
|
|
cSharpArgumentInfoFlags |= CSharpArgumentInfoFlags.NamedArgument;
|
|
}
|
|
if ((int)refKind == 2)
|
|
{
|
|
cSharpArgumentInfoFlags |= CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsOut;
|
|
}
|
|
else if ((int)refKind == 1)
|
|
{
|
|
cSharpArgumentInfoFlags |= CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsRef;
|
|
}
|
|
TypeSymbol type = boundArgument.Type;
|
|
if (boundArgument.ConstantValueOpt != (ConstantValue)null)
|
|
{
|
|
cSharpArgumentInfoFlags |= CSharpArgumentInfoFlags.Constant;
|
|
}
|
|
if ((object)type != null && !type.IsDynamic())
|
|
{
|
|
cSharpArgumentInfoFlags |= CSharpArgumentInfoFlags.UseCompileTimeType;
|
|
}
|
|
return _factory.Call(null, argumentInfoFactory, _factory.Literal((int)cSharpArgumentInfoFlags), _factory.Literal(name));
|
|
}
|
|
|
|
private static ImmutableArray<BoundExpression> GetCallSiteArguments(BoundExpression callSiteFieldAccess, BoundExpression? receiver, ImmutableArray<BoundExpression> arguments, BoundExpression? right)
|
|
{
|
|
BoundExpression[] array = new BoundExpression[1 + ((receiver != null) ? 1 : 0) + arguments.Length + ((right != null) ? 1 : 0)];
|
|
int num = 0;
|
|
array[num++] = callSiteFieldAccess;
|
|
if (receiver != null)
|
|
{
|
|
array[num++] = receiver;
|
|
}
|
|
arguments.CopyTo(array, num);
|
|
num += arguments.Length;
|
|
if (right != null)
|
|
{
|
|
array[num++] = right;
|
|
}
|
|
return ImmutableArrayExtensions.AsImmutableOrNull<BoundExpression>(array);
|
|
}
|
|
|
|
private TypeSymbol[] MakeCallSiteDelegateSignature(TypeSymbol callSiteType, BoundExpression? receiver, ImmutableArray<BoundExpression> arguments, BoundExpression? right, TypeSymbol resultType)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = _factory.SpecialType((SpecialType)1);
|
|
TypeSymbol[] array = new TypeSymbol[1 + ((receiver != null) ? 1 : 0) + arguments.Length + ((right != null) ? 1 : 0) + ((!resultType.IsVoidType()) ? 1 : 0)];
|
|
int num = 0;
|
|
array[num++] = callSiteType;
|
|
if (receiver != null)
|
|
{
|
|
array[num++] = receiver.Type ?? namedTypeSymbol;
|
|
}
|
|
for (int i = 0; i < arguments.Length; i++)
|
|
{
|
|
array[num++] = arguments[i].Type ?? namedTypeSymbol;
|
|
}
|
|
if (right != null)
|
|
{
|
|
array[num++] = right.Type ?? namedTypeSymbol;
|
|
}
|
|
if (num < array.Length)
|
|
{
|
|
array[num++] = resultType ?? namedTypeSymbol;
|
|
}
|
|
return array;
|
|
}
|
|
}
|