public virtual void WriteStoreLocal(StoreLocal s, ExpressionUsage u)
 {
     Begin(u);
     Write(s.Variable.Name + Assign);
     WriteExpression(s.Value);
     End(u);
 }
Exemple #2
0
        public void VisitBegin(BeginMethod method)
        {
            Log.DebugLine(this, "-----------------------------------");
            Log.DebugLine(this, "{0:F}", method.Info.Instructions);

            // Loop through each try block,
            int offset = -1;

            for (int i = 0; i < method.Info.Instructions.TryCatchCollection.Length && offset < 0; ++i)
            {
                TryCatch tc = method.Info.Instructions.TryCatchCollection[i];

                // and the associated catch blocks,
                for (int j = 0; j < tc.Catchers.Count && offset < 0; ++j)
                {
                    CatchBlock cb = tc.Catchers[j];

                    // if the first instruction in a catch is a store local then the code
                    // is storing a reference to the exception object and we need to check
                    // to see if it's being rethrown.
                    StoreLocal store = method.Info.Instructions[cb.Index] as StoreLocal;
                    if (store != null)
                    {
                        offset = DoCheckCatch(method.Info.Instructions, cb, store.Variable);
                    }
                }
            }

            if (offset >= 0)
            {
                Reporter.MethodFailed(method.Info.Method, CheckID, offset, string.Empty);
            }
        }
Exemple #3
0
        public override void Begin(ref Statement s)
        {
            ParentExpression = null;

            switch (s.StatementType)
            {
            case StatementType.VariableDeclaration:
            {
                var d = s as VariableDeclaration;
                for (var var = d.Variable; var != null; var = var.Next)
                {
                    if (MustCopyType(var.ValueType))
                    {
                        if (var.OptionalValue == null)
                        {
                            var.OptionalValue = new Default(var.Source, var.ValueType);
                        }
                        else if (MustCopyValue(var.OptionalValue))
                        {
                            s = new StoreLocal(var.Source, var, var.OptionalValue);
                            var.OptionalValue = new Default(var.Source, var.ValueType);
                            var.SetName(Type.GetUniqueIdentifier(var.Name));
                        }
                    }
                }
                break;
            }
            }
        }
Exemple #4
0
            private long?[] DoTransformLocals(int index)
            {
                long?[] locals = null;

                StoreLocal store = m_instructions[index] as StoreLocal;

                if (store != null)
                {
                    long?newValue = null;
                    if (m_state.Stack.Count > 0)                                        // may be zero if the stack hasn't been inited yet
                    {
                        newValue = m_state.Stack.Back().Value;
                    }

                    locals = new long?[m_state.Locals.Length];
                    m_state.Locals.CopyTo(locals, 0);
                    locals[store.Variable] = newValue;
                }
                else if (m_instructions[index].Untyped.OpCode.Code == Code.Ldloca || m_instructions[index].Untyped.OpCode.Code == Code.Ldloca_S)
                {
                    VariableDefinition param = m_instructions[index].Untyped.Operand as VariableDefinition;
                    if (param != null)
                    {
                        locals = new long?[m_state.Locals.Length];
                        m_state.Locals.CopyTo(locals, 0);
                        locals[param.Index] = null;
                    }
                }
                else
                {
                    locals = m_state.Locals;
                }

                return(locals);
            }
Exemple #5
0
        public static bool TryCreateIndirection(Namescope scope, ref Expression e, out Expression s)
        {
            if (e.NeedsIndirection())
            {
                var v = new Variable(e.Source, null, scope.GetUniqueIdentifier("ind"), e.ReturnType, VariableType.Indirection);
                var a = e as AddressOf;
                var q = e as SequenceOp;

                if (q?.Right is AddressOf)
                {
                    a       = q.Right as AddressOf;
                    q.Right = a.ActualValue;
                }

                s = new StoreLocal(e.Source, v, e.ActualValue);
                e = new LoadLocal(e.Source, v);

                if (a != null)
                {
                    e = new AddressOf(e, a.AddressType);
                }

                return(true);
            }

            s = null;
            return(false);
        }
Exemple #6
0
 public void VisitStore(StoreLocal store)
 {
     if (store.RealName)
     {
         DoAdd(store.Name);
     }
     else
     {
         Log.DebugLine(this, "no local names");
     }
 }
