Exemplo n.º 1
0
 /// <summary>
 /// Handles NullCoalescingInstruction case 1: reference types.
 ///
 /// stloc s(valueInst)
 /// if (comp(ldloc s == ldnull)) {
 ///		stloc s(fallbackInst)
 /// }
 /// =>
 /// stloc s(if.notnull(valueInst, fallbackInst))
 /// </summary>
 bool TransformRefTypes(Block block, int pos, StatementTransformContext context)
 {
     if (!(block.Instructions[pos] is StLoc stloc))
     {
         return(false);
     }
     if (stloc.Variable.Kind != VariableKind.StackSlot)
     {
         return(false);
     }
     if (!block.Instructions[pos + 1].MatchIfInstruction(out var condition, out var trueInst))
     {
         return(false);
     }
     trueInst = Block.Unwrap(trueInst);
     if (condition.MatchCompEquals(out var left, out var right) && left.MatchLdLoc(stloc.Variable) && right.MatchLdNull() &&
         trueInst.MatchStLoc(stloc.Variable, out var fallbackValue)
         )
     {
         context.Step("NullCoalescingTransform (reference types)", stloc);
         stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
         block.Instructions.RemoveAt(pos + 1);                 // remove if instruction
         ILInlining.InlineOneIfPossible(block, pos, false, context);
         return(true);
     }
     return(false);
 }
Exemplo n.º 2
0
 public void Run(Block block, BlockTransformContext context)
 {
     this.context = context;
     if (!context.Settings.AnonymousMethods)
     {
         return;
     }
     for (int i = block.Instructions.Count - 1; i >= 0; i--)
     {
         if (block.Instructions[i] is IfInstruction inst)
         {
             if (CachedDelegateInitializationWithField(inst))
             {
                 block.Instructions.RemoveAt(i);
                 continue;
             }
             if (CachedDelegateInitializationWithLocal(inst))
             {
                 ILInlining.InlineOneIfPossible(block, i, InliningOptions.Aggressive, context);
                 continue;
             }
             if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst))
             {
                 block.Instructions.RemoveAt(i);
                 continue;
             }
         }
     }
 }
Exemplo n.º 3
0
        public void Run(Block block, int pos, StatementTransformContext context)
        {
            if (!context.Settings.NamedArguments)
            {
                return;
            }
            var options = ILInlining.OptionsForBlock(block, pos, context);

            options |= InliningOptions.IntroduceNamedArguments;
            ILInlining.InlineOneIfPossible(block, pos, options, context: context);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Handles NullCoalescingInstruction case 1: reference types.
 ///
 /// stloc s(valueInst)
 /// if (comp(ldloc s == ldnull)) {
 ///		stloc s(fallbackInst)
 /// }
 /// =>
 /// stloc s(if.notnull(valueInst, fallbackInst))
 /// </summary>
 bool TransformRefTypes(Block block, int pos, StatementTransformContext context)
 {
     if (!(block.Instructions[pos] is StLoc stloc))
     {
         return(false);
     }
     if (stloc.Variable.Kind != VariableKind.StackSlot)
     {
         return(false);
     }
     if (!block.Instructions[pos + 1].MatchIfInstruction(out var condition, out var trueInst))
     {
         return(false);
     }
     if (!(condition.MatchCompEquals(out var left, out var right) && left.MatchLdLoc(stloc.Variable) && right.MatchLdNull()))
     {
         return(false);
     }
     trueInst = Block.Unwrap(trueInst);
     if (trueInst.MatchStLoc(stloc.Variable, out var fallbackValue))
     {
         context.Step("NullCoalescingTransform: simple (reference types)", stloc);
         stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
         block.Instructions.RemoveAt(pos + 1);                 // remove if instruction
         ILInlining.InlineOneIfPossible(block, pos, InliningOptions.None, context);
         return(true);
     }
     // sometimes the compiler generates:
     // stloc s(valueInst)
     // if (comp(ldloc s == ldnull)) {
     //		stloc v(fallbackInst)
     //      stloc s(ldloc v)
     // }
     // v must be single-assign and single-use.
     if (trueInst is Block trueBlock && trueBlock.Instructions.Count == 2 &&
         trueBlock.Instructions[0].MatchStLoc(out var temporary, out fallbackValue) &&
         temporary.IsSingleDefinition && temporary.LoadCount == 1 &&
         trueBlock.Instructions[1].MatchStLoc(stloc.Variable, out var useOfTemporary) &&
         useOfTemporary.MatchLdLoc(temporary))
     {
         context.Step("NullCoalescingTransform: with temporary variable (reference types)", stloc);
         stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
         block.Instructions.RemoveAt(pos + 1);                 // remove if instruction
         ILInlining.InlineOneIfPossible(block, pos, InliningOptions.None, context);
         return(true);
     }
     return(false);
 }