コード例 #1
0
 internal void EmitLoad(LocalOrParameter localOrParameter)
 {
     if (localOrParameter.Local != null)
     {
         EmitLocalLoad(localOrParameter.Local);
     }
     else
     {
         EmitLoadArgumentOpcode(localOrParameter.ParameterIndex);
     }
 }
コード例 #2
0
        internal SwitchIntegralJumpTableEmitter(
            ILBuilder builder,
            KeyValuePair <ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            Cci.PrimitiveTypeCode keyTypeCode,
            LocalOrParameter key)
        {
            _builder          = builder;
            _key              = key;
            _keyTypeCode      = keyTypeCode;
            _fallThroughLabel = fallThroughLabel;

            // Sort the switch case labels, see comments below for more details.
            Debug.Assert(caseLabels.Length > 0);
            Array.Sort(caseLabels, CompareIntegralSwitchLabels);
            _sortedCaseLabels = ImmutableArray.Create(caseLabels);
        }
コード例 #3
0
        internal void EmitIntegerSwitchJumpTable(
            KeyValuePair <ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            LocalOrParameter key,
            Cci.PrimitiveTypeCode keyTypeCode)
        {
            Debug.Assert(caseLabels.Length > 0);
            Debug.Assert(keyTypeCode != Cci.PrimitiveTypeCode.String);

            // CONSIDER: SwitchIntegralJumpTableEmitter will modify the caseLabels array by sorting it.
            // CONSIDER: Currently, only purpose of creating this caseLabels array is for Emitting the jump table.
            // CONSIDER: If this requirement changes, we may want to pass in ArrayBuilder<KeyValuePair<ConstantValue, object>> instead.

            var emitter = new SwitchIntegralJumpTableEmitter(this, caseLabels, fallThroughLabel, keyTypeCode, key);

            emitter.EmitJumpTable();
        }
コード例 #4
0
        internal SwitchIntegralJumpTableEmitter(
            ILBuilder builder,
            KeyValuePair<ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            Cci.PrimitiveTypeCode keyTypeCode,
            LocalOrParameter key)
        {
            this.builder = builder;
            this.key = key;
            this.keyTypeCode = keyTypeCode;
            this.fallThroughLabel = fallThroughLabel;

            // Sort the switch case labels, see comments below for more details.
            Debug.Assert(caseLabels.Length > 0);
            Array.Sort(caseLabels, CompareIntegralSwitchLabels);
            sortedCaseLabels = ImmutableArray.Create(caseLabels);
        }
コード例 #5
0
        internal SwitchStringJumpTableEmitter(
            ILBuilder builder,
            LocalOrParameter key,
            KeyValuePair<ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            LocalDefinition keyHash,
            EmitStringCompareAndBranch emitStringCondBranchDelegate,
            GetStringHashCode computeStringHashcodeDelegate)
        {
            Debug.Assert(caseLabels.Length > 0);
            Debug.Assert(emitStringCondBranchDelegate != null);

            _builder = builder;
            _key = key;
            _caseLabels = caseLabels;
            _fallThroughLabel = fallThroughLabel;
            _keyHash = keyHash;
            _emitStringCondBranchDelegate = emitStringCondBranchDelegate;
            _computeStringHashcodeDelegate = computeStringHashcodeDelegate;
        }
コード例 #6
0
        internal SwitchStringJumpTableEmitter(
            ILBuilder builder,
            LocalOrParameter key,
            KeyValuePair <ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            LocalDefinition?keyHash,
            EmitStringCompareAndBranch emitStringCondBranchDelegate,
            GetStringHashCode computeStringHashcodeDelegate)
        {
            Debug.Assert(caseLabels.Length > 0);
            RoslynDebug.Assert(emitStringCondBranchDelegate != null);

            _builder                       = builder;
            _key                           = key;
            _caseLabels                    = caseLabels;
            _fallThroughLabel              = fallThroughLabel;
            _keyHash                       = keyHash;
            _emitStringCondBranchDelegate  = emitStringCondBranchDelegate;
            _computeStringHashcodeDelegate = computeStringHashcodeDelegate;
        }
コード例 #7
0
        internal void EmitStringSwitchJumpTable(
            KeyValuePair <ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            LocalOrParameter key,
            LocalDefinition?keyHash,
            SwitchStringJumpTableEmitter.EmitStringCompareAndBranch emitStringCondBranchDelegate,
            SwitchStringJumpTableEmitter.GetStringHashCode computeStringHashcodeDelegate)
        {
            Debug.Assert(caseLabels.Length > 0);

            var emitter = new SwitchStringJumpTableEmitter(
                this,
                key,
                caseLabels,
                fallThroughLabel,
                keyHash,
                emitStringCondBranchDelegate,
                computeStringHashcodeDelegate);

            emitter.EmitJumpTable();
        }
