6902 lines
231 KiB
C#
6902 lines
231 KiB
C#
using System;
|
|||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Collections.Immutable;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Reflection.Metadata;
|
||
|
|
using System.Runtime.CompilerServices;
|
||
|
|
using System.Threading;
|
||
|
|
using Microsoft.Cci;
|
||
|
|
using Microsoft.CodeAnalysis.CSharp.Emit;
|
||
|
|
using Microsoft.CodeAnalysis.CSharp.Emit.NoPia;
|
||
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
||
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||
|
|
using Microsoft.CodeAnalysis.CodeGen;
|
||
|
|
using Microsoft.CodeAnalysis.Emit;
|
||
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
||
|
|
using Microsoft.CodeAnalysis.Symbols;
|
||
|
|
using Microsoft.CodeAnalysis.Text;
|
||
|
|
using Roslyn.Utilities;
|
||
|
|
|
||
|
|
namespace Microsoft.CodeAnalysis.CSharp.CodeGen;
|
||
|
|
|
||
|
|
internal sealed class CodeGenerator
|
||
|
|
{
|
||
|
|
private enum IndirectReturnState : byte
|
||
|
|
{
|
||
|
|
NotNeeded,
|
||
|
|
Needed,
|
||
|
|
Emitted
|
||
|
|
}
|
||
|
|
|
||
|
|
private enum ArrayInitializerStyle
|
||
|
|
{
|
||
|
|
Element,
|
||
|
|
Block,
|
||
|
|
Mixed
|
||
|
|
}
|
||
|
|
|
||
|
|
private readonly struct IndexDesc(int index, ImmutableArray<BoundExpression> initializers)
|
||
|
|
{
|
||
|
|
public readonly int Index = index;
|
||
|
|
|
||
|
|
public readonly ImmutableArray<BoundExpression> Initializers = initializers;
|
||
|
|
}
|
||
|
|
|
||
|
|
private class EmitCancelledException : Exception
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
private enum UseKind
|
||
|
|
{
|
||
|
|
Unused,
|
||
|
|
UsedAsValue,
|
||
|
|
UsedAsAddress
|
||
|
|
}
|
||
|
|
|
||
|
|
private sealed class IsConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
|
||
|
|
{
|
||
|
|
private readonly BoundLoweredConditionalAccess _conditionalAccess;
|
||
|
|
|
||
|
|
private bool? _result;
|
||
|
|
|
||
|
|
private IsConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker(BoundLoweredConditionalAccess conditionalAccess)
|
||
|
|
{
|
||
|
|
_conditionalAccess = conditionalAccess;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static bool Analyze(BoundLoweredConditionalAccess conditionalAccess)
|
||
|
|
{
|
||
|
|
IsConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker isConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker = new IsConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker(conditionalAccess);
|
||
|
|
isConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker.Visit(conditionalAccess.WhenNotNull);
|
||
|
|
return isConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker._result == true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode Visit(BoundNode node)
|
||
|
|
{
|
||
|
|
if (_result.HasValue)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return base.Visit(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override void VisitReceiver(BoundCall node)
|
||
|
|
{
|
||
|
|
if (node.ReceiverOpt is BoundConditionalReceiver { Id: var id } && id == _conditionalAccess.Id)
|
||
|
|
{
|
||
|
|
_result = !IsSafeToDereferenceReceiverRefAfterEvaluatingArguments(node.Arguments);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode VisitConditionalReceiver(BoundConditionalReceiver node)
|
||
|
|
{
|
||
|
|
if (node.Id == _conditionalAccess.Id)
|
||
|
|
{
|
||
|
|
_result = false;
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return base.VisitConditionalReceiver(node);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private enum CallKind
|
||
|
|
{
|
||
|
|
Call,
|
||
|
|
CallVirt,
|
||
|
|
ConstrainedCallVirt
|
||
|
|
}
|
||
|
|
|
||
|
|
private class FinallyCloner : BoundTreeRewriterWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
|
||
|
|
{
|
||
|
|
private Dictionary<LabelSymbol, GeneratedLabelSymbol> _labelClones;
|
||
|
|
|
||
|
|
private FinallyCloner()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
public static BoundBlock MakeFinallyClone(BoundTryStatement node)
|
||
|
|
{
|
||
|
|
return (BoundBlock)new FinallyCloner().Visit(node.FinallyBlockOpt);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode VisitLabelStatement(BoundLabelStatement node)
|
||
|
|
{
|
||
|
|
return node.Update(GetLabelClone(node.Label));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode VisitGotoStatement(BoundGotoStatement node)
|
||
|
|
{
|
||
|
|
GeneratedLabelSymbol labelClone = GetLabelClone(node.Label);
|
||
|
|
BoundExpression caseExpressionOpt = node.CaseExpressionOpt;
|
||
|
|
BoundLabel labelExpressionOpt = node.LabelExpressionOpt;
|
||
|
|
return node.Update(labelClone, caseExpressionOpt, labelExpressionOpt);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode VisitConditionalGoto(BoundConditionalGoto node)
|
||
|
|
{
|
||
|
|
GeneratedLabelSymbol labelClone = GetLabelClone(node.Label);
|
||
|
|
BoundExpression condition = node.Condition;
|
||
|
|
return node.Update(condition, node.JumpIfTrue, labelClone);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode VisitSwitchDispatch(BoundSwitchDispatch node)
|
||
|
|
{
|
||
|
|
BoundExpression expression = node.Expression;
|
||
|
|
GeneratedLabelSymbol labelClone = GetLabelClone(node.DefaultLabel);
|
||
|
|
ArrayBuilder<(ConstantValue, LabelSymbol)> instance = ArrayBuilder<(ConstantValue, LabelSymbol)>.GetInstance();
|
||
|
|
ImmutableArray<(ConstantValue, LabelSymbol)>.Enumerator enumerator = node.Cases.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
var (item, label) = enumerator.Current;
|
||
|
|
instance.Add((item, (LabelSymbol)GetLabelClone(label)));
|
||
|
|
}
|
||
|
|
LengthBasedStringSwitchData lengthBasedStringSwitchDataOpt = node.LengthBasedStringSwitchDataOpt;
|
||
|
|
if (lengthBasedStringSwitchDataOpt != null)
|
||
|
|
{
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs", 1965);
|
||
|
|
}
|
||
|
|
return node.Update(expression, instance.ToImmutableAndFree(), labelClone, lengthBasedStringSwitchDataOpt);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundNode VisitExpressionStatement(BoundExpressionStatement node)
|
||
|
|
{
|
||
|
|
return node;
|
||
|
|
}
|
||
|
|
|
||
|
|
private GeneratedLabelSymbol GetLabelClone(LabelSymbol label)
|
||
|
|
{
|
||
|
|
Dictionary<LabelSymbol, GeneratedLabelSymbol> dictionary = _labelClones;
|
||
|
|
if (dictionary == null)
|
||
|
|
{
|
||
|
|
dictionary = (_labelClones = new Dictionary<LabelSymbol, GeneratedLabelSymbol>());
|
||
|
|
}
|
||
|
|
if (!dictionary.TryGetValue(label, out var value))
|
||
|
|
{
|
||
|
|
value = new GeneratedLabelSymbol("cloned_" + label.Name);
|
||
|
|
dictionary.Add(label, value);
|
||
|
|
}
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[CompilerGenerated]
|
||
|
|
private static class _003C_003EO
|
||
|
|
{
|
||
|
|
public static Func<BoundExpression, bool> _003C0_003E__isSafeToDereferenceReceiverRefAfterEvaluatingArgument;
|
||
|
|
|
||
|
|
public static GetStringHashCode _003C1_003E__ComputeStringHash;
|
||
|
|
}
|
||
|
|
|
||
|
|
private readonly MethodSymbol _method;
|
||
|
|
|
||
|
|
private readonly SyntaxNode _methodBodySyntaxOpt;
|
||
|
|
|
||
|
|
private readonly BoundStatement _boundBody;
|
||
|
|
|
||
|
|
private readonly ILBuilder _builder;
|
||
|
|
|
||
|
|
private readonly PEModuleBuilder _module;
|
||
|
|
|
||
|
|
private readonly BindingDiagnosticBag _diagnostics;
|
||
|
|
|
||
|
|
private readonly ILEmitStyle _ilEmitStyle;
|
||
|
|
|
||
|
|
private readonly bool _emitPdbSequencePoints;
|
||
|
|
|
||
|
|
private readonly HashSet<LocalSymbol> _stackLocals;
|
||
|
|
|
||
|
|
private ArrayBuilder<LocalDefinition> _expressionTemps;
|
||
|
|
|
||
|
|
private int _tryNestingLevel;
|
||
|
|
|
||
|
|
private readonly SynthesizedLocalOrdinalsDispenser _synthesizedLocalOrdinals = new SynthesizedLocalOrdinalsDispenser();
|
||
|
|
|
||
|
|
private int _uniqueNameId;
|
||
|
|
|
||
|
|
private static readonly object s_returnLabel = new object();
|
||
|
|
|
||
|
|
private int _asyncCatchHandlerOffset = -1;
|
||
|
|
|
||
|
|
private ArrayBuilder<int> _asyncYieldPoints;
|
||
|
|
|
||
|
|
private ArrayBuilder<int> _asyncResumePoints;
|
||
|
|
|
||
|
|
private IndirectReturnState _indirectReturnState;
|
||
|
|
|
||
|
|
private PooledDictionary<object, TextSpan> _savedSequencePoints;
|
||
|
|
|
||
|
|
private LocalDefinition _returnTemp;
|
||
|
|
|
||
|
|
private bool _sawStackalloc;
|
||
|
|
|
||
|
|
private int _recursionDepth;
|
||
|
|
|
||
|
|
private static readonly ILOpCode[] s_compOpCodes = new ILOpCode[12]
|
||
|
|
{
|
||
|
|
ILOpCode.Clt,
|
||
|
|
ILOpCode.Cgt,
|
||
|
|
ILOpCode.Cgt,
|
||
|
|
ILOpCode.Clt,
|
||
|
|
ILOpCode.Clt_un,
|
||
|
|
ILOpCode.Cgt_un,
|
||
|
|
ILOpCode.Cgt_un,
|
||
|
|
ILOpCode.Clt_un,
|
||
|
|
ILOpCode.Clt,
|
||
|
|
ILOpCode.Cgt_un,
|
||
|
|
ILOpCode.Cgt,
|
||
|
|
ILOpCode.Clt_un
|
||
|
|
};
|
||
|
|
|
||
|
|
private const int IL_OP_CODE_ROW_LENGTH = 4;
|
||
|
|
|
||
|
|
private static readonly ILOpCode[] s_condJumpOpCodes = new ILOpCode[24]
|
||
|
|
{
|
||
|
|
ILOpCode.Blt,
|
||
|
|
ILOpCode.Ble,
|
||
|
|
ILOpCode.Bgt,
|
||
|
|
ILOpCode.Bge,
|
||
|
|
ILOpCode.Bge,
|
||
|
|
ILOpCode.Bgt,
|
||
|
|
ILOpCode.Ble,
|
||
|
|
ILOpCode.Blt,
|
||
|
|
ILOpCode.Blt_un,
|
||
|
|
ILOpCode.Ble_un,
|
||
|
|
ILOpCode.Bgt_un,
|
||
|
|
ILOpCode.Bge_un,
|
||
|
|
ILOpCode.Bge_un,
|
||
|
|
ILOpCode.Bgt_un,
|
||
|
|
ILOpCode.Ble_un,
|
||
|
|
ILOpCode.Blt_un,
|
||
|
|
ILOpCode.Blt,
|
||
|
|
ILOpCode.Ble,
|
||
|
|
ILOpCode.Bgt,
|
||
|
|
ILOpCode.Bge,
|
||
|
|
ILOpCode.Bge_un,
|
||
|
|
ILOpCode.Bgt_un,
|
||
|
|
ILOpCode.Ble_un,
|
||
|
|
ILOpCode.Blt_un
|
||
|
|
};
|
||
|
|
|
||
|
|
private LocalDefinition LazyReturnTemp
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
LocalDefinition val = _returnTemp;
|
||
|
|
if (val == null)
|
||
|
|
{
|
||
|
|
LocalSlotConstraints val2 = (LocalSlotConstraints)(((int)_method.RefKind != 0) ? 1 : 0);
|
||
|
|
SyntaxNode methodBodySyntaxOpt = _methodBodySyntaxOpt;
|
||
|
|
if ((int)_ilEmitStyle == 0 && methodBodySyntaxOpt != null)
|
||
|
|
{
|
||
|
|
int num = _method.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(methodBodySyntaxOpt), methodBodySyntaxOpt.SyntaxTree);
|
||
|
|
SynthesizedLocal synthesizedLocal = new SynthesizedLocal(_method, _method.ReturnTypeWithAnnotations, (SynthesizedLocalKind)21, methodBodySyntaxOpt, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0);
|
||
|
|
val = _builder.LocalSlotManager.DeclareLocal(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(synthesizedLocal.Type, methodBodySyntaxOpt, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), (ILocalSymbolInternal)(object)synthesizedLocal, (string)null, synthesizedLocal.SynthesizedKind, new LocalDebugId(num, 0), SynthesizedLocalKindExtensions.PdbAttributes(synthesizedLocal.SynthesizedKind), val2, ImmutableArray<bool>.Empty, ImmutableArray<string>.Empty, false);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
val = AllocateTemp(_method.ReturnType, _boundBody.Syntax, val2);
|
||
|
|
}
|
||
|
|
_returnTemp = val;
|
||
|
|
}
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool EnableEnumArrayBlockInitialization => ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.EnableEnumArrayBlockInitialization;
|
||
|
|
|
||
|
|
public CodeGenerator(MethodSymbol method, BoundStatement boundBody, ILBuilder builder, PEModuleBuilder moduleBuilder, BindingDiagnosticBag diagnostics, OptimizationLevel optimizations, bool emittingPdb)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000b: Expected O, but got Unknown
|
||
|
|
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0054: 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)
|
||
|
|
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0089: Invalid comparison between Unknown and I4
|
||
|
|
_method = method;
|
||
|
|
_boundBody = boundBody;
|
||
|
|
_builder = builder;
|
||
|
|
_module = moduleBuilder;
|
||
|
|
_diagnostics = diagnostics;
|
||
|
|
if (!method.GenerateDebugInfo)
|
||
|
|
{
|
||
|
|
_ilEmitStyle = (ILEmitStyle)2;
|
||
|
|
}
|
||
|
|
else if ((int)optimizations == 0)
|
||
|
|
{
|
||
|
|
_ilEmitStyle = (ILEmitStyle)0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_ilEmitStyle = (ILEmitStyle)(IsDebugPlus() ? 1 : 2);
|
||
|
|
}
|
||
|
|
_emitPdbSequencePoints = emittingPdb && method.GenerateDebugInfo;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
_boundBody = Optimizer.Optimize(boundBody, (int)_ilEmitStyle != 2, out _stackLocals);
|
||
|
|
}
|
||
|
|
catch (BoundTreeVisitor.CancelledByStackGuardException ex)
|
||
|
|
{
|
||
|
|
ex.AddAnError(diagnostics);
|
||
|
|
_boundBody = boundBody;
|
||
|
|
}
|
||
|
|
SourceMemberMethodSymbol sourceMemberMethodSymbol = method as SourceMemberMethodSymbol;
|
||
|
|
(BlockSyntax blockBody, ArrowExpressionClauseSyntax arrowBody) obj = sourceMemberMethodSymbol?.Bodies ?? default((BlockSyntax, ArrowExpressionClauseSyntax));
|
||
|
|
BlockSyntax item = obj.blockBody;
|
||
|
|
ArrowExpressionClauseSyntax item2 = obj.arrowBody;
|
||
|
|
_methodBodySyntaxOpt = (SyntaxNode)(object)(item ?? item2 ?? sourceMemberMethodSymbol?.SyntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsDebugPlus()
|
||
|
|
{
|
||
|
|
return ((CompilationOptions)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.Options).DebugPlusMode;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsPeVerifyCompatEnabled()
|
||
|
|
{
|
||
|
|
return ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.IsPeVerifyCompatEnabled;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool IsStackLocal(LocalSymbol local, HashSet<LocalSymbol> stackLocalsOpt)
|
||
|
|
{
|
||
|
|
return stackLocalsOpt?.Contains(local) ?? false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsStackLocal(LocalSymbol local)
|
||
|
|
{
|
||
|
|
return IsStackLocal(local, _stackLocals);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Generate(out bool hasStackalloc)
|
||
|
|
{
|
||
|
|
GenerateImpl();
|
||
|
|
hasStackalloc = _sawStackalloc;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Generate(out int asyncCatchHandlerOffset, out ImmutableArray<int> asyncYieldPoints, out ImmutableArray<int> asyncResumePoints, out bool hasStackAlloc)
|
||
|
|
{
|
||
|
|
GenerateImpl();
|
||
|
|
hasStackAlloc = _sawStackalloc;
|
||
|
|
asyncCatchHandlerOffset = (((BindingDiagnosticBag)_diagnostics).HasAnyErrors() ? (-1) : _builder.GetILOffsetFromMarker(_asyncCatchHandlerOffset));
|
||
|
|
ArrayBuilder<int> asyncYieldPoints2 = _asyncYieldPoints;
|
||
|
|
ArrayBuilder<int> asyncResumePoints2 = _asyncResumePoints;
|
||
|
|
if (asyncYieldPoints2 == null || ((BindingDiagnosticBag)_diagnostics).HasAnyErrors())
|
||
|
|
{
|
||
|
|
asyncYieldPoints = ImmutableArray<int>.Empty;
|
||
|
|
asyncResumePoints = ImmutableArray<int>.Empty;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ArrayBuilder<int> instance = ArrayBuilder<int>.GetInstance();
|
||
|
|
ArrayBuilder<int> instance2 = ArrayBuilder<int>.GetInstance();
|
||
|
|
int count = asyncYieldPoints2.Count;
|
||
|
|
for (int i = 0; i < count; i++)
|
||
|
|
{
|
||
|
|
int iLOffsetFromMarker = _builder.GetILOffsetFromMarker(asyncYieldPoints2[i]);
|
||
|
|
int iLOffsetFromMarker2 = _builder.GetILOffsetFromMarker(asyncResumePoints2[i]);
|
||
|
|
if (iLOffsetFromMarker > 0)
|
||
|
|
{
|
||
|
|
instance.Add(iLOffsetFromMarker);
|
||
|
|
instance2.Add(iLOffsetFromMarker2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
asyncYieldPoints = instance.ToImmutableAndFree();
|
||
|
|
asyncResumePoints = instance2.ToImmutableAndFree();
|
||
|
|
asyncYieldPoints2.Free();
|
||
|
|
asyncResumePoints2.Free();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void GenerateImpl()
|
||
|
|
{
|
||
|
|
SetInitialDebugDocument();
|
||
|
|
if (_emitPdbSequencePoints && _method.IsImplicitlyDeclared)
|
||
|
|
{
|
||
|
|
_builder.DefineInitialHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
try
|
||
|
|
{
|
||
|
|
EmitStatement(_boundBody);
|
||
|
|
if (_indirectReturnState == IndirectReturnState.Needed)
|
||
|
|
{
|
||
|
|
HandleReturn();
|
||
|
|
}
|
||
|
|
if (!((BindingDiagnosticBag)_diagnostics).HasAnyErrors())
|
||
|
|
{
|
||
|
|
_builder.Realize();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (EmitCancelledException)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
_synthesizedLocalOrdinals.Free();
|
||
|
|
_expressionTemps?.Free();
|
||
|
|
_savedSequencePoints?.Free();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void HandleReturn()
|
||
|
|
{
|
||
|
|
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
_builder.MarkLabel(s_returnLabel);
|
||
|
|
if (_emitPdbSequencePoints && !_method.IsIterator && !_method.IsAsync && _methodBodySyntaxOpt is BlockSyntax blockSyntax)
|
||
|
|
{
|
||
|
|
SyntaxTree syntaxTree = blockSyntax.SyntaxTree;
|
||
|
|
SyntaxToken closeBraceToken = blockSyntax.CloseBraceToken;
|
||
|
|
EmitSequencePoint(syntaxTree, ((SyntaxToken)(ref closeBraceToken)).Span);
|
||
|
|
}
|
||
|
|
if (_returnTemp != null)
|
||
|
|
{
|
||
|
|
_builder.EmitLocalLoad(LazyReturnTemp);
|
||
|
|
_builder.EmitRet(false);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitRet(true);
|
||
|
|
}
|
||
|
|
_indirectReturnState = IndirectReturnState.Emitted;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitTypeReferenceToken(ITypeReference symbol, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
_builder.EmitToken((IReference)(object)symbol, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSymbolToken(TypeSymbol symbol, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
EmitTypeReferenceToken(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(symbol, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), syntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSymbolToken(MethodSymbol method, SyntaxNode syntaxNode, BoundArgListOperator optArgList, bool encodeAsRawDefinitionToken = false)
|
||
|
|
{
|
||
|
|
IMethodReference val = _module.Translate(method, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, optArgList, encodeAsRawDefinitionToken);
|
||
|
|
_builder.EmitToken((IReference)(object)val, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)(encodeAsRawDefinitionToken ? 1 : 0));
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSymbolToken(FieldSymbol symbol, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
IFieldReference val = _module.Translate(symbol, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
_builder.EmitToken((IReference)(object)val, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSignatureToken(FunctionPointerTypeSymbol symbol, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
_builder.EmitToken(_module.Translate(symbol).Signature, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequencePointStatement(BoundSequencePoint node)
|
||
|
|
{
|
||
|
|
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
SyntaxNode syntax = node.Syntax;
|
||
|
|
if (_emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
if (syntax == null)
|
||
|
|
{
|
||
|
|
EmitHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitSequencePoint(syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
BoundStatement statementOpt = node.StatementOpt;
|
||
|
|
int num = 0;
|
||
|
|
if (statementOpt != null)
|
||
|
|
{
|
||
|
|
num = EmitStatementAndCountInstructions(statementOpt);
|
||
|
|
}
|
||
|
|
if (num == 0 && syntax != null && (int)_ilEmitStyle == 0)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequencePointStatement(BoundSequencePointWithSpan node)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_004e: 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)
|
||
|
|
TextSpan span = node.Span;
|
||
|
|
if (span != default(TextSpan) && _emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
EmitSequencePoint(node.SyntaxTree, span);
|
||
|
|
}
|
||
|
|
BoundStatement statementOpt = node.StatementOpt;
|
||
|
|
int num = 0;
|
||
|
|
if (statementOpt != null)
|
||
|
|
{
|
||
|
|
num = EmitStatementAndCountInstructions(statementOpt);
|
||
|
|
}
|
||
|
|
if (num == 0 && span != default(TextSpan) && (int)_ilEmitStyle == 0)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSavePreviousSequencePoint(BoundSavePreviousSequencePoint statement)
|
||
|
|
{
|
||
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (!_emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ArrayBuilder<RawSequencePoint> seqPointsOpt = _builder.SeqPointsOpt;
|
||
|
|
if (seqPointsOpt == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
for (int num = seqPointsOpt.Count - 1; num >= 0; num--)
|
||
|
|
{
|
||
|
|
TextSpan span = seqPointsOpt[num].Span;
|
||
|
|
if (!(span == RawSequencePoint.HiddenSequencePointSpan))
|
||
|
|
{
|
||
|
|
if (_savedSequencePoints == null)
|
||
|
|
{
|
||
|
|
_savedSequencePoints = PooledDictionary<object, TextSpan>.GetInstance();
|
||
|
|
}
|
||
|
|
((Dictionary<object, TextSpan>)(object)_savedSequencePoints).Add(statement.Identifier, span);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitRestorePreviousSequencePoint(BoundRestorePreviousSequencePoint node)
|
||
|
|
{
|
||
|
|
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (_savedSequencePoints != null && ((Dictionary<object, TextSpan>)(object)_savedSequencePoints).TryGetValue(node.Identifier, out TextSpan value))
|
||
|
|
{
|
||
|
|
EmitStepThroughSequencePoint(node.Syntax.SyntaxTree, value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStepThroughSequencePoint(BoundStepThroughSequencePoint node)
|
||
|
|
{
|
||
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
EmitStepThroughSequencePoint(node.Syntax.SyntaxTree, node.Span);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStepThroughSequencePoint(SyntaxTree syntaxTree, TextSpan span)
|
||
|
|
{
|
||
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (_emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
object obj = new object();
|
||
|
|
_builder.EmitConstantValue(ConstantValue.Create(true));
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
EmitSequencePoint(syntaxTree, span);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Nop);
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
EmitHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SetInitialDebugDocument()
|
||
|
|
{
|
||
|
|
if (_emitPdbSequencePoints && _methodBodySyntaxOpt != null)
|
||
|
|
{
|
||
|
|
_builder.SetInitialDebugDocument(_methodBodySyntaxOpt.SyntaxTree);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitHiddenSequencePoint()
|
||
|
|
{
|
||
|
|
_builder.DefineHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequencePoint(SyntaxNode syntax)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
EmitSequencePoint(syntax.SyntaxTree, syntax.Span);
|
||
|
|
}
|
||
|
|
|
||
|
|
private TextSpan EmitSequencePoint(SyntaxTree syntaxTree, TextSpan span)
|
||
|
|
{
|
||
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
_builder.DefineSequencePoint(syntaxTree, span);
|
||
|
|
return span;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AddExpressionTemp(LocalDefinition temp)
|
||
|
|
{
|
||
|
|
if (temp != null)
|
||
|
|
{
|
||
|
|
ArrayBuilder<LocalDefinition> val = _expressionTemps;
|
||
|
|
if (val == null)
|
||
|
|
{
|
||
|
|
val = (_expressionTemps = ArrayBuilder<LocalDefinition>.GetInstance());
|
||
|
|
}
|
||
|
|
val.Add(temp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ReleaseExpressionTemps()
|
||
|
|
{
|
||
|
|
ArrayBuilder<LocalDefinition> expressionTemps = _expressionTemps;
|
||
|
|
if (expressionTemps != null && expressionTemps.Count > 0)
|
||
|
|
{
|
||
|
|
for (int num = _expressionTemps.Count - 1; num >= 0; num--)
|
||
|
|
{
|
||
|
|
LocalDefinition temp = _expressionTemps[num];
|
||
|
|
FreeTemp(temp);
|
||
|
|
}
|
||
|
|
_expressionTemps.Clear();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitAddress(BoundExpression expression, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
//IL_0242: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0247: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0248: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_024a: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0259: Invalid comparison between Unknown and I4
|
||
|
|
switch (expression.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.RefValueOperator:
|
||
|
|
EmitRefValueAddress((BoundRefValueOperator)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.Local:
|
||
|
|
return EmitLocalAddress((BoundLocal)expression, addressKind);
|
||
|
|
case BoundKind.Dup:
|
||
|
|
return EmitDupAddress((BoundDup)expression, addressKind);
|
||
|
|
case BoundKind.ComplexConditionalReceiver:
|
||
|
|
EmitComplexConditionalReceiverAddress((BoundComplexConditionalReceiver)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.Parameter:
|
||
|
|
return EmitParameterAddress((BoundParameter)expression, addressKind);
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
return EmitFieldAddress((BoundFieldAccess)expression, addressKind);
|
||
|
|
case BoundKind.ArrayAccess:
|
||
|
|
if (HasHome(expression, addressKind))
|
||
|
|
{
|
||
|
|
EmitArrayElementAddress((BoundArrayAccess)expression, addressKind);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
if (expression.Type.IsValueType)
|
||
|
|
{
|
||
|
|
if (HasHome(expression, addressKind))
|
||
|
|
{
|
||
|
|
_builder.EmitLoadArgumentOpcode(0);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
}
|
||
|
|
_builder.EmitLoadArgumentAddrOpcode(0);
|
||
|
|
break;
|
||
|
|
case BoundKind.PreviousSubmissionReference:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)expression.Kind);
|
||
|
|
case BoundKind.PassByCopy:
|
||
|
|
return EmitPassByCopyAddress((BoundPassByCopy)expression, addressKind);
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
return EmitSequenceAddress((BoundSequence)expression, addressKind);
|
||
|
|
case BoundKind.PointerIndirectionOperator:
|
||
|
|
{
|
||
|
|
BoundExpression operand = ((BoundPointerIndirectionOperator)expression).Operand;
|
||
|
|
EmitExpression(operand, used: true);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.PseudoVariable:
|
||
|
|
EmitPseudoVariableAddress((BoundPseudoVariable)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.Call:
|
||
|
|
{
|
||
|
|
BoundCall call = (BoundCall)expression;
|
||
|
|
if (UseCallResultAsAddress(call, addressKind))
|
||
|
|
{
|
||
|
|
EmitCallExpression(call, UseKind.UsedAsAddress);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
}
|
||
|
|
case BoundKind.FunctionPointerInvocation:
|
||
|
|
{
|
||
|
|
BoundFunctionPointerInvocation boundFunctionPointerInvocation = (BoundFunctionPointerInvocation)expression;
|
||
|
|
RefKind refKind = boundFunctionPointerInvocation.FunctionPointer.Signature.RefKind;
|
||
|
|
if ((int)refKind == 1 || (Binder.IsAnyReadOnly(addressKind) && (int)refKind == 3))
|
||
|
|
{
|
||
|
|
EmitCalli(boundFunctionPointerInvocation, UseKind.UsedAsAddress);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
}
|
||
|
|
case BoundKind.DefaultExpression:
|
||
|
|
{
|
||
|
|
TypeSymbol type = expression.Type;
|
||
|
|
LocalDefinition val = AllocateTemp(type, expression.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalAddress(val);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Initobj);
|
||
|
|
EmitSymbolToken(type, expression.Syntax);
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
case BoundKind.ConditionalOperator:
|
||
|
|
if (HasHome(expression, addressKind))
|
||
|
|
{
|
||
|
|
EmitConditionalOperatorAddress((BoundConditionalOperator)expression, addressKind);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
case BoundKind.AssignmentOperator:
|
||
|
|
{
|
||
|
|
BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)expression;
|
||
|
|
if (boundAssignmentOperator.IsRef && HasHome(boundAssignmentOperator, addressKind))
|
||
|
|
{
|
||
|
|
EmitAssignmentExpression(boundAssignmentOperator, UseKind.UsedAsAddress);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
}
|
||
|
|
case BoundKind.ThrowExpression:
|
||
|
|
EmitExpression(expression, used: true);
|
||
|
|
return null;
|
||
|
|
default:
|
||
|
|
return EmitAddressOfTempClone(expression);
|
||
|
|
case BoundKind.BaseReference:
|
||
|
|
case BoundKind.ConditionalReceiver:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool UseCallResultAsAddress(BoundCall call, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000e: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001a: Invalid comparison between Unknown and I4
|
||
|
|
RefKind refKind = call.Method.RefKind;
|
||
|
|
if ((int)refKind != 1)
|
||
|
|
{
|
||
|
|
if (Binder.IsAnyReadOnly(addressKind))
|
||
|
|
{
|
||
|
|
return (int)refKind == 3;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitPassByCopyAddress(BoundPassByCopy passByCopyExpr, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
if (passByCopyExpr.Expression is BoundSequence boundSequence && DigForValueLocal(boundSequence, boundSequence.Value) != null)
|
||
|
|
{
|
||
|
|
return EmitSequenceAddress(boundSequence, addressKind);
|
||
|
|
}
|
||
|
|
return EmitAddressOfTempClone(passByCopyExpr);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConditionalOperatorAddress(BoundConditionalOperator expr, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
object dest = new object();
|
||
|
|
object obj = new object();
|
||
|
|
EmitCondBranch(expr.Condition, ref dest, sense: true);
|
||
|
|
AddExpressionTemp(EmitAddress(expr.Alternative, addressKind));
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj, ILOpCode.Nop);
|
||
|
|
_builder.AdjustStack(-1);
|
||
|
|
_builder.MarkLabel(dest);
|
||
|
|
AddExpressionTemp(EmitAddress(expr.Consequence, addressKind));
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitComplexConditionalReceiverAddress(BoundComplexConditionalReceiver expression)
|
||
|
|
{
|
||
|
|
TypeSymbol type = expression.Type;
|
||
|
|
object obj = new object();
|
||
|
|
object obj2 = new object();
|
||
|
|
EmitInitObj(type, used: true, expression.Syntax);
|
||
|
|
EmitBox(type, expression.Syntax);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
EmitAddress(expression.ReferenceTypeReceiver, Binder.AddressKind.ReadOnly);
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj2, ILOpCode.Nop);
|
||
|
|
_builder.AdjustStack(-1);
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
EmitReceiverRef(expression.ValueTypeReceiver, Binder.AddressKind.Constrained);
|
||
|
|
_builder.MarkLabel(obj2);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitLocalAddress(BoundLocal localAccess, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
LocalSymbol localSymbol = localAccess.LocalSymbol;
|
||
|
|
if (!HasHome(localAccess, addressKind))
|
||
|
|
{
|
||
|
|
return EmitAddressOfTempClone(localAccess);
|
||
|
|
}
|
||
|
|
if (IsStackLocal(localSymbol))
|
||
|
|
{
|
||
|
|
if ((int)localSymbol.RefKind == 0)
|
||
|
|
{
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)localSymbol.RefKind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitLocalAddress(GetLocal(localAccess));
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitDupAddress(BoundDup dup, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
if (!HasHome(dup, addressKind))
|
||
|
|
{
|
||
|
|
return EmitAddressOfTempClone(dup);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitPseudoVariableAddress(BoundPseudoVariable expression)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.EmitExpressions.GetAddress(expression), used: true);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitRefValueAddress(BoundRefValueOperator refValue)
|
||
|
|
{
|
||
|
|
EmitExpression(refValue.Operand, used: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Refanyval);
|
||
|
|
EmitSymbolToken(refValue.Type, refValue.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitAddressOfTempClone(BoundExpression expression)
|
||
|
|
{
|
||
|
|
EmitExpression(expression, used: true);
|
||
|
|
LocalDefinition val = AllocateTemp(expression.Type, expression.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val);
|
||
|
|
_builder.EmitLocalAddress(val);
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitSequenceAddress(BoundSequence sequence, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
DefineAndRecordLocals(sequence);
|
||
|
|
EmitSideEffects(sequence);
|
||
|
|
LocalDefinition result = EmitAddress(sequence.Value, addressKind);
|
||
|
|
CloseScopeAndKeepLocals(sequence);
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static LocalSymbol DigForValueLocal(BoundSequence topSequence, BoundExpression value)
|
||
|
|
{
|
||
|
|
switch (value.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.Local:
|
||
|
|
{
|
||
|
|
LocalSymbol localSymbol = ((BoundLocal)value).LocalSymbol;
|
||
|
|
if (topSequence.Locals.Contains(localSymbol))
|
||
|
|
{
|
||
|
|
return localSymbol;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
return DigForValueLocal(topSequence, ((BoundSequence)value).Value);
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
{
|
||
|
|
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)value;
|
||
|
|
if (!boundFieldAccess.FieldSymbol.IsStatic)
|
||
|
|
{
|
||
|
|
BoundExpression receiverOpt = boundFieldAccess.ReceiverOpt;
|
||
|
|
if (!receiverOpt.Type.IsReferenceType)
|
||
|
|
{
|
||
|
|
return DigForValueLocal(topSequence, receiverOpt);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayIndices(ImmutableArray<BoundExpression> indices)
|
||
|
|
{
|
||
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
for (int i = 0; i < indices.Length; i++)
|
||
|
|
{
|
||
|
|
BoundExpression boundExpression = indices[i];
|
||
|
|
EmitExpression(boundExpression, used: true);
|
||
|
|
TreatLongsAsNative(boundExpression.Type.PrimitiveTypeCode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayElementAddress(BoundArrayAccess arrayAccess, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
EmitExpression(arrayAccess.Expression, used: true);
|
||
|
|
EmitArrayIndices(arrayAccess.Indices);
|
||
|
|
if (ShouldEmitReadOnlyPrefix(arrayAccess, addressKind))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Readonly);
|
||
|
|
}
|
||
|
|
if (((ArrayTypeSymbol)arrayAccess.Expression.Type).IsSZArray)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelema);
|
||
|
|
TypeSymbol type = arrayAccess.Type;
|
||
|
|
EmitSymbolToken(type, arrayAccess.Syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitArrayElementAddress(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), arrayAccess.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool ShouldEmitReadOnlyPrefix(BoundArrayAccess arrayAccess, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
if (addressKind == Binder.AddressKind.Constrained)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (!Binder.IsAnyReadOnly(addressKind))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return !arrayAccess.Type.IsValueType;
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitFieldAddress(BoundFieldAccess fieldAccess, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
FieldSymbol fieldSymbol = fieldAccess.FieldSymbol;
|
||
|
|
if (!HasHome(fieldAccess, addressKind))
|
||
|
|
{
|
||
|
|
return EmitAddressOfTempClone(fieldAccess);
|
||
|
|
}
|
||
|
|
if (fieldAccess.FieldSymbol.IsStatic)
|
||
|
|
{
|
||
|
|
EmitStaticFieldAddress(fieldSymbol, fieldAccess.Syntax);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return EmitInstanceFieldAddress(fieldAccess, addressKind);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStaticFieldAddress(FieldSymbol field, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsflda);
|
||
|
|
EmitSymbolToken(field, syntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool HasHome(BoundExpression expression, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
return Binder.HasHome(expression, addressKind, _method, IsPeVerifyCompatEnabled(), _stackLocals);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitParameterAddress(BoundParameter parameter, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
ParameterSymbol parameterSymbol = parameter.ParameterSymbol;
|
||
|
|
if (!HasHome(parameter, addressKind))
|
||
|
|
{
|
||
|
|
return EmitAddressOfTempClone(parameter);
|
||
|
|
}
|
||
|
|
int num = ParameterSlot(parameter);
|
||
|
|
if ((int)parameterSymbol.RefKind == 0)
|
||
|
|
{
|
||
|
|
_builder.EmitLoadArgumentAddrOpcode(num);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitLoadArgumentOpcode(num);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitReceiverRef(BoundExpression receiver, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
TypeSymbol type = receiver.Type;
|
||
|
|
if (type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitExpression(receiver, used: true);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
if (BoxNonVerifierReferenceReceiver(type, addressKind))
|
||
|
|
{
|
||
|
|
EmitExpression(receiver, used: true);
|
||
|
|
if (receiver.Kind != BoundKind.ConditionalReceiver)
|
||
|
|
{
|
||
|
|
EmitBox(receiver.Type, receiver.Syntax);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return EmitAddress(receiver, addressKind);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool BoxNonVerifierReferenceReceiver(TypeSymbol receiverType, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0008: Invalid comparison between Unknown and I4
|
||
|
|
if ((int)receiverType.TypeKind == 11)
|
||
|
|
{
|
||
|
|
return addressKind != Binder.AddressKind.Constrained;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitInstanceFieldAddress(BoundFieldAccess fieldAccess, Binder.AddressKind addressKind)
|
||
|
|
{
|
||
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
FieldSymbol fieldSymbol = fieldAccess.FieldSymbol;
|
||
|
|
LocalDefinition result = EmitReceiverRef(fieldAccess.ReceiverOpt, ((int)fieldSymbol.RefKind != 0) ? ((addressKind != Binder.AddressKind.ReadOnlyStrict) ? Binder.AddressKind.ReadOnly : addressKind) : ((addressKind != Binder.AddressKind.Constrained) ? addressKind : Binder.AddressKind.Writeable));
|
||
|
|
_builder.EmitOpCode(((int)fieldSymbol.RefKind == 0) ? ILOpCode.Ldflda : ILOpCode.Ldfld);
|
||
|
|
EmitSymbolToken(fieldSymbol, fieldAccess.Syntax);
|
||
|
|
if (fieldSymbol.IsFixedSizeBuffer)
|
||
|
|
{
|
||
|
|
FieldSymbol fixedElementField = fieldSymbol.FixedImplementationType(_module).FixedElementField;
|
||
|
|
if ((object)fixedElementField != null)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldflda);
|
||
|
|
EmitSymbolToken(fixedElementField, fieldAccess.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayInitializers(ArrayTypeSymbol arrayType, BoundArrayInitialization inits)
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundExpression> initializers = inits.Initializers;
|
||
|
|
ArrayInitializerStyle arrayInitializerStyle = ShouldEmitBlockInitializer(arrayType.ElementType, initializers);
|
||
|
|
if (arrayInitializerStyle == ArrayInitializerStyle.Element)
|
||
|
|
{
|
||
|
|
EmitElementInitializers(arrayType, initializers, includeConstants: true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ImmutableArray<byte> rawData = GetRawData(initializers);
|
||
|
|
_builder.EmitArrayBlockInitializer(rawData, inits.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
if (arrayInitializerStyle == ArrayInitializerStyle.Mixed)
|
||
|
|
{
|
||
|
|
EmitElementInitializers(arrayType, initializers, includeConstants: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitElementInitializers(ArrayTypeSymbol arrayType, ImmutableArray<BoundExpression> inits, bool includeConstants)
|
||
|
|
{
|
||
|
|
if (!IsMultidimensionalInitializer(inits))
|
||
|
|
{
|
||
|
|
EmitVectorElementInitializers(arrayType, inits, includeConstants);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitMultidimensionalElementInitializers(arrayType, inits, includeConstants);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitVectorElementInitializers(ArrayTypeSymbol arrayType, ImmutableArray<BoundExpression> inits, bool includeConstants)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < inits.Length; i++)
|
||
|
|
{
|
||
|
|
BoundExpression boundExpression = inits[i];
|
||
|
|
if (ShouldEmitInitExpression(includeConstants, boundExpression))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitIntConstant(i);
|
||
|
|
EmitExpression(boundExpression, used: true);
|
||
|
|
EmitVectorElementStore(arrayType, boundExpression.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool ShouldEmitInitExpression(bool includeConstants, BoundExpression init)
|
||
|
|
{
|
||
|
|
if (init.IsDefaultValue())
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (!includeConstants)
|
||
|
|
{
|
||
|
|
return init.ConstantValueOpt == (ConstantValue)null;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitMultidimensionalElementInitializers(ArrayTypeSymbol arrayType, ImmutableArray<BoundExpression> inits, bool includeConstants)
|
||
|
|
{
|
||
|
|
ArrayBuilder<IndexDesc> val = new ArrayBuilder<IndexDesc>();
|
||
|
|
for (int i = 0; i < inits.Length; i++)
|
||
|
|
{
|
||
|
|
ArrayBuilderExtensions.Push<IndexDesc>(val, new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers));
|
||
|
|
EmitAllElementInitializersRecursive(arrayType, val, includeConstants);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitAllElementInitializersRecursive(ArrayTypeSymbol arrayType, ArrayBuilder<IndexDesc> indices, bool includeConstants)
|
||
|
|
{
|
||
|
|
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
ImmutableArray<BoundExpression> initializers = ArrayBuilderExtensions.Peek<IndexDesc>(indices).Initializers;
|
||
|
|
if (IsMultidimensionalInitializer(initializers))
|
||
|
|
{
|
||
|
|
for (int i = 0; i < initializers.Length; i++)
|
||
|
|
{
|
||
|
|
ArrayBuilderExtensions.Push<IndexDesc>(indices, new IndexDesc(i, ((BoundArrayInitialization)initializers[i]).Initializers));
|
||
|
|
EmitAllElementInitializersRecursive(arrayType, indices, includeConstants);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
for (int j = 0; j < initializers.Length; j++)
|
||
|
|
{
|
||
|
|
BoundExpression boundExpression = initializers[j];
|
||
|
|
if (ShouldEmitInitExpression(includeConstants, boundExpression))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
Enumerator<IndexDesc> enumerator = indices.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
IndexDesc current = enumerator.Current;
|
||
|
|
_builder.EmitIntConstant(current.Index);
|
||
|
|
}
|
||
|
|
_builder.EmitIntConstant(j);
|
||
|
|
BoundExpression expression = initializers[j];
|
||
|
|
EmitExpression(expression, used: true);
|
||
|
|
EmitArrayElementStore(arrayType, boundExpression.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
ArrayBuilderExtensions.Pop<IndexDesc>(indices);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static ConstantValue AsConstOrDefault(BoundExpression init)
|
||
|
|
{
|
||
|
|
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
ConstantValue constantValueOpt = init.ConstantValueOpt;
|
||
|
|
if (constantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
return constantValueOpt;
|
||
|
|
}
|
||
|
|
return ConstantValue.Default(init.Type.EnumUnderlyingTypeOrSelf().SpecialType);
|
||
|
|
}
|
||
|
|
|
||
|
|
private ArrayInitializerStyle ShouldEmitBlockInitializer(TypeSymbol elementType, ImmutableArray<BoundExpression> inits)
|
||
|
|
{
|
||
|
|
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (((CommonPEModuleBuilder)_module).IsEncDelta)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Element;
|
||
|
|
}
|
||
|
|
if (elementType.IsEnumType())
|
||
|
|
{
|
||
|
|
if (!EnableEnumArrayBlockInitialization)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Element;
|
||
|
|
}
|
||
|
|
elementType = elementType.EnumUnderlyingTypeOrSelf();
|
||
|
|
}
|
||
|
|
if (SpecialTypeExtensions.IsBlittable(elementType.SpecialType))
|
||
|
|
{
|
||
|
|
if (((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).GetInitArrayHelper() == null)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Element;
|
||
|
|
}
|
||
|
|
int initCount = 0;
|
||
|
|
int constInits = 0;
|
||
|
|
InitializerCountRecursive(inits, ref initCount, ref constInits);
|
||
|
|
if (initCount > 2)
|
||
|
|
{
|
||
|
|
if (initCount == constInits)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Block;
|
||
|
|
}
|
||
|
|
int num = Math.Max(3, initCount / 3);
|
||
|
|
if (constInits >= num)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Mixed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ArrayInitializerStyle.Element;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void InitializerCountRecursive(ImmutableArray<BoundExpression> inits, ref int initCount, ref int constInits)
|
||
|
|
{
|
||
|
|
if (inits.Length == 0)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = inits.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
if (current is BoundArrayInitialization boundArrayInitialization)
|
||
|
|
{
|
||
|
|
InitializerCountRecursive(boundArrayInitialization.Initializers, ref initCount, ref constInits);
|
||
|
|
}
|
||
|
|
else if (!current.IsDefaultValue())
|
||
|
|
{
|
||
|
|
initCount++;
|
||
|
|
if (current.ConstantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
constInits++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private ImmutableArray<byte> GetRawData(ImmutableArray<BoundExpression> initializers)
|
||
|
|
{
|
||
|
|
BlobBuilder blobBuilder = new BlobBuilder(initializers.Length * 4);
|
||
|
|
SerializeArrayRecursive(blobBuilder, initializers);
|
||
|
|
return blobBuilder.ToImmutableArray();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SerializeArrayRecursive(BlobBuilder bw, ImmutableArray<BoundExpression> inits)
|
||
|
|
{
|
||
|
|
if (inits.Length == 0)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (inits[0].Kind == BoundKind.ArrayInitialization)
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = inits.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
SerializeArrayRecursive(bw, ((BoundArrayInitialization)current).Initializers);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = inits.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
AsConstOrDefault(enumerator.Current).Serialize(bw);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsMultidimensionalInitializer(ImmutableArray<BoundExpression> inits)
|
||
|
|
{
|
||
|
|
if (inits.Length != 0)
|
||
|
|
{
|
||
|
|
return inits[0].Kind == BoundKind.ArrayInitialization;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool TryEmitReadonlySpanAsBlobWrapper(NamedTypeSymbol spanType, BoundExpression wrappedExpression, bool used, BoundExpression inPlaceTarget, out bool avoidInPlace, BoundExpression? start = null, BoundExpression? length = null)
|
||
|
|
{
|
||
|
|
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e8: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0100: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0294: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (start == null != (length == null))
|
||
|
|
{
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/CodeGen/EmitArrayInitializer.cs", 438);
|
||
|
|
}
|
||
|
|
int num = -1;
|
||
|
|
avoidInPlace = false;
|
||
|
|
SpecialType val = (SpecialType)0;
|
||
|
|
if (((CommonPEModuleBuilder)_module).IsEncDelta)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
MethodSymbol methodSymbol = (MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)403, _diagnostics, null, wrappedExpression.Syntax, isOptional: true);
|
||
|
|
if ((object)methodSymbol == null)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
ImmutableArray<byte> data = default(ImmutableArray<byte>);
|
||
|
|
ArrayTypeSymbol arrayTypeSymbol = null;
|
||
|
|
TypeSymbol typeSymbol = null;
|
||
|
|
if (wrappedExpression is BoundArrayCreation boundArrayCreation)
|
||
|
|
{
|
||
|
|
arrayTypeSymbol = (ArrayTypeSymbol)boundArrayCreation.Type;
|
||
|
|
typeSymbol = arrayTypeSymbol.ElementType;
|
||
|
|
val = typeSymbol.EnumUnderlyingTypeOrSelf().SpecialType;
|
||
|
|
if (!IsTypeAllowedInBlobWrapper(val))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
num = TryGetRawDataForArrayInit(boundArrayCreation.InitializerOpt, out data);
|
||
|
|
}
|
||
|
|
if (num < 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
int num2;
|
||
|
|
if (start != null)
|
||
|
|
{
|
||
|
|
ConstantValue? constantValueOpt = start.ConstantValueOpt;
|
||
|
|
if (constantValueOpt == null || !constantValueOpt.IsDefaultValue || (int)start.ConstantValueOpt.Discriminator != 6)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
ConstantValue? constantValueOpt2 = length.ConstantValueOpt;
|
||
|
|
if (constantValueOpt2 == null || (int)constantValueOpt2.Discriminator != 6)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
num2 = length.ConstantValueOpt.Int32Value;
|
||
|
|
if (num2 > num || num2 < 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
num2 = num;
|
||
|
|
}
|
||
|
|
if (inPlaceTarget == null && !used)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (num == 0)
|
||
|
|
{
|
||
|
|
if (inPlaceTarget != null)
|
||
|
|
{
|
||
|
|
EmitAddress(inPlaceTarget, Binder.AddressKind.Writeable);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Initobj);
|
||
|
|
EmitSymbolToken(spanType, wrappedExpression.Syntax);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitExpression(inPlaceTarget, used: true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitDefaultValue(spanType, used, wrappedExpression.Syntax);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (IsPeVerifyCompatEnabled())
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (SpecialTypeExtensions.SizeInBytes(val) == 1)
|
||
|
|
{
|
||
|
|
if (inPlaceTarget != null)
|
||
|
|
{
|
||
|
|
EmitAddress(inPlaceTarget, Binder.AddressKind.Writeable);
|
||
|
|
}
|
||
|
|
IFieldReference fieldForData = _builder.module.GetFieldForData(data, (ushort)1, wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsflda);
|
||
|
|
_builder.EmitToken((IReference)(object)fieldForData, wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitIntConstant(num2);
|
||
|
|
if (inPlaceTarget != null)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, -3);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Newobj, -1);
|
||
|
|
}
|
||
|
|
EmitSymbolToken(methodSymbol.AsMember(spanType), wrappedExpression.Syntax, null);
|
||
|
|
if (inPlaceTarget != null && used)
|
||
|
|
{
|
||
|
|
EmitExpression(inPlaceTarget, used: true);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (num2 != num)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (inPlaceTarget != null)
|
||
|
|
{
|
||
|
|
avoidInPlace = true;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
MethodSymbol methodSymbol2 = (MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)123, _diagnostics, null, wrappedExpression.Syntax, isOptional: true);
|
||
|
|
if ((object)methodSymbol2 != null)
|
||
|
|
{
|
||
|
|
IFieldReference fieldForData2 = _builder.module.GetFieldForData(data, (ushort)SpecialTypeExtensions.SizeInBytes(val), wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
_builder.EmitToken((IReference)(object)fieldForData2, wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
EmitSymbolToken(methodSymbol2.Construct(typeSymbol), wrappedExpression.Syntax, null);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
MethodSymbol methodSymbol3 = (MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)404, _diagnostics, null, wrappedExpression.Syntax, isOptional: true);
|
||
|
|
if ((object)methodSymbol3 == null)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
arrayTypeSymbol = arrayTypeSymbol.WithElementType(TypeWithAnnotations.Create(typeSymbol.EnumUnderlyingTypeOrSelf()));
|
||
|
|
IFieldReference arrayCachingFieldForData = _builder.module.GetArrayCachingFieldForData(data, _module.Translate(arrayTypeSymbol), wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
object obj = new object();
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsfld);
|
||
|
|
_builder.EmitToken((IReference)(object)arrayCachingFieldForData, wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
_builder.EmitIntConstant(num);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Newarr);
|
||
|
|
EmitSymbolToken(arrayTypeSymbol.ElementType, wrappedExpression.Syntax);
|
||
|
|
_builder.EmitArrayBlockInitializer(data, wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stsfld);
|
||
|
|
_builder.EmitToken((IReference)(object)arrayCachingFieldForData, wrappedExpression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Newobj, 0);
|
||
|
|
EmitSymbolToken(methodSymbol3.AsMember(spanType), wrappedExpression.Syntax, null);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool IsTypeAllowedInBlobWrapper(SpecialType type)
|
||
|
|
{
|
||
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0005: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000c: Invalid comparison between Unknown and I4
|
||
|
|
if (type - 7 <= 9 || type - 18 <= 1)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private int TryGetRawDataForArrayInit(BoundArrayInitialization initializer, out ImmutableArray<byte> data)
|
||
|
|
{
|
||
|
|
data = default(ImmutableArray<byte>);
|
||
|
|
if (initializer == null)
|
||
|
|
{
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
ImmutableArray<BoundExpression> initializers = initializer.Initializers;
|
||
|
|
if (initializers.Any((BoundExpression init) => init.ConstantValueOpt == (ConstantValue)null))
|
||
|
|
{
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
int length = initializers.Length;
|
||
|
|
if (length == 0)
|
||
|
|
{
|
||
|
|
data = ImmutableArray<byte>.Empty;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
BlobBuilder blobBuilder = new BlobBuilder(initializers.Length * 4);
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = initializer.Initializers.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
enumerator.Current.ConstantValueOpt.Serialize(blobBuilder);
|
||
|
|
}
|
||
|
|
data = blobBuilder.ToImmutableArray();
|
||
|
|
return length;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsNumeric(TypeSymbol type)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_004f: Expected I4, but got Unknown
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = type.PrimitiveTypeCode;
|
||
|
|
switch (primitiveTypeCode - 1)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
case 1:
|
||
|
|
case 2:
|
||
|
|
case 3:
|
||
|
|
case 4:
|
||
|
|
case 5:
|
||
|
|
case 6:
|
||
|
|
case 11:
|
||
|
|
case 12:
|
||
|
|
case 13:
|
||
|
|
case 14:
|
||
|
|
return true;
|
||
|
|
case 7:
|
||
|
|
case 15:
|
||
|
|
return type.IsNativeIntegerType;
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConversionExpression(BoundConversion conversion, bool used)
|
||
|
|
{
|
||
|
|
switch (conversion.ConversionKind)
|
||
|
|
{
|
||
|
|
case ConversionKind.MethodGroup:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)conversion.ConversionKind);
|
||
|
|
case ConversionKind.ImplicitNullToPointer:
|
||
|
|
_builder.EmitIntConstant(0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_u);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
BoundExpression operand = conversion.Operand;
|
||
|
|
if (!used && !conversion.ConversionHasSideEffects())
|
||
|
|
{
|
||
|
|
EmitExpression(operand, used: false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
EmitExpression(operand, used: true);
|
||
|
|
EmitConversion(conversion);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitReadOnlySpanFromArrayExpression(BoundReadOnlySpanFromArray expression, bool used)
|
||
|
|
{
|
||
|
|
BoundExpression operand = expression.Operand;
|
||
|
|
NamedTypeSymbol spanType = (NamedTypeSymbol)expression.Type;
|
||
|
|
if (!TryEmitReadonlySpanAsBlobWrapper(spanType, operand, used, null, out var _))
|
||
|
|
{
|
||
|
|
EmitExpression(operand, used);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
EmitSymbolToken(expression.ConversionMethod, expression.Syntax, null);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConversion(BoundConversion conversion)
|
||
|
|
{
|
||
|
|
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
switch (conversion.ConversionKind)
|
||
|
|
{
|
||
|
|
case ConversionKind.Identity:
|
||
|
|
EmitIdentityConversion(conversion);
|
||
|
|
break;
|
||
|
|
case ConversionKind.ImplicitNumeric:
|
||
|
|
case ConversionKind.ExplicitNumeric:
|
||
|
|
EmitNumericConversion(conversion);
|
||
|
|
break;
|
||
|
|
case ConversionKind.ImplicitReference:
|
||
|
|
case ConversionKind.Boxing:
|
||
|
|
EmitImplicitReferenceConversion(conversion);
|
||
|
|
break;
|
||
|
|
case ConversionKind.ExplicitReference:
|
||
|
|
case ConversionKind.Unboxing:
|
||
|
|
EmitExplicitReferenceConversion(conversion);
|
||
|
|
break;
|
||
|
|
case ConversionKind.ImplicitEnumeration:
|
||
|
|
case ConversionKind.ExplicitEnumeration:
|
||
|
|
EmitEnumConversion(conversion);
|
||
|
|
break;
|
||
|
|
case ConversionKind.ImplicitThrow:
|
||
|
|
case ConversionKind.ImplicitTupleLiteral:
|
||
|
|
case ConversionKind.ImplicitTuple:
|
||
|
|
case ConversionKind.ExplicitTupleLiteral:
|
||
|
|
case ConversionKind.ExplicitTuple:
|
||
|
|
case ConversionKind.ImplicitDynamic:
|
||
|
|
case ConversionKind.ExplicitDynamic:
|
||
|
|
case ConversionKind.ImplicitUserDefined:
|
||
|
|
case ConversionKind.AnonymousFunction:
|
||
|
|
case ConversionKind.MethodGroup:
|
||
|
|
case ConversionKind.ExplicitUserDefined:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)conversion.ConversionKind);
|
||
|
|
case ConversionKind.ImplicitPointerToVoid:
|
||
|
|
case ConversionKind.ImplicitPointer:
|
||
|
|
case ConversionKind.ExplicitPointerToPointer:
|
||
|
|
break;
|
||
|
|
case ConversionKind.ExplicitIntegerToPointer:
|
||
|
|
case ConversionKind.ExplicitPointerToInteger:
|
||
|
|
{
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = conversion.Operand.Type.PrimitiveTypeCode;
|
||
|
|
PrimitiveTypeCode primitiveTypeCode2 = conversion.Type.PrimitiveTypeCode;
|
||
|
|
_builder.EmitNumericConversion(primitiveTypeCode, primitiveTypeCode2, conversion.Checked);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case ConversionKind.PinnedObjectToPointer:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_u);
|
||
|
|
break;
|
||
|
|
case ConversionKind.ImplicitNullToPointer:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)conversion.ConversionKind);
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)conversion.ConversionKind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIdentityConversion(BoundConversion conversion)
|
||
|
|
{
|
||
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0018: Invalid comparison between Unknown and I4
|
||
|
|
if (conversion.ExplicitCastInCode)
|
||
|
|
{
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = conversion.Type.PrimitiveTypeCode;
|
||
|
|
if (primitiveTypeCode - 3 <= 1 && conversion.Operand.ConstantValueOpt == (ConstantValue)null)
|
||
|
|
{
|
||
|
|
EmitNumericConversion(conversion);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitNumericConversion(BoundConversion conversion)
|
||
|
|
{
|
||
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//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_0023: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = conversion.Operand.Type.PrimitiveTypeCode;
|
||
|
|
PrimitiveTypeCode primitiveTypeCode2 = conversion.Type.PrimitiveTypeCode;
|
||
|
|
_builder.EmitNumericConversion(primitiveTypeCode, primitiveTypeCode2, conversion.Checked);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitImplicitReferenceConversion(BoundConversion conversion)
|
||
|
|
{
|
||
|
|
if (!conversion.Operand.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(conversion.Operand.Type, conversion.Operand.Syntax);
|
||
|
|
}
|
||
|
|
TypeSymbol type = conversion.Type;
|
||
|
|
if (!type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Unbox_any);
|
||
|
|
EmitSymbolToken(conversion.Type, conversion.Syntax);
|
||
|
|
}
|
||
|
|
else if (type.IsArray())
|
||
|
|
{
|
||
|
|
EmitStaticCast(conversion.Type, conversion.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitExplicitReferenceConversion(BoundConversion conversion)
|
||
|
|
{
|
||
|
|
if (!conversion.Operand.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(conversion.Operand.Type, conversion.Operand.Syntax);
|
||
|
|
}
|
||
|
|
if (conversion.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Castclass);
|
||
|
|
EmitSymbolToken(conversion.Type, conversion.Syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Unbox_any);
|
||
|
|
EmitSymbolToken(conversion.Type, conversion.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitEnumConversion(BoundConversion conversion)
|
||
|
|
{
|
||
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
TypeSymbol typeSymbol = conversion.Operand.Type;
|
||
|
|
if (typeSymbol.IsEnumType())
|
||
|
|
{
|
||
|
|
typeSymbol = ((NamedTypeSymbol)typeSymbol).EnumUnderlyingType;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = typeSymbol.PrimitiveTypeCode;
|
||
|
|
TypeSymbol typeSymbol2 = conversion.Type;
|
||
|
|
if (typeSymbol2.IsEnumType())
|
||
|
|
{
|
||
|
|
typeSymbol2 = ((NamedTypeSymbol)typeSymbol2).EnumUnderlyingType;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode2 = typeSymbol2.PrimitiveTypeCode;
|
||
|
|
_builder.EmitNumericConversion(primitiveTypeCode, primitiveTypeCode2, conversion.Checked);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitDelegateCreation(BoundExpression node, BoundExpression receiver, bool isExtensionMethod, MethodSymbol method, TypeSymbol delegateType, bool used)
|
||
|
|
{
|
||
|
|
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0060: Invalid comparison between Unknown and I4
|
||
|
|
bool flag = receiver == null || (!isExtensionMethod && method.IsStatic);
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
if (!flag)
|
||
|
|
{
|
||
|
|
EmitExpression(receiver, used: false);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
_builder.EmitNullConstant();
|
||
|
|
if (method.IsAbstract || method.IsVirtual)
|
||
|
|
{
|
||
|
|
if (receiver is BoundTypeExpression boundTypeExpression)
|
||
|
|
{
|
||
|
|
TypeSymbol type = boundTypeExpression.Type;
|
||
|
|
if ((object)type != null && (int)type.TypeKind == 11)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Constrained);
|
||
|
|
EmitSymbolToken(receiver.Type, receiver.Syntax);
|
||
|
|
goto IL_00bd;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs", 333);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitExpression(receiver, used: true);
|
||
|
|
if (!receiver.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(receiver.Type, receiver.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
goto IL_00bd;
|
||
|
|
IL_00bd:
|
||
|
|
if (!method.IsStatic && method.IsMetadataVirtual() && !method.ContainingType.IsDelegateType() && !receiver.SuppressVirtualCalls)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldvirtftn);
|
||
|
|
method = method.GetConstructedLeastOverriddenMethod(_method.ContainingType, requireSameReturnType: true);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldftn);
|
||
|
|
}
|
||
|
|
EmitSymbolToken(method, node.Syntax, null);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Newobj, -1);
|
||
|
|
MethodSymbol methodSymbol = DelegateConstructor(node.Syntax, delegateType);
|
||
|
|
if ((object)methodSymbol != null)
|
||
|
|
{
|
||
|
|
EmitSymbolToken(methodSymbol, node.Syntax, null);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private MethodSymbol DelegateConstructor(SyntaxNode syntax, TypeSymbol delegateType)
|
||
|
|
{
|
||
|
|
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_004a: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0059: 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_0060: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0064: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_006a: Invalid comparison between Unknown and I4
|
||
|
|
ImmutableArray<Symbol>.Enumerator enumerator = delegateType.GetMembers(".ctor").GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
if (enumerator.Current is MethodSymbol { Parameters: { Length: 2 } parameters } methodSymbol && (int)parameters[0].Type.SpecialType == 1)
|
||
|
|
{
|
||
|
|
SpecialType specialType = parameters[1].Type.SpecialType;
|
||
|
|
if ((int)specialType == 21 || (int)specialType == 22)
|
||
|
|
{
|
||
|
|
return methodSymbol;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_diagnostics.Add(ErrorCode.ERR_BadDelegateConstructor, syntax.Location, delegateType);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitExpression(BoundExpression expression, bool used)
|
||
|
|
{
|
||
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_002d: Invalid comparison between Unknown and I4
|
||
|
|
if (expression == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ConstantValue constantValueOpt = expression.ConstantValueOpt;
|
||
|
|
if (constantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if ((object)expression.Type == null || ((int)expression.Type.SpecialType != 17 && !expression.Type.IsNullableType()))
|
||
|
|
{
|
||
|
|
EmitConstantExpression(expression.Type, constantValueOpt, used, expression.Syntax);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_recursionDepth++;
|
||
|
|
if (_recursionDepth > 1)
|
||
|
|
{
|
||
|
|
StackGuard.EnsureSufficientExecutionStack(_recursionDepth);
|
||
|
|
EmitExpressionCore(expression, used);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitExpressionCoreWithStackGuard(expression, used);
|
||
|
|
}
|
||
|
|
_recursionDepth--;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitExpressionCoreWithStackGuard(BoundExpression expression, bool used)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
EmitExpressionCore(expression, used);
|
||
|
|
}
|
||
|
|
catch (InsufficientExecutionStackException)
|
||
|
|
{
|
||
|
|
_diagnostics.Add(ErrorCode.ERR_InsufficientStack, BoundTreeVisitor.CancelledByStackGuardException.GetTooLongOrComplexExpressionErrorLocation(expression));
|
||
|
|
throw new EmitCancelledException();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitExpressionCore(BoundExpression expression, bool used)
|
||
|
|
{
|
||
|
|
switch (expression.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.AssignmentOperator:
|
||
|
|
EmitAssignmentExpression((BoundAssignmentOperator)expression, used ? UseKind.UsedAsValue : UseKind.Unused);
|
||
|
|
break;
|
||
|
|
case BoundKind.Call:
|
||
|
|
EmitCallExpression((BoundCall)expression, used ? UseKind.UsedAsValue : UseKind.Unused);
|
||
|
|
break;
|
||
|
|
case BoundKind.ObjectCreationExpression:
|
||
|
|
EmitObjectCreationExpression((BoundObjectCreationExpression)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.DelegateCreationExpression:
|
||
|
|
EmitDelegateCreationExpression((BoundDelegateCreationExpression)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ArrayCreation:
|
||
|
|
EmitArrayCreationExpression((BoundArrayCreation)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ConvertedStackAllocExpression:
|
||
|
|
EmitConvertedStackAllocExpression((BoundConvertedStackAllocExpression)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ReadOnlySpanFromArray:
|
||
|
|
EmitReadOnlySpanFromArrayExpression((BoundReadOnlySpanFromArray)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.Conversion:
|
||
|
|
EmitConversionExpression((BoundConversion)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.Local:
|
||
|
|
EmitLocalLoad((BoundLocal)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.Dup:
|
||
|
|
EmitDupExpression((BoundDup)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.PassByCopy:
|
||
|
|
EmitExpression(((BoundPassByCopy)expression).Expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.Parameter:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitParameterLoad((BoundParameter)expression);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
EmitFieldLoad((BoundFieldAccess)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ArrayAccess:
|
||
|
|
EmitArrayElementLoad((BoundArrayAccess)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ArrayLength:
|
||
|
|
EmitArrayLength((BoundArrayLength)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitThisReferenceExpression((BoundThisReference)expression);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.PreviousSubmissionReference:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)expression.Kind);
|
||
|
|
case BoundKind.BaseReference:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
NamedTypeSymbol containingType = _method.ContainingType;
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldarg_0);
|
||
|
|
if (containingType.IsValueType)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(containingType, expression.Syntax);
|
||
|
|
EmitBox(containingType, expression.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
EmitSequenceExpression((BoundSequence)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.SequencePointExpression:
|
||
|
|
EmitSequencePointExpression((BoundSequencePointExpression)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.UnaryOperator:
|
||
|
|
EmitUnaryOperatorExpression((BoundUnaryOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.BinaryOperator:
|
||
|
|
EmitBinaryOperatorExpression((BoundBinaryOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.NullCoalescingOperator:
|
||
|
|
EmitNullCoalescingOperator((BoundNullCoalescingOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.IsOperator:
|
||
|
|
EmitIsExpression((BoundIsOperator)expression, used, omitBooleanConversion: false);
|
||
|
|
break;
|
||
|
|
case BoundKind.AsOperator:
|
||
|
|
EmitAsExpression((BoundAsOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.DefaultExpression:
|
||
|
|
EmitDefaultExpression((BoundDefaultExpression)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.TypeOfOperator:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitTypeOfExpression((BoundTypeOfOperator)expression);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.SizeOfOperator:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitSizeOfExpression((BoundSizeOfOperator)expression);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.ModuleVersionId:
|
||
|
|
EmitModuleVersionIdLoad((BoundModuleVersionId)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.ModuleVersionIdString:
|
||
|
|
EmitModuleVersionIdStringLoad();
|
||
|
|
break;
|
||
|
|
case BoundKind.InstrumentationPayloadRoot:
|
||
|
|
EmitInstrumentationPayloadRootLoad((BoundInstrumentationPayloadRoot)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.MethodDefIndex:
|
||
|
|
EmitMethodDefIndexExpression((BoundMethodDefIndex)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.MaximumMethodDefIndex:
|
||
|
|
EmitMaximumMethodDefIndexExpression((BoundMaximumMethodDefIndex)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.SourceDocumentIndex:
|
||
|
|
EmitSourceDocumentIndex((BoundSourceDocumentIndex)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.LocalId:
|
||
|
|
EmitLocalIdExpression((BoundLocalId)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.ParameterId:
|
||
|
|
EmitParameterIdExpression((BoundParameterId)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.MethodInfo:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitMethodInfoExpression((BoundMethodInfo)expression);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.FieldInfo:
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitFieldInfoExpression((BoundFieldInfo)expression);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.ConditionalOperator:
|
||
|
|
EmitConditionalOperator((BoundConditionalOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.AddressOfOperator:
|
||
|
|
EmitAddressOfExpression((BoundAddressOfOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.PointerIndirectionOperator:
|
||
|
|
EmitPointerIndirectionOperator((BoundPointerIndirectionOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ArgList:
|
||
|
|
EmitArgList(used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ArgListOperator:
|
||
|
|
EmitArgListOperator((BoundArgListOperator)expression);
|
||
|
|
break;
|
||
|
|
case BoundKind.RefTypeOperator:
|
||
|
|
EmitRefTypeOperator((BoundRefTypeOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.MakeRefOperator:
|
||
|
|
EmitMakeRefOperator((BoundMakeRefOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.RefValueOperator:
|
||
|
|
EmitRefValueOperator((BoundRefValueOperator)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.LoweredConditionalAccess:
|
||
|
|
EmitLoweredConditionalAccessExpression((BoundLoweredConditionalAccess)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ConditionalReceiver:
|
||
|
|
EmitConditionalReceiver((BoundConditionalReceiver)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ComplexConditionalReceiver:
|
||
|
|
EmitComplexConditionalReceiver((BoundComplexConditionalReceiver)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.PseudoVariable:
|
||
|
|
EmitPseudoVariableValue((BoundPseudoVariable)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.ThrowExpression:
|
||
|
|
EmitThrowExpression((BoundThrowExpression)expression, used);
|
||
|
|
break;
|
||
|
|
case BoundKind.FunctionPointerInvocation:
|
||
|
|
EmitCalli((BoundFunctionPointerInvocation)expression, used ? UseKind.UsedAsValue : UseKind.Unused);
|
||
|
|
break;
|
||
|
|
case BoundKind.FunctionPointerLoad:
|
||
|
|
EmitLoadFunction((BoundFunctionPointerLoad)expression, used);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)expression.Kind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitThrowExpression(BoundThrowExpression node, bool used)
|
||
|
|
{
|
||
|
|
EmitThrow(node.Expression);
|
||
|
|
EmitDefaultValue(node.Type, used, node.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitComplexConditionalReceiver(BoundComplexConditionalReceiver expression, bool used)
|
||
|
|
{
|
||
|
|
TypeSymbol type = expression.Type;
|
||
|
|
object obj = new object();
|
||
|
|
object obj2 = new object();
|
||
|
|
EmitInitObj(type, used: true, expression.Syntax);
|
||
|
|
EmitBox(type, expression.Syntax);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
EmitExpression(expression.ReferenceTypeReceiver, used);
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj2, ILOpCode.Nop);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.AdjustStack(-1);
|
||
|
|
}
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
EmitExpression(expression.ValueTypeReceiver, used);
|
||
|
|
_builder.MarkLabel(obj2);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAccess expression, bool used)
|
||
|
|
{
|
||
|
|
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a9: Invalid comparison between Unknown and I4
|
||
|
|
BoundExpression receiver = expression.Receiver;
|
||
|
|
TypeSymbol type = receiver.Type;
|
||
|
|
LocalDefinition val = null;
|
||
|
|
ConstantValue? constantValueOpt = receiver.ConstantValueOpt;
|
||
|
|
if (constantValueOpt != null && !constantValueOpt.IsNull)
|
||
|
|
{
|
||
|
|
val = EmitReceiverRef(receiver, Binder.AddressKind.ReadOnly);
|
||
|
|
EmitExpression(expression.WhenNotNull, used);
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
object obj = new object();
|
||
|
|
object obj2 = new object();
|
||
|
|
LocalDefinition val2 = null;
|
||
|
|
bool flag = !type.IsReferenceType && !type.IsValueType;
|
||
|
|
bool flag2 = (expression.ForceCopyOfNullableValueType && flag && ((TypeParameterSymbol)type).EffectiveInterfacesNoUseSiteDiagnostics.IsEmpty) || LocalRewriter.CanChangeValueBetweenReads(receiver, localsMayBeAssignedOrCaptured: false) || (type.IsReferenceType && (int)type.TypeKind == 11) || (receiver.Kind == BoundKind.Local && IsStackLocal(((BoundLocal)receiver).LocalSymbol)) || (flag && IsConditionalConstrainedCallThatMustUseTempForReferenceTypeReceiverWalker.Analyze(expression));
|
||
|
|
if (flag2)
|
||
|
|
{
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
val = EmitReceiverRef(receiver, Binder.AddressKind.Constrained);
|
||
|
|
if (val == null)
|
||
|
|
{
|
||
|
|
EmitDefaultValue(type, used: true, receiver.Syntax);
|
||
|
|
EmitBox(type, receiver.Syntax);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
EmitLoadIndirect(type, receiver.Syntax);
|
||
|
|
val2 = AllocateTemp(type, receiver.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val2);
|
||
|
|
_builder.EmitLocalAddress(val2);
|
||
|
|
_builder.EmitLocalLoad(val2);
|
||
|
|
EmitBox(type, receiver.Syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
EmitLoadIndirect(type, receiver.Syntax);
|
||
|
|
EmitBox(type, receiver.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Binder.AddressKind addressKind = Binder.AddressKind.ReadOnly;
|
||
|
|
val = EmitReceiverRef(receiver, addressKind);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
val = EmitReceiverRef(receiver, Binder.AddressKind.ReadOnly);
|
||
|
|
}
|
||
|
|
MethodSymbol hasValueMethodOpt = expression.HasValueMethodOpt;
|
||
|
|
if (hasValueMethodOpt != null)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
EmitSymbolToken(hasValueMethodOpt, expression.Syntax, null);
|
||
|
|
}
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
if (val != null && !flag2)
|
||
|
|
{
|
||
|
|
FreeTemp(val);
|
||
|
|
val = null;
|
||
|
|
}
|
||
|
|
if (flag2)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
}
|
||
|
|
BoundExpression whenNullOpt = expression.WhenNullOpt;
|
||
|
|
if (whenNullOpt == null)
|
||
|
|
{
|
||
|
|
EmitDefaultValue(expression.Type, used, expression.Syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitExpression(whenNullOpt, used);
|
||
|
|
}
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj2, ILOpCode.Nop);
|
||
|
|
if (flag2)
|
||
|
|
{
|
||
|
|
_builder.AdjustStack(1);
|
||
|
|
}
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.AdjustStack(-1);
|
||
|
|
}
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
if (!flag2)
|
||
|
|
{
|
||
|
|
val = EmitReceiverRef(receiver, Binder.AddressKind.Constrained);
|
||
|
|
}
|
||
|
|
EmitExpression(expression.WhenNotNull, used);
|
||
|
|
_builder.MarkLabel(obj2);
|
||
|
|
if (val2 != null)
|
||
|
|
{
|
||
|
|
FreeTemp(val2);
|
||
|
|
}
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConditionalReceiver(BoundConditionalReceiver expression, bool used)
|
||
|
|
{
|
||
|
|
if (!expression.Type.IsReferenceType)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(expression.Type, expression.Syntax);
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitRefValueOperator(BoundRefValueOperator expression, bool used)
|
||
|
|
{
|
||
|
|
EmitRefValueAddress(expression);
|
||
|
|
EmitLoadIndirect(expression.Type, expression.Syntax);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitMakeRefOperator(BoundMakeRefOperator expression, bool used)
|
||
|
|
{
|
||
|
|
EmitAddress(expression.Operand, Binder.AddressKind.Writeable);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Mkrefany);
|
||
|
|
EmitSymbolToken(expression.Operand.Type, expression.Operand.Syntax);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitRefTypeOperator(BoundRefTypeOperator expression, bool used)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.Operand, used: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Refanytype);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
MethodSymbol getTypeFromHandle = expression.GetTypeFromHandle;
|
||
|
|
EmitSymbolToken(getTypeFromHandle, expression.Syntax, null);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArgList(bool used)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Arglist);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArgListOperator(BoundArgListOperator expression)
|
||
|
|
{
|
||
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
for (int i = 0; i < expression.Arguments.Length; i++)
|
||
|
|
{
|
||
|
|
BoundExpression argument = expression.Arguments[i];
|
||
|
|
RefKind refKind = (RefKind)((!expression.ArgumentRefKindsOpt.IsDefaultOrEmpty) ? ((int)expression.ArgumentRefKindsOpt[i]) : 0);
|
||
|
|
EmitArgument(argument, refKind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArgument(BoundExpression argument, RefKind refKind)
|
||
|
|
{
|
||
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0005: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0027: Invalid comparison between Unknown and I4
|
||
|
|
if ((int)refKind != 0)
|
||
|
|
{
|
||
|
|
if ((int)refKind == 3)
|
||
|
|
{
|
||
|
|
LocalDefinition temp = EmitAddress(argument, Binder.AddressKind.ReadOnly);
|
||
|
|
AddExpressionTemp(temp);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
LocalDefinition val = EmitAddress(argument, ((int)refKind == 5) ? Binder.AddressKind.ReadOnlyStrict : Binder.AddressKind.Writeable);
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
AddExpressionTemp(val);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitExpression(argument, used: true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitAddressOfExpression(BoundAddressOfOperator expression, bool used)
|
||
|
|
{
|
||
|
|
EmitAddress(expression.Operand, Binder.AddressKind.ReadOnlyStrict);
|
||
|
|
if (used && !expression.IsManaged)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_u);
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitPointerIndirectionOperator(BoundPointerIndirectionOperator expression, bool used)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.Operand, used: true);
|
||
|
|
if (!expression.RefersToLocation)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(expression.Type, expression.Syntax);
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitDupExpression(BoundDup expression, bool used)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if ((int)expression.RefKind == 0)
|
||
|
|
{
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
EmitLoadIndirect(expression.Type, expression.Syntax);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitDelegateCreationExpression(BoundDelegateCreationExpression expression, bool used)
|
||
|
|
{
|
||
|
|
BoundExpression boundExpression = ((expression.Argument is BoundMethodGroup boundMethodGroup) ? boundMethodGroup.ReceiverOpt : expression.Argument);
|
||
|
|
MethodSymbol method = expression.MethodOpt ?? boundExpression.Type.DelegateInvokeMethod();
|
||
|
|
EmitDelegateCreation(expression, boundExpression, expression.IsExtensionMethod, method, expression.Type, used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitThisReferenceExpression(BoundThisReference thisRef)
|
||
|
|
{
|
||
|
|
TypeSymbol type = thisRef.Type;
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldarg_0);
|
||
|
|
if (type.IsValueType)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(type, thisRef.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitPseudoVariableValue(BoundPseudoVariable expression, bool used)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.EmitExpressions.GetValue(expression, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequencePointExpression(BoundSequencePointExpression node, bool used)
|
||
|
|
{
|
||
|
|
EmitSequencePoint(node);
|
||
|
|
EmitExpression(node.Expression, used: true);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequencePoint(BoundSequencePointExpression node)
|
||
|
|
{
|
||
|
|
SyntaxNode syntax = node.Syntax;
|
||
|
|
if (_emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
if (syntax == null)
|
||
|
|
{
|
||
|
|
EmitHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitSequencePoint(syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequenceExpression(BoundSequence sequence, bool used)
|
||
|
|
{
|
||
|
|
DefineLocals(sequence);
|
||
|
|
EmitSideEffects(sequence);
|
||
|
|
if (sequence.Value.Kind != BoundKind.TypeExpression)
|
||
|
|
{
|
||
|
|
EmitExpression(sequence.Value, used);
|
||
|
|
}
|
||
|
|
FreeLocals(sequence);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void DefineLocals(BoundSequence sequence)
|
||
|
|
{
|
||
|
|
if (!sequence.Locals.IsEmpty)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)0, (ITypeReference)null);
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = sequence.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current = enumerator.Current;
|
||
|
|
DefineLocal(current, sequence.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FreeLocals(BoundSequence sequence)
|
||
|
|
{
|
||
|
|
if (!sequence.Locals.IsEmpty)
|
||
|
|
{
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = sequence.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current = enumerator.Current;
|
||
|
|
FreeLocal(current);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void DefineAndRecordLocals(BoundSequence sequence)
|
||
|
|
{
|
||
|
|
if (!sequence.Locals.IsEmpty)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)0, (ITypeReference)null);
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = sequence.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current = enumerator.Current;
|
||
|
|
LocalDefinition temp = DefineLocal(current, sequence.Syntax);
|
||
|
|
AddExpressionTemp(temp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void CloseScopeAndKeepLocals(BoundSequence sequence)
|
||
|
|
{
|
||
|
|
if (!sequence.Locals.IsEmpty)
|
||
|
|
{
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSideEffects(BoundSequence sequence)
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundExpression> sideEffects = sequence.SideEffects;
|
||
|
|
if (!sideEffects.IsDefaultOrEmpty)
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = sideEffects.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
EmitExpression(current, used: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArguments(ImmutableArray<BoundExpression> arguments, ImmutableArray<ParameterSymbol> parameters, ImmutableArray<RefKind> argRefKindsOpt)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
for (int i = 0; i < arguments.Length; i++)
|
||
|
|
{
|
||
|
|
RefKind argumentRefKind = GetArgumentRefKind(arguments, parameters, argRefKindsOpt, i);
|
||
|
|
EmitArgument(arguments[i], argumentRefKind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static RefKind GetArgumentRefKind(ImmutableArray<BoundExpression> arguments, ImmutableArray<ParameterSymbol> parameters, ImmutableArray<RefKind> argRefKindsOpt, int i)
|
||
|
|
{
|
||
|
|
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0038: Invalid comparison between Unknown and I4
|
||
|
|
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (i < parameters.Length)
|
||
|
|
{
|
||
|
|
if (!argRefKindsOpt.IsDefault && i < argRefKindsOpt.Length)
|
||
|
|
{
|
||
|
|
return argRefKindsOpt[i];
|
||
|
|
}
|
||
|
|
RefKind refKind = parameters[i].RefKind;
|
||
|
|
return ((int)refKind != 4) ? refKind : ((RefKind)3);
|
||
|
|
}
|
||
|
|
return (RefKind)0;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayElementLoad(BoundArrayAccess arrayAccess, bool used)
|
||
|
|
{
|
||
|
|
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00ab: Expected I4, but got Unknown
|
||
|
|
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_01bc: Invalid comparison between Unknown and I4
|
||
|
|
EmitExpression(arrayAccess.Expression, used: true);
|
||
|
|
EmitArrayIndices(arrayAccess.Indices);
|
||
|
|
if (((ArrayTypeSymbol)arrayAccess.Expression.Type).IsSZArray)
|
||
|
|
{
|
||
|
|
TypeSymbol typeSymbol = arrayAccess.Type;
|
||
|
|
if (typeSymbol.IsEnumType())
|
||
|
|
{
|
||
|
|
typeSymbol = ((NamedTypeSymbol)typeSymbol).EnumUnderlyingType;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = typeSymbol.PrimitiveTypeCode;
|
||
|
|
switch ((int)primitiveTypeCode)
|
||
|
|
{
|
||
|
|
case 2:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_i1);
|
||
|
|
break;
|
||
|
|
case 0:
|
||
|
|
case 12:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_u1);
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_i2);
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
case 13:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_u2);
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_i4);
|
||
|
|
break;
|
||
|
|
case 14:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_u4);
|
||
|
|
break;
|
||
|
|
case 7:
|
||
|
|
case 15:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_i8);
|
||
|
|
break;
|
||
|
|
case 8:
|
||
|
|
case 9:
|
||
|
|
case 16:
|
||
|
|
case 19:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_i);
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_r4);
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_r8);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
if (typeSymbol.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem_ref);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelem);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if ((int)typeSymbol.TypeKind == 11)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Readonly);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldelema);
|
||
|
|
}
|
||
|
|
EmitSymbolToken(typeSymbol, arrayAccess.Syntax);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitArrayElementLoad(_module.Translate((ArrayTypeSymbol)arrayAccess.Expression.Type), arrayAccess.Expression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitFieldLoad(BoundFieldAccess fieldAccess, bool used)
|
||
|
|
{
|
||
|
|
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
FieldSymbol fieldSymbol = fieldAccess.FieldSymbol;
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
if (fieldSymbol.IsCapturedFrame)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!fieldSymbol.IsVolatile && !fieldSymbol.IsStatic && fieldAccess.ReceiverOpt.Type.IsVerifierValue() && (int)fieldSymbol.RefKind == 0)
|
||
|
|
{
|
||
|
|
EmitExpression(fieldAccess.ReceiverOpt, used: false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitFieldLoadNoIndirection(fieldAccess, used);
|
||
|
|
if ((int)fieldSymbol.RefKind != 0)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(fieldSymbol.Type, fieldAccess.Syntax);
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitFieldLoadNoIndirection(BoundFieldAccess fieldAccess, bool used)
|
||
|
|
{
|
||
|
|
FieldSymbol fieldSymbol = fieldAccess.FieldSymbol;
|
||
|
|
if (fieldSymbol.IsStatic)
|
||
|
|
{
|
||
|
|
if (fieldSymbol.IsVolatile)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Volatile);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsfld);
|
||
|
|
EmitSymbolToken(fieldSymbol, fieldAccess.Syntax);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
BoundExpression receiverOpt = fieldAccess.ReceiverOpt;
|
||
|
|
TypeSymbol type = fieldSymbol.Type;
|
||
|
|
if (type.IsValueType && (object)type == receiverOpt.Type)
|
||
|
|
{
|
||
|
|
EmitExpression(receiverOpt, used);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
LocalDefinition val = EmitFieldLoadReceiver(receiverOpt);
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
if (fieldSymbol.IsVolatile)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Volatile);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldfld);
|
||
|
|
EmitSymbolToken(fieldSymbol, fieldAccess.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitFieldLoadReceiver(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
if (FieldLoadMustUseRef(receiver) || FieldLoadPrefersRef(receiver))
|
||
|
|
{
|
||
|
|
if (!EmitFieldLoadReceiverAddress(receiver))
|
||
|
|
{
|
||
|
|
return EmitReceiverRef(receiver, Binder.AddressKind.ReadOnly);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
EmitExpression(receiver, used: true);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool EmitFieldLoadReceiverAddress(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
if (receiver == null || !receiver.Type.IsValueType)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (receiver.Kind == BoundKind.Conversion)
|
||
|
|
{
|
||
|
|
BoundConversion boundConversion = (BoundConversion)receiver;
|
||
|
|
if (boundConversion.ConversionKind == ConversionKind.Unboxing)
|
||
|
|
{
|
||
|
|
EmitExpression(boundConversion.Operand, used: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Unbox);
|
||
|
|
EmitSymbolToken(receiver.Type, receiver.Syntax);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (receiver.Kind == BoundKind.FieldAccess)
|
||
|
|
{
|
||
|
|
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)receiver;
|
||
|
|
FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol;
|
||
|
|
if (!fieldSymbol.IsStatic && EmitFieldLoadReceiverAddress(boundFieldAccess.ReceiverOpt))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldflda);
|
||
|
|
EmitSymbolToken(fieldSymbol, boundFieldAccess.Syntax);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool FieldLoadPrefersRef(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0088: Invalid comparison between Unknown and I4
|
||
|
|
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0074: Invalid comparison between Unknown and I4
|
||
|
|
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (!receiver.Type.IsVerifierValue())
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (receiver.Kind == BoundKind.Conversion && ((BoundConversion)receiver).ConversionKind == ConversionKind.Unboxing)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (!HasHome(receiver, Binder.AddressKind.ReadOnly))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
switch (receiver.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.Parameter:
|
||
|
|
return (int)((BoundParameter)receiver).ParameterSymbol.RefKind > 0;
|
||
|
|
case BoundKind.Local:
|
||
|
|
return (int)((BoundLocal)receiver).LocalSymbol.RefKind > 0;
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
return FieldLoadPrefersRef(((BoundSequence)receiver).Value);
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
{
|
||
|
|
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)receiver;
|
||
|
|
FieldSymbol fieldSymbol = boundFieldAccess.FieldSymbol;
|
||
|
|
if (fieldSymbol.IsStatic || (int)fieldSymbol.RefKind != 0)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (DiagnosticsPass.IsNonAgileFieldAccess(boundFieldAccess, ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return FieldLoadPrefersRef(boundFieldAccess.ReceiverOpt);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool FieldLoadMustUseRef(BoundExpression expr)
|
||
|
|
{
|
||
|
|
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00ac: Expected I4, but got Unknown
|
||
|
|
TypeSymbol type = expr.Type;
|
||
|
|
if (type.IsTypeParameter())
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
SpecialType specialType = type.SpecialType;
|
||
|
|
switch (specialType - 7)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
case 1:
|
||
|
|
case 2:
|
||
|
|
case 3:
|
||
|
|
case 4:
|
||
|
|
case 5:
|
||
|
|
case 6:
|
||
|
|
case 7:
|
||
|
|
case 8:
|
||
|
|
case 9:
|
||
|
|
case 11:
|
||
|
|
case 12:
|
||
|
|
case 14:
|
||
|
|
case 15:
|
||
|
|
case 31:
|
||
|
|
case 32:
|
||
|
|
case 33:
|
||
|
|
case 34:
|
||
|
|
return true;
|
||
|
|
default:
|
||
|
|
return type.IsEnumType();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int ParameterSlot(BoundParameter parameter)
|
||
|
|
{
|
||
|
|
ParameterSymbol parameterSymbol = parameter.ParameterSymbol;
|
||
|
|
int num = parameterSymbol.Ordinal;
|
||
|
|
if (!parameterSymbol.ContainingSymbol.IsStatic)
|
||
|
|
{
|
||
|
|
num++;
|
||
|
|
}
|
||
|
|
return num;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLocalLoad(BoundLocal local, bool used)
|
||
|
|
{
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000c: Invalid comparison between Unknown and I4
|
||
|
|
bool flag = (int)local.LocalSymbol.RefKind > 0;
|
||
|
|
if (IsStackLocal(local.LocalSymbol))
|
||
|
|
{
|
||
|
|
EmitPopIfUnused(used || flag);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!(used || flag))
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
LocalDefinition local2 = GetLocal(local);
|
||
|
|
_builder.EmitLocalLoad(local2);
|
||
|
|
}
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(local.LocalSymbol.Type, local.Syntax);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitParameterLoad(BoundParameter parameter)
|
||
|
|
{
|
||
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
int num = ParameterSlot(parameter);
|
||
|
|
_builder.EmitLoadArgumentOpcode(num);
|
||
|
|
if ((int)parameter.ParameterSymbol.RefKind != 0)
|
||
|
|
{
|
||
|
|
TypeSymbol type = parameter.ParameterSymbol.Type;
|
||
|
|
EmitLoadIndirect(type, parameter.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLoadIndirect(TypeSymbol type, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001b: 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_0072: Expected I4, but got Unknown
|
||
|
|
if (type.IsEnumType())
|
||
|
|
{
|
||
|
|
type = ((NamedTypeSymbol)type).EnumUnderlyingType;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = type.PrimitiveTypeCode;
|
||
|
|
switch ((int)primitiveTypeCode)
|
||
|
|
{
|
||
|
|
case 2:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_i1);
|
||
|
|
return;
|
||
|
|
case 0:
|
||
|
|
case 12:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_u1);
|
||
|
|
return;
|
||
|
|
case 5:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_i2);
|
||
|
|
return;
|
||
|
|
case 1:
|
||
|
|
case 13:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_u2);
|
||
|
|
return;
|
||
|
|
case 6:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_i4);
|
||
|
|
return;
|
||
|
|
case 14:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_u4);
|
||
|
|
return;
|
||
|
|
case 7:
|
||
|
|
case 15:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_i8);
|
||
|
|
return;
|
||
|
|
case 8:
|
||
|
|
case 9:
|
||
|
|
case 16:
|
||
|
|
case 19:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_i);
|
||
|
|
return;
|
||
|
|
case 3:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_r4);
|
||
|
|
return;
|
||
|
|
case 4:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_r8);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_ref);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldobj);
|
||
|
|
EmitSymbolToken(type, syntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool CanUseCallOnRefTypeReceiver(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0130: Invalid comparison between Unknown and I4
|
||
|
|
if (receiver.Type.IsTypeParameter())
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
ConstantValue constantValueOpt = receiver.ConstantValueOpt;
|
||
|
|
if (constantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
return !constantValueOpt.IsNull;
|
||
|
|
}
|
||
|
|
switch (receiver.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.ArrayCreation:
|
||
|
|
return true;
|
||
|
|
case BoundKind.ObjectCreationExpression:
|
||
|
|
return true;
|
||
|
|
case BoundKind.Conversion:
|
||
|
|
{
|
||
|
|
BoundConversion boundConversion = (BoundConversion)receiver;
|
||
|
|
switch (boundConversion.ConversionKind)
|
||
|
|
{
|
||
|
|
case ConversionKind.Boxing:
|
||
|
|
return true;
|
||
|
|
case ConversionKind.AnonymousFunction:
|
||
|
|
case ConversionKind.MethodGroup:
|
||
|
|
return true;
|
||
|
|
case ConversionKind.ImplicitReference:
|
||
|
|
case ConversionKind.ExplicitReference:
|
||
|
|
return CanUseCallOnRefTypeReceiver(boundConversion.Operand);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
return true;
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
return ((BoundFieldAccess)receiver).FieldSymbol.IsCapturedFrame;
|
||
|
|
case BoundKind.Local:
|
||
|
|
return (int)((BoundLocal)receiver).LocalSymbol.SynthesizedKind == -5;
|
||
|
|
case BoundKind.DelegateCreationExpression:
|
||
|
|
return true;
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
{
|
||
|
|
BoundExpression value = ((BoundSequence)receiver).Value;
|
||
|
|
return CanUseCallOnRefTypeReceiver(value);
|
||
|
|
}
|
||
|
|
case BoundKind.AssignmentOperator:
|
||
|
|
{
|
||
|
|
BoundExpression right = ((BoundAssignmentOperator)receiver).Right;
|
||
|
|
return CanUseCallOnRefTypeReceiver(right);
|
||
|
|
}
|
||
|
|
case BoundKind.TypeOfOperator:
|
||
|
|
return true;
|
||
|
|
case BoundKind.ConditionalReceiver:
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsThisReceiver(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
switch (receiver.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
return true;
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
{
|
||
|
|
BoundExpression value = ((BoundSequence)receiver).Value;
|
||
|
|
return IsThisReceiver(value);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCallExpression(BoundCall call, UseKind useKind)
|
||
|
|
{
|
||
|
|
if (call.Method.IsDefaultValueTypeConstructor())
|
||
|
|
{
|
||
|
|
EmitDefaultValueTypeConstructorCallExpression(call);
|
||
|
|
}
|
||
|
|
else if (!call.Method.RequiresInstanceReceiver)
|
||
|
|
{
|
||
|
|
EmitStaticCallExpression(call, useKind);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitInstanceCallExpression(call, useKind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
private void EmitDefaultValueTypeConstructorCallExpression(BoundCall call)
|
||
|
|
{
|
||
|
|
MethodSymbol method = call.Method;
|
||
|
|
BoundExpression receiverOpt = call.ReceiverOpt;
|
||
|
|
LocalDefinition temp = EmitReceiverRef(receiverOpt, Binder.AddressKind.Writeable);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Initobj);
|
||
|
|
EmitSymbolToken(method.ContainingType, call.Syntax);
|
||
|
|
FreeOptTemp(temp);
|
||
|
|
}
|
||
|
|
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
private void EmitStaticCallExpression(BoundCall call, UseKind useKind)
|
||
|
|
{
|
||
|
|
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0062: Invalid comparison between Unknown and I4
|
||
|
|
MethodSymbol method = call.Method;
|
||
|
|
BoundExpression receiverOpt = call.ReceiverOpt;
|
||
|
|
ImmutableArray<BoundExpression> arguments = call.Arguments;
|
||
|
|
EmitArguments(arguments, method.Parameters, call.ArgumentRefKindsOpt);
|
||
|
|
int callStackBehavior = GetCallStackBehavior(method, arguments);
|
||
|
|
if (method.IsAbstract || method.IsVirtual)
|
||
|
|
{
|
||
|
|
if (receiverOpt is BoundTypeExpression boundTypeExpression)
|
||
|
|
{
|
||
|
|
TypeSymbol type = boundTypeExpression.Type;
|
||
|
|
if ((object)type != null && (int)type.TypeKind == 11)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Constrained);
|
||
|
|
EmitSymbolToken(receiverOpt.Type, receiverOpt.Syntax);
|
||
|
|
goto IL_0096;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs", 1644);
|
||
|
|
}
|
||
|
|
goto IL_0096;
|
||
|
|
IL_0096:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, callStackBehavior);
|
||
|
|
EmitSymbolToken(method, call.Syntax, method.IsVararg ? ((BoundArgListOperator)arguments[arguments.Length - 1]) : null);
|
||
|
|
EmitCallCleanup(call.Syntax, useKind, method);
|
||
|
|
}
|
||
|
|
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
private void EmitInstanceCallExpression(BoundCall call, UseKind useKind)
|
||
|
|
{
|
||
|
|
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
CallKind callKind;
|
||
|
|
Binder.AddressKind? addressKind;
|
||
|
|
bool box;
|
||
|
|
LocalDefinition tempOpt;
|
||
|
|
if (receiverIsInstanceCall(call, out var nested))
|
||
|
|
{
|
||
|
|
ArrayBuilder<BoundCall> instance = ArrayBuilder<BoundCall>.GetInstance();
|
||
|
|
ArrayBuilderExtensions.Push<BoundCall>(instance, call);
|
||
|
|
call = nested;
|
||
|
|
while (receiverIsInstanceCall(call, out nested))
|
||
|
|
{
|
||
|
|
ArrayBuilderExtensions.Push<BoundCall>(instance, call);
|
||
|
|
call = nested;
|
||
|
|
}
|
||
|
|
callKind = determineEmitReceiverStrategy(call, out addressKind, out box);
|
||
|
|
emitReceiver(call, callKind, addressKind, box, out tempOpt);
|
||
|
|
while (instance.Count != 0)
|
||
|
|
{
|
||
|
|
BoundCall boundCall = ArrayBuilderExtensions.Pop<BoundCall>(instance);
|
||
|
|
CallKind num = determineEmitReceiverStrategy(boundCall, out addressKind, out box);
|
||
|
|
TypeSymbol type = call.Type;
|
||
|
|
UseKind useKind2;
|
||
|
|
if (!addressKind.HasValue)
|
||
|
|
{
|
||
|
|
useKind2 = UseKind.UsedAsValue;
|
||
|
|
}
|
||
|
|
else if (BoxNonVerifierReferenceReceiver(type, addressKind.GetValueOrDefault()))
|
||
|
|
{
|
||
|
|
useKind2 = UseKind.UsedAsValue;
|
||
|
|
box = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_ = call.Method.RefKind;
|
||
|
|
useKind2 = ((!UseCallResultAsAddress(call, addressKind.GetValueOrDefault())) ? UseKind.UsedAsValue : UseKind.UsedAsAddress);
|
||
|
|
}
|
||
|
|
emitArgumentsAndCallEpilogue(call, callKind, useKind2);
|
||
|
|
FreeOptTemp(tempOpt);
|
||
|
|
tempOpt = null;
|
||
|
|
nested = call;
|
||
|
|
call = boundCall;
|
||
|
|
callKind = num;
|
||
|
|
if (box)
|
||
|
|
{
|
||
|
|
EmitBox(type, nested.Syntax);
|
||
|
|
}
|
||
|
|
else if (addressKind.HasValue)
|
||
|
|
{
|
||
|
|
if (useKind2 != UseKind.UsedAsAddress)
|
||
|
|
{
|
||
|
|
tempOpt = AllocateTemp(type, nested.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(tempOpt);
|
||
|
|
_builder.EmitLocalAddress(tempOpt);
|
||
|
|
}
|
||
|
|
emitGenericReceiverCloneIfNecessary(call, callKind, ref tempOpt);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
instance.Free();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
callKind = determineEmitReceiverStrategy(call, out addressKind, out box);
|
||
|
|
emitReceiver(call, callKind, addressKind, box, out tempOpt);
|
||
|
|
}
|
||
|
|
emitArgumentsAndCallEpilogue(call, callKind, useKind);
|
||
|
|
FreeOptTemp(tempOpt);
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
CallKind determineEmitReceiverStrategy(BoundCall boundCall2, out Binder.AddressKind? reference2, out bool reference)
|
||
|
|
{
|
||
|
|
MethodSymbol method = boundCall2.Method;
|
||
|
|
BoundExpression receiverOpt = boundCall2.ReceiverOpt;
|
||
|
|
TypeSymbol type2 = receiverOpt.Type;
|
||
|
|
reference = false;
|
||
|
|
CallKind callKind2;
|
||
|
|
if (type2.IsVerifierReference())
|
||
|
|
{
|
||
|
|
reference2 = null;
|
||
|
|
callKind2 = ((!receiverOpt.SuppressVirtualCalls && (method.IsMetadataVirtual() || !CanUseCallOnRefTypeReceiver(receiverOpt))) ? CallKind.CallVirt : CallKind.Call);
|
||
|
|
}
|
||
|
|
else if (type2.IsVerifierValue())
|
||
|
|
{
|
||
|
|
NamedTypeSymbol containingType = method.ContainingType;
|
||
|
|
if (containingType.IsVerifierValue())
|
||
|
|
{
|
||
|
|
reference2 = (IsReadOnlyCall(method, containingType) ? Binder.AddressKind.ReadOnly : Binder.AddressKind.Writeable);
|
||
|
|
callKind2 = ((!MayUseCallForStructMethod(method)) ? CallKind.ConstrainedCallVirt : CallKind.Call);
|
||
|
|
}
|
||
|
|
else if (method.IsMetadataVirtual())
|
||
|
|
{
|
||
|
|
reference2 = Binder.AddressKind.Writeable;
|
||
|
|
callKind2 = CallKind.ConstrainedCallVirt;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
reference2 = null;
|
||
|
|
reference = true;
|
||
|
|
callKind2 = CallKind.Call;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
callKind2 = ((type2.IsReferenceType && !IsRef(receiverOpt)) ? CallKind.CallVirt : CallKind.ConstrainedCallVirt);
|
||
|
|
reference2 = ((callKind2 == CallKind.ConstrainedCallVirt) ? Binder.AddressKind.Constrained : Binder.AddressKind.Writeable);
|
||
|
|
}
|
||
|
|
return callKind2;
|
||
|
|
}
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
void emitArgumentsAndCallEpilogue(BoundCall boundCall2, CallKind callKind2, UseKind useKind3)
|
||
|
|
{
|
||
|
|
MethodSymbol method = boundCall2.Method;
|
||
|
|
BoundExpression receiverOpt = boundCall2.ReceiverOpt;
|
||
|
|
MethodSymbol methodSymbol = method;
|
||
|
|
if (method.IsOverride && callKind2 != CallKind.Call)
|
||
|
|
{
|
||
|
|
methodSymbol = method.GetConstructedLeastOverriddenMethod(_method.ContainingType, requireSameReturnType: true);
|
||
|
|
}
|
||
|
|
if (callKind2 == CallKind.ConstrainedCallVirt && methodSymbol.ContainingType.IsValueType)
|
||
|
|
{
|
||
|
|
callKind2 = CallKind.Call;
|
||
|
|
}
|
||
|
|
if (callKind2 == CallKind.CallVirt)
|
||
|
|
{
|
||
|
|
if (IsThisReceiver(receiverOpt) && methodSymbol.ContainingType.IsSealed && (object)methodSymbol.ContainingModule == _method.ContainingModule)
|
||
|
|
{
|
||
|
|
callKind2 = CallKind.Call;
|
||
|
|
}
|
||
|
|
else if (methodSymbol.IsMetadataFinal && CanUseCallOnRefTypeReceiver(receiverOpt))
|
||
|
|
{
|
||
|
|
callKind2 = CallKind.Call;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
ImmutableArray<BoundExpression> arguments = boundCall2.Arguments;
|
||
|
|
EmitArguments(arguments, method.Parameters, boundCall2.ArgumentRefKindsOpt);
|
||
|
|
int callStackBehavior = GetCallStackBehavior(method, arguments);
|
||
|
|
switch (callKind2)
|
||
|
|
{
|
||
|
|
case CallKind.Call:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, callStackBehavior);
|
||
|
|
break;
|
||
|
|
case CallKind.CallVirt:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Callvirt, callStackBehavior);
|
||
|
|
break;
|
||
|
|
case CallKind.ConstrainedCallVirt:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Constrained);
|
||
|
|
EmitSymbolToken(receiverOpt.Type, receiverOpt.Syntax);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Callvirt, callStackBehavior);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
EmitSymbolToken(methodSymbol, boundCall2.Syntax, methodSymbol.IsVararg ? ((BoundArgListOperator)arguments[arguments.Length - 1]) : null);
|
||
|
|
EmitCallCleanup(boundCall2.Syntax, useKind3, method);
|
||
|
|
}
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
void emitGenericReceiverCloneIfNecessary(BoundCall boundCall2, CallKind callKind2, ref LocalDefinition reference)
|
||
|
|
{
|
||
|
|
BoundExpression receiverOpt = boundCall2.ReceiverOpt;
|
||
|
|
TypeSymbol type2 = receiverOpt.Type;
|
||
|
|
if (callKind2 == CallKind.ConstrainedCallVirt && reference == null && !type2.IsValueType && !ReceiverIsKnownToReferToTempIfReferenceType(receiverOpt) && !IsSafeToDereferenceReceiverRefAfterEvaluatingArguments(boundCall2.Arguments))
|
||
|
|
{
|
||
|
|
object obj = null;
|
||
|
|
if (!type2.IsReferenceType)
|
||
|
|
{
|
||
|
|
EmitDefaultValue(type2, used: true, receiverOpt.Syntax);
|
||
|
|
EmitBox(type2, receiverOpt.Syntax);
|
||
|
|
obj = new object();
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
EmitLoadIndirect(type2, receiverOpt.Syntax);
|
||
|
|
reference = AllocateTemp(type2, receiverOpt.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(reference);
|
||
|
|
_builder.EmitLocalAddress(reference);
|
||
|
|
if (obj != null)
|
||
|
|
{
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||
|
|
void emitReceiver(BoundCall boundCall2, CallKind callKind2, Binder.AddressKind? addressKind2, bool flag, out LocalDefinition reference)
|
||
|
|
{
|
||
|
|
BoundExpression receiverOpt = boundCall2.ReceiverOpt;
|
||
|
|
TypeSymbol type2 = receiverOpt.Type;
|
||
|
|
reference = null;
|
||
|
|
if (!addressKind2.HasValue)
|
||
|
|
{
|
||
|
|
EmitExpression(receiverOpt, used: true);
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
EmitBox(type2, receiverOpt.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
reference = EmitReceiverRef(receiverOpt, addressKind2.GetValueOrDefault());
|
||
|
|
emitGenericReceiverCloneIfNecessary(boundCall2, callKind2, ref reference);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
static bool receiverIsInstanceCall(BoundCall boundCall3, out BoundCall reference)
|
||
|
|
{
|
||
|
|
if (boundCall3.ReceiverOpt is BoundCall boundCall2)
|
||
|
|
{
|
||
|
|
MethodSymbol method = boundCall2.Method;
|
||
|
|
if ((object)method != null && method.RequiresInstanceReceiver && !method.IsDefaultValueTypeConstructor())
|
||
|
|
{
|
||
|
|
reference = boundCall2;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
reference = null;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool IsPossibleReferenceTypeReceiverOfConstrainedCall(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
TypeSymbol type = receiver.Type;
|
||
|
|
if (type.IsVerifierReference() || type.IsVerifierValue())
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return !type.IsValueType;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool ReceiverIsKnownToReferToTempIfReferenceType(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
while (receiver is BoundSequence boundSequence)
|
||
|
|
{
|
||
|
|
receiver = boundSequence.Value;
|
||
|
|
}
|
||
|
|
if (receiver is BoundLocal boundLocal)
|
||
|
|
{
|
||
|
|
LocalSymbol localSymbol = boundLocal.LocalSymbol;
|
||
|
|
if ((object)localSymbol != null && localSymbol.IsKnownToReferToTempIfReferenceType)
|
||
|
|
{
|
||
|
|
goto IL_0062;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (receiver is BoundComplexConditionalReceiver)
|
||
|
|
{
|
||
|
|
goto IL_0062;
|
||
|
|
}
|
||
|
|
if (receiver is BoundConditionalReceiver boundConditionalReceiver)
|
||
|
|
{
|
||
|
|
TypeSymbol type = boundConditionalReceiver.Type;
|
||
|
|
if ((object)type != null && !type.IsReferenceType && !type.IsValueType)
|
||
|
|
{
|
||
|
|
goto IL_0062;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool flag = false;
|
||
|
|
goto IL_006a;
|
||
|
|
IL_006a:
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
IL_0062:
|
||
|
|
flag = true;
|
||
|
|
goto IL_006a;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool IsSafeToDereferenceReceiverRefAfterEvaluatingArguments(ImmutableArray<BoundExpression> arguments)
|
||
|
|
{
|
||
|
|
return arguments.All(isSafeToDereferenceReceiverRefAfterEvaluatingArgument);
|
||
|
|
static bool isSafeToDereferenceReceiverRefAfterEvaluatingArgument(BoundExpression expression)
|
||
|
|
{
|
||
|
|
BoundExpression boundExpression = expression;
|
||
|
|
while (!(boundExpression.ConstantValueOpt != (ConstantValue)null))
|
||
|
|
{
|
||
|
|
switch (boundExpression.Kind)
|
||
|
|
{
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
case BoundKind.TypeExpression:
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
case BoundKind.Local:
|
||
|
|
case BoundKind.Parameter:
|
||
|
|
return true;
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
boundExpression = ((BoundFieldAccess)boundExpression).ReceiverOpt;
|
||
|
|
if (boundExpression == null)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BoundKind.PassByCopy:
|
||
|
|
boundExpression = ((BoundPassByCopy)boundExpression).Expression;
|
||
|
|
break;
|
||
|
|
case BoundKind.BinaryOperator:
|
||
|
|
{
|
||
|
|
BoundBinaryOperator boundBinaryOperator = (BoundBinaryOperator)boundExpression;
|
||
|
|
if (boundBinaryOperator.OperatorKind.IsUserDefined() || !isSafeToDereferenceReceiverRefAfterEvaluatingArgument(boundBinaryOperator.Right))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
boundExpression = boundBinaryOperator.Left;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Conversion:
|
||
|
|
{
|
||
|
|
BoundConversion boundConversion = (BoundConversion)boundExpression;
|
||
|
|
if (boundConversion.ConversionKind.IsUserDefinedConversion())
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
boundExpression = boundConversion.Operand;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsReadOnlyCall(MethodSymbol method, NamedTypeSymbol methodContainingType)
|
||
|
|
{
|
||
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000f: Invalid comparison between Unknown and I4
|
||
|
|
if (method.IsEffectivelyReadOnly && (int)method.MethodKind != 1)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (methodContainingType.IsNullableType())
|
||
|
|
{
|
||
|
|
MethodSymbol originalDefinition = method.OriginalDefinition;
|
||
|
|
if ((object)originalDefinition == ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetSpecialTypeMember((SpecialMember)114) || (object)originalDefinition == ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetSpecialTypeMember((SpecialMember)115) || (object)originalDefinition == ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetSpecialTypeMember((SpecialMember)116))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool IsRef(BoundExpression receiver)
|
||
|
|
{
|
||
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_005c: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0098: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0089: Invalid comparison between Unknown and I4
|
||
|
|
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0070: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0048: Invalid comparison between Unknown and I4
|
||
|
|
return receiver.Kind switch
|
||
|
|
{
|
||
|
|
BoundKind.Local => (int)((BoundLocal)receiver).LocalSymbol.RefKind > 0,
|
||
|
|
BoundKind.Parameter => (int)((BoundParameter)receiver).ParameterSymbol.RefKind > 0,
|
||
|
|
BoundKind.Call => (int)((BoundCall)receiver).Method.RefKind > 0,
|
||
|
|
BoundKind.FunctionPointerInvocation => (int)((BoundFunctionPointerInvocation)receiver).FunctionPointer.Signature.RefKind > 0,
|
||
|
|
BoundKind.Dup => (int)((BoundDup)receiver).RefKind > 0,
|
||
|
|
BoundKind.Sequence => IsRef(((BoundSequence)receiver).Value),
|
||
|
|
_ => false,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int GetCallStackBehavior(MethodSymbol method, ImmutableArray<BoundExpression> arguments)
|
||
|
|
{
|
||
|
|
int num = 0;
|
||
|
|
if (!method.ReturnsVoid)
|
||
|
|
{
|
||
|
|
num++;
|
||
|
|
}
|
||
|
|
if (method.RequiresInstanceReceiver)
|
||
|
|
{
|
||
|
|
num--;
|
||
|
|
}
|
||
|
|
if (method.IsVararg)
|
||
|
|
{
|
||
|
|
int num2 = arguments.Length - 1;
|
||
|
|
int length = ((BoundArgListOperator)arguments[num2]).Arguments.Length;
|
||
|
|
num -= num2;
|
||
|
|
return num - length;
|
||
|
|
}
|
||
|
|
return num - arguments.Length;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int GetObjCreationStackBehavior(BoundObjectCreationExpression objCreation)
|
||
|
|
{
|
||
|
|
int num = 0;
|
||
|
|
num++;
|
||
|
|
if (objCreation.Constructor.IsVararg)
|
||
|
|
{
|
||
|
|
int num2 = objCreation.Arguments.Length - 1;
|
||
|
|
int length = ((BoundArgListOperator)objCreation.Arguments[num2]).Arguments.Length;
|
||
|
|
num -= num2;
|
||
|
|
return num - length;
|
||
|
|
}
|
||
|
|
return num - objCreation.Arguments.Length;
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static bool MayUseCallForStructMethod(MethodSymbol method)
|
||
|
|
{
|
||
|
|
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0033: Invalid comparison between Unknown and I4
|
||
|
|
if (!method.IsMetadataVirtual() || method.IsStatic)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
MethodSymbol overriddenMethod = method.OverriddenMethod;
|
||
|
|
if ((object)overriddenMethod == null || overriddenMethod.IsAbstract)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return (int)method.ContainingType.SpecialType > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void TreatLongsAsNative(PrimitiveTypeCode tc)
|
||
|
|
{
|
||
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0002: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0018: Invalid comparison between Unknown and I4
|
||
|
|
if ((int)tc == 7)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_ovf_i);
|
||
|
|
}
|
||
|
|
else if ((int)tc == 15)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_ovf_i_un);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayLength(BoundArrayLength expression, bool used)
|
||
|
|
{
|
||
|
|
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
EmitExpression(expression.Expression, used: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldlen);
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = expression.Type.PrimitiveTypeCode;
|
||
|
|
PrimitiveTypeCode val = (PrimitiveTypeCode)(PrimitiveTypeCodeExtensions.IsUnsigned(primitiveTypeCode) ? 16 : 8);
|
||
|
|
_builder.EmitNumericConversion(val, primitiveTypeCode, false);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayCreationExpression(BoundArrayCreation expression, bool used)
|
||
|
|
{
|
||
|
|
ArrayTypeSymbol arrayTypeSymbol = (ArrayTypeSymbol)expression.Type;
|
||
|
|
EmitArrayIndices(expression.Bounds);
|
||
|
|
if (arrayTypeSymbol.IsSZArray)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Newarr);
|
||
|
|
EmitSymbolToken(arrayTypeSymbol.ElementType, expression.Syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitArrayCreation(_module.Translate(arrayTypeSymbol), expression.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
if (expression.InitializerOpt != null)
|
||
|
|
{
|
||
|
|
EmitArrayInitializers(arrayTypeSymbol, expression.InitializerOpt);
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConvertedStackAllocExpression(BoundConvertedStackAllocExpression expression, bool used)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.Count, used);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_sawStackalloc = true;
|
||
|
|
_builder.EmitOpCode(ILOpCode.Localloc);
|
||
|
|
}
|
||
|
|
BoundArrayInitialization initializerOpt = expression.InitializerOpt;
|
||
|
|
if (initializerOpt == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitStackAllocInitializers(expression.Type, initializerOpt);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = initializerOpt.Initializers.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
EmitExpression(current, used: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitObjectCreationExpression(BoundObjectCreationExpression expression, bool used)
|
||
|
|
{
|
||
|
|
MethodSymbol constructor = expression.Constructor;
|
||
|
|
bool avoidInPlace;
|
||
|
|
if (constructor.IsDefaultValueTypeConstructor())
|
||
|
|
{
|
||
|
|
EmitInitObj(expression.Type, used, expression.Syntax);
|
||
|
|
}
|
||
|
|
else if (!used && ConstructorNotSideEffecting(constructor))
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = expression.Arguments.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
EmitExpression(current, used: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (!TryEmitReadonlySpanAsBlobWrapper(expression, used, null, out avoidInPlace))
|
||
|
|
{
|
||
|
|
EmitArguments(expression.Arguments, constructor.Parameters, expression.ArgumentRefKindsOpt);
|
||
|
|
int objCreationStackBehavior = GetObjCreationStackBehavior(expression);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Newobj, objCreationStackBehavior);
|
||
|
|
EmitSymbolToken(constructor, expression.Syntax, constructor.IsVararg ? ((BoundArgListOperator)expression.Arguments[expression.Arguments.Length - 1]) : null);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool TryEmitReadonlySpanAsBlobWrapper(BoundObjectCreationExpression expression, bool used, BoundExpression inPlaceTarget, out bool avoidInPlace)
|
||
|
|
{
|
||
|
|
int length = expression.Arguments.Length;
|
||
|
|
avoidInPlace = false;
|
||
|
|
if ((length == 1 && (object)expression.Constructor.OriginalDefinition == ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetWellKnownTypeMember((WellKnownMember)404)) || (length == 3 && (object)expression.Constructor.OriginalDefinition == ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetWellKnownTypeMember((WellKnownMember)405)))
|
||
|
|
{
|
||
|
|
return TryEmitReadonlySpanAsBlobWrapper((NamedTypeSymbol)expression.Type, expression.Arguments[0], used, inPlaceTarget, out avoidInPlace, (length == 3) ? expression.Arguments[1] : null, (length == 3) ? expression.Arguments[2] : null);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool ConstructorNotSideEffecting(MethodSymbol constructor)
|
||
|
|
{
|
||
|
|
MethodSymbol originalDefinition = constructor.OriginalDefinition;
|
||
|
|
CSharpCompilation compilation = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation;
|
||
|
|
if (originalDefinition == compilation.GetSpecialTypeMember((SpecialMember)117))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (originalDefinition.ContainingType.Name == "ValueTuple" && (originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)345) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)346) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)347) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)348) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)349) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)350) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)351) || originalDefinition == compilation.GetWellKnownTypeMember((WellKnownMember)344)))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitAssignmentExpression(BoundAssignmentOperator assignmentOperator, UseKind useKind)
|
||
|
|
{
|
||
|
|
if (!TryEmitAssignmentInPlace(assignmentOperator, useKind != UseKind.Unused))
|
||
|
|
{
|
||
|
|
bool lhsUsesStack = EmitAssignmentPreamble(assignmentOperator);
|
||
|
|
EmitAssignmentValue(assignmentOperator);
|
||
|
|
LocalDefinition temp = EmitAssignmentDuplication(assignmentOperator, useKind, lhsUsesStack);
|
||
|
|
EmitStore(assignmentOperator);
|
||
|
|
EmitAssignmentPostfix(assignmentOperator, temp, useKind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool TryEmitAssignmentInPlace(BoundAssignmentOperator assignmentOperator, bool used)
|
||
|
|
{
|
||
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_005d: Invalid comparison between Unknown and I4
|
||
|
|
if (assignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
BoundExpression left = assignmentOperator.Left;
|
||
|
|
if (used && !TargetIsNotOnHeap(left))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (!SafeToGetWriteableReference(left))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
BoundExpression right = assignmentOperator.Right;
|
||
|
|
TypeSymbol type = right.Type;
|
||
|
|
if (!type.IsTypeParameter() && (type.IsReferenceType || (right.ConstantValueOpt != (ConstantValue)null && (int)type.SpecialType != 17)))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (right.IsDefaultValue())
|
||
|
|
{
|
||
|
|
InPlaceInit(left, used);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (right is BoundObjectCreationExpression boundObjectCreationExpression)
|
||
|
|
{
|
||
|
|
if (boundObjectCreationExpression.Arguments.Length > 0 && boundObjectCreationExpression.Arguments[0].Kind == BoundKind.ConvertedStackAllocExpression)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (PartialCtorResultCannotEscape(left))
|
||
|
|
{
|
||
|
|
MethodSymbol constructor = boundObjectCreationExpression.Constructor;
|
||
|
|
if (constructor.Parameters.All((ParameterSymbol p) => (int)p.RefKind == 0) && !constructor.IsVararg && TryInPlaceCtorCall(left, boundObjectCreationExpression, used))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool SafeToGetWriteableReference(BoundExpression left)
|
||
|
|
{
|
||
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0023: Invalid comparison between Unknown and I4
|
||
|
|
if (!HasHome(left, Binder.AddressKind.Writeable))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (left.Kind == BoundKind.ArrayAccess && (int)left.Type.TypeKind == 11 && !left.Type.IsValueType)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (left.Kind == BoundKind.FieldAccess)
|
||
|
|
{
|
||
|
|
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)left;
|
||
|
|
if (boundFieldAccess.FieldSymbol.IsVolatile || DiagnosticsPass.IsNonAgileFieldAccess(boundFieldAccess, ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void InPlaceInit(BoundExpression target, bool used)
|
||
|
|
{
|
||
|
|
EmitAddress(target, Binder.AddressKind.Writeable);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Initobj);
|
||
|
|
EmitSymbolToken(target.Type, target.Syntax);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitExpression(target, used);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool TryInPlaceCtorCall(BoundExpression target, BoundObjectCreationExpression objCreation, bool used)
|
||
|
|
{
|
||
|
|
if (TryEmitReadonlySpanAsBlobWrapper(objCreation, used, target, out var avoidInPlace))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (avoidInPlace)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
EmitAddress(target, Binder.AddressKind.Writeable);
|
||
|
|
MethodSymbol constructor = objCreation.Constructor;
|
||
|
|
EmitArguments(objCreation.Arguments, constructor.Parameters, objCreation.ArgumentRefKindsOpt);
|
||
|
|
int num = GetObjCreationStackBehavior(objCreation) - 2;
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, num);
|
||
|
|
EmitSymbolToken(constructor, objCreation.Syntax, constructor.IsVararg ? ((BoundArgListOperator)objCreation.Arguments[objCreation.Arguments.Length - 1]) : null);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
EmitExpression(target, used: true);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool PartialCtorResultCannotEscape(BoundExpression left)
|
||
|
|
{
|
||
|
|
if (TargetIsNotOnHeap(left))
|
||
|
|
{
|
||
|
|
if (_tryNestingLevel != 0)
|
||
|
|
{
|
||
|
|
if (left is BoundLocal localExpression && !_builder.PossiblyDefinedOutsideOfTry(GetLocal(localExpression)))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool TargetIsNotOnHeap(BoundExpression left)
|
||
|
|
{
|
||
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0036: Invalid comparison between Unknown and I4
|
||
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0022: Invalid comparison between Unknown and I4
|
||
|
|
return left.Kind switch
|
||
|
|
{
|
||
|
|
BoundKind.Parameter => (int)((BoundParameter)left).ParameterSymbol.RefKind == 0,
|
||
|
|
BoundKind.Local => (int)((BoundLocal)left).LocalSymbol.RefKind == 0,
|
||
|
|
_ => false,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool EmitAssignmentPreamble(BoundAssignmentOperator assignmentOperator)
|
||
|
|
{
|
||
|
|
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
BoundExpression left = assignmentOperator.Left;
|
||
|
|
bool result = false;
|
||
|
|
switch (left.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.RefValueOperator:
|
||
|
|
EmitRefValueAddress((BoundRefValueOperator)left);
|
||
|
|
break;
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
{
|
||
|
|
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)left;
|
||
|
|
if ((int)boundFieldAccess.FieldSymbol.RefKind != 0 && !assignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
EmitFieldLoadNoIndirection(boundFieldAccess, used: true);
|
||
|
|
}
|
||
|
|
else if (!boundFieldAccess.FieldSymbol.IsStatic)
|
||
|
|
{
|
||
|
|
EmitReceiverRef(boundFieldAccess.ReceiverOpt, Binder.AddressKind.Writeable);
|
||
|
|
result = true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Parameter:
|
||
|
|
{
|
||
|
|
BoundParameter boundParameter = (BoundParameter)left;
|
||
|
|
if ((int)boundParameter.ParameterSymbol.RefKind != 0 && !assignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
_builder.EmitLoadArgumentOpcode(ParameterSlot(boundParameter));
|
||
|
|
result = true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Local:
|
||
|
|
{
|
||
|
|
BoundLocal boundLocal = (BoundLocal)left;
|
||
|
|
if ((int)boundLocal.LocalSymbol.RefKind != 0 && !assignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
if (!IsStackLocal(boundLocal.LocalSymbol))
|
||
|
|
{
|
||
|
|
LocalDefinition local = GetLocal(boundLocal);
|
||
|
|
_builder.EmitLocalLoad(local);
|
||
|
|
}
|
||
|
|
result = true;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.ArrayAccess:
|
||
|
|
{
|
||
|
|
BoundArrayAccess boundArrayAccess = (BoundArrayAccess)left;
|
||
|
|
EmitExpression(boundArrayAccess.Expression, used: true);
|
||
|
|
EmitArrayIndices(boundArrayAccess.Indices);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
{
|
||
|
|
BoundThisReference expression3 = (BoundThisReference)left;
|
||
|
|
EmitAddress(expression3, Binder.AddressKind.Writeable);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Dup:
|
||
|
|
{
|
||
|
|
BoundDup expression2 = (BoundDup)left;
|
||
|
|
EmitAddress(expression2, Binder.AddressKind.Writeable);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.ConditionalOperator:
|
||
|
|
{
|
||
|
|
BoundConditionalOperator expression = (BoundConditionalOperator)left;
|
||
|
|
EmitAddress(expression, Binder.AddressKind.Writeable);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.PointerIndirectionOperator:
|
||
|
|
{
|
||
|
|
BoundPointerIndirectionOperator boundPointerIndirectionOperator = (BoundPointerIndirectionOperator)left;
|
||
|
|
EmitExpression(boundPointerIndirectionOperator.Operand, used: true);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
{
|
||
|
|
BoundSequence boundSequence = (BoundSequence)left;
|
||
|
|
DefineAndRecordLocals(boundSequence);
|
||
|
|
EmitSideEffects(boundSequence);
|
||
|
|
result = EmitAssignmentPreamble(assignmentOperator.Update(boundSequence.Value, assignmentOperator.Right, assignmentOperator.IsRef, assignmentOperator.Type));
|
||
|
|
CloseScopeAndKeepLocals(boundSequence);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Call:
|
||
|
|
{
|
||
|
|
BoundCall call = (BoundCall)left;
|
||
|
|
EmitCallExpression(call, UseKind.UsedAsAddress);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.FunctionPointerInvocation:
|
||
|
|
{
|
||
|
|
BoundFunctionPointerInvocation ptrInvocation = (BoundFunctionPointerInvocation)left;
|
||
|
|
EmitCalli(ptrInvocation, UseKind.UsedAsAddress);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.PreviousSubmissionReference:
|
||
|
|
case BoundKind.PropertyAccess:
|
||
|
|
case BoundKind.IndexerAccess:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)left.Kind);
|
||
|
|
case BoundKind.PseudoVariable:
|
||
|
|
EmitPseudoVariableAddress((BoundPseudoVariable)left);
|
||
|
|
result = true;
|
||
|
|
break;
|
||
|
|
case BoundKind.AssignmentOperator:
|
||
|
|
{
|
||
|
|
BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)left;
|
||
|
|
if (boundAssignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
EmitAssignmentExpression(boundAssignmentOperator, UseKind.UsedAsAddress);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
goto default;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)left.Kind);
|
||
|
|
case BoundKind.InstrumentationPayloadRoot:
|
||
|
|
case BoundKind.ModuleVersionId:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator)
|
||
|
|
{
|
||
|
|
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0045: Invalid comparison between Unknown and I4
|
||
|
|
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (!assignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
EmitExpression(assignmentOperator.Right, used: true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int num = _expressionTemps?.Count ?? 0;
|
||
|
|
BoundExpression left = assignmentOperator.Left;
|
||
|
|
BoundExpression right = assignmentOperator.Right;
|
||
|
|
RefKind refKind = left.GetRefKind();
|
||
|
|
bool flag = refKind - 3 <= 2;
|
||
|
|
LocalDefinition temp = EmitAddress(right, flag ? Binder.AddressKind.ReadOnlyStrict : Binder.AddressKind.Writeable);
|
||
|
|
AddExpressionTemp(temp);
|
||
|
|
int num2 = _expressionTemps?.Count ?? 0;
|
||
|
|
if (left.Kind == BoundKind.Local && SynthesizedLocalKindExtensions.IsLongLived(((BoundLocal)left).LocalSymbol.SynthesizedKind) && num2 > num)
|
||
|
|
{
|
||
|
|
_expressionTemps.Count = num;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition EmitAssignmentDuplication(BoundAssignmentOperator assignmentOperator, UseKind useKind, bool lhsUsesStack)
|
||
|
|
{
|
||
|
|
LocalDefinition val = null;
|
||
|
|
if (useKind != UseKind.Unused)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
if (lhsUsesStack)
|
||
|
|
{
|
||
|
|
val = AllocateTemp(assignmentOperator.Left.Type, assignmentOperator.Left.Syntax, (LocalSlotConstraints)(assignmentOperator.IsRef ? 1 : 0));
|
||
|
|
_builder.EmitLocalStore(val);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStore(BoundAssignmentOperator assignment)
|
||
|
|
{
|
||
|
|
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
BoundExpression left = assignment.Left;
|
||
|
|
switch (left.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
EmitFieldStore((BoundFieldAccess)left, assignment.IsRef);
|
||
|
|
return;
|
||
|
|
case BoundKind.Local:
|
||
|
|
{
|
||
|
|
BoundLocal boundLocal = (BoundLocal)left;
|
||
|
|
if ((int)boundLocal.LocalSymbol.RefKind != 0 && !assignment.IsRef)
|
||
|
|
{
|
||
|
|
EmitIndirectStore(boundLocal.LocalSymbol.Type, boundLocal.Syntax);
|
||
|
|
}
|
||
|
|
else if (!IsStackLocal(boundLocal.LocalSymbol))
|
||
|
|
{
|
||
|
|
_builder.EmitLocalStore(GetLocal(boundLocal));
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
case BoundKind.ArrayAccess:
|
||
|
|
{
|
||
|
|
ArrayTypeSymbol arrayType = (ArrayTypeSymbol)((BoundArrayAccess)left).Expression.Type;
|
||
|
|
EmitArrayElementStore(arrayType, left.Syntax);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
case BoundKind.ThisReference:
|
||
|
|
EmitThisStore((BoundThisReference)left);
|
||
|
|
return;
|
||
|
|
case BoundKind.Parameter:
|
||
|
|
EmitParameterStore((BoundParameter)left, assignment.IsRef);
|
||
|
|
return;
|
||
|
|
case BoundKind.Dup:
|
||
|
|
EmitIndirectStore(left.Type, left.Syntax);
|
||
|
|
return;
|
||
|
|
case BoundKind.ConditionalOperator:
|
||
|
|
EmitIndirectStore(left.Type, left.Syntax);
|
||
|
|
return;
|
||
|
|
case BoundKind.PointerIndirectionOperator:
|
||
|
|
case BoundKind.RefValueOperator:
|
||
|
|
case BoundKind.PseudoVariable:
|
||
|
|
EmitIndirectStore(left.Type, left.Syntax);
|
||
|
|
return;
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
{
|
||
|
|
BoundSequence boundSequence = (BoundSequence)left;
|
||
|
|
EmitStore(assignment.Update(boundSequence.Value, assignment.Right, assignment.IsRef, assignment.Type));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
case BoundKind.Call:
|
||
|
|
EmitIndirectStore(left.Type, left.Syntax);
|
||
|
|
return;
|
||
|
|
case BoundKind.FunctionPointerInvocation:
|
||
|
|
EmitIndirectStore(left.Type, left.Syntax);
|
||
|
|
return;
|
||
|
|
case BoundKind.ModuleVersionId:
|
||
|
|
EmitModuleVersionIdStore((BoundModuleVersionId)left);
|
||
|
|
return;
|
||
|
|
case BoundKind.InstrumentationPayloadRoot:
|
||
|
|
EmitInstrumentationPayloadRootStore((BoundInstrumentationPayloadRoot)left);
|
||
|
|
return;
|
||
|
|
case BoundKind.AssignmentOperator:
|
||
|
|
{
|
||
|
|
BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)left;
|
||
|
|
if (boundAssignmentOperator.IsRef)
|
||
|
|
{
|
||
|
|
EmitIndirectStore(boundAssignmentOperator.Type, left.Syntax);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)left.Kind);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitAssignmentPostfix(BoundAssignmentOperator assignment, LocalDefinition temp, UseKind useKind)
|
||
|
|
{
|
||
|
|
if (temp != null)
|
||
|
|
{
|
||
|
|
if (useKind == UseKind.UsedAsAddress)
|
||
|
|
{
|
||
|
|
_builder.EmitLocalAddress(temp);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitLocalLoad(temp);
|
||
|
|
}
|
||
|
|
FreeTemp(temp);
|
||
|
|
}
|
||
|
|
if (useKind == UseKind.UsedAsValue && assignment.IsRef)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(assignment.Type, assignment.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitThisStore(BoundThisReference thisRef)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stobj);
|
||
|
|
EmitSymbolToken(thisRef.Type, thisRef.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitArrayElementStore(ArrayTypeSymbol arrayType, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
if (arrayType.IsSZArray)
|
||
|
|
{
|
||
|
|
EmitVectorElementStore(arrayType, syntaxNode);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitArrayElementStore(_module.Translate(arrayType), syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitVectorElementStore(ArrayTypeSymbol arrayType, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0078: Expected I4, but got Unknown
|
||
|
|
TypeSymbol typeSymbol = arrayType.ElementType;
|
||
|
|
if (typeSymbol.IsEnumType())
|
||
|
|
{
|
||
|
|
typeSymbol = ((NamedTypeSymbol)typeSymbol).EnumUnderlyingType;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = typeSymbol.PrimitiveTypeCode;
|
||
|
|
switch ((int)primitiveTypeCode)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
case 2:
|
||
|
|
case 12:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_i1);
|
||
|
|
return;
|
||
|
|
case 1:
|
||
|
|
case 5:
|
||
|
|
case 13:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_i2);
|
||
|
|
return;
|
||
|
|
case 6:
|
||
|
|
case 14:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_i4);
|
||
|
|
return;
|
||
|
|
case 7:
|
||
|
|
case 15:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_i8);
|
||
|
|
return;
|
||
|
|
case 8:
|
||
|
|
case 9:
|
||
|
|
case 16:
|
||
|
|
case 19:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_i);
|
||
|
|
return;
|
||
|
|
case 3:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_r4);
|
||
|
|
return;
|
||
|
|
case 4:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_r8);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (typeSymbol.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem_ref);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stelem);
|
||
|
|
EmitSymbolToken(typeSymbol, syntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitFieldStore(BoundFieldAccess fieldAccess, bool refAssign)
|
||
|
|
{
|
||
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
FieldSymbol fieldSymbol = fieldAccess.FieldSymbol;
|
||
|
|
if (fieldSymbol.IsVolatile)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Volatile);
|
||
|
|
}
|
||
|
|
if ((int)fieldSymbol.RefKind != 0 && !refAssign)
|
||
|
|
{
|
||
|
|
EmitIndirectStore(fieldSymbol.Type, fieldAccess.Syntax);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(fieldSymbol.IsStatic ? ILOpCode.Stsfld : ILOpCode.Stfld);
|
||
|
|
EmitSymbolToken(fieldSymbol, fieldAccess.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitParameterStore(BoundParameter parameter, bool refAssign)
|
||
|
|
{
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if ((int)parameter.ParameterSymbol.RefKind != 0 && !refAssign)
|
||
|
|
{
|
||
|
|
EmitIndirectStore(parameter.ParameterSymbol.Type, parameter.Syntax);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
int num = ParameterSlot(parameter);
|
||
|
|
_builder.EmitStoreArgumentOpcode(num);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIndirectStore(TypeSymbol type, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001b: 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_0072: Expected I4, but got Unknown
|
||
|
|
if (type.IsEnumType())
|
||
|
|
{
|
||
|
|
type = ((NamedTypeSymbol)type).EnumUnderlyingType;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = type.PrimitiveTypeCode;
|
||
|
|
switch ((int)primitiveTypeCode)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
case 2:
|
||
|
|
case 12:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_i1);
|
||
|
|
return;
|
||
|
|
case 1:
|
||
|
|
case 5:
|
||
|
|
case 13:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_i2);
|
||
|
|
return;
|
||
|
|
case 6:
|
||
|
|
case 14:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_i4);
|
||
|
|
return;
|
||
|
|
case 7:
|
||
|
|
case 15:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_i8);
|
||
|
|
return;
|
||
|
|
case 8:
|
||
|
|
case 9:
|
||
|
|
case 16:
|
||
|
|
case 19:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_i);
|
||
|
|
return;
|
||
|
|
case 3:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_r4);
|
||
|
|
return;
|
||
|
|
case 4:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_r8);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stind_ref);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stobj);
|
||
|
|
EmitSymbolToken(type, syntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitPopIfUnused(bool used)
|
||
|
|
{
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIsExpression(BoundIsOperator isOp, bool used, bool omitBooleanConversion)
|
||
|
|
{
|
||
|
|
BoundExpression operand = isOp.Operand;
|
||
|
|
EmitExpression(operand, used);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
if (!operand.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(operand.Type, operand.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Isinst);
|
||
|
|
EmitSymbolToken(isOp.TargetType.Type, isOp.Syntax);
|
||
|
|
if (!omitBooleanConversion)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldnull);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Cgt_un);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitAsExpression(BoundAsOperator asOp, bool used)
|
||
|
|
{
|
||
|
|
BoundExpression operand = asOp.Operand;
|
||
|
|
EmitExpression(operand, used);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
TypeSymbol type = operand.Type;
|
||
|
|
TypeSymbol type2 = asOp.Type;
|
||
|
|
if ((object)type != null && !type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(type, operand.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Isinst);
|
||
|
|
EmitSymbolToken(type2, asOp.Syntax);
|
||
|
|
if (!type2.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Unbox_any);
|
||
|
|
EmitSymbolToken(type2, asOp.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitDefaultValue(TypeSymbol type, bool used, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0016: Invalid comparison between Unknown and I4
|
||
|
|
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0045: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_006d: Invalid comparison between Unknown and I4
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!type.IsTypeParameter() && (int)type.SpecialType != 17)
|
||
|
|
{
|
||
|
|
ConstantValue defaultValue = type.GetDefaultValue();
|
||
|
|
if (defaultValue != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
_builder.EmitConstantValue(defaultValue);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (type.IsPointerOrFunctionPointer() || (int)type.SpecialType == 22)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldc_i4_0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_u);
|
||
|
|
}
|
||
|
|
else if ((int)type.SpecialType == 21)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldc_i4_0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_i);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitInitObj(type, used: true, syntaxNode);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitDefaultExpression(BoundDefaultExpression expression, bool used)
|
||
|
|
{
|
||
|
|
EmitDefaultValue(expression.Type, used, expression.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConstantExpression(TypeSymbol type, ConstantValue constantValue, bool used, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000e: Invalid comparison between Unknown and I4
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
if ((object)type != null && (int)type.TypeKind == 11 && constantValue.IsNull)
|
||
|
|
{
|
||
|
|
EmitInitObj(type, used, syntaxNode);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitConstantValue(constantValue);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitInitObj(TypeSymbol type, bool used, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
LocalDefinition val = AllocateTemp(type, syntaxNode, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalAddress(val);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Initobj);
|
||
|
|
EmitSymbolToken(type, syntaxNode);
|
||
|
|
_builder.EmitLocalLoad(val);
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitGetTypeFromHandle(BoundTypeOf boundTypeOf)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
MethodSymbol getTypeFromHandle = boundTypeOf.GetTypeFromHandle;
|
||
|
|
EmitSymbolToken(getTypeFromHandle, boundTypeOf.Syntax, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitTypeOfExpression(BoundTypeOfOperator boundTypeOfOperator)
|
||
|
|
{
|
||
|
|
TypeSymbol type = boundTypeOfOperator.SourceType.Type;
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
EmitSymbolToken(type, boundTypeOfOperator.SourceType.Syntax);
|
||
|
|
EmitGetTypeFromHandle(boundTypeOfOperator);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSizeOfExpression(BoundSizeOfOperator boundSizeOfOperator)
|
||
|
|
{
|
||
|
|
TypeSymbol type = boundSizeOfOperator.SourceType.Type;
|
||
|
|
_builder.EmitOpCode(ILOpCode.Sizeof);
|
||
|
|
EmitSymbolToken(type, boundSizeOfOperator.SourceType.Syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitMethodDefIndexExpression(BoundMethodDefIndex node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
MethodSymbol method = node.Method.PartialDefinitionPart ?? node.Method;
|
||
|
|
EmitSymbolToken(method, node.Syntax, null, encodeAsRawDefinitionToken: true);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLocalIdExpression(BoundLocalId node)
|
||
|
|
{
|
||
|
|
if ((object)node.HoistedField == null)
|
||
|
|
{
|
||
|
|
_builder.EmitIntConstant(GetLocal(node.Local).SlotIndex);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitHoistedVariableId(node.HoistedField, node.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitParameterIdExpression(BoundParameterId node)
|
||
|
|
{
|
||
|
|
if ((object)node.HoistedField == null)
|
||
|
|
{
|
||
|
|
_builder.EmitIntConstant(node.Parameter.Ordinal);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitHoistedVariableId(node.HoistedField, node.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitHoistedVariableId(FieldSymbol field, SyntaxNode syntax)
|
||
|
|
{
|
||
|
|
IFieldReference val = _module.Translate(field, syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, needDeclaration: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
_builder.EmitToken((IReference)(object)val, syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)4);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitMaximumMethodDefIndexExpression(BoundMaximumMethodDefIndex node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
_builder.EmitGreatestMethodToken();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitModuleVersionIdLoad(BoundModuleVersionId node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsfld);
|
||
|
|
EmitModuleVersionIdToken(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitModuleVersionIdStore(BoundModuleVersionId node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stsfld);
|
||
|
|
EmitModuleVersionIdToken(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitModuleVersionIdToken(BoundModuleVersionId node)
|
||
|
|
{
|
||
|
|
_builder.EmitToken((IReference)(object)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).GetModuleVersionId(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(node.Type, node.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), node.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), node.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitModuleVersionIdStringLoad()
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldstr);
|
||
|
|
_builder.EmitModuleVersionIdStringToken();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitInstrumentationPayloadRootLoad(BoundInstrumentationPayloadRoot node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsfld);
|
||
|
|
EmitInstrumentationPayloadRootToken(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitInstrumentationPayloadRootStore(BoundInstrumentationPayloadRoot node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Stsfld);
|
||
|
|
EmitInstrumentationPayloadRootToken(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitInstrumentationPayloadRootToken(BoundInstrumentationPayloadRoot node)
|
||
|
|
{
|
||
|
|
_builder.EmitToken((IReference)(object)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).GetInstrumentationPayloadRoot(node.AnalysisKind, ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(node.Type, node.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), node.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), node.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSourceDocumentIndex(BoundSourceDocumentIndex node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
_builder.EmitSourceDocumentIndexToken(node.Document);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitMethodInfoExpression(BoundMethodInfo node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
EmitSymbolToken(node.Method, node.Syntax, null);
|
||
|
|
MethodSymbol getMethodFromHandle = node.GetMethodFromHandle;
|
||
|
|
if (getMethodFromHandle.ParameterCount == 1)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
EmitSymbolToken(node.Method.ContainingType, node.Syntax);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, -1);
|
||
|
|
}
|
||
|
|
EmitSymbolToken(getMethodFromHandle, node.Syntax, null);
|
||
|
|
if (!TypeSymbol.Equals(node.Type, getMethodFromHandle.ReturnType, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Castclass);
|
||
|
|
EmitSymbolToken(node.Type, node.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitFieldInfoExpression(BoundFieldInfo node)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
EmitSymbolToken(node.Field, node.Syntax);
|
||
|
|
MethodSymbol getFieldFromHandle = node.GetFieldFromHandle;
|
||
|
|
if (getFieldFromHandle.ParameterCount == 1)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldtoken);
|
||
|
|
EmitSymbolToken(node.Field.ContainingType, node.Syntax);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, -1);
|
||
|
|
}
|
||
|
|
EmitSymbolToken(getFieldFromHandle, node.Syntax, null);
|
||
|
|
if (!TypeSymbol.Equals(node.Type, getFieldFromHandle.ReturnType, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Castclass);
|
||
|
|
EmitSymbolToken(node.Type, node.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConditionalOperator(BoundConditionalOperator expr, bool used)
|
||
|
|
{
|
||
|
|
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001e: 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_0061: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (used && (int)_ilEmitStyle != 0 && (IsNumeric(expr.Type) || (int)expr.Type.PrimitiveTypeCode == 0) && hasIntegralValueZeroOrOne(expr.Consequence, out var isOne) && hasIntegralValueZeroOrOne(expr.Alternative, out var isOne2) && isOne != isOne2 && TryEmitComparison(expr.Condition, isOne))
|
||
|
|
{
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = expr.Type.PrimitiveTypeCode;
|
||
|
|
if ((int)primitiveTypeCode != 0)
|
||
|
|
{
|
||
|
|
_builder.EmitNumericConversion((PrimitiveTypeCode)6, primitiveTypeCode, false);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
object dest = new object();
|
||
|
|
object obj = new object();
|
||
|
|
EmitCondBranch(expr.Condition, ref dest, sense: true);
|
||
|
|
EmitExpression(expr.Alternative, used);
|
||
|
|
TypeSymbol typeSymbol = StackMergeType(expr.Alternative);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
if (IsVarianceCast(expr.Type, typeSymbol))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
typeSymbol = expr.Type;
|
||
|
|
}
|
||
|
|
else if (expr.Type.IsInterfaceType() && !TypeSymbol.Equals(expr.Type, typeSymbol, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj, ILOpCode.Nop);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.AdjustStack(-1);
|
||
|
|
}
|
||
|
|
_builder.MarkLabel(dest);
|
||
|
|
EmitExpression(expr.Consequence, used);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
TypeSymbol typeSymbol2 = StackMergeType(expr.Consequence);
|
||
|
|
if (IsVarianceCast(expr.Type, typeSymbol2))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
typeSymbol2 = expr.Type;
|
||
|
|
}
|
||
|
|
else if (expr.Type.IsInterfaceType() && !TypeSymbol.Equals(expr.Type, typeSymbol2, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
static bool hasIntegralValueZeroOrOne(BoundExpression boundExpression, out bool reference)
|
||
|
|
{
|
||
|
|
ConstantValue constantValueOpt = boundExpression.ConstantValueOpt;
|
||
|
|
ulong uInt64Value = default(ulong);
|
||
|
|
bool flag;
|
||
|
|
if (constantValueOpt != null)
|
||
|
|
{
|
||
|
|
if (constantValueOpt != null && constantValueOpt.IsIntegral)
|
||
|
|
{
|
||
|
|
uInt64Value = constantValueOpt.UInt64Value;
|
||
|
|
if (uInt64Value <= 1)
|
||
|
|
{
|
||
|
|
flag = true;
|
||
|
|
goto IL_0029;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
flag = false;
|
||
|
|
goto IL_0029;
|
||
|
|
}
|
||
|
|
goto IL_007a;
|
||
|
|
IL_007a:
|
||
|
|
reference = false;
|
||
|
|
return false;
|
||
|
|
IL_0029:
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
reference = uInt64Value == 1;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (constantValueOpt != null && constantValueOpt.IsBoolean)
|
||
|
|
{
|
||
|
|
bool booleanValue = constantValueOpt.BooleanValue;
|
||
|
|
reference = booleanValue;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
char charValue = default(char);
|
||
|
|
if (constantValueOpt != null && constantValueOpt.IsChar)
|
||
|
|
{
|
||
|
|
charValue = constantValueOpt.CharValue;
|
||
|
|
if (charValue == '\0' || charValue == '\u0001')
|
||
|
|
{
|
||
|
|
flag = true;
|
||
|
|
goto IL_006e;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
flag = false;
|
||
|
|
goto IL_006e;
|
||
|
|
IL_006e:
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
reference = charValue == '\u0001';
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
goto IL_007a;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitNullCoalescingOperator(BoundNullCoalescingOperator expr, bool used)
|
||
|
|
{
|
||
|
|
EmitExpression(expr.LeftOperand, used: true);
|
||
|
|
TypeSymbol typeSymbol = StackMergeType(expr.LeftOperand);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
if (IsVarianceCast(expr.Type, typeSymbol))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
typeSymbol = expr.Type;
|
||
|
|
}
|
||
|
|
else if (expr.Type.IsInterfaceType() && !TypeSymbol.Equals(expr.Type, typeSymbol, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
}
|
||
|
|
if (expr.Type.IsTypeParameter())
|
||
|
|
{
|
||
|
|
EmitBox(expr.Type, expr.LeftOperand.Syntax);
|
||
|
|
}
|
||
|
|
object obj = new object();
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj, ILOpCode.Nop);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
}
|
||
|
|
EmitExpression(expr.RightOperand, used);
|
||
|
|
if (used)
|
||
|
|
{
|
||
|
|
TypeSymbol typeSymbol2 = StackMergeType(expr.RightOperand);
|
||
|
|
if (IsVarianceCast(expr.Type, typeSymbol2))
|
||
|
|
{
|
||
|
|
EmitStaticCast(expr.Type, expr.Syntax);
|
||
|
|
typeSymbol2 = expr.Type;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
}
|
||
|
|
|
||
|
|
private TypeSymbol StackMergeType(BoundExpression expr)
|
||
|
|
{
|
||
|
|
if (!expr.Type.IsInterfaceType() && !expr.Type.IsDelegateType())
|
||
|
|
{
|
||
|
|
return expr.Type;
|
||
|
|
}
|
||
|
|
switch (expr.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.Conversion:
|
||
|
|
{
|
||
|
|
BoundConversion boundConversion = (BoundConversion)expr;
|
||
|
|
ConversionKind conversionKind = boundConversion.ConversionKind;
|
||
|
|
if (conversionKind.IsImplicitConversion() && conversionKind != ConversionKind.MethodGroup && conversionKind != ConversionKind.NullLiteral && conversionKind != ConversionKind.DefaultLiteral)
|
||
|
|
{
|
||
|
|
return StackMergeType(boundConversion.Operand);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.AssignmentOperator:
|
||
|
|
{
|
||
|
|
BoundAssignmentOperator boundAssignmentOperator = (BoundAssignmentOperator)expr;
|
||
|
|
return StackMergeType(boundAssignmentOperator.Right);
|
||
|
|
}
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
{
|
||
|
|
BoundSequence boundSequence = (BoundSequence)expr;
|
||
|
|
return StackMergeType(boundSequence.Value);
|
||
|
|
}
|
||
|
|
case BoundKind.Local:
|
||
|
|
{
|
||
|
|
BoundLocal boundLocal = (BoundLocal)expr;
|
||
|
|
if (IsStackLocal(boundLocal.LocalSymbol))
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.Dup:
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return expr.Type;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsVarianceCast(TypeSymbol to, TypeSymbol from)
|
||
|
|
{
|
||
|
|
if (TypeSymbol.Equals(to, from, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if ((object)from == null)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (to.IsArray())
|
||
|
|
{
|
||
|
|
return IsVarianceCast(((ArrayTypeSymbol)to).ElementType, ((ArrayTypeSymbol)from).ElementType);
|
||
|
|
}
|
||
|
|
if (!to.IsDelegateType() || TypeSymbol.Equals(to, from, (TypeCompareKind)0))
|
||
|
|
{
|
||
|
|
if (to.IsInterfaceType() && from.IsInterfaceType())
|
||
|
|
{
|
||
|
|
return !from.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics.ContainsKey((NamedTypeSymbol)to);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStaticCast(TypeSymbol to, SyntaxNode syntax)
|
||
|
|
{
|
||
|
|
LocalDefinition val = AllocateTemp(to, syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val);
|
||
|
|
_builder.EmitLocalLoad(val);
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBox(TypeSymbol type, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Box);
|
||
|
|
EmitSymbolToken(type, syntaxNode);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCalli(BoundFunctionPointerInvocation ptrInvocation, UseKind useKind)
|
||
|
|
{
|
||
|
|
EmitExpression(ptrInvocation.InvokedExpression, used: true);
|
||
|
|
LocalDefinition val = null;
|
||
|
|
if (ptrInvocation.Arguments.Length > 0)
|
||
|
|
{
|
||
|
|
val = AllocateTemp(ptrInvocation.InvokedExpression.Type, ptrInvocation.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val);
|
||
|
|
}
|
||
|
|
FunctionPointerMethodSymbol signature = ptrInvocation.FunctionPointer.Signature;
|
||
|
|
EmitArguments(ptrInvocation.Arguments, signature.Parameters, ptrInvocation.ArgumentRefKindsOpt);
|
||
|
|
int callStackBehavior = GetCallStackBehavior(ptrInvocation.FunctionPointer.Signature, ptrInvocation.Arguments);
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
_builder.EmitLocalLoad(val);
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Calli, callStackBehavior);
|
||
|
|
EmitSignatureToken(ptrInvocation.FunctionPointer, ptrInvocation.Syntax);
|
||
|
|
EmitCallCleanup(ptrInvocation.Syntax, useKind, signature);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCallCleanup(SyntaxNode syntax, UseKind useKind, MethodSymbol method)
|
||
|
|
{
|
||
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (!method.ReturnsVoid)
|
||
|
|
{
|
||
|
|
EmitPopIfUnused(useKind != UseKind.Unused);
|
||
|
|
}
|
||
|
|
else if ((int)_ilEmitStyle == 0)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
if (useKind == UseKind.UsedAsValue && (int)method.RefKind != 0)
|
||
|
|
{
|
||
|
|
EmitLoadIndirect(method.ReturnType, syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_ = 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLoadFunction(BoundFunctionPointerLoad load, bool used)
|
||
|
|
{
|
||
|
|
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003f: Invalid comparison between Unknown and I4
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if ((load.TargetMethod.IsAbstract || load.TargetMethod.IsVirtual) && load.TargetMethod.IsStatic)
|
||
|
|
{
|
||
|
|
TypeSymbol constrainedToTypeOpt = load.ConstrainedToTypeOpt;
|
||
|
|
if ((object)constrainedToTypeOpt == null || (int)constrainedToTypeOpt.TypeKind != 11)
|
||
|
|
{
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs", 4073);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Constrained);
|
||
|
|
EmitSymbolToken(load.ConstrainedToTypeOpt, load.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldftn);
|
||
|
|
EmitSymbolToken(load.TargetMethod, load.Syntax, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitUnaryOperatorExpression(BoundUnaryOperator expression, bool used)
|
||
|
|
{
|
||
|
|
UnaryOperatorKind operatorKind = expression.OperatorKind;
|
||
|
|
if (operatorKind.IsChecked())
|
||
|
|
{
|
||
|
|
EmitUnaryCheckedOperatorExpression(expression, used);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!used)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.Operand, used: false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (operatorKind == UnaryOperatorKind.BoolLogicalNegation)
|
||
|
|
{
|
||
|
|
EmitCondExpr(expression.Operand, sense: false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
EmitExpression(expression.Operand, used: true);
|
||
|
|
switch (operatorKind.Operator())
|
||
|
|
{
|
||
|
|
case UnaryOperatorKind.UnaryMinus:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Neg);
|
||
|
|
break;
|
||
|
|
case UnaryOperatorKind.BitwiseComplement:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Not);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)operatorKind.Operator());
|
||
|
|
case UnaryOperatorKind.UnaryPlus:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryOperatorExpression(BoundBinaryOperator expression, bool used)
|
||
|
|
{
|
||
|
|
BinaryOperatorKind operatorKind = expression.OperatorKind;
|
||
|
|
if (operatorKind.EmitsAsCheckedInstruction())
|
||
|
|
{
|
||
|
|
EmitBinaryOperator(expression);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!used && !operatorKind.IsLogical() && !OperatorHasSideEffects(operatorKind))
|
||
|
|
{
|
||
|
|
EmitExpression(expression.Left, used: false);
|
||
|
|
EmitExpression(expression.Right, used: false);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (IsConditional(operatorKind))
|
||
|
|
{
|
||
|
|
EmitBinaryCondOperator(expression, sense: true);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitBinaryOperator(expression);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryOperator(BoundBinaryOperator expression)
|
||
|
|
{
|
||
|
|
BoundExpression left = expression.Left;
|
||
|
|
if (left.Kind != BoundKind.BinaryOperator || left.ConstantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
EmitBinaryOperatorSimple(expression);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
BoundBinaryOperator boundBinaryOperator = (BoundBinaryOperator)left;
|
||
|
|
BinaryOperatorKind operatorKind = boundBinaryOperator.OperatorKind;
|
||
|
|
if (!operatorKind.EmitsAsCheckedInstruction() && IsConditional(operatorKind))
|
||
|
|
{
|
||
|
|
EmitBinaryOperatorSimple(expression);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ArrayBuilder<BoundBinaryOperator> instance = ArrayBuilder<BoundBinaryOperator>.GetInstance();
|
||
|
|
ArrayBuilderExtensions.Push<BoundBinaryOperator>(instance, expression);
|
||
|
|
do
|
||
|
|
{
|
||
|
|
ArrayBuilderExtensions.Push<BoundBinaryOperator>(instance, boundBinaryOperator);
|
||
|
|
left = boundBinaryOperator.Left;
|
||
|
|
if (left.Kind != BoundKind.BinaryOperator || left.ConstantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
boundBinaryOperator = (BoundBinaryOperator)left;
|
||
|
|
operatorKind = boundBinaryOperator.OperatorKind;
|
||
|
|
}
|
||
|
|
while (operatorKind.EmitsAsCheckedInstruction() || !IsConditional(operatorKind));
|
||
|
|
EmitExpression(left, used: true);
|
||
|
|
do
|
||
|
|
{
|
||
|
|
boundBinaryOperator = ArrayBuilderExtensions.Pop<BoundBinaryOperator>(instance);
|
||
|
|
EmitExpression(boundBinaryOperator.Right, used: true);
|
||
|
|
bool flag = boundBinaryOperator.OperatorKind.EmitsAsCheckedInstruction();
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
EmitBinaryCheckedOperatorInstruction(boundBinaryOperator);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitBinaryOperatorInstruction(boundBinaryOperator);
|
||
|
|
}
|
||
|
|
EmitConversionToEnumUnderlyingType(boundBinaryOperator, flag);
|
||
|
|
}
|
||
|
|
while (instance.Count > 0);
|
||
|
|
instance.Free();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryOperatorSimple(BoundBinaryOperator expression)
|
||
|
|
{
|
||
|
|
EmitExpression(expression.Left, used: true);
|
||
|
|
EmitExpression(expression.Right, used: true);
|
||
|
|
bool flag = expression.OperatorKind.EmitsAsCheckedInstruction();
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
EmitBinaryCheckedOperatorInstruction(expression);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitBinaryOperatorInstruction(expression);
|
||
|
|
}
|
||
|
|
EmitConversionToEnumUnderlyingType(expression, flag);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryOperatorInstruction(BoundBinaryOperator expression)
|
||
|
|
{
|
||
|
|
switch (expression.OperatorKind.Operator())
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.Multiplication:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Mul);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Addition:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Add);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Subtraction:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Sub);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Division:
|
||
|
|
if (IsUnsignedBinaryOperator(expression))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Div_un);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Div);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Remainder:
|
||
|
|
if (IsUnsignedBinaryOperator(expression))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Rem_un);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Rem);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.LeftShift:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Shl);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.RightShift:
|
||
|
|
if (IsUnsignedBinaryOperator(expression))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Shr_un);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Shr);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.UnsignedRightShift:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Shr_un);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.And:
|
||
|
|
_builder.EmitOpCode(ILOpCode.And);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Xor:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Xor);
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Or:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Or);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)expression.OperatorKind.Operator());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitShortCircuitingOperator(BoundBinaryOperator condition, bool sense, bool stopSense, bool stopValue)
|
||
|
|
{
|
||
|
|
object dest = null;
|
||
|
|
EmitCondBranch(condition.Left, ref dest, stopSense);
|
||
|
|
EmitCondExpr(condition.Right, sense);
|
||
|
|
if (dest != null)
|
||
|
|
{
|
||
|
|
object obj = new object();
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj, ILOpCode.Nop);
|
||
|
|
_builder.AdjustStack(-1);
|
||
|
|
_builder.MarkLabel(dest);
|
||
|
|
_builder.EmitBoolConstant(stopValue);
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryCondOperator(BoundBinaryOperator binOp, bool sense)
|
||
|
|
{
|
||
|
|
bool flag = sense;
|
||
|
|
BinaryOperatorKind binaryOperatorKind = binOp.OperatorKind.OperatorWithLogical();
|
||
|
|
int num;
|
||
|
|
if (binaryOperatorKind <= BinaryOperatorKind.GreaterThanOrEqual)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind <= BinaryOperatorKind.NotEqual)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.Equal)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.NotEqual)
|
||
|
|
{
|
||
|
|
goto IL_01db;
|
||
|
|
}
|
||
|
|
sense = !sense;
|
||
|
|
}
|
||
|
|
ConstantValue constantValueOpt = binOp.Left.ConstantValueOpt;
|
||
|
|
BoundExpression boundExpression = binOp.Right;
|
||
|
|
if (constantValueOpt == (ConstantValue)null)
|
||
|
|
{
|
||
|
|
constantValueOpt = boundExpression.ConstantValueOpt;
|
||
|
|
boundExpression = binOp.Left;
|
||
|
|
}
|
||
|
|
if (constantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
if (constantValueOpt.IsDefaultValue)
|
||
|
|
{
|
||
|
|
if (!constantValueOpt.IsFloating)
|
||
|
|
{
|
||
|
|
if (sense)
|
||
|
|
{
|
||
|
|
EmitIsNullOrZero(boundExpression, constantValueOpt);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitIsNotNullOrZero(boundExpression, constantValueOpt);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (constantValueOpt.IsBoolean)
|
||
|
|
{
|
||
|
|
EmitExpression(boundExpression, used: true);
|
||
|
|
EmitIsSense(sense);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitBinaryCondOperatorHelper(ILOpCode.Ceq, binOp.Left, binOp.Right, sense);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.GreaterThan)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.LessThan)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.GreaterThanOrEqual)
|
||
|
|
{
|
||
|
|
goto IL_01db;
|
||
|
|
}
|
||
|
|
num = 3;
|
||
|
|
sense = !sense;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
num = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
num = 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind > BinaryOperatorKind.Xor)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.Or)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.LogicalAnd)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.LogicalOr)
|
||
|
|
{
|
||
|
|
goto IL_01db;
|
||
|
|
}
|
||
|
|
flag = !flag;
|
||
|
|
}
|
||
|
|
if (!flag)
|
||
|
|
{
|
||
|
|
EmitShortCircuitingOperator(binOp, sense, sense, stopValue: true);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitShortCircuitingOperator(binOp, sense, !sense, stopValue: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitBinaryCondOperatorHelper(ILOpCode.Or, binOp.Left, binOp.Right, sense);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.LessThanOrEqual)
|
||
|
|
{
|
||
|
|
switch (binaryOperatorKind)
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.And:
|
||
|
|
EmitBinaryCondOperatorHelper(ILOpCode.And, binOp.Left, binOp.Right, sense);
|
||
|
|
return;
|
||
|
|
case BinaryOperatorKind.Xor:
|
||
|
|
if (sense)
|
||
|
|
{
|
||
|
|
EmitBinaryCondOperatorHelper(ILOpCode.Xor, binOp.Left, binOp.Right, sense: true);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitBinaryCondOperatorHelper(ILOpCode.Ceq, binOp.Left, binOp.Right, sense: true);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
goto IL_01db;
|
||
|
|
}
|
||
|
|
num = 1;
|
||
|
|
sense = !sense;
|
||
|
|
}
|
||
|
|
if (IsUnsignedBinaryOperator(binOp))
|
||
|
|
{
|
||
|
|
num += 4;
|
||
|
|
}
|
||
|
|
else if (IsFloat(binOp.OperatorKind))
|
||
|
|
{
|
||
|
|
num += 8;
|
||
|
|
}
|
||
|
|
EmitBinaryCondOperatorHelper(s_compOpCodes[num], binOp.Left, binOp.Right, sense);
|
||
|
|
return;
|
||
|
|
IL_01db:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)binOp.OperatorKind.OperatorWithLogical());
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIsNotNullOrZero(BoundExpression comparand, ConstantValue nullOrZero)
|
||
|
|
{
|
||
|
|
EmitExpression(comparand, used: true);
|
||
|
|
TypeSymbol type = comparand.Type;
|
||
|
|
if (type.IsReferenceType && !type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(type, comparand.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitConstantValue(nullOrZero);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Cgt_un);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIsNullOrZero(BoundExpression comparand, ConstantValue nullOrZero)
|
||
|
|
{
|
||
|
|
EmitExpression(comparand, used: true);
|
||
|
|
TypeSymbol type = comparand.Type;
|
||
|
|
if (type.IsReferenceType && !type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(type, comparand.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitConstantValue(nullOrZero);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ceq);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryCondOperatorHelper(ILOpCode opCode, BoundExpression left, BoundExpression right, bool sense)
|
||
|
|
{
|
||
|
|
EmitExpression(left, used: true);
|
||
|
|
EmitExpression(right, used: true);
|
||
|
|
_builder.EmitOpCode(opCode);
|
||
|
|
EmitIsSense(sense);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCondExpr(BoundExpression condition, bool sense)
|
||
|
|
{
|
||
|
|
RemoveNegation(ref condition, ref sense);
|
||
|
|
ConstantValue constantValueOpt = condition.ConstantValueOpt;
|
||
|
|
if (constantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
bool booleanValue = constantValueOpt.BooleanValue;
|
||
|
|
_builder.EmitBoolConstant(booleanValue == sense);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (condition.Kind == BoundKind.BinaryOperator)
|
||
|
|
{
|
||
|
|
BoundBinaryOperator boundBinaryOperator = (BoundBinaryOperator)condition;
|
||
|
|
if (IsConditional(boundBinaryOperator.OperatorKind))
|
||
|
|
{
|
||
|
|
EmitBinaryCondOperator(boundBinaryOperator, sense);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitExpression(condition, used: true);
|
||
|
|
EmitIsSense(sense);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool TryEmitComparison(BoundExpression condition, bool sense)
|
||
|
|
{
|
||
|
|
RemoveNegation(ref condition, ref sense);
|
||
|
|
ConstantValue constantValueOpt = condition.ConstantValueOpt;
|
||
|
|
if (constantValueOpt != null)
|
||
|
|
{
|
||
|
|
_builder.EmitBoolConstant(constantValueOpt.BooleanValue == sense);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (condition is BoundBinaryOperator boundBinaryOperator)
|
||
|
|
{
|
||
|
|
if (boundBinaryOperator.OperatorKind.IsComparison())
|
||
|
|
{
|
||
|
|
EmitBinaryCondOperator(boundBinaryOperator, sense);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (condition is BoundIsOperator isOp)
|
||
|
|
{
|
||
|
|
EmitIsExpression(isOp, used: true, omitBooleanConversion: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldnull);
|
||
|
|
_builder.EmitOpCode(sense ? ILOpCode.Cgt_un : ILOpCode.Ceq);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
EmitExpression(condition, used: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldc_i4_0);
|
||
|
|
_builder.EmitOpCode(sense ? ILOpCode.Cgt_un : ILOpCode.Ceq);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void RemoveNegation(ref BoundExpression condition, ref bool sense)
|
||
|
|
{
|
||
|
|
while (condition is BoundUnaryOperator boundUnaryOperator)
|
||
|
|
{
|
||
|
|
condition = boundUnaryOperator.Operand;
|
||
|
|
sense = !sense;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitUnaryCheckedOperatorExpression(BoundUnaryOperator expression, bool used)
|
||
|
|
{
|
||
|
|
UnaryOperatorKind unaryOperatorKind = expression.OperatorKind.OperandTypes();
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldc_i4_0);
|
||
|
|
switch (unaryOperatorKind)
|
||
|
|
{
|
||
|
|
case UnaryOperatorKind.Long:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_i8);
|
||
|
|
break;
|
||
|
|
case UnaryOperatorKind.NInt:
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_i);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
EmitExpression(expression.Operand, used: true);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Sub_ovf);
|
||
|
|
EmitPopIfUnused(used);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConversionToEnumUnderlyingType(BoundBinaryOperator expression, bool @checked)
|
||
|
|
{
|
||
|
|
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b3: Expected I4, but got Unknown
|
||
|
|
TypeSymbol typeSymbol;
|
||
|
|
switch (expression.OperatorKind.Operator() | expression.OperatorKind.OperandTypes())
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.EnumAndUnderlyingAddition:
|
||
|
|
case BinaryOperatorKind.EnumSubtraction:
|
||
|
|
case BinaryOperatorKind.EnumAndUnderlyingSubtraction:
|
||
|
|
typeSymbol = expression.Left.Type;
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.EnumAnd:
|
||
|
|
case BinaryOperatorKind.EnumXor:
|
||
|
|
case BinaryOperatorKind.EnumOr:
|
||
|
|
typeSymbol = null;
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.UnderlyingAndEnumAddition:
|
||
|
|
case BinaryOperatorKind.UnderlyingAndEnumSubtraction:
|
||
|
|
typeSymbol = expression.Right.Type;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
typeSymbol = null;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if ((object)typeSymbol != null)
|
||
|
|
{
|
||
|
|
SpecialType specialType = typeSymbol.GetEnumUnderlyingType().SpecialType;
|
||
|
|
switch (specialType - 9)
|
||
|
|
{
|
||
|
|
case 1:
|
||
|
|
_builder.EmitNumericConversion((PrimitiveTypeCode)6, (PrimitiveTypeCode)12, @checked);
|
||
|
|
break;
|
||
|
|
case 0:
|
||
|
|
_builder.EmitNumericConversion((PrimitiveTypeCode)6, (PrimitiveTypeCode)2, @checked);
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
_builder.EmitNumericConversion((PrimitiveTypeCode)6, (PrimitiveTypeCode)5, @checked);
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
_builder.EmitNumericConversion((PrimitiveTypeCode)6, (PrimitiveTypeCode)13, @checked);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBinaryCheckedOperatorInstruction(BoundBinaryOperator expression)
|
||
|
|
{
|
||
|
|
bool flag = IsUnsignedBinaryOperator(expression);
|
||
|
|
switch (expression.OperatorKind.Operator())
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.Multiplication:
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Mul_ovf_un);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Mul_ovf);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Addition:
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Add_ovf_un);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Add_ovf);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.Subtraction:
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Sub_ovf_un);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Sub_ovf);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)expression.OperatorKind.Operator());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool OperatorHasSideEffects(BinaryOperatorKind kind)
|
||
|
|
{
|
||
|
|
BinaryOperatorKind binaryOperatorKind = kind.Operator();
|
||
|
|
if (binaryOperatorKind == BinaryOperatorKind.Division || binaryOperatorKind == BinaryOperatorKind.Remainder)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return kind.IsChecked();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIsSense(bool sense)
|
||
|
|
{
|
||
|
|
if (!sense)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldc_i4_0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ceq);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsUnsigned(SpecialType type)
|
||
|
|
{
|
||
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0025: Expected I4, but got Unknown
|
||
|
|
switch (type - 10)
|
||
|
|
{
|
||
|
|
case 0:
|
||
|
|
case 2:
|
||
|
|
case 4:
|
||
|
|
case 6:
|
||
|
|
return true;
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsUnsignedBinaryOperator(BoundBinaryOperator op)
|
||
|
|
{
|
||
|
|
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
switch (op.OperatorKind.OperandTypes())
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.Enum:
|
||
|
|
case BinaryOperatorKind.EnumAndUnderlying:
|
||
|
|
return IsUnsigned(Binder.GetEnumPromotedType(op.Left.Type.GetEnumUnderlyingType().SpecialType));
|
||
|
|
case BinaryOperatorKind.UnderlyingAndEnum:
|
||
|
|
return IsUnsigned(Binder.GetEnumPromotedType(op.Right.Type.GetEnumUnderlyingType().SpecialType));
|
||
|
|
case BinaryOperatorKind.UInt:
|
||
|
|
case BinaryOperatorKind.ULong:
|
||
|
|
case BinaryOperatorKind.NUInt:
|
||
|
|
case BinaryOperatorKind.Pointer:
|
||
|
|
case BinaryOperatorKind.PointerAndInt:
|
||
|
|
case BinaryOperatorKind.PointerAndUInt:
|
||
|
|
case BinaryOperatorKind.PointerAndLong:
|
||
|
|
case BinaryOperatorKind.PointerAndULong:
|
||
|
|
case BinaryOperatorKind.ULongAndPointer:
|
||
|
|
return true;
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsConditional(BinaryOperatorKind opKind)
|
||
|
|
{
|
||
|
|
switch (opKind.OperatorWithLogical())
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.Equal:
|
||
|
|
case BinaryOperatorKind.NotEqual:
|
||
|
|
case BinaryOperatorKind.GreaterThan:
|
||
|
|
case BinaryOperatorKind.LessThan:
|
||
|
|
case BinaryOperatorKind.GreaterThanOrEqual:
|
||
|
|
case BinaryOperatorKind.LessThanOrEqual:
|
||
|
|
case BinaryOperatorKind.LogicalAnd:
|
||
|
|
case BinaryOperatorKind.LogicalOr:
|
||
|
|
return true;
|
||
|
|
case BinaryOperatorKind.And:
|
||
|
|
case BinaryOperatorKind.Xor:
|
||
|
|
case BinaryOperatorKind.Or:
|
||
|
|
return opKind.OperandTypes() == BinaryOperatorKind.Bool;
|
||
|
|
default:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsFloat(BinaryOperatorKind opKind)
|
||
|
|
{
|
||
|
|
BinaryOperatorKind binaryOperatorKind = opKind.OperandTypes();
|
||
|
|
if ((uint)(binaryOperatorKind - 12) <= 1u)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStackAllocInitializers(TypeSymbol type, BoundArrayInitialization inits)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0008: Invalid comparison between Unknown and I4
|
||
|
|
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
TypeSymbol type2 = (((int)type.TypeKind == 9) ? ((PointerTypeSymbol)type).PointedAtTypeWithAnnotations : ((NamedTypeSymbol)type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0]).Type;
|
||
|
|
ImmutableArray<BoundExpression> initializers = inits.Initializers;
|
||
|
|
ArrayInitializerStyle arrayInitializerStyle = ShouldEmitBlockInitializerForStackAlloc(type2, initializers);
|
||
|
|
if (arrayInitializerStyle == ArrayInitializerStyle.Element)
|
||
|
|
{
|
||
|
|
EmitElementStackAllocInitializers(type2, initializers, includeConstants: true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ImmutableArray<byte> data = GetRawData(initializers);
|
||
|
|
if (data.All((byte datum) => datum == data[0]))
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitIntConstant((int)data[0]);
|
||
|
|
_builder.EmitIntConstant(data.Length);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Initblk, -3);
|
||
|
|
if (arrayInitializerStyle == ArrayInitializerStyle.Mixed)
|
||
|
|
{
|
||
|
|
EmitElementStackAllocInitializers(type2, initializers, includeConstants: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (SpecialTypeExtensions.SizeInBytes(type2.EnumUnderlyingTypeOrSelf().SpecialType) == 1)
|
||
|
|
{
|
||
|
|
IFieldReference fieldForData = _builder.module.GetFieldForData(data, (ushort)1, inits.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldsflda);
|
||
|
|
_builder.EmitToken((IReference)(object)fieldForData, inits.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitIntConstant(data.Length);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Cpblk, -3);
|
||
|
|
if (arrayInitializerStyle == ArrayInitializerStyle.Mixed)
|
||
|
|
{
|
||
|
|
EmitElementStackAllocInitializers(type2, initializers, includeConstants: false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitElementStackAllocInitializers(type2, initializers, includeConstants: true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private ArrayInitializerStyle ShouldEmitBlockInitializerForStackAlloc(TypeSymbol elementType, ImmutableArray<BoundExpression> inits)
|
||
|
|
{
|
||
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (((CommonPEModuleBuilder)_module).IsEncDelta)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Element;
|
||
|
|
}
|
||
|
|
if (SpecialTypeExtensions.IsBlittable(elementType.EnumUnderlyingTypeOrSelf().SpecialType))
|
||
|
|
{
|
||
|
|
int initCount = 0;
|
||
|
|
int constInits = 0;
|
||
|
|
StackAllocInitializerCount(inits, ref initCount, ref constInits);
|
||
|
|
if (initCount > 2)
|
||
|
|
{
|
||
|
|
if (initCount == constInits)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Block;
|
||
|
|
}
|
||
|
|
int num = Math.Max(3, initCount / 3);
|
||
|
|
if (constInits >= num)
|
||
|
|
{
|
||
|
|
return ArrayInitializerStyle.Mixed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ArrayInitializerStyle.Element;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void StackAllocInitializerCount(ImmutableArray<BoundExpression> inits, ref int initCount, ref int constInits)
|
||
|
|
{
|
||
|
|
if (inits.Length == 0)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = inits.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
initCount++;
|
||
|
|
if (current.ConstantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
constInits++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitElementStackAllocInitializers(TypeSymbol elementType, ImmutableArray<BoundExpression> inits, bool includeConstants)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
int num = 0;
|
||
|
|
int elementTypeSizeInBytes = SpecialTypeExtensions.SizeInBytes(elementType.EnumUnderlyingTypeOrSelf().SpecialType);
|
||
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = inits.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundExpression current = enumerator.Current;
|
||
|
|
if (includeConstants || current.ConstantValueOpt == (ConstantValue)null)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
EmitPointerElementAccess(current, elementType, elementTypeSizeInBytes, num);
|
||
|
|
EmitExpression(current, used: true);
|
||
|
|
EmitIndirectStore(elementType, current.Syntax);
|
||
|
|
}
|
||
|
|
num++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitPointerElementAccess(BoundExpression init, TypeSymbol elementType, int elementTypeSizeInBytes, int index)
|
||
|
|
{
|
||
|
|
if (index != 0)
|
||
|
|
{
|
||
|
|
if (elementTypeSizeInBytes == 1)
|
||
|
|
{
|
||
|
|
_builder.EmitIntConstant(index);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Add);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (index == 1)
|
||
|
|
{
|
||
|
|
EmitIntConstantOrSizeOf(init, elementType, elementTypeSizeInBytes);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Add);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_builder.EmitIntConstant(index);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Conv_i);
|
||
|
|
EmitIntConstantOrSizeOf(init, elementType, elementTypeSizeInBytes);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Mul);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Add);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitIntConstantOrSizeOf(BoundExpression init, TypeSymbol elementType, int elementTypeSizeInBytes)
|
||
|
|
{
|
||
|
|
if (elementTypeSizeInBytes == 0)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Sizeof);
|
||
|
|
EmitSymbolToken(elementType, init.Syntax);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitIntConstant(elementTypeSizeInBytes);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStatement(BoundStatement statement)
|
||
|
|
{
|
||
|
|
switch (statement.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.Block:
|
||
|
|
EmitBlock((BoundBlock)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.Scope:
|
||
|
|
EmitScope((BoundScope)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.SequencePoint:
|
||
|
|
EmitSequencePointStatement((BoundSequencePoint)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.SequencePointWithSpan:
|
||
|
|
EmitSequencePointStatement((BoundSequencePointWithSpan)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.SavePreviousSequencePoint:
|
||
|
|
EmitSavePreviousSequencePoint((BoundSavePreviousSequencePoint)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.RestorePreviousSequencePoint:
|
||
|
|
EmitRestorePreviousSequencePoint((BoundRestorePreviousSequencePoint)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.StepThroughSequencePoint:
|
||
|
|
EmitStepThroughSequencePoint((BoundStepThroughSequencePoint)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.ExpressionStatement:
|
||
|
|
EmitExpression(((BoundExpressionStatement)statement).Expression, used: false);
|
||
|
|
break;
|
||
|
|
case BoundKind.StatementList:
|
||
|
|
EmitStatementList((BoundStatementList)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.ReturnStatement:
|
||
|
|
EmitReturnStatement((BoundReturnStatement)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.GotoStatement:
|
||
|
|
EmitGotoStatement((BoundGotoStatement)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.LabelStatement:
|
||
|
|
EmitLabelStatement((BoundLabelStatement)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.ConditionalGoto:
|
||
|
|
EmitConditionalGoto((BoundConditionalGoto)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.ThrowStatement:
|
||
|
|
EmitThrowStatement((BoundThrowStatement)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.TryStatement:
|
||
|
|
EmitTryStatement((BoundTryStatement)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.SwitchDispatch:
|
||
|
|
EmitSwitchDispatch((BoundSwitchDispatch)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.StateMachineScope:
|
||
|
|
EmitStateMachineScope((BoundStateMachineScope)statement);
|
||
|
|
break;
|
||
|
|
case BoundKind.NoOpStatement:
|
||
|
|
EmitNoOpStatement((BoundNoOpStatement)statement);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)statement.Kind);
|
||
|
|
}
|
||
|
|
ReleaseExpressionTemps();
|
||
|
|
}
|
||
|
|
|
||
|
|
private int EmitStatementAndCountInstructions(BoundStatement statement)
|
||
|
|
{
|
||
|
|
int instructionsEmitted = _builder.InstructionsEmitted;
|
||
|
|
EmitStatement(statement);
|
||
|
|
return _builder.InstructionsEmitted - instructionsEmitted;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStatementList(BoundStatementList list)
|
||
|
|
{
|
||
|
|
int i = 0;
|
||
|
|
for (int length = list.Statements.Length; i < length; i++)
|
||
|
|
{
|
||
|
|
EmitStatement(list.Statements[i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitNoOpStatement(BoundNoOpStatement statement)
|
||
|
|
{
|
||
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
switch (statement.Flavor)
|
||
|
|
{
|
||
|
|
case NoOpStatementFlavor.Default:
|
||
|
|
if ((int)_ilEmitStyle == 0)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case NoOpStatementFlavor.AwaitYieldPoint:
|
||
|
|
if (_asyncYieldPoints == null)
|
||
|
|
{
|
||
|
|
_asyncYieldPoints = ArrayBuilder<int>.GetInstance();
|
||
|
|
_asyncResumePoints = ArrayBuilder<int>.GetInstance();
|
||
|
|
}
|
||
|
|
_asyncYieldPoints.Add(_builder.AllocateILMarker());
|
||
|
|
break;
|
||
|
|
case NoOpStatementFlavor.AwaitResumePoint:
|
||
|
|
_asyncResumePoints.Add(_builder.AllocateILMarker());
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)statement.Flavor);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitThrowStatement(BoundThrowStatement node)
|
||
|
|
{
|
||
|
|
EmitThrow(node.ExpressionOpt);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitThrow(BoundExpression thrown)
|
||
|
|
{
|
||
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001d: Invalid comparison between Unknown and I4
|
||
|
|
if (thrown != null)
|
||
|
|
{
|
||
|
|
EmitExpression(thrown, used: true);
|
||
|
|
TypeSymbol type = thrown.Type;
|
||
|
|
if ((object)type != null && (int)type.TypeKind == 11)
|
||
|
|
{
|
||
|
|
EmitBox(type, thrown.Syntax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
_builder.EmitThrow(thrown == null);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitConditionalGoto(BoundConditionalGoto boundConditionalGoto)
|
||
|
|
{
|
||
|
|
object dest = boundConditionalGoto.Label;
|
||
|
|
EmitCondBranch(boundConditionalGoto.Condition, ref dest, boundConditionalGoto.JumpIfTrue);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool CanPassToBrfalse(TypeSymbol ts)
|
||
|
|
{
|
||
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0015: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001a: Invalid comparison between Unknown and I4
|
||
|
|
if (ts.IsEnumType())
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
PrimitiveTypeCode primitiveTypeCode = ts.PrimitiveTypeCode;
|
||
|
|
if (primitiveTypeCode - 3 > 1)
|
||
|
|
{
|
||
|
|
if ((int)primitiveTypeCode == 18)
|
||
|
|
{
|
||
|
|
return ts.IsReferenceType;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static BoundExpression TryReduce(BoundBinaryOperator condition, ref bool sense)
|
||
|
|
{
|
||
|
|
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0076: Invalid comparison between Unknown and I4
|
||
|
|
BinaryOperatorKind binaryOperatorKind = condition.OperatorKind.Operator();
|
||
|
|
BoundExpression boundExpression = ((condition.Left.ConstantValueOpt != (ConstantValue)null) ? condition.Left : null);
|
||
|
|
BoundExpression boundExpression2;
|
||
|
|
if (boundExpression != null)
|
||
|
|
{
|
||
|
|
boundExpression2 = condition.Right;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
boundExpression = ((condition.Right.ConstantValueOpt != (ConstantValue)null) ? condition.Right : null);
|
||
|
|
if (boundExpression == null)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
boundExpression2 = condition.Left;
|
||
|
|
}
|
||
|
|
TypeSymbol type = boundExpression2.Type;
|
||
|
|
if (!CanPassToBrfalse(type))
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
bool num = (int)type.PrimitiveTypeCode == 0;
|
||
|
|
bool isDefaultValue = boundExpression.ConstantValueOpt.IsDefaultValue;
|
||
|
|
if (!num && !isDefaultValue)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
if (isDefaultValue)
|
||
|
|
{
|
||
|
|
sense = !sense;
|
||
|
|
}
|
||
|
|
if (binaryOperatorKind == BinaryOperatorKind.NotEqual)
|
||
|
|
{
|
||
|
|
sense = !sense;
|
||
|
|
}
|
||
|
|
return boundExpression2;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static ILOpCode CodeForJump(BoundBinaryOperator op, bool sense, out ILOpCode revOpCode)
|
||
|
|
{
|
||
|
|
int num;
|
||
|
|
switch (op.OperatorKind.Operator())
|
||
|
|
{
|
||
|
|
case BinaryOperatorKind.Equal:
|
||
|
|
revOpCode = ((!sense) ? ILOpCode.Beq : ILOpCode.Bne_un);
|
||
|
|
if (!sense)
|
||
|
|
{
|
||
|
|
return ILOpCode.Bne_un;
|
||
|
|
}
|
||
|
|
return ILOpCode.Beq;
|
||
|
|
case BinaryOperatorKind.NotEqual:
|
||
|
|
revOpCode = ((!sense) ? ILOpCode.Bne_un : ILOpCode.Beq);
|
||
|
|
if (!sense)
|
||
|
|
{
|
||
|
|
return ILOpCode.Beq;
|
||
|
|
}
|
||
|
|
return ILOpCode.Bne_un;
|
||
|
|
case BinaryOperatorKind.LessThan:
|
||
|
|
num = 0;
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.LessThanOrEqual:
|
||
|
|
num = 1;
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.GreaterThan:
|
||
|
|
num = 2;
|
||
|
|
break;
|
||
|
|
case BinaryOperatorKind.GreaterThanOrEqual:
|
||
|
|
num = 3;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)op.OperatorKind.Operator());
|
||
|
|
}
|
||
|
|
if (IsUnsignedBinaryOperator(op))
|
||
|
|
{
|
||
|
|
num += 8;
|
||
|
|
}
|
||
|
|
else if (IsFloat(op.OperatorKind))
|
||
|
|
{
|
||
|
|
num += 16;
|
||
|
|
}
|
||
|
|
int num2 = num;
|
||
|
|
if (!sense)
|
||
|
|
{
|
||
|
|
num += 4;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
num2 += 4;
|
||
|
|
}
|
||
|
|
revOpCode = s_condJumpOpCodes[num2];
|
||
|
|
return s_condJumpOpCodes[num];
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCondBranch(BoundExpression condition, ref object dest, bool sense)
|
||
|
|
{
|
||
|
|
_recursionDepth++;
|
||
|
|
if (_recursionDepth > 1)
|
||
|
|
{
|
||
|
|
StackGuard.EnsureSufficientExecutionStack(_recursionDepth);
|
||
|
|
EmitCondBranchCore(condition, ref dest, sense);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitCondBranchCoreWithStackGuard(condition, ref dest, sense);
|
||
|
|
}
|
||
|
|
_recursionDepth--;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCondBranchCoreWithStackGuard(BoundExpression condition, ref object dest, bool sense)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
EmitCondBranchCore(condition, ref dest, sense);
|
||
|
|
}
|
||
|
|
catch (InsufficientExecutionStackException)
|
||
|
|
{
|
||
|
|
_diagnostics.Add(ErrorCode.ERR_InsufficientStack, BoundTreeVisitor.CancelledByStackGuardException.GetTooLongOrComplexExpressionErrorLocation(condition));
|
||
|
|
throw new EmitCancelledException();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCondBranchCore(BoundExpression condition, ref object dest, bool sense)
|
||
|
|
{
|
||
|
|
BoundBinaryOperator boundBinaryOperator2 = default(BoundBinaryOperator);
|
||
|
|
ILOpCode iLOpCode;
|
||
|
|
while (true)
|
||
|
|
{
|
||
|
|
if (condition.ConstantValueOpt != (ConstantValue)null)
|
||
|
|
{
|
||
|
|
if (condition.ConstantValueOpt.IsDefaultValue != sense)
|
||
|
|
{
|
||
|
|
dest = dest ?? new object();
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, dest, ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
switch (condition.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.BinaryOperator:
|
||
|
|
{
|
||
|
|
BoundBinaryOperator boundBinaryOperator = (BoundBinaryOperator)condition;
|
||
|
|
BinaryOperatorKind binaryOperatorKind = boundBinaryOperator.OperatorKind.OperatorWithLogical();
|
||
|
|
if ((binaryOperatorKind == BinaryOperatorKind.LogicalAnd || binaryOperatorKind == BinaryOperatorKind.LogicalOr) ? true : false)
|
||
|
|
{
|
||
|
|
ArrayBuilder<(BoundExpression, StrongBox<object>, bool)> instance = ArrayBuilder<(BoundExpression, StrongBox<object>, bool)>.GetInstance();
|
||
|
|
StrongBox<object> strongBox = new StrongBox<object>(dest);
|
||
|
|
ArrayBuilderExtensions.Push<(BoundExpression, StrongBox<object>, bool)>(instance, ((BoundExpression)boundBinaryOperator, strongBox, sense));
|
||
|
|
(BoundExpression, StrongBox<object>, bool) tuple;
|
||
|
|
while (true)
|
||
|
|
{
|
||
|
|
tuple = ArrayBuilderExtensions.Pop<(BoundExpression, StrongBox<object>, bool)>(instance);
|
||
|
|
if (tuple.Item1 == null)
|
||
|
|
{
|
||
|
|
object value = tuple.Item2.Value;
|
||
|
|
if (value != null)
|
||
|
|
{
|
||
|
|
_builder.MarkLabel(value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
int num;
|
||
|
|
if (tuple.Item1.ConstantValueOpt == null)
|
||
|
|
{
|
||
|
|
boundBinaryOperator2 = tuple.Item1 as BoundBinaryOperator;
|
||
|
|
num = ((boundBinaryOperator2 != null) ? 1 : 0);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
num = 0;
|
||
|
|
}
|
||
|
|
bool flag = (byte)num != 0;
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
binaryOperatorKind = boundBinaryOperator2.OperatorKind.OperatorWithLogical();
|
||
|
|
bool flag2 = ((binaryOperatorKind == BinaryOperatorKind.LogicalAnd || binaryOperatorKind == BinaryOperatorKind.LogicalOr) ? true : false);
|
||
|
|
flag = flag2;
|
||
|
|
}
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
if ((boundBinaryOperator2.OperatorKind.OperatorWithLogical() == BinaryOperatorKind.LogicalOr) ? (!tuple.Item3) : tuple.Item3)
|
||
|
|
{
|
||
|
|
StrongBox<object> item = new StrongBox<object>();
|
||
|
|
ArrayBuilderExtensions.Push<(BoundExpression, StrongBox<object>, bool)>(instance, ((BoundExpression)null, item, true));
|
||
|
|
ArrayBuilderExtensions.Push<(BoundExpression, StrongBox<object>, bool)>(instance, (boundBinaryOperator2.Right, tuple.Item2, tuple.Item3));
|
||
|
|
ArrayBuilderExtensions.Push<(BoundExpression, StrongBox<object>, bool)>(instance, (boundBinaryOperator2.Left, item, !tuple.Item3));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ArrayBuilderExtensions.Push<(BoundExpression, StrongBox<object>, bool)>(instance, (boundBinaryOperator2.Right, tuple.Item2, tuple.Item3));
|
||
|
|
ArrayBuilderExtensions.Push<(BoundExpression, StrongBox<object>, bool)>(instance, (boundBinaryOperator2.Left, tuple.Item2, tuple.Item3));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (instance.Count == 0 && strongBox == tuple.Item2)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
EmitCondBranch(tuple.Item1, ref tuple.Item2.Value, tuple.Item3);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (instance.Count == 0)
|
||
|
|
{
|
||
|
|
dest = strongBox.Value;
|
||
|
|
instance.Free();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
condition = tuple.Item1;
|
||
|
|
sense = tuple.Item3;
|
||
|
|
dest = strongBox.Value;
|
||
|
|
instance.Free();
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
binaryOperatorKind = boundBinaryOperator.OperatorKind.OperatorWithLogical();
|
||
|
|
if (binaryOperatorKind <= BinaryOperatorKind.LessThan)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind <= BinaryOperatorKind.NotEqual)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.Equal && binaryOperatorKind != BinaryOperatorKind.NotEqual)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
BoundExpression boundExpression = TryReduce(boundBinaryOperator, ref sense);
|
||
|
|
if (boundExpression != null)
|
||
|
|
{
|
||
|
|
condition = boundExpression;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (binaryOperatorKind != BinaryOperatorKind.GreaterThan && binaryOperatorKind != BinaryOperatorKind.LessThan)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind > BinaryOperatorKind.LessThanOrEqual)
|
||
|
|
{
|
||
|
|
if (binaryOperatorKind == BinaryOperatorKind.LogicalAnd || binaryOperatorKind == BinaryOperatorKind.LogicalOr)
|
||
|
|
{
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/CodeGen/EmitStatement.cs", 496);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (binaryOperatorKind != BinaryOperatorKind.GreaterThanOrEqual && binaryOperatorKind != BinaryOperatorKind.LessThanOrEqual)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitExpression(boundBinaryOperator.Left, used: true);
|
||
|
|
EmitExpression(boundBinaryOperator.Right, used: true);
|
||
|
|
iLOpCode = CodeForJump(boundBinaryOperator, sense, out var revOpCode);
|
||
|
|
dest = dest ?? new object();
|
||
|
|
_builder.EmitBranch(iLOpCode, dest, revOpCode);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
case BoundKind.LoweredConditionalAccess:
|
||
|
|
{
|
||
|
|
BoundLoweredConditionalAccess boundLoweredConditionalAccess = (BoundLoweredConditionalAccess)condition;
|
||
|
|
BoundExpression receiver = boundLoweredConditionalAccess.Receiver;
|
||
|
|
if (!receiver.Type.IsReferenceType || LocalRewriter.CanChangeValueBetweenReads(receiver, localsMayBeAssignedOrCaptured: false) || (receiver.Kind == BoundKind.Local && IsStackLocal(((BoundLocal)receiver).LocalSymbol)))
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
BoundExpression? whenNullOpt = boundLoweredConditionalAccess.WhenNullOpt;
|
||
|
|
if (whenNullOpt != null && !whenNullOpt.IsDefaultValue())
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (sense)
|
||
|
|
{
|
||
|
|
object dest2 = null;
|
||
|
|
EmitCondBranch(receiver, ref dest2, sense: false);
|
||
|
|
EmitReceiverRef(receiver, Binder.AddressKind.ReadOnly);
|
||
|
|
EmitCondBranch(boundLoweredConditionalAccess.WhenNotNull, ref dest, sense: true);
|
||
|
|
if (dest2 != null)
|
||
|
|
{
|
||
|
|
_builder.MarkLabel(dest2);
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
EmitCondBranch(receiver, ref dest, sense: false);
|
||
|
|
EmitReceiverRef(receiver, Binder.AddressKind.ReadOnly);
|
||
|
|
condition = boundLoweredConditionalAccess.WhenNotNull;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
case BoundKind.UnaryOperator:
|
||
|
|
{
|
||
|
|
BoundUnaryOperator boundUnaryOperator = (BoundUnaryOperator)condition;
|
||
|
|
if (boundUnaryOperator.OperatorKind == UnaryOperatorKind.BoolLogicalNegation)
|
||
|
|
{
|
||
|
|
sense = !sense;
|
||
|
|
condition = boundUnaryOperator.Operand;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.IsOperator:
|
||
|
|
{
|
||
|
|
BoundIsOperator boundIsOperator = (BoundIsOperator)condition;
|
||
|
|
BoundExpression operand = boundIsOperator.Operand;
|
||
|
|
EmitExpression(operand, used: true);
|
||
|
|
if (!operand.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(operand.Type, operand.Syntax);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Isinst);
|
||
|
|
EmitSymbolToken(boundIsOperator.TargetType.Type, boundIsOperator.TargetType.Syntax);
|
||
|
|
iLOpCode = (sense ? ILOpCode.Brtrue : ILOpCode.Brfalse);
|
||
|
|
dest = dest ?? new object();
|
||
|
|
_builder.EmitBranch(iLOpCode, dest, ILOpCode.Nop);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
case BoundKind.Sequence:
|
||
|
|
{
|
||
|
|
BoundSequence sequence = (BoundSequence)condition;
|
||
|
|
EmitSequenceCondBranch(sequence, ref dest, sense);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
EmitExpression(condition, used: true);
|
||
|
|
TypeSymbol type = condition.Type;
|
||
|
|
if (type.IsReferenceType && !type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
EmitBox(type, condition.Syntax);
|
||
|
|
}
|
||
|
|
iLOpCode = (sense ? ILOpCode.Brtrue : ILOpCode.Brfalse);
|
||
|
|
dest = dest ?? new object();
|
||
|
|
_builder.EmitBranch(iLOpCode, dest, ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSequenceCondBranch(BoundSequence sequence, ref object dest, bool sense)
|
||
|
|
{
|
||
|
|
DefineLocals(sequence);
|
||
|
|
EmitSideEffects(sequence);
|
||
|
|
EmitCondBranch(sequence.Value, ref dest, sense);
|
||
|
|
FreeLocals(sequence);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLabelStatement(BoundLabelStatement boundLabelStatement)
|
||
|
|
{
|
||
|
|
_builder.MarkLabel((object)boundLabelStatement.Label);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitGotoStatement(BoundGotoStatement boundGotoStatement)
|
||
|
|
{
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, (object)boundGotoStatement.Label, ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsLastBlockInMethod(BoundBlock block)
|
||
|
|
{
|
||
|
|
if (_boundBody == block)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (_boundBody is BoundStatementList boundStatementList && boundStatementList.Statements.LastOrDefault() == block)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitBlock(BoundBlock block)
|
||
|
|
{
|
||
|
|
if (block.Instrumentation != null)
|
||
|
|
{
|
||
|
|
EmitInstrumentedBlock(block.Instrumentation, block);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitUninstrumentedBlock(block);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitInstrumentedBlock(BoundBlockInstrumentation instrumentation, BoundBlock block)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)0, (ITypeReference)null);
|
||
|
|
DefineLocal(instrumentation.Local, block.Syntax);
|
||
|
|
if (_emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
EmitHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
EmitStatement(instrumentation.Prologue);
|
||
|
|
_builder.OpenLocalScope((ScopeType)1, (ITypeReference)null);
|
||
|
|
_builder.OpenLocalScope((ScopeType)2, (ITypeReference)null);
|
||
|
|
EmitUninstrumentedBlock(block);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
_builder.OpenLocalScope((ScopeType)5, (ITypeReference)null);
|
||
|
|
if (_emitPdbSequencePoints)
|
||
|
|
{
|
||
|
|
EmitHiddenSequencePoint();
|
||
|
|
}
|
||
|
|
EmitStatement(instrumentation.Epilogue);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
FreeLocal(instrumentation.Local);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitUninstrumentedBlock(BoundBlock block)
|
||
|
|
{
|
||
|
|
bool flag = !block.Locals.IsEmpty;
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)0, (ITypeReference)null);
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = block.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current = enumerator.Current;
|
||
|
|
ImmutableArray<SyntaxReference> declaringSyntaxReferences = current.DeclaringSyntaxReferences;
|
||
|
|
DefineLocal(current, (SyntaxNode)(object)((!declaringSyntaxReferences.IsEmpty) ? ((CSharpSyntaxNode)(object)declaringSyntaxReferences[0].GetSyntax(default(CancellationToken))) : ((CSharpSyntaxNode)(object)block.Syntax)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitStatements(block.Statements);
|
||
|
|
if (_indirectReturnState == IndirectReturnState.Needed && IsLastBlockInMethod(block))
|
||
|
|
{
|
||
|
|
if (block.Instrumentation != null)
|
||
|
|
{
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, s_returnLabel, ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
HandleReturn();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = block.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current2 = enumerator.Current;
|
||
|
|
FreeLocal(current2);
|
||
|
|
}
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStatements(ImmutableArray<BoundStatement> statements)
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundStatement>.Enumerator enumerator = statements.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundStatement current = enumerator.Current;
|
||
|
|
EmitStatement(current);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitScope(BoundScope block)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)0, (ITypeReference)null);
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = block.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current = enumerator.Current;
|
||
|
|
if (!current.IsConst && !IsStackLocal(current))
|
||
|
|
{
|
||
|
|
_builder.AddLocalToScope(_builder.LocalSlotManager.GetLocal((ILocalSymbolInternal)(object)current));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitStatements(block.Statements);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStateMachineScope(BoundStateMachineScope scope)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)7, (ITypeReference)null);
|
||
|
|
ImmutableArray<StateMachineFieldSymbol>.Enumerator enumerator = scope.Fields.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
StateMachineFieldSymbol current = enumerator.Current;
|
||
|
|
if (current.SlotIndex >= 0)
|
||
|
|
{
|
||
|
|
_builder.DefineUserDefinedStateMachineHoistedLocal(current.SlotIndex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitStatement(scope.Statement);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool ShouldUseIndirectReturn()
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if ((int)_ilEmitStyle == 0 && _method.GenerateDebugInfo)
|
||
|
|
{
|
||
|
|
SyntaxNode methodBodySyntaxOpt = _methodBodySyntaxOpt;
|
||
|
|
if (methodBodySyntaxOpt != null && methodBodySyntaxOpt.IsKind(SyntaxKind.Block))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return _builder.InExceptionHandler;
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool CanHandleReturnLabel(BoundReturnStatement boundReturnStatement)
|
||
|
|
{
|
||
|
|
if (boundReturnStatement.WasCompilerGenerated)
|
||
|
|
{
|
||
|
|
if (!boundReturnStatement.Syntax.IsKind(SyntaxKind.Block))
|
||
|
|
{
|
||
|
|
MethodSymbol method = _method;
|
||
|
|
if ((object)method == null || !method.IsImplicitConstructor)
|
||
|
|
{
|
||
|
|
goto IL_003d;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return !_builder.InExceptionHandler;
|
||
|
|
}
|
||
|
|
goto IL_003d;
|
||
|
|
IL_003d:
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitReturnStatement(BoundReturnStatement boundReturnStatement)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0027: Invalid comparison between Unknown and I4
|
||
|
|
BoundExpression expressionOpt = boundReturnStatement.ExpressionOpt;
|
||
|
|
if ((int)boundReturnStatement.RefKind == 0)
|
||
|
|
{
|
||
|
|
EmitExpression(expressionOpt, used: true);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitAddress(expressionOpt, ((int)_method.RefKind == 3) ? Binder.AddressKind.ReadOnlyStrict : Binder.AddressKind.Writeable);
|
||
|
|
}
|
||
|
|
if (ShouldUseIndirectReturn())
|
||
|
|
{
|
||
|
|
if (expressionOpt != null)
|
||
|
|
{
|
||
|
|
_builder.EmitLocalStore(LazyReturnTemp);
|
||
|
|
}
|
||
|
|
if (_indirectReturnState != IndirectReturnState.Emitted && CanHandleReturnLabel(boundReturnStatement))
|
||
|
|
{
|
||
|
|
HandleReturn();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, s_returnLabel, ILOpCode.Nop);
|
||
|
|
if (_indirectReturnState == IndirectReturnState.NotNeeded)
|
||
|
|
{
|
||
|
|
_indirectReturnState = IndirectReturnState.Needed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (_indirectReturnState == IndirectReturnState.Needed && CanHandleReturnLabel(boundReturnStatement))
|
||
|
|
{
|
||
|
|
if (expressionOpt != null)
|
||
|
|
{
|
||
|
|
_builder.EmitLocalStore(LazyReturnTemp);
|
||
|
|
}
|
||
|
|
HandleReturn();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (expressionOpt != null)
|
||
|
|
{
|
||
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(expressionOpt.Type, boundReturnStatement.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
_builder.EmitRet(expressionOpt == null);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitTryStatement(BoundTryStatement statement, bool emitCatchesOnly = false)
|
||
|
|
{
|
||
|
|
bool num = !emitCatchesOnly && statement.CatchBlocks.Length > 0 && statement.FinallyBlockOpt != null;
|
||
|
|
_builder.OpenLocalScope((ScopeType)1, (ITypeReference)null);
|
||
|
|
_builder.OpenLocalScope((ScopeType)2, (ITypeReference)null);
|
||
|
|
_tryNestingLevel++;
|
||
|
|
if (num)
|
||
|
|
{
|
||
|
|
EmitTryStatement(statement, emitCatchesOnly: true);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitBlock(statement.TryBlock);
|
||
|
|
}
|
||
|
|
_tryNestingLevel--;
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
if (!num)
|
||
|
|
{
|
||
|
|
ImmutableArray<BoundCatchBlock>.Enumerator enumerator = statement.CatchBlocks.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
BoundCatchBlock current = enumerator.Current;
|
||
|
|
EmitCatchBlock(current);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (!emitCatchesOnly && statement.FinallyBlockOpt != null)
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)(statement.PreferFaultHandler ? 6 : 5), (ITypeReference)null);
|
||
|
|
EmitBlock(statement.FinallyBlockOpt);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
if (statement.PreferFaultHandler)
|
||
|
|
{
|
||
|
|
BoundBlock block = FinallyCloner.MakeFinallyClone(statement);
|
||
|
|
EmitBlock(block);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCatchBlock(BoundCatchBlock catchBlock)
|
||
|
|
{
|
||
|
|
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
object obj = null;
|
||
|
|
_builder.AdjustStack(1);
|
||
|
|
if (catchBlock.ExceptionFilterOpt == null)
|
||
|
|
{
|
||
|
|
ITypeReference obj2;
|
||
|
|
if ((object)catchBlock.ExceptionTypeOpt == null)
|
||
|
|
{
|
||
|
|
ITypeReference specialType = (ITypeReference)(object)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).GetSpecialType((SpecialType)1, catchBlock.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
obj2 = specialType;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
obj2 = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
ITypeReference val = obj2;
|
||
|
|
_builder.OpenLocalScope((ScopeType)3, val);
|
||
|
|
RecordAsyncCatchHandlerOffset(catchBlock);
|
||
|
|
if (_emitPdbSequencePoints && catchBlock.Syntax is CatchClauseSyntax catchClauseSyntax)
|
||
|
|
{
|
||
|
|
TextSpan span;
|
||
|
|
if (catchClauseSyntax.Declaration == null)
|
||
|
|
{
|
||
|
|
SyntaxToken catchKeyword = catchClauseSyntax.CatchKeyword;
|
||
|
|
span = ((SyntaxToken)(ref catchKeyword)).Span;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
int spanStart = ((SyntaxNode)catchClauseSyntax).SpanStart;
|
||
|
|
TextSpan span2 = ((SyntaxNode)catchClauseSyntax.Declaration).Span;
|
||
|
|
span = TextSpan.FromBounds(spanStart, ((TextSpan)(ref span2)).End);
|
||
|
|
}
|
||
|
|
EmitSequencePoint(catchBlock.SyntaxTree, span);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.OpenLocalScope((ScopeType)4, (ITypeReference)null);
|
||
|
|
RecordAsyncCatchHandlerOffset(catchBlock);
|
||
|
|
object obj3 = new object();
|
||
|
|
obj = new object();
|
||
|
|
if ((object)catchBlock.ExceptionTypeOpt != null)
|
||
|
|
{
|
||
|
|
ITypeReference val2 = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(catchBlock.ExceptionTypeOpt, catchBlock.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Isinst);
|
||
|
|
_builder.EmitToken((IReference)(object)val2, catchBlock.Syntax, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Dup);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, obj3, ILOpCode.Nop);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
_builder.EmitIntConstant(0);
|
||
|
|
_builder.EmitBranch(ILOpCode.Br, obj, ILOpCode.Nop);
|
||
|
|
}
|
||
|
|
_builder.MarkLabel(obj3);
|
||
|
|
}
|
||
|
|
ImmutableArray<LocalSymbol>.Enumerator enumerator = catchBlock.Locals.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LocalSymbol current = enumerator.Current;
|
||
|
|
ImmutableArray<SyntaxReference> declaringSyntaxReferences = current.DeclaringSyntaxReferences;
|
||
|
|
SyntaxNode syntaxNode = (SyntaxNode)(object)((!declaringSyntaxReferences.IsEmpty) ? ((CSharpSyntaxNode)(object)declaringSyntaxReferences[0].GetSyntax(default(CancellationToken))) : ((CSharpSyntaxNode)(object)catchBlock.Syntax));
|
||
|
|
DefineLocal(current, syntaxNode);
|
||
|
|
}
|
||
|
|
BoundExpression exceptionSourceOpt = catchBlock.ExceptionSourceOpt;
|
||
|
|
if (exceptionSourceOpt != null)
|
||
|
|
{
|
||
|
|
if (!exceptionSourceOpt.Type.IsVerifierReference())
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Unbox_any);
|
||
|
|
EmitSymbolToken(exceptionSourceOpt.Type, exceptionSourceOpt.Syntax);
|
||
|
|
}
|
||
|
|
BoundExpression boundExpression = exceptionSourceOpt;
|
||
|
|
while (boundExpression.Kind == BoundKind.Sequence)
|
||
|
|
{
|
||
|
|
BoundSequence boundSequence = (BoundSequence)boundExpression;
|
||
|
|
EmitSideEffects(boundSequence);
|
||
|
|
boundExpression = boundSequence.Value;
|
||
|
|
}
|
||
|
|
switch (boundExpression.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.Local:
|
||
|
|
{
|
||
|
|
BoundLocal boundLocal = (BoundLocal)boundExpression;
|
||
|
|
if (!IsStackLocal(boundLocal.LocalSymbol))
|
||
|
|
{
|
||
|
|
_builder.EmitLocalStore(GetLocal(boundLocal));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case BoundKind.FieldAccess:
|
||
|
|
{
|
||
|
|
BoundFieldAccess boundFieldAccess = (BoundFieldAccess)boundExpression;
|
||
|
|
if (boundFieldAccess.FieldSymbol is StateMachineFieldSymbol { SlotIndex: >=0 } stateMachineFieldSymbol)
|
||
|
|
{
|
||
|
|
_builder.DefineUserDefinedStateMachineHoistedLocal(stateMachineFieldSymbol.SlotIndex);
|
||
|
|
}
|
||
|
|
LocalDefinition val3 = AllocateTemp(boundExpression.Type, boundExpression.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val3);
|
||
|
|
EmitReceiverRef(boundFieldAccess.ReceiverOpt, Binder.AddressKind.Writeable);
|
||
|
|
_builder.EmitLocalLoad(val3);
|
||
|
|
FreeTemp(val3);
|
||
|
|
EmitFieldStore(boundFieldAccess, refAssign: false);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
throw ExceptionUtilities.UnexpectedValue((object)boundExpression.Kind);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
}
|
||
|
|
if (catchBlock.ExceptionFilterPrologueOpt != null)
|
||
|
|
{
|
||
|
|
EmitStatements(catchBlock.ExceptionFilterPrologueOpt.Statements);
|
||
|
|
}
|
||
|
|
if (catchBlock.ExceptionFilterOpt != null)
|
||
|
|
{
|
||
|
|
EmitCondExpr(catchBlock.ExceptionFilterOpt, sense: true);
|
||
|
|
_builder.EmitIntConstant(0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Cgt_un);
|
||
|
|
_builder.MarkLabel(obj);
|
||
|
|
_builder.MarkFilterConditionEnd();
|
||
|
|
_builder.EmitOpCode(ILOpCode.Pop);
|
||
|
|
}
|
||
|
|
EmitBlock(catchBlock.Body);
|
||
|
|
_builder.CloseLocalScope();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void RecordAsyncCatchHandlerOffset(BoundCatchBlock catchBlock)
|
||
|
|
{
|
||
|
|
if (catchBlock.IsSynthesizedAsyncCatchAll)
|
||
|
|
{
|
||
|
|
_asyncCatchHandlerOffset = _builder.AllocateILMarker();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSwitchDispatch(BoundSwitchDispatch dispatch)
|
||
|
|
{
|
||
|
|
EmitSwitchHeader(dispatch.Expression, dispatch.Cases.Select<(ConstantValue, LabelSymbol), KeyValuePair<ConstantValue, object>>(((ConstantValue value, LabelSymbol label) p) => new KeyValuePair<ConstantValue, object>(p.value, p.label)).ToArray(), dispatch.DefaultLabel, dispatch.LengthBasedStringSwitchDataOpt);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitSwitchHeader(BoundExpression expression, KeyValuePair<ConstantValue, object>[] switchCaseLabels, LabelSymbol fallThroughLabel, LengthBasedStringSwitchData lengthBasedSwitchStringJumpTableOpt)
|
||
|
|
{
|
||
|
|
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00f8: Invalid comparison between Unknown and I4
|
||
|
|
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
LocalDefinition val = null;
|
||
|
|
BoundSequence boundSequence = null;
|
||
|
|
if (expression.Kind == BoundKind.Sequence)
|
||
|
|
{
|
||
|
|
boundSequence = (BoundSequence)expression;
|
||
|
|
DefineLocals(boundSequence);
|
||
|
|
EmitSideEffects(boundSequence);
|
||
|
|
expression = boundSequence.Value;
|
||
|
|
}
|
||
|
|
if (expression.Kind == BoundKind.SequencePointExpression)
|
||
|
|
{
|
||
|
|
BoundSequencePointExpression boundSequencePointExpression = (BoundSequencePointExpression)expression;
|
||
|
|
EmitSequencePoint(boundSequencePointExpression);
|
||
|
|
expression = boundSequencePointExpression.Expression;
|
||
|
|
}
|
||
|
|
BoundKind kind = expression.Kind;
|
||
|
|
LocalOrParameter val2;
|
||
|
|
if (kind != BoundKind.Local)
|
||
|
|
{
|
||
|
|
if (kind == BoundKind.Parameter)
|
||
|
|
{
|
||
|
|
BoundParameter boundParameter = (BoundParameter)expression;
|
||
|
|
if ((int)boundParameter.ParameterSymbol.RefKind == 0)
|
||
|
|
{
|
||
|
|
val2 = LocalOrParameter.op_Implicit(ParameterSlot(boundParameter));
|
||
|
|
goto IL_00eb;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
LocalSymbol localSymbol = ((BoundLocal)expression).LocalSymbol;
|
||
|
|
if ((int)localSymbol.RefKind == 0 && !IsStackLocal(localSymbol))
|
||
|
|
{
|
||
|
|
val2 = LocalOrParameter.op_Implicit(GetLocal(localSymbol));
|
||
|
|
goto IL_00eb;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EmitExpression(expression, used: true);
|
||
|
|
val = AllocateTemp(expression.Type, expression.Syntax, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val);
|
||
|
|
val2 = LocalOrParameter.op_Implicit(val);
|
||
|
|
goto IL_00eb;
|
||
|
|
IL_00eb:
|
||
|
|
if ((int)expression.Type.SpecialType == 20 || expression.Type.IsSpanOrReadOnlySpanChar())
|
||
|
|
{
|
||
|
|
if (lengthBasedSwitchStringJumpTableOpt == null)
|
||
|
|
{
|
||
|
|
EmitStringSwitchJumpTable(switchCaseLabels, fallThroughLabel, val2, expression.Syntax, expression.Type);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitLengthBasedStringSwitchJumpTable(lengthBasedSwitchStringJumpTableOpt, fallThroughLabel, val2, expression.Syntax, expression.Type);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitIntegerSwitchJumpTable(switchCaseLabels, (object)fallThroughLabel, val2, expression.Type.EnumUnderlyingTypeOrSelf().PrimitiveTypeCode);
|
||
|
|
}
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
if (boundSequence != null)
|
||
|
|
{
|
||
|
|
FreeLocals(boundSequence);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitLengthBasedStringSwitchJumpTable(LengthBasedStringSwitchData lengthBasedSwitchData, LabelSymbol fallThroughLabel, LocalOrParameter keyTemp, SyntaxNode syntaxNode, TypeSymbol keyType)
|
||
|
|
{
|
||
|
|
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
bool flag = keyType.IsSpanChar();
|
||
|
|
bool flag2 = keyType.IsReadOnlySpanChar();
|
||
|
|
bool isSpanOrReadOnlySpan = flag || flag2;
|
||
|
|
IMethodReference indexerRef = GetIndexerRef(syntaxNode, keyType, flag2, isSpanOrReadOnlySpan);
|
||
|
|
IMethodReference lengthMethodRef = GetLengthMethodRef(syntaxNode, keyType, flag2, isSpanOrReadOnlySpan);
|
||
|
|
emitLengthDispatch(lengthBasedSwitchData, keyTemp, fallThroughLabel, syntaxNode);
|
||
|
|
emitCharDispatches(lengthBasedSwitchData, keyTemp, fallThroughLabel, syntaxNode);
|
||
|
|
emitFinalDispatches(lengthBasedSwitchData, keyTemp, keyType, fallThroughLabel, syntaxNode);
|
||
|
|
void emitCharDispatches(LengthBasedStringSwitchData lengthBasedSwitchInfo, LocalOrParameter val3, LabelSymbol labelSymbol, SyntaxNode val)
|
||
|
|
{
|
||
|
|
//IL_006c: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
NamedTypeSymbol specialType = Binder.GetSpecialType(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (SpecialType)8, val, _diagnostics);
|
||
|
|
LocalDefinition val2 = AllocateTemp(specialType, val, (LocalSlotConstraints)0);
|
||
|
|
ImmutableArray<LengthBasedStringSwitchData.CharJumpTable>.Enumerator enumerator = lengthBasedSwitchInfo.CharBasedJumpTables.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LengthBasedStringSwitchData.CharJumpTable current = enumerator.Current;
|
||
|
|
_builder.MarkLabel((object)current.Label);
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
_builder.EmitLoadAddress(val3);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitLoad(val3);
|
||
|
|
}
|
||
|
|
_builder.EmitIntConstant(current.SelectedCharPosition);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, -1);
|
||
|
|
emitMethodRef(indexerRef);
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
_builder.EmitOpCode(ILOpCode.Ldind_u2);
|
||
|
|
}
|
||
|
|
_builder.EmitLocalStore(val2);
|
||
|
|
_builder.EmitIntegerSwitchJumpTable(current.CharCaseLabels.Select<(char, LabelSymbol), KeyValuePair<ConstantValue, object>>(((char value, LabelSymbol label) p) => new KeyValuePair<ConstantValue, object>(ConstantValue.Create(p.value), p.label)).ToArray(), (object)labelSymbol, LocalOrParameter.op_Implicit(val2), specialType.PrimitiveTypeCode);
|
||
|
|
}
|
||
|
|
FreeTemp(val2);
|
||
|
|
}
|
||
|
|
void emitFinalDispatches(LengthBasedStringSwitchData lengthBasedSwitchInfo, LocalOrParameter key, TypeSymbol keyType2, LabelSymbol fallThroughLabel2, SyntaxNode syntaxNode2)
|
||
|
|
{
|
||
|
|
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
ImmutableArray<LengthBasedStringSwitchData.StringJumpTable>.Enumerator enumerator = lengthBasedSwitchInfo.StringBasedJumpTables.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
LengthBasedStringSwitchData.StringJumpTable current = enumerator.Current;
|
||
|
|
_builder.MarkLabel((object)current.Label);
|
||
|
|
EmitStringSwitchJumpTable(current.StringCaseLabels.Select<(string, LabelSymbol), KeyValuePair<ConstantValue, object>>(((string value, LabelSymbol label) p) => new KeyValuePair<ConstantValue, object>(ConstantValue.Create(p.value), p.label)).ToArray(), fallThroughLabel2, key, syntaxNode2, keyType2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void emitLengthDispatch(LengthBasedStringSwitchData lengthBasedSwitchInfo, LocalOrParameter val, LabelSymbol labelSymbol, SyntaxNode val2)
|
||
|
|
{
|
||
|
|
//IL_000f: 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)
|
||
|
|
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
if (!isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
_builder.EmitLoad(val);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brfalse, (object)(lengthBasedSwitchInfo.LengthBasedJumpTable.NullCaseLabel ?? labelSymbol), ILOpCode.Brtrue);
|
||
|
|
}
|
||
|
|
NamedTypeSymbol specialType = Binder.GetSpecialType(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (SpecialType)13, val2, _diagnostics);
|
||
|
|
LocalDefinition val3 = AllocateTemp(specialType, val2, (LocalSlotConstraints)0);
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
_builder.EmitLoadAddress(val);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitLoad(val);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
emitMethodRef(lengthMethodRef);
|
||
|
|
_builder.EmitLocalStore(val3);
|
||
|
|
_builder.EmitIntegerSwitchJumpTable(lengthBasedSwitchInfo.LengthBasedJumpTable.LengthCaseLabels.Select<(int, LabelSymbol), KeyValuePair<ConstantValue, object>>(((int value, LabelSymbol label) p) => new KeyValuePair<ConstantValue, object>(ConstantValue.Create(p.value), p.label)).ToArray(), (object)labelSymbol, LocalOrParameter.op_Implicit(val3), specialType.PrimitiveTypeCode);
|
||
|
|
FreeTemp(val3);
|
||
|
|
}
|
||
|
|
void emitMethodRef(IMethodReference val)
|
||
|
|
{
|
||
|
|
DiagnosticBag instance = DiagnosticBag.GetInstance();
|
||
|
|
_builder.EmitToken((ISignature)(object)val, (SyntaxNode)null, instance);
|
||
|
|
instance.Free();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStringSwitchJumpTable(KeyValuePair<ConstantValue, object>[] switchCaseLabels, LabelSymbol fallThroughLabel, LocalOrParameter key, SyntaxNode syntaxNode, TypeSymbol keyType)
|
||
|
|
{
|
||
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0251: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0258: Expected O, but got Unknown
|
||
|
|
//IL_0261: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_027e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0284: Expected O, but got Unknown
|
||
|
|
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
bool flag = keyType.IsSpanChar();
|
||
|
|
bool flag2 = keyType.IsReadOnlySpanChar();
|
||
|
|
bool isSpanOrReadOnlySpan = flag || flag2;
|
||
|
|
LocalDefinition val = null;
|
||
|
|
if (SwitchStringJumpTableEmitter.ShouldGenerateHashTableSwitch(switchCaseLabels.Length))
|
||
|
|
{
|
||
|
|
IReference method = (IReference)(object)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).GetPrivateImplClass(syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag).GetMethod((!isSpanOrReadOnlySpan) ? "ComputeStringHash" : (flag2 ? "ComputeReadOnlySpanHash" : "ComputeSpanHash"));
|
||
|
|
if (method != null)
|
||
|
|
{
|
||
|
|
_builder.EmitLoad(key);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
_builder.EmitToken(method, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
NamedTypeSymbol specialType = Binder.GetSpecialType(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (SpecialType)14, syntaxNode, _diagnostics);
|
||
|
|
val = AllocateTemp(specialType, syntaxNode, (LocalSlotConstraints)0);
|
||
|
|
_builder.EmitLocalStore(val);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
IMethodReference stringEqualityMethodRef = null;
|
||
|
|
IMethodReference sequenceEqualsMethodRef = null;
|
||
|
|
IMethodReference asSpanMethodRef = null;
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
MethodSymbol methodSymbol = ((MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)(flag2 ? 474 : 473), _diagnostics, null, syntaxNode)).Construct(Binder.GetSpecialType(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (SpecialType)8, syntaxNode, _diagnostics));
|
||
|
|
sequenceEqualsMethodRef = _module.Translate(methodSymbol, null, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
MethodSymbol methodSymbol2 = (MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)475, _diagnostics, null, syntaxNode);
|
||
|
|
asSpanMethodRef = _module.Translate(methodSymbol2, null, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
MethodSymbol methodSymbol3 = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetSpecialTypeMember((SpecialMember)9) as MethodSymbol;
|
||
|
|
stringEqualityMethodRef = _module.Translate(methodSymbol3, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
IMethodReference lengthMethodRef = GetLengthMethodRef(syntaxNode, keyType, flag2, isSpanOrReadOnlySpan);
|
||
|
|
EmitStringCompareAndBranch val2 = (EmitStringCompareAndBranch)delegate(LocalOrParameter keyArg, ConstantValue stringConstant, object targetLabel)
|
||
|
|
{
|
||
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a1: 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)
|
||
|
|
if (stringConstant == ConstantValue.Null)
|
||
|
|
{
|
||
|
|
_builder.EmitLoad(keyArg);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brfalse, targetLabel, ILOpCode.Brtrue);
|
||
|
|
}
|
||
|
|
else if (stringConstant.StringValue.Length == 0 && lengthMethodRef != null)
|
||
|
|
{
|
||
|
|
object obj3 = new object();
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
_builder.EmitLoadAddress(keyArg);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
_builder.EmitLoad(keyArg);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brfalse, obj3, ILOpCode.Brtrue);
|
||
|
|
_builder.EmitLoad(keyArg);
|
||
|
|
}
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
DiagnosticBag instance = DiagnosticBag.GetInstance();
|
||
|
|
_builder.EmitToken((ISignature)(object)lengthMethodRef, (SyntaxNode)null, instance);
|
||
|
|
instance.Free();
|
||
|
|
_builder.EmitBranch(ILOpCode.Brfalse, targetLabel, ILOpCode.Brtrue);
|
||
|
|
_builder.MarkLabel(obj3);
|
||
|
|
}
|
||
|
|
else if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
EmitCharCompareAndBranch(key, syntaxNode, stringConstant, targetLabel, (IReference)(object)sequenceEqualsMethodRef, (IReference)(object)asSpanMethodRef);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
EmitStringCompareAndBranch(key, syntaxNode, stringConstant, targetLabel, (IReference)(object)stringEqualityMethodRef);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
ILBuilder builder = _builder;
|
||
|
|
LocalOrParameter val3 = key;
|
||
|
|
LocalDefinition obj = val;
|
||
|
|
object obj2 = _003C_003EO._003C1_003E__ComputeStringHash;
|
||
|
|
if (obj2 == null)
|
||
|
|
{
|
||
|
|
GetStringHashCode val4 = SynthesizedStringSwitchHashMethod.ComputeStringHash;
|
||
|
|
_003C_003EO._003C1_003E__ComputeStringHash = val4;
|
||
|
|
obj2 = (object)val4;
|
||
|
|
}
|
||
|
|
builder.EmitStringSwitchJumpTable(switchCaseLabels, (object)fallThroughLabel, val3, obj, val2, (GetStringHashCode)obj2);
|
||
|
|
if (val != null)
|
||
|
|
{
|
||
|
|
FreeTemp(val);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private IMethodReference? GetLengthMethodRef(SyntaxNode syntaxNode, TypeSymbol keyType, bool isReadOnlySpan, bool isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
MethodSymbol methodSymbol = ((MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)(isReadOnlySpan ? 407 : 401), _diagnostics, null, syntaxNode)).AsMember((NamedTypeSymbol)keyType);
|
||
|
|
return _module.Translate(methodSymbol, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
MethodSymbol methodSymbol2 = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetSpecialTypeMember((SpecialMember)11) as MethodSymbol;
|
||
|
|
if (methodSymbol2 != null && !methodSymbol2.HasUseSiteError)
|
||
|
|
{
|
||
|
|
return _module.Translate(methodSymbol2, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private IMethodReference? GetIndexerRef(SyntaxNode syntaxNode, TypeSymbol keyType, bool isReadOnlySpan, bool isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
if (isSpanOrReadOnlySpan)
|
||
|
|
{
|
||
|
|
MethodSymbol methodSymbol = (MethodSymbol)Binder.GetWellKnownTypeMember(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation, (WellKnownMember)(isReadOnlySpan ? 406 : 400), _diagnostics, null, syntaxNode);
|
||
|
|
if (methodSymbol != null && !methodSymbol.HasUseSiteError)
|
||
|
|
{
|
||
|
|
MethodSymbol methodSymbol2 = methodSymbol.AsMember((NamedTypeSymbol)keyType);
|
||
|
|
return _module.Translate(methodSymbol2, null, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
MethodSymbol methodSymbol3 = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Compilation.GetSpecialTypeMember((SpecialMember)12) as MethodSymbol;
|
||
|
|
if (methodSymbol3 != null && !methodSymbol3.HasUseSiteError)
|
||
|
|
{
|
||
|
|
return _module.Translate(methodSymbol3, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitStringCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxNode, ConstantValue stringConstant, object targetLabel, IReference stringEqualityMethodRef)
|
||
|
|
{
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
_builder.EmitLoad(key);
|
||
|
|
_builder.EmitConstantValue(stringConstant);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, -1);
|
||
|
|
_builder.EmitToken(stringEqualityMethodRef, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void EmitCharCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxNode, ConstantValue stringConstant, object targetLabel, IReference sequenceEqualsRef, IReference asSpanRef)
|
||
|
|
{
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
_builder.EmitLoad(key);
|
||
|
|
_builder.EmitConstantValue(stringConstant);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, 0);
|
||
|
|
_builder.EmitToken(asSpanRef, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitOpCode(ILOpCode.Call, -1);
|
||
|
|
_builder.EmitToken(sequenceEqualsRef, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag, (RawTokenEncoding)0);
|
||
|
|
_builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition GetLocal(BoundLocal localExpression)
|
||
|
|
{
|
||
|
|
LocalSymbol localSymbol = localExpression.LocalSymbol;
|
||
|
|
return GetLocal(localSymbol);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition GetLocal(LocalSymbol symbol)
|
||
|
|
{
|
||
|
|
return _builder.LocalSlotManager.GetLocal((ILocalSymbolInternal)(object)symbol);
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition DefineLocal(LocalSymbol local, SyntaxNode syntaxNode)
|
||
|
|
{
|
||
|
|
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0096: Expected O, but got Unknown
|
||
|
|
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_01a7: Invalid comparison between Unknown and I4
|
||
|
|
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_01cf: Invalid comparison between Unknown and I4
|
||
|
|
ImmutableArray<bool> immutableArray = ((!local.IsCompilerGenerated && local.Type.ContainsDynamic()) ? CSharpCompilation.DynamicTransformsEncoder.Encode(local.Type, (RefKind)0, 0) : ImmutableArray<bool>.Empty);
|
||
|
|
ImmutableArray<string> immutableArray2 = ((!local.IsCompilerGenerated && local.Type.ContainsTupleNames()) ? CSharpCompilation.TupleNamesEncoder.Encode(local.Type) : ImmutableArray<string>.Empty);
|
||
|
|
if (local.IsConst)
|
||
|
|
{
|
||
|
|
MetadataConstant val = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).CreateConstant(local.Type, local.ConstantValue, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
LocalConstantDefinition val2 = new LocalConstantDefinition(local.Name, local.GetFirstLocationOrNone(), val, immutableArray, immutableArray2);
|
||
|
|
_builder.AddLocalConstantToScope(val2);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
if (IsStackLocal(local))
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
LocalSlotConstraints val3;
|
||
|
|
ITypeReference val4;
|
||
|
|
if (local.DeclarationKind == LocalDeclarationKind.FixedVariable && local.IsPinned)
|
||
|
|
{
|
||
|
|
val3 = (LocalSlotConstraints)3;
|
||
|
|
TypeSymbol pointedAtType = ((PointerTypeSymbol)local.Type).PointedAtType;
|
||
|
|
ITypeReference obj;
|
||
|
|
if (!pointedAtType.IsVoidType())
|
||
|
|
{
|
||
|
|
obj = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(pointedAtType, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ITypeReference specialType = (ITypeReference)(object)((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).GetSpecialType((SpecialType)21, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
obj = specialType;
|
||
|
|
}
|
||
|
|
val4 = obj;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
val3 = (LocalSlotConstraints)((local.IsPinned ? 2 : 0) | (((int)local.RefKind != 0) ? 1 : 0));
|
||
|
|
val4 = ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(local.Type, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
}
|
||
|
|
((CommonPEModuleBuilder)_module).GetFakeSymbolTokenForIL((IReference)(object)val4, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag);
|
||
|
|
LocalDebugId localId;
|
||
|
|
string localDebugName = GetLocalDebugName((ILocalSymbolInternal)(object)local, out localId);
|
||
|
|
LocalDefinition val5 = _builder.LocalSlotManager.DeclareLocal(val4, (ILocalSymbolInternal)(object)local, localDebugName, local.SynthesizedKind, localId, SynthesizedLocalKindExtensions.PdbAttributes(local.SynthesizedKind), val3, immutableArray, immutableArray2, SynthesizedLocalKindExtensions.IsSlotReusable(local.SynthesizedKind, (int)_ilEmitStyle != 2));
|
||
|
|
bool flag = val5.Name != null;
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
bool flag2 = (int)local.SynthesizedKind == 0;
|
||
|
|
if (flag2)
|
||
|
|
{
|
||
|
|
bool flag3;
|
||
|
|
switch (local.ScopeDesignatorOpt?.Kind())
|
||
|
|
{
|
||
|
|
case SyntaxKind.SwitchSection:
|
||
|
|
case SyntaxKind.SwitchExpressionArm:
|
||
|
|
flag3 = true;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
flag3 = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
flag2 = flag3;
|
||
|
|
}
|
||
|
|
flag = !flag2;
|
||
|
|
}
|
||
|
|
if (flag)
|
||
|
|
{
|
||
|
|
_builder.AddLocalToScope(val5);
|
||
|
|
}
|
||
|
|
return val5;
|
||
|
|
}
|
||
|
|
|
||
|
|
private string GetLocalDebugName(ILocalSymbolInternal local, out LocalDebugId localId)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_002c: Invalid comparison between Unknown and I4
|
||
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_005d: 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)
|
||
|
|
//IL_006d: 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)
|
||
|
|
localId = LocalDebugId.None;
|
||
|
|
if (local.IsImportedFromMetadata)
|
||
|
|
{
|
||
|
|
return ((ISymbolInternal)local).Name;
|
||
|
|
}
|
||
|
|
SynthesizedLocalKind synthesizedKind = local.SynthesizedKind;
|
||
|
|
if (!SynthesizedLocalKindExtensions.IsLongLived(synthesizedKind) || (int)synthesizedKind == 34)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
if ((int)_ilEmitStyle == 0)
|
||
|
|
{
|
||
|
|
SyntaxNode declaratorSyntax = local.GetDeclaratorSyntax();
|
||
|
|
int num = _method.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(declaratorSyntax), declaratorSyntax.SyntaxTree);
|
||
|
|
int num2 = _synthesizedLocalOrdinals.AssignLocalOrdinal(synthesizedKind, num);
|
||
|
|
localId = new LocalDebugId(num, num2);
|
||
|
|
}
|
||
|
|
return ((ISymbolInternal)local).Name ?? GeneratedNames.MakeSynthesizedLocalName(synthesizedKind, ref _uniqueNameId);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool IsSlotReusable(LocalSymbol local)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_000d: Invalid comparison between Unknown and I4
|
||
|
|
return SynthesizedLocalKindExtensions.IsSlotReusable(local.SynthesizedKind, (int)_ilEmitStyle != 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FreeLocal(LocalSymbol local)
|
||
|
|
{
|
||
|
|
if (local.Name == null && IsSlotReusable(local) && !IsStackLocal(local))
|
||
|
|
{
|
||
|
|
_builder.LocalSlotManager.FreeLocal((ILocalSymbolInternal)(object)local);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private LocalDefinition AllocateTemp(TypeSymbol type, SyntaxNode syntaxNode, LocalSlotConstraints slotConstraints = (LocalSlotConstraints)0)
|
||
|
|
{
|
||
|
|
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
return _builder.LocalSlotManager.AllocateSlot(((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)_module).Translate(type, syntaxNode, ((BindingDiagnosticBag)_diagnostics).DiagnosticBag), slotConstraints, default(ImmutableArray<bool>), default(ImmutableArray<string>));
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FreeTemp(LocalDefinition temp)
|
||
|
|
{
|
||
|
|
_builder.LocalSlotManager.FreeSlot(temp);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FreeOptTemp(LocalDefinition temp)
|
||
|
|
{
|
||
|
|
if (temp != null)
|
||
|
|
{
|
||
|
|
FreeTemp(temp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|