示例#1
0
文件: Transforms.cs 项目: mortend/uno
        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);
        }
示例#2
0
        void GetIndirection(ref Expression e)
        {
            Variable var;
            var      s = e as LoadArgument;

            if (s != null && GetIndirection(s.Index, s.Parameter, out var))
            {
                e = new LoadLocal(s.Source, var);
            }
        }
示例#3
0
            public override void Begin(ref Expression e, ExpressionUsage u)
            {
                switch (e.ExpressionType)
                {
                case ExpressionType.CapturedArgument:
                {
                    var s = e as CapturedArgument;
                    e = new LoadArgument(s.Source, s.Function, s.ParameterIndex);
                }
                break;

                case ExpressionType.CapturedLocal:
                {
                    var s = e as CapturedLocal;
                    e = new LoadLocal(s.Source, s.Variable);
                }
                break;

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

                    switch (s.Operand.ExpressionType)
                    {
                    case ExpressionType.LoadField:
                    {
                        var v = s.Operand as LoadField;

                        if (TransformedVars.Contains(v.Field))
                        {
                            e = s.Operand;
                            Begin(ref e, u);
                        }
                    }
                    break;

                    case ExpressionType.LoadLocal:
                    {
                        var v = s.Operand as LoadLocal;

                        if (TransformedVars.Contains(v.Variable))
                        {
                            e = s.Operand;
                            Begin(ref e, u);
                        }
                    }
                    break;
                    }
                }
                break;
                }
            }
示例#4
0
            private static void DoSpliceEq(TypedInstructionCollection instructions, BasicBlock block)
            {
                int index = block.Last.Index;

                // ldloc.0 V_0
                // ldnull
                // beq     2F
                LoadArg   arg   = null;
                LoadLocal local = null;

                if (instructions[index - 1].Untyped.OpCode.Code == Code.Ldnull)
                {
                    arg   = instructions[block.Last.Index - 2] as LoadArg;
                    local = instructions[block.Last.Index - 2] as LoadLocal;
                }
                else if (instructions[index - 2].Untyped.OpCode.Code == Code.Ldnull)
                {
                    arg   = instructions[block.Last.Index - 1] as LoadArg;
                    local = instructions[block.Last.Index - 1] as LoadLocal;
                }

                if (arg != null || local != null)
                {
                    TypedInstruction instruction = instructions[block.Last.Index];
                    Code             code        = instruction.Untyped.OpCode.Code;

                    if (code == Code.Bne_Un || code == Code.Bne_Un_S)
                    {
                        if (arg != null)
                        {
                            DoSpliceNull(block, FirstNullArgBlockLen - arg.Arg, FirstNonNullArgBlockLen - arg.Arg);
                        }

                        else
                        {
                            DoSpliceNull(block, FirstNullLocalBlockLen - local.Variable, FirstNonNullLocalBlockLen - local.Variable);
                        }
                    }
                    else
                    {
                        if (arg != null)
                        {
                            DoSpliceNull(block, FirstNonNullArgBlockLen - arg.Arg, FirstNullArgBlockLen - arg.Arg);
                        }

                        else
                        {
                            DoSpliceNull(block, FirstNonNullLocalBlockLen - local.Variable, FirstNullLocalBlockLen - local.Variable);
                        }
                    }
                }
            }
示例#5
0
        private TypeReference DoGetType(int index, int nth)
        {
            TypeReference type = null;

            int i = m_info.Tracker.GetStackIndex(index, nth);

            if (i >= 0)
            {
                do                      // TODO: would be nice to do something with load constant instructions as well
                {
                    LoadArg arg = m_info.Instructions[i] as LoadArg;
                    if (arg != null && arg.Arg >= 1)
                    {
                        ParameterDefinition p = m_info.Method.Parameters[arg.Arg - 1];
                        type = p.ParameterType;
                        break;
                    }

                    LoadField field = m_info.Instructions[i] as LoadField;
                    if (field != null)
                    {
                        type = field.Field.FieldType;
                        break;
                    }

                    LoadLocal local = m_info.Instructions[i] as LoadLocal;
                    if (local != null)
                    {
                        VariableDefinition v = m_info.Method.Body.Variables[local.Variable];
                        type = v.VariableType;
                        break;
                    }

                    LoadStaticField sfield = m_info.Instructions[i] as LoadStaticField;
                    if (sfield != null)
                    {
                        type = sfield.Field.FieldType;
                        break;
                    }

                    Box box = m_info.Instructions[i] as Box;
                    if (box != null)
                    {
                        type = box.Type;
                        break;
                    }
                }while (false);
            }

            return(type);
        }