Exemple #7
0
 public void VisitStoreLocal(StoreLocal store)
 {
     if (m_offset < 0 && store.Index > 0)
     {
         StoreLocal prev = m_info.Instructions[store.Index - 1] as StoreLocal;
         if (prev != null && prev.Variable == store.Variable)
         {
             m_offset = store.Untyped.Offset;
             Log.DebugLine(this, "Matched at {0:X2}", m_offset);
         }
     }
 }
Exemple #8
0
        // stloc.0  V_0
        // ldloc.0  V_0
        private bool DoStoresLocal(int index)
        {
            bool found = false;

            if (index > 0)
            {
                LoadLocal  load  = m_info.Instructions[index] as LoadLocal;
                StoreLocal store = m_info.Instructions[index - 1] as StoreLocal;

                found = load != null && store != null && load.Variable == store.Variable;
            }

            return(found);
        }
Exemple #9
0
 public void VisitStoreLocal(StoreLocal store)
 {
     if (m_needsCheck)
     {
         Log.Indent();
         LoadArg load = m_info.Instructions[store.Index - 1] as LoadArg;
         if (load != null && m_types[load.Arg] != null)
         {
             Log.DebugLine(this, "arg{0}: was saved to a local (at {1:X2})", load.Arg, store.Untyped.Offset);
             m_types[load.Arg] = null;
         }
         Log.Unindent();
     }
 }
Exemple #10
0
 // ldarg.0  this
 // stloc.0  V_0
 public void VisitStore(StoreLocal store)
 {
     if (m_needsCheck && m_offset < 0)
     {
         LoadArg load = m_info.Instructions[store.Index - 1] as LoadArg;
         if (load != null && load.Arg == 0)
         {
             m_thisLocals.Add(store.Variable);
             Log.DebugLine(this, "{0} = this at {1:X2}", store.Name, store.Untyped.Offset);
         }
         else
         {
             Unused.Value = m_thisLocals.Remove(store.Variable);
         }
     }
 }
Exemple #11
0
        public void VisitStore(StoreLocal store)
        {
            if (store.Index > 0)
            {
                LoadConstantInt load = m_info.Instructions[store.Index - 1] as LoadConstantInt;
                if (load != null)
                {
                    if (load.Value < 0 || load.Value > 255)
                    {
                        Log.DebugLine(this, "store at {0:X2}", store.Untyped.Offset);

                        if (m_stores.IndexOf(store.Variable) < 0)
                        {
                            m_stores.Add(store.Variable);
                        }
                    }
                }
            }
        }
        // newobj  System.Void System.IO.StreamReader::.ctor(System.String)
        // stloc.1 V_1
        private int DoGetNewDisposableLocal(StoreLocal store)
        {
            int variable = -1;

            NewObj obj = m_info.Instructions[store.Index - 1] as NewObj;

            if (obj != null && obj.Ctor.Name.EndsWith(".ctor"))
            {
                TypeDefinition type = Cache.FindType(obj.Ctor.DeclaringType);
                if (type != null && type.TypeOrBaseImplements("System.IDisposable", Cache))
                {
                    m_details = "Type: " + obj.Ctor.DeclaringType.FullName;
                    Log.DebugLine(this, "{0} = new {1}", store.Name, obj.Ctor.DeclaringType.FullName);
                    variable = store.Variable;
                }
            }

            return(variable);
        }
 public void VisitStoreLocal(StoreLocal store)
 {
     if (m_offset < 0)
     {
         int variable = DoGetNewDisposableLocal(store);
         if (variable >= 0)
         {
             List <int> loads = DoGetDisposableLoads(store.Index + 1, variable);
             if (loads.Count > 0)
             {
                 if (DoNeedsDispose(loads, store.Index + 1))
                 {
                     m_offset = store.Untyped.Offset;
                     Log.DebugLine(this, "no dispose call");
                 }
             }
         }
     }
 }
Exemple #14
0
            // This method is used by the Transform above and later on when we
            // need to compute the state for each instruction in a method.
            public Lattice Transform(int index)
            {
                DBC.Pre(index >= 0 && index < m_instructions.Length, "index is oor");                   // real code would probably use FastPre

                StoreLocal store = m_instructions[index] as StoreLocal;

                if (store != null)
                {
                    LoadConstantInt load = m_instructions[index - 1] as LoadConstantInt;                        // test code so we only track constant loads
                    if (load != null)
                    {
                        return(new Lattice(m_instructions, new State(load.Value)));
                    }
                    else
                    {
                        return(new Lattice(m_instructions, Indeterminate));
                    }
                }

                return(this);
            }