コード例 #8
0
ファイル: EmitStatement.cs プロジェクト: jkotas/roslyn
        /// <summary>
        /// Delegate to emit string compare call and conditional branch based on the compare result.
        /// </summary>
        /// <param name="key">Key to compare</param>
        /// <param name="syntaxNode">Node for diagnostics.</param>
        /// <param name="stringConstant">Case constant to compare the key against</param>
        /// <param name="targetLabel">Target label to branch to if key = stringConstant</param>
        /// <param name="stringEqualityMethodRef">String equality method</param>
        private void EmitStringCompareAndBranch(LocalOrParameter key, SyntaxNode syntaxNode, ConstantValue stringConstant, object targetLabel, Microsoft.Cci.IReference stringEqualityMethodRef)
        {
            // Emit compare and branch:

            // if (key == stringConstant)
            //      goto targetLabel;

            Debug.Assert(stringEqualityMethodRef != null);

#if DEBUG
            var assertDiagnostics = DiagnosticBag.GetInstance();
            Debug.Assert(stringEqualityMethodRef == _module.Translate((MethodSymbol)_module.Compilation.GetSpecialTypeMember(SpecialMember.System_String__op_Equality), (CSharpSyntaxNode)syntaxNode, assertDiagnostics));
            assertDiagnostics.Free();
#endif

            // static bool String.Equals(string a, string b)
            // pop 2 (a, b)
            // push 1 (bool return value)

            // stackAdjustment = (pushCount - popCount) = -1

            _builder.EmitLoad(key);
            _builder.EmitConstantValue(stringConstant);
            _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: -1);
            _builder.EmitToken(stringEqualityMethodRef, syntaxNode, _diagnostics);

            // Branch to targetLabel if String.Equals returned true.
            _builder.EmitBranch(ILOpCode.Brtrue, targetLabel, ILOpCode.Brfalse);
        }
コード例 #9
0
ファイル: EmitStatement.cs プロジェクト: jkotas/roslyn
        private void EmitStringSwitchJumpTable(
            BoundSwitchStatement switchStatement,
            KeyValuePair<ConstantValue, object>[] switchCaseLabels,
            LabelSymbol fallThroughLabel,
            LocalOrParameter key,
            SyntaxNode syntaxNode)
        {
            LocalDefinition keyHash = null;

            // Condition is necessary, but not sufficient (e.g. might be missing a special or well-known member).
            if (SwitchStringJumpTableEmitter.ShouldGenerateHashTableSwitch(_module, switchCaseLabels.Length))
            {
                Debug.Assert(_module.SupportsPrivateImplClass);

                var privateImplClass = _module.GetPrivateImplClass(syntaxNode, _diagnostics);
                Cci.IReference stringHashMethodRef = privateImplClass.GetMethod(PrivateImplementationDetails.SynthesizedStringHashFunctionName);

                // Heuristics and well-known member availability determine the existence
                // of this helper.  Rather than reproduce that (language-specific) logic here,
                // we simply check for the information we really want - whether the helper is
                // available.
                if (stringHashMethodRef != null)
                {
                    // static uint ComputeStringHash(string s)
                    // pop 1 (s)
                    // push 1 (uint return value)
                    // stackAdjustment = (pushCount - popCount) = 0

                    _builder.EmitLoad(key);
                    _builder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0);
                    _builder.EmitToken(stringHashMethodRef, syntaxNode, _diagnostics);

                    var UInt32Type = _module.Compilation.GetSpecialType(SpecialType.System_UInt32);
                    keyHash = AllocateTemp(UInt32Type, syntaxNode);

                    _builder.EmitLocalStore(keyHash);
                }
            }

            Cci.IReference stringEqualityMethodRef = _module.Translate(switchStatement.StringEquality, syntaxNode, _diagnostics);

            Cci.IMethodReference stringLengthRef = null;
            var stringLengthMethod = _module.Compilation.GetSpecialTypeMember(SpecialMember.System_String__Length) as MethodSymbol;
            if (stringLengthMethod != null && !stringLengthMethod.HasUseSiteError)
            {
                stringLengthRef = _module.Translate(stringLengthMethod, syntaxNode, _diagnostics);
            }

            SwitchStringJumpTableEmitter.EmitStringCompareAndBranch emitStringCondBranchDelegate =
                (keyArg, stringConstant, targetLabel) =>
                {
                    if (stringConstant == ConstantValue.Null)
                    {
                        // if (key == null)
                        //      goto targetLabel
                        _builder.EmitLoad(keyArg);
                        _builder.EmitBranch(ILOpCode.Brfalse, targetLabel, ILOpCode.Brtrue);
                    }
                    else if (stringConstant.StringValue.Length == 0 && stringLengthRef != null)
                    {
                        // if (key != null && key.Length == 0)
                        //      goto targetLabel

                        object skipToNext = new object();
                        _builder.EmitLoad(keyArg);
                        _builder.EmitBranch(ILOpCode.Brfalse, skipToNext, ILOpCode.Brtrue);

                        _builder.EmitLoad(keyArg);
                        // Stack: key --> length
                        _builder.EmitOpCode(ILOpCode.Call, 0);
                        var diag = DiagnosticBag.GetInstance();
                        _builder.EmitToken(stringLengthRef, null, diag);
                        Debug.Assert(diag.IsEmptyWithoutResolution);
                        diag.Free();

                        _builder.EmitBranch(ILOpCode.Brfalse, targetLabel, ILOpCode.Brtrue);
                        _builder.MarkLabel(skipToNext);
                    }
                    else
                    {
                        this.EmitStringCompareAndBranch(key, syntaxNode, stringConstant, targetLabel, stringEqualityMethodRef);
                    }
                };

            _builder.EmitStringSwitchJumpTable(
                caseLabels: switchCaseLabels,
                fallThroughLabel: fallThroughLabel,
                key: key,
                keyHash: keyHash,
                emitStringCondBranchDelegate: emitStringCondBranchDelegate,
                computeStringHashcodeDelegate: SynthesizedStringSwitchHashMethod.ComputeStringHash);

            if (keyHash != null)
            {
                FreeTemp(keyHash);
            }
        }