示例#6
0
        public void VisitBinary(BinaryOp op)
        {
            if (m_offset < 0 && (op.Untyped.OpCode.Code == Code.Div || op.Untyped.OpCode.Code == Code.Div_Un))
            {
                do
                {
                    LoadConstantInt load1 = m_info.Instructions[op.Index - 1] as LoadConstantInt;
                    if (load1 != null)
                    {
                        if (load1.Value == 0)
                        {
                            m_offset = op.Untyped.Offset;
                            Log.DebugLine(this, "zero constant denominator at {0:X2}", m_offset);
                        }
                        break;
                    }

                    LoadLocal load2 = m_info.Instructions[op.Index - 1] as LoadLocal;
                    if (load2 != null)
                    {
                        if (DoIsIntType(load2.Type))
                        {
                            State state = m_info.Tracker.State(op.Index - 1);
                            long? value = state.Locals[load2.Variable];
                            if (value.HasValue && value.Value == 0)
                            {
                                m_offset = op.Untyped.Offset;
                                Log.DebugLine(this, "zero local denominator at {0:X2}", m_offset);
                            }
                        }
                        break;
                    }

                    LoadArg load3 = m_info.Instructions[op.Index - 1] as LoadArg;
                    if (load3 != null)
                    {
                        if (DoIsIntType(load3.Type))
                        {
                            State state2 = m_info.Tracker.State(op.Index - 1);
                            long? value2 = state2.Arguments[m_info.Method.HasThis ? load3.Arg : load3.Arg - 1];
                            if (value2.HasValue && value2.Value == 0)
                            {
                                m_offset = op.Untyped.Offset;
                                Log.DebugLine(this, "zero arg denominator at {0:X2}", m_offset);
                            }
                        }
                        break;
                    }
                }while (false);
            }
        }
示例#7
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);
        }
示例#8
0
 // ldloc.0  V_0
 // call     System.Void System.Threading.Monitor::Enter(System.Object)
 public void VisitCall(Call call)
 {
     if (m_needsCheck && m_offset < 0)
     {
         if (call.Target.ToString() == "System.Void System.Threading.Monitor::Enter(System.Object)")
         {
             LoadLocal local = m_info.Instructions[call.Index - 1] as LoadLocal;
             if (local != null && m_thisLocals.IndexOf(local.Variable) >= 0)
             {
                 m_offset = call.Untyped.Offset;
                 Log.DebugLine(this, "found lock(this) at {0:X2}", m_offset);
             }
         }
     }
 }
        private List <int> DoGetDisposableLoads(int index, int variable)
        {
            List <int> loads = new List <int>();

            for (int i = index; i < m_info.Instructions.Length; ++i)
            {
                LoadLocal load = m_info.Instructions[i] as LoadLocal;
                if (load != null && load.Variable == variable)
                {
                    loads.Add(i);
                    Log.DebugLine(this, "found load at offset {0:X2}", load.Untyped.Offset);
                }
            }

            return(loads);
        }
示例#10
0
        private TypeReference DoGetThisType(Call call)
        {
            TypeReference self = null;

            if (call.Target.HasThis)
            {
                int index = call.GetThisIndex(m_info);

                if (index >= 0)
                {
                    do
                    {
                        LoadArg arg = m_info.Instructions[index] as LoadArg;
                        if (arg != null)
                        {
                            self = arg.Type;
                            break;
                        }

                        LoadField field = m_info.Instructions[index] as LoadField;
                        if (field != null)
                        {
                            self = field.Field.FieldType;
                            break;
                        }

                        LoadStaticField sfield = m_info.Instructions[index] as LoadStaticField;
                        if (sfield != null)
                        {
                            self = sfield.Field.FieldType;
                            break;
                        }

                        LoadLocal local = m_info.Instructions[index] as LoadLocal;
                        if (local != null)
                        {
                            self = local.Type;
                            break;
                        }
                    }while (false);
                }
            }

            return(self);
        }
