Esempio n. 1
0
        protected internal override void VisitLdFlda(LdFlda inst)
        {
            base.VisitLdFlda(inst);
            // Get display class info
            if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass displayClass, out IField field))
            {
                return;
            }
            // We want the specialized version, so that display-class type parameters are
            // substituted with the type parameters from the use-site.
            var fieldType = field.Type;

            // However, use the unspecialized member definition to make reference comparisons in dictionary possible.
            field = (IField)field.MemberDefinition;
            if (!displayClass.Variables.TryGetValue(field, out var v))
            {
                context.Step($"Introduce captured variable for {field.FullName}", inst);
                // Introduce a fresh variable for the display class field.
                Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition);
                v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, fieldType, field.Name);
                v.HasInitialValue = true;
                v.CaptureScope    = displayClass.CaptureScope;
                inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
                displayClass.Variables.Add(field, v);
            }
            else
            {
                context.Step($"Reuse captured variable {v.Name} for {field.FullName}", inst);
                inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
            }
        }
 protected internal override void VisitLdFlda(LdFlda inst)
 {
     base.VisitLdFlda(inst);
     // Get display class info
     if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass displayClass, out IField field))
         return;
     var keyField = (IField)field.MemberDefinition;
     var v = displayClass.VariablesToDeclare[keyField];
     context.Step($"Replace {field.Name} with captured variable {v.Name}", inst);
     ILVariable variable = v.GetOrDeclare();
     inst.ReplaceWith(new LdLoca(variable).WithILRange(inst));
     // add captured variable to all descendant functions from the declaring function to this use-site function
     foreach (var f in currentFunctions) {
         if (f == variable.Function)
             break;
         f.CapturedVariables.Add(variable);
     }
 }
Esempio n. 3
0
        /// <code>
        /// stloc s(ldflda)
        /// stloc s2(ldobj(ldflda(ldloc s)))
        /// stloc l(ldloc s2)
        /// stobj (ldflda(ldloc s), binary.add(ldloc s2, ldc.i4 1))
        /// -->
        /// stloc l(compound.op.old(ldobj(ldflda(ldflda)), ldc.i4 1))
        /// </code>
        bool TransformCSharp4PostIncDecOperatorOnAddress(Block block, int i)
        {
            var baseFieldAddress      = block.Instructions[i] as StLoc;
            var fieldValue            = block.Instructions.ElementAtOrDefault(i + 1) as StLoc;
            var fieldValueCopyToLocal = block.Instructions.ElementAtOrDefault(i + 2) as StLoc;
            var stobj = block.Instructions.ElementAtOrDefault(i + 3) as StObj;

            if (baseFieldAddress == null || fieldValue == null || fieldValueCopyToLocal == null || stobj == null)
            {
                return(false);
            }
            if (baseFieldAddress.Variable.Kind != VariableKind.StackSlot || fieldValue.Variable.Kind != VariableKind.StackSlot || fieldValueCopyToLocal.Variable.Kind != VariableKind.Local)
            {
                return(false);
            }
            IType         t;
            IField        targetField;
            ILInstruction targetFieldLoad, baseFieldAddressLoad2;

            if (!fieldValue.Value.MatchLdObj(out targetFieldLoad, out t))
            {
                return(false);
            }
            ILInstruction baseAddress;

            if (baseFieldAddress.Value is LdFlda)
            {
                IField        targetField2;
                ILInstruction baseFieldAddressLoad3;
                if (!targetFieldLoad.MatchLdFlda(out baseFieldAddressLoad2, out targetField) || !baseFieldAddressLoad2.MatchLdLoc(baseFieldAddress.Variable))
                {
                    return(false);
                }
                if (!stobj.Target.MatchLdFlda(out baseFieldAddressLoad3, out targetField2) || !baseFieldAddressLoad3.MatchLdLoc(baseFieldAddress.Variable) || !IsSameMember(targetField, targetField2))
                {
                    return(false);
                }
                baseAddress = new LdFlda(baseFieldAddress.Value, targetField);
            }
            else if (baseFieldAddress.Value is LdElema)
            {
                if (!targetFieldLoad.MatchLdLoc(baseFieldAddress.Variable) || !stobj.Target.MatchLdLoc(baseFieldAddress.Variable))
                {
                    return(false);
                }
                baseAddress = baseFieldAddress.Value;
            }
            else
            {
                return(false);
            }
            BinaryNumericInstruction binary = stobj.Value as BinaryNumericInstruction;

            if (binary == null || !binary.Left.MatchLdLoc(fieldValue.Variable) || !binary.Right.MatchLdcI4(1) ||
                (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub))
            {
                return(false);
            }
            context.Step($"TransformCSharp4PostIncDecOperatorOnAddress", baseFieldAddress);
            var assignment = new CompoundAssignmentInstruction(binary, new LdObj(baseAddress, t), binary.Right, t, CompoundAssignmentType.EvaluatesToOldValue);

            stobj.ReplaceWith(new StLoc(fieldValueCopyToLocal.Variable, assignment));
            block.Instructions.RemoveAt(i + 2);
            block.Instructions.RemoveAt(i + 1);
            return(true);
        }