Exemple #15
0
        static Expression CreateAssertIndirection(ref Expression e, List <StoreLocal> locals, Namescope scope)
        {
            switch (e.ExpressionType)
            {
            case ExpressionType.AddressOf:
                return(CreateAssertIndirection(ref (e as AddressOf).Operand, locals, scope));

            case ExpressionType.LoadLocal:
            case ExpressionType.LoadArgument:
            case ExpressionType.LoadField:
            case ExpressionType.LoadElement:
            case ExpressionType.Invalid:
            case ExpressionType.Constant:
                return(e);
            }

            var v = new Variable(e.Source, null, scope.GetUniqueIdentifier("assert"), e.ReturnType);
            var s = new StoreLocal(e.Source, v, e);
            var l = new LoadLocal(e.Source, v);

            locals.Add(s);
            return(e = l);
        }
Exemple #16
0
        private bool DoMatch(CodeBlock lhs, CodeBlock rhs, int count)
        {
            Log.DebugLine(this, "   lhs: {0} at {1:X2}", lhs.Method, lhs.Instructions[lhs.Index].Untyped.Offset);
            Log.DebugLine(this, "   rhs: {0} at {1:X2}", rhs.Method, rhs.Instructions[rhs.Index].Untyped.Offset);
            Log.DebugLine(this, "   count: {0}", count);

            for (int i = 0; i < count; ++i)
            {
                TypedInstruction left  = lhs.Instructions[lhs.Index + i];
                TypedInstruction right = rhs.Instructions[rhs.Index + i];

                LoadLocal        load1  = left as LoadLocal;
                LoadLocal        load2  = right as LoadLocal;
                LoadLocalAddress load1b = left as LoadLocalAddress;
                LoadLocalAddress load2b = right as LoadLocalAddress;
                StoreLocal       store1 = left as StoreLocal;
                StoreLocal       store2 = right as StoreLocal;

                if (load1 != null && load2 != null)
                {
                    // If we have real names for the local variables (from the mdb file) then
                    // life is good and we can compare the names. If not we're stuck: we can't
                    // simply use the variable index because we'll get false positives.
                    if (!load1.RealName)
                    {
                        Log.DebugLine(this, "   can't match local name");
                        return(false);
                    }
                    // This should be a temporary in which case we can't use the variable index.
                    else if (load1.Name.StartsWith("V_") && load1.Type.FullName != load2.Type.FullName)
                    {
                        Log.DebugLine(this, "   {0} != {1} ({2} and {3})", left, right, load1.Type.FullName, load2.Type.FullName);
                        return(false);
                    }
                    else if (!load1.Name.StartsWith("V_") && load1.Name != load2.Name)
                    {
                        Log.DebugLine(this, "   {0} != {1} ({2} and {3})", left, right, load1.Name, load2.Name);
                        return(false);
                    }
                }
                else if (load1b != null && load2b != null)
                {
                    if (!load1b.RealName)
                    {
                        Log.DebugLine(this, "   can't match local name");
                        return(false);
                    }
                    else if (load1b.Name.StartsWith("V_") && load1b.Type.FullName != load2b.Type.FullName)
                    {
                        Log.DebugLine(this, "   {0} != {1} ({2} and {3})", left, right, load1b.Type.FullName, load2b.Type.FullName);
                        return(false);
                    }
                    else if (!load1b.Name.StartsWith("V_") && load1b.Name != load2b.Name)
                    {
                        Log.DebugLine(this, "   {0} != {1} ({2} and {3})", left, right, load1b.Name, load2b.Name);
                        return(false);
                    }
                }
                else if (store1 != null && store2 != null)
                {
                    if (!store1.RealName)
                    {
                        Log.DebugLine(this, "   can't match local name");
                        return(false);
                    }
                    else if (store1.Name.StartsWith("V_") && store1.Type.FullName != store2.Type.FullName)
                    {
                        Log.DebugLine(this, "   {0} != {1} ({2} and {3})", left, right, store1.Type.FullName, store2.Type.FullName);
                        return(false);
                    }
                    else if (!store1.Name.StartsWith("V_") && store1.Name != store2.Name)
                    {
                        Log.DebugLine(this, "   {0} != {1} ({2} and {3})", left, right, store1.Name, store2.Name);
                        return(false);
                    }
                }
                else if (!left.Untyped.Matches(right.Untyped))
                {
                    Log.DebugLine(this, "   {0} != {1}", left, right);
                    return(false);
                }
            }

            return(true);
        }