示例#11
0
        private void RegisterTestMethods()
        {
            var registryObject   = ILFactory.NewObject(_source, _testRegistryType);
            var registryVariable = new Variable(_source, _mainConstructor, "registry", _testRegistryType, VariableType.Default, registryObject);
            var body             = new Scope(_source);

            body.Statements.Add(new CallConstructor(_source, _appClass.Constructors[0]));
            body.Statements.Add(new VariableDeclaration(registryVariable));

            var methods = _methods;

            if (_testOptions.Filter != null)
            {
                var regex = new Regex(_testOptions.Filter, RegexOptions.CultureInvariant);
                methods = methods.Where(m => regex.IsMatch(m.FullName)).ToList();
            }

            methods.Sort((a, b) => string.Compare(a.FullName, b.FullName, StringComparison.InvariantCultureIgnoreCase));

            var ret = new List <TestMethod>();

            foreach (var method in methods)
            {
                var testMethod      = CreateTestMethod(method);
                var invokerMethod   = CreateInvoker(method);
                var invokerInstance = InstantiateTestFixture(invokerMethod);
                var testExpression  = RegisterTest(testMethod,
                                                   new LoadLocal(_source, registryVariable),
                                                   new NewDelegate(_source, _actionType,
                                                                   invokerInstance, invokerMethod));

                body.Statements.Add(testExpression);
                ret.Add(testMethod);
            }

            var registryExpr          = new LoadLocal(_source, registryVariable);
            var testSetupConstruction = ILFactory.NewObject(_source, _testSetupType, registryExpr);

            body.Statements.Add(new StoreField(_source, new This(_source, _mainClass), _testSetupField, testSetupConstruction));

            _mainConstructor.SetBody(body);
        }
示例#12
0
        Expression EnqueueLocal(Source src, MetaProperty mp, MetaLocation loc, Expression e)
        {
            // TODO: Bugs without if test.
            if (e is PlaceholderArray)
            {
                var var = new Variable(src, null, Generator.CreateLocalName(mp, loc, e), e.ReturnType, VariableType.Default, new PlaceholderValue(mp, loc, e, CurrentMetaPropertyStage));
                LocalQueue.Add(var);

                var result = new LoadLocal(e.Source, var);
                LoadHistory.Add(result);

                if (result.ReturnType is FixedArrayType)
                {
                    return(new AddressOf(result));
                }

                return(result);
            }

            return(e);
        }
示例#13
0
            private static void DoSpliceTrue(TypedInstructionCollection instructions, BasicBlock block)
            {
                int index = block.Last.Index;

                // ldarg.1 a1
                // brtrue  10	(not taken is the first branch)
                LoadArg   arg   = instructions[index - 1] as LoadArg;
                LoadLocal local = instructions[index - 1] as LoadLocal;

                if (arg != null || local != null)
                {
                    TypedInstruction instruction = instructions[index];
                    Code             code        = instruction.Untyped.OpCode.Code;

                    if (code == Code.Brtrue || code == Code.Brtrue_S)
                    {
                        if (arg != null)
                        {
                            DoSpliceNull(block, FirstNullArgBlockLen - arg.Arg, FirstNonNullArgBlockLen - arg.Arg);
                        }

                        else
                        {
                            DoSpliceNull(block, FirstNullLocalBlockLen - local.Variable, FirstNonNullLocalBlockLen - local.Variable);
                        }
                    }
                    else
                    {
                        if (arg != null)
                        {
                            DoSpliceNull(block, FirstNonNullArgBlockLen - arg.Arg, FirstNullArgBlockLen - arg.Arg);
                        }

                        else
                        {
                            DoSpliceNull(block, FirstNonNullLocalBlockLen - local.Variable, FirstNullLocalBlockLen - local.Variable);
                        }
                    }
                }
            }
示例#14
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);
        }
示例#15
0
        private void DoCheckLoad(TypedInstruction instruction)
        {
            LoadConstantInt load = m_info.Instructions[instruction.Index - 1] as LoadConstantInt;

            if (load != null)
            {
                if (load.Value < 0 || load.Value > 255)
                {
                    m_offset = instruction.Untyped.Offset;
                    Log.DebugLine(this, "bad exit at {0:X2}", m_offset);
                }
            }

            LoadLocal local = m_info.Instructions[instruction.Index - 1] as LoadLocal;

            if (local != null)
            {
                Log.DebugLine(this, "{0} at {1:X2}", instruction.Untyped.OpCode, instruction.Untyped.Offset);
                if (m_candidateLoads.IndexOf(local.Variable) < 0)
                {
                    m_candidateLoads.Add(local.Variable);
                }
            }
        }
示例#16
0
        private int DoCheckCatch(TypedInstructionCollection instructions, CatchBlock cb, int varIndex)
        {
            int offset = -1;

            // Loop through all of the instructions in the catch block,
            for (int index = cb.Index; index < cb.Index + cb.Length && offset < 0; ++index)
            {
                TypedInstruction instruction = instructions[index];

                // if we find a throw instruction,
                if (instruction.Untyped.OpCode.Code == Code.Throw)
                {
                    // and it's preceded by a load from varIndex then we have a problem.
                    LoadLocal load = instructions[index - 1] as LoadLocal;
                    if (load != null && load.Variable == varIndex)
                    {
                        offset = instruction.Untyped.Offset;
                        Log.DebugLine(this, "bad throw at {0:X2}", offset);
                    }
                }
            }

            return(offset);
        }