コード例 #10
0
ファイル: ILBuilderEmit.cs プロジェクト: kangkot/roslyn
 internal void EmitLoad(LocalOrParameter localOrParameter)
 {
     if (localOrParameter.Local != null)
     {
         EmitLocalLoad(localOrParameter.Local);
     }
     else
     {
         EmitLoadArgumentOpcode(localOrParameter.ParameterIndex);
     }
 }
コード例 #11
0
ファイル: ILBuilderEmit.cs プロジェクト: kangkot/roslyn
        /// <summary>
        /// Primary method for emitting integer switch jump table.
        /// </summary>
        /// <param name="caseLabels">switch case labels</param>
        /// <param name="fallThroughLabel">fall through label for the jump table.</param>
        /// <param name="key">Local or parameter holding the value to switch on.
        /// This value has already been loaded onto the execution stack.
        /// </param>
        /// <param name="keyTypeCode">Primitive type code of switch key.</param>
        internal void EmitIntegerSwitchJumpTable(
            KeyValuePair<ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            LocalOrParameter key,
            Cci.PrimitiveTypeCode keyTypeCode)
        {
            Debug.Assert(caseLabels.Length > 0);
            Debug.Assert(keyTypeCode != Cci.PrimitiveTypeCode.String);

            // CONSIDER: SwitchIntegralJumpTableEmitter will modify the caseLabels array by sorting it.
            // CONSIDER: Currently, only purpose of creating this caseLabels array is for Emitting the jump table.
            // CONSIDER: If this requirement changes, we may want to pass in ArrayBuilder<KeyValuePair<ConstantValue, object>> instead.

            var emitter = new SwitchIntegralJumpTableEmitter(this, caseLabels, fallThroughLabel, keyTypeCode, key);
            emitter.EmitJumpTable();
        }
コード例 #12
0
ファイル: ILBuilderEmit.cs プロジェクト: kangkot/roslyn
        /// <summary>
        /// Primary method for emitting string switch jump table
        /// </summary>
        /// <param name="caseLabels">switch case labels</param>
        /// <param name="fallThroughLabel">fall through label for the jump table</param>
        /// <param name="key">Local holding the value to switch on.
        /// This value has already been loaded onto the execution stack.
        /// </param>
        /// <param name="keyHash">Local holding the hash value of the key for emitting
        /// hash table switch. Hash value has already been computed and loaded into keyHash.
        /// This parameter is null if emitting non hash table switch.
        /// </param>
        /// <param name="emitStringCondBranchDelegate">
        /// Delegate to emit string compare call and conditional branch based on the compare result.
        /// </param>
        /// <param name="computeStringHashcodeDelegate">
        /// Delegate to compute string hash consistent with value of keyHash.
        /// </param>
        internal void EmitStringSwitchJumpTable(
            KeyValuePair<ConstantValue, object>[] caseLabels,
            object fallThroughLabel,
            LocalOrParameter key,
            LocalDefinition keyHash,
            SwitchStringJumpTableEmitter.EmitStringCompareAndBranch emitStringCondBranchDelegate,
            SwitchStringJumpTableEmitter.GetStringHashCode computeStringHashcodeDelegate)
        {
            Debug.Assert(caseLabels.Length > 0);

            var emitter = new SwitchStringJumpTableEmitter(
                this,
                key,
                caseLabels,
                fallThroughLabel,
                keyHash,
                emitStringCondBranchDelegate,
                computeStringHashcodeDelegate);

            emitter.EmitJumpTable();
        }