Exemple #17
0
        public Expression CompileNewExpression(AstNew e)
        {
            // Implicitly typed arrays
            if (e.OptionalType == null)
            {
                if (e.OptionalArguments != null)
                {
                    return(Error(e.Source, ErrorCode.E2001, "Array constructors cannot have argument list"));
                }
                if (e.OptionalArraySize != null)
                {
                    return(Error(e.Source, ErrorCode.E2002, "Cannot specify size on implicitly typed arrays"));
                }
                if (e.OptionalCollectionInitializer == null || e.OptionalCollectionInitializer.Count == 0)
                {
                    return(Error(e.Source, ErrorCode.E2003, "Must provide non-empty initializer list for implicitly typed arrays"));
                }

                var values = new Expression[e.OptionalCollectionInitializer.Count];
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = CompileExpression(e.OptionalCollectionInitializer[i]);
                }

                var et = TryGetImplicitElementType(values);

                if (et == null)
                {
                    return(Error(e.Source, ErrorCode.E2004, "No best type found for implicitly typed array"));
                }

                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = CompileImplicitCast(e.Source, et, values[i]);
                }

                return(et.IsValueType || et.IsReferenceType
                        ? new NewArray(e.Source, TypeBuilder.GetArray(et), values) :
                       et != DataType.Invalid
                        ? Error(e.Source, ErrorCode.E2080, "Cannot create an implicitly typed array of type " + et.Quote())
                        : Expression.Invalid);
            }

            var dt = NameResolver.GetType(Namescope, e.OptionalType);

            switch (dt.TypeType)
            {
            case TypeType.RefArray:
            {
                if (e.OptionalArguments != null)
                {
                    return(Error(e.Source, ErrorCode.E2005, "Array constructors cannot have argument list"));
                }

                var        at   = dt as RefArrayType;
                Expression size = null;

                if (e.OptionalArraySize != null)
                {
                    size = CompileImplicitCast(e.Source, Essentials.Int, CompileExpression(e.OptionalArraySize));
                    if (size.IsInvalid)
                    {
                        return(Expression.Invalid);
                    }
                }

                if (e.OptionalCollectionInitializer != null)
                {
                    var values = new Expression[e.OptionalCollectionInitializer.Count];
                    for (int i = 0; i < values.Length; i++)
                    {
                        values[i] = CompileExpression(e.OptionalCollectionInitializer[i]);
                    }

                    if (size != null)
                    {
                        var c = Compiler.ConstantFolder.TryMakeConstant(size);
                        if (c == null || !c.Value.Equals(values.Length))
                        {
                            return(Error(size.Source, ErrorCode.E2006, "Inconsistent array size and initializer list length"));
                        }
                    }

                    switch (at.ElementType.BuiltinType)
                    {
                    case BuiltinType.Bool:
                    case BuiltinType.Byte:
                    case BuiltinType.Char:
                    case BuiltinType.Double:
                    case BuiltinType.Int:
                    case BuiltinType.Float:
                    case BuiltinType.Long:
                    case BuiltinType.SByte:
                    case BuiltinType.Short:
                    case BuiltinType.UInt:
                    case BuiltinType.ULong:
                    case BuiltinType.UShort:
                        // Disable warning on primitive types
                        break;

                    default:
                        if (TryGetImplicitElementType(values) == at.ElementType)
                        {
                            Log.Warning3(e.Source, ErrorCode.W2007, "Array can be instantiated as implicitly typed array (new[] { ... })");
                        }

                        break;
                    }

                    for (int i = 0; i < values.Length; i++)
                    {
                        values[i] = CompileImplicitCast(values[i].Source, at.ElementType, values[i]);
                    }

                    return(new NewArray(e.Source, at, values));
                }

                return(new NewArray(e.Source, at, size));
            }

            case TypeType.Class:
            case TypeType.Struct:
            case TypeType.GenericParameter:
            {
                if (dt.IsStatic)
                {
                    return(Error(e.Source, ErrorCode.E2090, "Cannot instantiate static class"));
                }

                if (e.OptionalArguments != null || e.OptionalCollectionInitializer != null)
                {
                    if (e.OptionalArraySize != null)
                    {
                        return(Error(e.Source, ErrorCode.E2008, "Object constructors cannot have array size"));
                    }

                    Expression newObject;

                    if (dt.IsStruct && (e.OptionalArguments == null || e.OptionalArguments.Count == 0))
                    {
                        newObject = new Default(e.Source, dt);
                    }
                    else
                    {
                        dt.PopulateMembers();

                        Constructor  ctor;
                        Expression[] args;

                        if (!TryResolveConstructorOverload(e.Source, dt.Constructors, e.OptionalArguments ?? AstArgument.Empty, out ctor, out args))
                        {
                            return(e.OptionalArguments != null && e.OptionalArguments.Count > 0
                                    ? (dt.Constructors.Count == 1
                                        ? Error(e.Source, ErrorCode.E2009, "Call to " + (dt + PrintableParameterList(dt.Constructors[0].Parameters)).Quote() + " has some invalid arguments " +
                                                PrintableArgumentList(e.OptionalArguments))
                                        : Error(e.Source, ErrorCode.E2009, dt.Quote() + " has no constructors matching the argument list " +
                                                PrintableArgumentList(e.OptionalArguments) +
                                                NameResolver.SuggestCandidates(dt.Constructors)))
                                    : Error(e.Source, ErrorCode.E0000, dt.Quote() + " has no default constructor"));
                        }

                        newObject = new NewObject(e.Source, ctor, args);
                    }

                    if (e.OptionalCollectionInitializer != null && e.OptionalCollectionInitializer.Count > 0)
                    {
                        var var = new Variable(e.Source, Function, Namescope.GetUniqueIdentifier("collection"), newObject.ReturnType);
                        CurrentVariableScope.Variables.Add(var.Name, var);

                        Expression root = new StoreLocal(e.Source, var, newObject);

                        // See if it is a member initializer or collection initializer
                        var containsAssignOp = false;

                        foreach (var i in e.OptionalCollectionInitializer)
                        {
                            if (i is AstBinary && (i as AstBinary).IsAssign)
                            {
                                containsAssignOp = true;
                                break;
                            }
                        }

                        if (containsAssignOp)
                        {
                            var initedMembers = new List <string>();

                            // Assign members
                            foreach (var i in e.OptionalCollectionInitializer)
                            {
                                var binOp = i as AstBinary;
                                if (binOp == null || binOp.Type != AstBinaryType.Assign || !(binOp.Left is AstIdentifier))
                                {
                                    Log.Error(i.Source, ErrorCode.E2077, "Invalid initalizer member declarator");
                                    continue;
                                }

                                var id     = (AstIdentifier)binOp.Left;
                                var member = new AstMember(new AstIdentifier(i.Source, var.Name), id);

                                if (binOp.Right is AstArrayInitializer)
                                {
                                    var ai         = binOp.Right as AstArrayInitializer;
                                    var collection = CompileExpression(member);

                                    var cvar = new Variable(e.Source, Function, Namescope.GetUniqueIdentifier("array"), collection.ReturnType);
                                    CurrentVariableScope.Variables.Add(cvar.Name, cvar);

                                    root = new SequenceOp(root, new StoreLocal(collection.Source, cvar, collection));

                                    if (collection.IsInvalid)
                                    {
                                        continue;
                                    }

                                    foreach (var ci in ai.Values)
                                    {
                                        root = new SequenceOp(root, CompileAddToCollection(cvar.Name, ci));
                                    }
                                }
                                else
                                {
                                    var assign = CompileAssign(new AstBinary(AstBinaryType.Assign, member, i.Source, binOp.Right));
                                    root = new SequenceOp(root, assign);

                                    if (assign.IsInvalid)
                                    {
                                        continue;
                                    }
                                }

                                foreach (var m in initedMembers)
                                {
                                    if (m == id.Symbol)
                                    {
                                        Log.Error(i.Source, ErrorCode.E2078, "Duplicate initialization of member " + id.Symbol.Quote());
                                        break;
                                    }
                                }

                                initedMembers.Add(id.Symbol);
                            }
                        }
                        else
                        {
                            // Add to collection
                            foreach (var i in e.OptionalCollectionInitializer)
                            {
                                root = new SequenceOp(root, CompileAddToCollection(var.Name, i));
                            }
                        }

                        return(new SequenceOp(root, new LoadLocal(e.Source, var)));
                    }

                    if (e.OptionalType is AstBuiltinType && dt.IsStruct)
                    {
                        Log.Warning(e.Source, ErrorCode.W0000, "Redundant 'new' operator on builtin struct initialization");
                    }

                    return(newObject);
                }

                return(Error(e.Source, ErrorCode.E2011, "Must provide argument list for object constructor"));
            }

            case TypeType.Delegate:
            {
                if (e.OptionalArguments == null)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Must provide argument list for delegate constructor"));
                }

                var args = CompileArgumentList(e.OptionalArguments);

                if (e.OptionalCollectionInitializer != null)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Delegate construction cannot have collection initializer"));
                }
                if (e.OptionalArraySize != null)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Delegate construction cannot have array size"));
                }
                if (args.Length != 1 || args[0].ExpressionType != ExpressionType.MethodGroup)
                {
                    return(Error(e.Source, ErrorCode.E0000, "Delegate construction requires one method argument"));
                }

                return(CompileImplicitCast(e.Source, dt, args[0]));
            }

            case TypeType.Invalid:
                return(Expression.Invalid);

            default:
                return(Error(e.Source, ErrorCode.E2012, "Instances of type " + dt.Quote() + " cannot be created using 'new' because it is not a class, struct or array type"));
            }
        }