示例#17
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);
        }
示例#18
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;
        }
示例#19
0
        protected override void ProcessNext()
        {
            if (DmlTokens.IsMatch(CurrentToken, DmlTokens.AT) ||
                DmlTokens.IsMatch(CurrentToken, DmlTokens.DOLLAR) ||
                DmlTokens.IsNonKeywordName(CurrentToken) ||
                DmlTokens.IsBuiltin(CurrentToken))
            {
                Instruction load;
                string      badName = "Invalid syntax; invalid name \"{0}\".";
                if (DmlTokens.IsMatch(CurrentToken, DmlTokens.AT))
                {
                    Advance(exception: new DmlSyntaxError("Invalid syntax: global identifier `@` must be followed by a name."));
                    if (!DmlTokens.IsName(CurrentToken))
                    {
                        throw new DmlSyntaxError(String.Format(badName, CurrentToken));
                    }
                    load = new LoadGlobal(CurrentToken);
                }
                else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.DOLLAR))
                {
                    Advance(exception: new DmlSyntaxError("Invalid syntax: identifier `$` must be followed by a name."));
                    if (DmlTokens.IsName(CurrentToken))
                    {
                        switch (CurrentToken)
                        {
                        case DmlTokens.INTRINSIC_DIRECTION:
                            load = LoadIntrinsicBulletProperty.Direction;
                            break;

                        case DmlTokens.INTRINSIC_SPEED:
                            load = LoadIntrinsicBulletProperty.Speed;
                            break;

                        case DmlTokens.INTRINSIC_COLOUR:
                            load = LoadIntrinsicBulletProperty.Colour;
                            break;

                        case DmlTokens.INTRINSIC_ORIGIN:
                            load = LoadIntrinsicBulletProperty.Origin;
                            break;

                        case DmlTokens.INTRINSIC_POSITION:
                            load = LoadIntrinsicBulletProperty.Position;
                            break;

                        case DmlTokens.INTRINSIC_VELOCITY:
                            load = LoadIntrinsicBulletProperty.Velocity;
                            break;

                        case DmlTokens.INTRINSIC_TIME:
                            load = LoadIntrinsicBulletProperty.Time;
                            break;

                        default:
                            load = new LoadInstanceBound(CurrentToken);
                            break;
                        }
                    }
                    else
                    {
                        throw new DmlSyntaxError(String.Format(badName, CurrentToken));
                    }
                }
                else if (DmlTokens.IsName(CurrentToken))
                {
                    load = new LoadLocal(CurrentToken);
                }
                else
                {
                    load = new LoadConstant(BuiltinsDict.Builtins[CurrentToken]);
                }

                bool isCall = false;
                // Check if this is a function call.
                // We actually want to catch the ParserError thrown by Advance() in this case
                // because it's very possible the expression could end with a name.
                if (NextToken != null)
                {
                    Advance();
                    if (DmlTokens.IsMatch(CurrentToken, DmlTokens.LPAR))
                    {
                        isCall = true;
                        ParseFuncCall(load);
                    }
                    else
                    {
                        Reverse();
                    }
                }
                if (!isCall)
                {
                    instructions.Add(load);
                }
            }
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_TRUE))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, true)));
            }
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_FALSE))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, false)));
            }
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_NULL))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Null, null)));
            }
            // Check for a left parenthesis.
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.LPAR))
            {
                // We know this will never be the start of a function call because
                // that case would be caught by the above if block.
                operators.Push(CurrentToken);
            }
            // Check for a right parenthesis.
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.RPAR))
            {
                // By the shunting-yard algorithm, we pop every operator until we find a left
                // parenthesis. If we don't find one, then there are mismatched parentheses.
                if (operators.Count == 0 || !operators.Contains(DmlTokens.LPAR))
                {
                    throw DmlSyntaxError.MismatchedParentheses();
                }
                string top;
                while (operators.Count > 0)
                {
                    top = operators.First();
                    if (DmlTokens.IsMatch(top, DmlTokens.LPAR))
                    {
                        operators.Pop();
                        break;
                    }
                    instructions.Add(OPERATOR_INSTRUCTIONS[operators.Pop()]);
                }
            }
            // Check if the next token is a valid mathematical operator.
            else if (IsOperator(CurrentToken))
            {
                if (operators.Count == 0)
                {
                    operators.Push(CurrentToken);
                }
                // If there are prior operators, pop them and add them to the instructions according to their
                // associativity and precedence.
                else
                {
                    string top;
                    while (operators.Count > 0)
                    {
                        top = operators.First();
                        if ((IsLeftAssociative(top) && OPERATOR_PRECEDENCE[top] >= OPERATOR_PRECEDENCE[CurrentToken]) ||
                            (IsRightAssociative(top) && OPERATOR_PRECEDENCE[top] > OPERATOR_PRECEDENCE[CurrentToken]))
                        {
                            instructions.Add(OPERATOR_INSTRUCTIONS[operators.Pop()]);
                        }
                        else
                        {
                            break;
                        }
                    }
                    operators.Push(CurrentToken);
                }
            }
            // Check for a number.
            else if (DmlTokens.IsNumber(CurrentToken))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Number, Double.Parse(CurrentToken))));
            }
            // Check for True.
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_TRUE))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, true)));
            }
            // Check for False.
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_FALSE))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Bool, false)));
            }
            // Check for Null.
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_NULL))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.Null, null)));
            }
            else if (DmlTokens.IsString(CurrentToken))
            {
                instructions.Add(new LoadConstant(new DmlObject(DmlType.String, CurrentToken)));
            }
            // Check for Lambda.
            else if (DmlTokens.IsMatch(CurrentToken, DmlTokens.KW_LAMBDA))
            {
                throw new NotImplementedException("This hasn't been implemented yet, sorry!");
            }
            else
            {
                throw DmlSyntaxError.InvalidTokenForContext(CurrentToken, "expression");
            }
        }
示例#20
0
        public static bool IsIntOperand(MethodInfo info, int index, int nth)
        {
            bool isInt = false;

            int i = info.Tracker.GetStackIndex(index, nth);

            if (i >= 0)
            {
                do
                {
                    LoadArg arg = info.Instructions[i] as LoadArg;
                    if (arg != null && arg.Arg >= 1)
                    {
                        ParameterDefinition p = info.Method.Parameters[arg.Arg - 1];
                        if (p.ParameterType.FullName == "System.Int32")
                        {
                            isInt = true;
                        }
                        break;
                    }

                    LoadConstantInt constant = info.Instructions[i] as LoadConstantInt;
                    if (constant != null)
                    {
                        Code code = constant.Untyped.OpCode.Code;
                        switch (code)
                        {
                        case Code.Ldc_I4_M1:
                        case Code.Ldc_I4_0:
                        case Code.Ldc_I4_1:
                        case Code.Ldc_I4_2:
                        case Code.Ldc_I4_3:
                        case Code.Ldc_I4_4:
                        case Code.Ldc_I4_5:
                        case Code.Ldc_I4_6:
                        case Code.Ldc_I4_7:
                        case Code.Ldc_I4_8:
                        case Code.Ldc_I4_S:
                        case Code.Ldc_I4:
                            isInt = true;
                            break;
                        }
                        break;
                    }

                    LoadField field = info.Instructions[i] as LoadField;
                    if (field != null)
                    {
                        if (field.Field.FieldType.FullName == "System.Int32")
                        {
                            isInt = true;
                        }
                        break;
                    }

                    LoadLocal local = info.Instructions[i] as LoadLocal;
                    if (local != null)
                    {
                        VariableDefinition v = info.Method.Body.Variables[local.Variable];
                        if (v.VariableType.FullName == "System.Int32")
                        {
                            isInt = true;
                        }
                        break;
                    }

                    LoadStaticField sfield = info.Instructions[i] as LoadStaticField;
                    if (sfield != null)
                    {
                        if (sfield.Field.FieldType.FullName == "System.Int32")
                        {
                            isInt = true;
                        }
                        break;
                    }
                }while (false);
            }

            return(isInt);
        }
示例#21
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;
            }
            }
        }