Exemple #18
0
        public override void Begin(ref Expression e, ExpressionUsage u)
        {
            switch (e.ExpressionType)
            {
            case ExpressionType.FixOp:
            {
                var s = (FixOp)e;
                GetIndirection(ref s.Operand);
                break;
            }

            case ExpressionType.AddressOf:
            {
                var s = (AddressOf)e;
                switch (s.AddressType)
                {
                case AddressType.Out:
                case AddressType.Ref:
                    GetIndirection(ref s.Operand);
                    break;
                }
                break;
            }

            case ExpressionType.StoreField:
            {
                var s = e as StoreField;
                OnObject(ref s.Object);
                break;
            }

            case ExpressionType.StoreElement:
            {
                var s = e as StoreElement;
                OnObject(ref s.Array);
                break;
            }

            case ExpressionType.StoreArgument:
            {
                Variable var;
                var      s = e as StoreArgument;
                if (GetIndirection(s.Index, s.Parameter, out var))
                {
                    e = new StoreLocal(s.Source, var, s.Value);
                    Begin(ref e, u);
                }
                else
                {
                    VerifyPointer(s.Parameter, s.Value);
                }
                break;
            }

            case ExpressionType.LoadArgument:
            {
                Variable var;
                var      s = e as LoadArgument;
                if (GetIndirection(s.Index, s.Parameter, out var))
                {
                    e = new LoadLocal(s.Source, var);
                    Begin(ref e, u);
                }
                break;
            }

            case ExpressionType.StoreLocal:
            {
                var s = e as StoreLocal;
                VerifyPointer(s.Variable, s.Value);
                break;
            }

            case ExpressionType.LoadField:
            {
                var s = e as LoadField;
                OnObject(ref s.Object);
                break;
            }

            case ExpressionType.LoadElement:
            {
                var s = e as LoadElement;
                OnObject(ref s.Array);
                break;
            }

            case ExpressionType.AddListener:
            case ExpressionType.RemoveListener:
            case ExpressionType.GetProperty:
            case ExpressionType.SetProperty:
            case ExpressionType.CallMethod:
            case ExpressionType.CallDelegate:
            {
                var s = (CallExpression)e;
                OnObject(ref s.Object);

                if (!s.Function.ReturnType.IsVoid && (
                        Backend.IsConstrained(s.Function) ||
                        s.Object is Base && s.Function.IsVirtual)
                    )
                {
                    s.Storage = new Variable(s.Source, Function, Type.GetUniqueIdentifier("ret"), s.Function.ReturnType, VariableType.Indirection);
                    Variables.Add(s.Storage);
                }
                break;
            }

            case ExpressionType.NewDelegate:
            {
                var s = (NewDelegate)e;
                OnObject(ref s.Object);
                break;
            }

            case ExpressionType.NewArray:
            {
                var s = e as NewArray;

                // Structs with non-trivial copy-ctor cannot be passed through '...' (uInitArray<T>)
                if (s.Initializers != null && IsNonTrivialStruct(s.ArrayType.ElementType))
                {
                    var v = new Variable(s.Source, null, Type.GetUniqueIdentifier("array"), s.ReturnType);
                    e = new StoreLocal(s.Source, v, new NewArray(s.Source, s.ArrayType, new Constant(s.Source, Essentials.Int, s.Initializers.Length)));

                    for (int i = 0; i < s.Initializers.Length; i++)
                    {
                        e = new SequenceOp(e,
                                           new StoreElement(s.Source,
                                                            new LoadLocal(s.Source, v),
                                                            new Constant(s.Source, Essentials.Int, i),
                                                            s.Initializers[i]));
                    }

                    e = new SequenceOp(e, new LoadLocal(s.Source, v));
                }
                break;
            }
            }
        }