示例#22
0
        private bool DoIsBad(int index)
        {
            bool bad = false;

            do
            {
                LoadArg arg = m_info.Instructions[index] as LoadArg;
                if (arg != null && arg.Arg >= 1)
                {
                    Log.DebugLine(this, "arg: {0}", arg.Arg);

                    ParameterDefinition p = m_info.Method.Parameters[arg.Arg - 1];
                    Log.DebugLine(this, "param {0} is of type {1}", arg.Arg, p.ParameterType.FullName);
                    if (DoIsBad(p.ParameterType))
                    {
                        bad = true;
                    }
                    break;
                }

                LoadLocal local = m_info.Instructions[index] as LoadLocal;
                if (local != null)
                {
                    Log.DebugLine(this, "local: {0}", local.Variable);

                    TypeReference type = m_info.Method.Body.Variables[local.Variable].VariableType;
                    Log.DebugLine(this, "local {0} is of type {1}", local.Variable, type.FullName);
                    if (DoIsBad(type))
                    {
                        bad = true;
                    }
                    break;
                }

                LoadField field = m_info.Instructions[index] as LoadField;
                if (field != null)
                {
                    Log.DebugLine(this, "field: {0}", field.Field.Name);

                    TypeReference type = field.Field.FieldType;
                    Log.DebugLine(this, "field {0} is of type {1}", field.Field.Name, type.FullName);
                    if (DoIsBad(type))
                    {
                        bad = true;
                    }
                    break;
                }

                LoadStaticField sfield = m_info.Instructions[index] as LoadStaticField;
                if (sfield != null)
                {
                    Log.DebugLine(this, "static field: {0}", sfield.Field.Name);

                    TypeReference type = sfield.Field.FieldType;
                    Log.DebugLine(this, "static field {0} is of type {1}", sfield.Field.Name, type.FullName);
                    if (DoIsBad(type))
                    {
                        bad = true;
                    }
                    break;
                }
            }while (false);

            return(bad);
        }
示例#23
0
            private void DoStackPushes(List <StackEntry> stack, int index, List <StackEntry> oldStack)
            {
                long?value;

                TypedInstruction instruction = m_instructions[index];

                switch (instruction.Untyped.OpCode.Code)
                {
                case Code.Add:
                case Code.Sub:
                case Code.Mul:
                case Code.Div:
                case Code.Div_Un:
                case Code.Rem:
                case Code.Rem_Un:
                case Code.And:
                case Code.Or:
                case Code.Xor:
                case Code.Shl:
                case Code.Shr:
                case Code.Shr_Un:
                case Code.Neg:
                case Code.Not:
                case Code.Add_Ovf:
                case Code.Add_Ovf_Un:
                case Code.Mul_Ovf:
                case Code.Mul_Ovf_Un:
                case Code.Sub_Ovf:
                case Code.Sub_Ovf_Un:
                    stack.Add(new StackEntry(null, index));                                     // could compute these, but we don't care too much about integer values atm
                    break;

                case Code.Arglist:                                              // push non-null
                case Code.Box:
                case Code.Ldarga:
                case Code.Ldarga_S:
                case Code.Ldelema:
                case Code.Ldflda:
                case Code.Ldftn:
                case Code.Ldind_Ref:
                case Code.Ldloca:
                case Code.Ldloca_S:
                case Code.Ldobj:
                case Code.Ldsflda:
                case Code.Ldstr:
                case Code.Ldtoken:
                case Code.Ldvirtftn:
                case Code.Localloc:
                case Code.Mkrefany:
                case Code.Newarr:
                case Code.Newobj:
                case Code.Refanytype:
                case Code.Refanyval:
                case Code.Unbox:
                case Code.Unbox_Any:
                    stack.Add(new StackEntry(1, index));
                    break;

                case Code.Call:
                case Code.Calli:
                case Code.Callvirt:
                    Call call = instruction as Call;
                    if (call.Target.ReturnType.ReturnType.ToString() != "System.Void")
                    {
                        stack.Add(new StackEntry(null, index));
                    }
                    break;

                case Code.Castclass:
                    value = oldStack.Back().Value;
                    if (value.HasValue && value.Value == 0)
                    {
                        stack.Add(new StackEntry(0, index));
                    }
                    else
                    {
                        stack.Add(new StackEntry(1, index));
                    }
                    break;

                case Code.Ceq:                                          // push indeterminate
                case Code.Cgt:
                case Code.Cgt_Un:
                case Code.Clt:
                case Code.Clt_Un:
                case Code.Ckfinite:
                case Code.Conv_I1:
                case Code.Conv_I2:
                case Code.Conv_I4:
                case Code.Conv_I8:
                case Code.Conv_U4:
                case Code.Conv_U8:
                case Code.Conv_R4:
                case Code.Conv_R8:
                case Code.Conv_U2:
                case Code.Conv_U1:
                case Code.Conv_I:
                case Code.Conv_R_Un:
                case Code.Conv_U:
                case Code.Ldelem_I1:
                case Code.Ldelem_U1:
                case Code.Ldelem_I2:
                case Code.Ldelem_U2:
                case Code.Ldelem_I4:
                case Code.Ldelem_U4:
                case Code.Ldelem_I8:
                case Code.Ldelem_I:
                case Code.Ldelem_R4:
                case Code.Ldelem_R8:
                case Code.Ldelem_Ref:
                case Code.Ldelem_Any:
                case Code.Ldind_I1:
                case Code.Ldind_U1:
                case Code.Ldind_I2:
                case Code.Ldind_U2:
                case Code.Ldind_I4:
                case Code.Ldind_U4:
                case Code.Ldind_I8:
                case Code.Ldind_I:
                case Code.Ldind_R4:
                case Code.Ldind_R8:
                case Code.Ldfld:
                case Code.Ldsfld:
                case Code.Ldlen:
                case Code.Sizeof:
                    stack.Add(new StackEntry(null, index));
                    break;

                case Code.Conv_Ovf_I1:                                  // push previous value
                case Code.Conv_Ovf_U1:
                case Code.Conv_Ovf_I2:
                case Code.Conv_Ovf_U2:
                case Code.Conv_Ovf_I4:
                case Code.Conv_Ovf_U4:
                case Code.Conv_Ovf_I8:
                case Code.Conv_Ovf_U8:
                case Code.Conv_Ovf_I:
                case Code.Conv_Ovf_U:
                case Code.Conv_Ovf_I1_Un:
                case Code.Conv_Ovf_I2_Un:
                case Code.Conv_Ovf_I4_Un:
                case Code.Conv_Ovf_I8_Un:
                case Code.Conv_Ovf_U1_Un:
                case Code.Conv_Ovf_U2_Un:
                case Code.Conv_Ovf_U4_Un:
                case Code.Conv_Ovf_U8_Un:
                case Code.Conv_Ovf_I_Un:
                case Code.Conv_Ovf_U_Un:
                    value = oldStack.Back().Value;
                    stack.Add(new StackEntry(value, index));
                    break;

                case Code.Dup:
                    value = oldStack.Back().Value;
                    stack.Add(new StackEntry(value, index));
                    stack.Add(new StackEntry(value, index));
                    break;

                case Code.Isinst:
                    value = oldStack.Back().Value;
                    if (value.HasValue && value.Value == 0)
                    {
                        stack.Add(new StackEntry(0, index));
                    }
                    else
                    {
                        stack.Add(new StackEntry(null, index));
                    }
                    break;

                case Code.Ldarg_0:
                case Code.Ldarg_1:
                case Code.Ldarg_2:
                case Code.Ldarg_3:
                case Code.Ldarg:
                case Code.Ldarg_S:
                    LoadArg arg = instruction as LoadArg;
                    value = m_state.Arguments[arg.Arg];
                    stack.Add(new StackEntry(value, index));
                    break;

                case Code.Ldc_I4_M1:
                case Code.Ldc_I4_0:
                case Code.Ldc_I4_1:
                case Code.Ldc_I4_2:
                case Code.Ldc_I4_3:
                case Code.Ldc_I4_4:
                case Code.Ldc_I4_5:
                case Code.Ldc_I4_6:
                case Code.Ldc_I4_7:
                case Code.Ldc_I4_8:
                case Code.Ldc_I4_S:
                case Code.Ldc_I4:
                case Code.Ldc_I8:
                    LoadConstantInt constant = instruction as LoadConstantInt;
                    stack.Add(new StackEntry(constant.Value, index));
                    break;

                case Code.Ldc_R4:
                case Code.Ldc_R8:
                    LoadConstantFloat constant2 = instruction as LoadConstantFloat;
                    if (constant2.Value == 0.0)
                    {
                        stack.Add(new StackEntry(0, index));
                    }
                    else
                    {
                        stack.Add(new StackEntry(null, index));
                    }
                    break;

                case Code.Ldloc_0:
                case Code.Ldloc_1:
                case Code.Ldloc_2:
                case Code.Ldloc_3:
                case Code.Ldloc:
                case Code.Ldloc_S:
                    LoadLocal local = instruction as LoadLocal;
                    value = m_state.Locals[local.Variable];
                    stack.Add(new StackEntry(value, index));
                    break;

                case Code.Ldnull:                                                               // push null
                    stack.Add(new StackEntry(0, index));
                    break;

                default:
                    DBC.Assert(instruction.Untyped.OpCode.StackBehaviourPush == StackBehaviour.Push0, "Expected {0} to push nothing", instruction.Untyped.OpCode);
                    break;
                }
            }