Exemple #19
0
        public override void Begin(ref Expression e, ExpressionUsage u)
        {
            CurrentExpression = e;

            switch (e.ExpressionType)
            {
            case ExpressionType.LoadArgument:
            {
                var s = e as LoadArgument;
                if (ParameterVariables[s.Index] != null)
                {
                    e = new LoadLocal(s.Source, ParameterVariables[s.Index]);
                }
                break;
            }

            case ExpressionType.StoreArgument:
            {
                var s = e as StoreArgument;
                if (MustCopyType(s.Parameter.Type) && MustCopyValue(s.Value))
                {
                    e = Assign(new LoadArgument(s.Source, s.Function, s.Index), s.Value);
                }
                else if (ParameterVariables[s.Index] != null)
                {
                    e = new StoreLocal(s.Source, ParameterVariables[s.Index], s.Value);
                }
                break;
            }

            case ExpressionType.StoreField:
            {
                var s = e as StoreField;
                OnObject(ref s.Object);

                if (MustCopyType(s.Field.ReturnType) && MustCopyValue(s.Value))
                {
                    e = Assign(new LoadField(s.Source, s.Object, s.Field), s.Value);
                }
                break;
            }

            case ExpressionType.StoreThis:
            {
                var s = e as StoreThis;
                e = Assign(new This(s.Source, s.ReturnType), s.Value);
                break;
            }

            case ExpressionType.StoreLocal:
            {
                var s = e as StoreLocal;
                if (MustCopyType(s.Variable.ValueType) && MustCopyValue(s.Value))
                {
                    e = Assign(new LoadLocal(s.Source, s.Variable), s.Value);
                }
                break;
            }

            case ExpressionType.StoreElement:
            {
                var s = e as StoreElement;
                if (MustCopyType(s.Array.ReturnType.ElementType) && MustCopyValue(s.Value))
                {
                    e = Assign(new LoadElement(s.Source, s.Array, s.Index), s.Value);
                }
                break;
            }

            case ExpressionType.CallMethod:
            {
                var s = e as CallMethod;
                if (MustCopyBeforeCall(s.Method))
                {
                    OnObject(ref s.Object);
                }
                break;
            }

            case ExpressionType.GetProperty:
            {
                var s = e as GetProperty;
                if (MustCopyBeforeCall(s.Property.GetMethod))
                {
                    OnObject(ref s.Object);
                }
                break;
            }

            case ExpressionType.SetProperty:
            {
                var s = e as SetProperty;
                if (MustCopyBeforeCall(s.Property.SetMethod))
                {
                    OnObject(ref s.Object);
                }
                break;
            }

            case ExpressionType.AddListener:
            {
                var s = e as AddListener;
                if (MustCopyBeforeCall(s.Event.AddMethod))
                {
                    OnObject(ref s.Object);
                }
                break;
            }

            case ExpressionType.RemoveListener:
            {
                var s = e as RemoveListener;
                if (MustCopyBeforeCall(s.Event.RemoveMethod))
                {
                    OnObject(ref s.Object);
                }
                break;
            }
            }

            ParentExpression = e;
        }