示例#24
0
 public virtual void WriteLoadLocal(LoadLocal s, ExpressionUsage u)
 {
     Write(s.Variable.Name);
 }
示例#25
0
        private bool DoIsFloat(int index)
        {
            TypedInstruction instruction = m_info.Instructions[index];
            TypeReference    type        = null;

            do
            {
                LoadArg arg = instruction as LoadArg;
                if (arg != null && arg.Arg >= 1)
                {
                    type = m_info.Method.Parameters[arg.Arg - 1].ParameterType;
                    break;
                }

                LoadLocal local = instruction as LoadLocal;
                if (local != null)
                {
                    type = m_info.Method.Body.Variables[local.Variable].VariableType;
                    break;
                }

                LoadField field = instruction as LoadField;
                if (field != null)
                {
                    type = field.Field.FieldType;
                    break;
                }

                LoadStaticField sfield = instruction as LoadStaticField;
                if (sfield != null)
                {
                    type = sfield.Field.FieldType;
                    break;
                }

                LoadConstantFloat cf = instruction as LoadConstantFloat;
                if (cf != null)
                {
                    return(cf.Value != double.PositiveInfinity && cf.Value != double.NegativeInfinity);
                }

                BinaryOp binary = instruction as BinaryOp;
                if (binary != null)
                {
                    int j = m_info.Tracker.GetStackIndex(instruction.Index, 0);
                    int k = m_info.Tracker.GetStackIndex(instruction.Index, 1);

                    if (j >= 0 && k >= 0)
                    {
                        if (DoIsFloat(j) && DoIsFloat(k))
                        {
                            return(true);
                        }
                    }
                }

                if (instruction.Untyped.OpCode.Code == Code.Conv_R4 || instruction.Untyped.OpCode.Code == Code.Conv_R8 || instruction.Untyped.OpCode.Code == Code.Conv_R_Un)
                {
                    return(true);
                }

                Call call = instruction as Call;
                if (call != null)
                {
                    type = call.Target.ReturnType.ReturnType;
                    break;
                }
            }while (false);

            return(type != null && (type.FullName == "System.Single" || type.FullName == "System.Double"));
        }
示例#26
0
        bool VisitVariableDeclaration(VariableDeclaration s, Scope scope, ref int i, ref int endIndex)
        {
            var mpv = s.Variable.OptionalValue as PlaceholderValue;

            if (mpv != null)
            {
                Parent = s;

                Begin(ref mpv.Value);
                mpv.Value.Visit(this);
                End(ref mpv.Value);

                FlushLocalQueue(scope, ref i, ref endIndex);

                var var = s.Variable;
                var fa  = mpv.Value as PlaceholderArray;

                if (fa != null && CurrentMetaPropertyStage > MetaStage.Volatile)
                {
                    var.OptionalValue   = null;
                    scope.Statements[i] = new FixedArrayDeclaration(var, fa.OptionalInitializer);
                    EmittedValues.Add(mpv, new StageValue(new AddressOf(new LoadLocal(mpv.Source, var)), CurrentMetaPropertyStage, CurrentMetaPropertyStage));
                    return(true);
                }
                else
                {
                    var.OptionalValue = mpv.Value;
                }

                var key   = var.OptionalValue.ToString();
                var found = false;

                for (int j = 0; j < i; j++)
                {
                    if (scope.Statements[j] is VariableDeclaration)
                    {
                        var pvar = (scope.Statements[j] as VariableDeclaration).Variable;

                        if (pvar.ValueType.Equals(var.ValueType) && pvar.OptionalValue != null && pvar.OptionalValue.ToString() == key)
                        {
                            Expression value = new LoadLocal(s.Source, pvar);

                            if (value.ReturnType is FixedArrayType)
                            {
                                value = new AddressOf(value);
                            }

                            foreach (var load in LoadHistory)
                            {
                                if (load.Variable == var)
                                {
                                    load.Variable = pvar;
                                }
                            }

                            EmittedValues.Add(mpv, new StageValue(value, CurrentMetaPropertyStage, CurrentMetaPropertyStage));
                            scope.Statements.RemoveAt(i--);
                            found = true;
                            endIndex--;

                            break;
                        }
                    }
                }

                if (!found)
                {
                    Expression value = new LoadLocal(s.Source, var);

                    if (value.ReturnType is FixedArrayType)
                    {
                        value = new AddressOf(value);
                    }

                    EmittedValues.Add(mpv, new StageValue(value, CurrentMetaPropertyStage, CurrentMetaPropertyStage));
                }

                return(true);
            }

            return(false);
        }