Exemple #1
0
 protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObjByRef();                                       // stack: [&obj]
     context.Il.Call(Type.GetProperty("HasValue").GetGetMethod()); // stack: obj.HasValue
     context.Il.Brtrue(notEmptyLabel);                             // if(obj.HasValue) goto notEmpty;
     return(true);
 }
        private static void EmitNullableBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
        {
            // a.GetValueOrDefault() == b.GetValueOrDefault() && a.HasValue == b.HasValue;
            var type = getMethod.ReturnType;
            var getValueOrDefault = type.GetMethod("GetValueOrDefault", new Type[0]);
            var hasValue          = type.GetMethod("get_HasValue");
            var a = il.DeclareLocal(type);
            var b = il.DeclareLocal(type);

            il.Ldarg(0);
            il.Call(getMethod);
            il.Stloc(a);
            il.Ldarg(1);
            il.Call(getMethod);
            il.Stloc(b);

            il.Ldloca(a);
            il.Call(getValueOrDefault);
            il.Ldloca(b);
            il.Call(getValueOrDefault);
            il.Bne_Un(returnFalse);

            il.Ldloca(a);
            il.Call(hasValue);
            il.Ldloca(b);
            il.Call(hasValue);
            il.Bne_Un(returnFalse);
        }
Exemple #3
0
        private static void EmitSwitch <T>(TrieNode node, EmittingContext context)
        {
            var il           = context.Il;
            var curChar      = context.CurChar;
            int n            = CalcSize(node.children.Keys.ToArray());
            var defaultLabel = il.DefineLabel("default");
            var labels       = new GroboIL.Label[n];

            for (int i = 0; i < labels.Length; ++i)
            {
                labels[i] = defaultLabel;
            }
            foreach (var key in node.children.Keys)
            {
                labels[key % n] = il.DefineLabel("case_" + key);
            }

            il.Ldloc(curChar);   // stack: [curChar]
            il.Ldc_I4(n);        // stack: [curChar, n]
            il.Rem(false);       // stack: [curChar % n]
            il.Switch(labels);   // goto labels[curChar % n]; stack: []
            il.Br(defaultLabel); // default;
            foreach (var pair in node.children)
            {
                il.MarkLabel(labels[pair.Key % n]); // case_{key}; stack: []
                InlineTrie <T>(pair.Value, context);
            }
            il.MarkLabel(defaultLabel);
            il.Ldc_I4(0); // stack: [false]
            il.Ret();
        }
Exemple #4
0
        protected void SaveOrCheck(GroboIL il, EvaluationStack stack, GroboIL.Label label)
        {
            ESType[] labelStack;
            if (!il.labelStacks.TryGetValue(label, out labelStack))
            {
                il.labelStacks.Add(label, stack.Reverse().ToArray());
                Propogate(il, il.ilCode.GetLabelLineNumber(label), stack);
            }
            else
            {
                ESType[] merged;
                var      comparisonResult = CompareStacks(stack.Reverse().ToArray(), labelStack, out merged);
                switch (comparisonResult)
                {
                case StacksComparisonResult.Equal:
                    return;

                case StacksComparisonResult.Inconsistent:
                    ThrowError(il, string.Format("Inconsistent stack for the label '{0}'{1}Stack #1: {2}{1}Stack #2: {3}", label.Name, Environment.NewLine, stack, new EvaluationStack(labelStack)));
                    break;

                case StacksComparisonResult.Equivalent:
                    il.labelStacks[label] = merged;
                    Propogate(il, il.ilCode.GetLabelLineNumber(label), new EvaluationStack(merged));
                    break;
                }
            }
        }
        // todo обобщить
        private static void EmitExpressionAsVoid(Expression node, EmittingContext context)
        {
            var il = context.Il;

            GroboIL.Label skipLabel = context.CanReturn ? il.DefineLabel("skip") : null;
            Type          resultType;
            bool          skipLabelUsed = ExpressionEmittersCollection.Emit(node, context, skipLabel, ResultType.Void, false, out resultType);

            if (skipLabelUsed)
            {
                var endLabel = il.DefineLabel("end");
                if (resultType != typeof(void))
                {
                    if (!resultType.IsStruct())
                    {
                        il.Pop();
                    }
                    else
                    {
                        using (var temp = context.DeclareLocal(resultType))
                            il.Stloc(temp);
                    }
                }
                il.Br(endLabel);
                context.MarkLabelAndSurroundWithSP(skipLabel);
                il.Pop();
                context.MarkLabelAndSurroundWithSP(endLabel);
            }
        }
        protected override bool EmitInternal(NewArrayExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            var il = context.Il;

            if (node.Expressions.Count != 1)
            {
                context.EmitLoadArguments(node.Expressions.ToArray());
                il.Newobj(node.Type.GetConstructor(node.Expressions.Select(exp => exp.Type).ToArray()));
            }
            else
            {
                GroboIL.Label lengthIsNullLabel = context.CanReturn ? il.DefineLabel("lengthIsNull") : null;
                Type          lengthType;
                var           labelUsed = ExpressionEmittersCollection.Emit(node.Expressions.Single(), context, lengthIsNullLabel, out lengthType);
                if (lengthType != typeof(int))
                {
                    throw new InvalidOperationException("Cannot create an array with length of type '" + lengthType + "'");
                }
                if (labelUsed && context.CanReturn)
                {
                    var lengthIsNotNullLabel = il.DefineLabel("lengthIsNotNull");
                    il.Br(lengthIsNotNullLabel);
                    context.MarkLabelAndSurroundWithSP(lengthIsNullLabel);
                    il.Pop();
                    il.Ldc_I4(0);
                    context.MarkLabelAndSurroundWithSP(lengthIsNotNullLabel);
                }
                il.Newarr(node.Type.GetElementType());
            }
            resultType = node.Type;
            return(false);
        }
 public void EmitReturnDefaultValue(Type type, GroboIL.Label valueIsNullLabel, GroboIL.Label valueIsNotNullLabel)
 {
     Il.Br(valueIsNotNullLabel);
     MarkLabelAndSurroundWithSP(valueIsNullLabel);
     Il.Pop();
     EmitLoadDefaultValue(type);
     MarkLabelAndSurroundWithSP(valueIsNotNullLabel);
 }
Exemple #8
0
 public static void ReadObjectNull(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local typeSize)
 {
     il.Ldloc(buffer);
     il.Ldloc(offset);
     il.Ldelem(typeof(byte));
     WriteOffsetAppend(il, offset, 1);
     il.Brtrue(finishMethod);
 }
 private static void EmitBne(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
 {
     // a.Property == b.Property
     il.Ldarg(0);
     il.Call(getMethod);
     il.Ldarg(1);
     il.Call(getMethod);
     il.Bne_Un(returnFalse);
 }
        protected override bool EmitInternal(BinaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            if (node.Conversion != null)
            {
                throw new NotSupportedException("Coalesce with conversion is not supported");
            }
            // note ich: баг решарпера
            // ReSharper disable HeuristicUnreachableCode
            var     left  = node.Left;
            var     right = node.Right;
            GroboIL il    = context.Il;

            GroboIL.Label valueIsNullLabel = il.DefineLabel("valueIsNull");
            Type          leftType;
            bool          labelUsed = ExpressionEmittersCollection.Emit(left, context, valueIsNullLabel, out leftType);

            if (left.Type.IsValueType)
            {
                using (var temp = context.DeclareLocal(left.Type))
                {
                    il.Stloc(temp);
                    il.Ldloca(temp);
                }
            }
            labelUsed |= context.EmitNullChecking(left.Type, valueIsNullLabel);
            if (left.Type.IsValueType)
            {
                if (!left.Type.IsNullable())
                {
                    throw new InvalidOperationException("Type '" + left.Type + "' cannot be null");
                }
                if (node.Type != left.Type)
                {
                    context.EmitValueAccess(left.Type);
                }
                else
                {
                    il.Ldobj(left.Type);
                }
            }
            var valueIsNotNullLabel = il.DefineLabel("valueIsNotNull");

            il.Br(valueIsNotNullLabel);
            if (labelUsed)
            {
                context.MarkLabelAndSurroundWithSP(valueIsNullLabel);
                il.Pop();
            }
            Type rightType;
            var  result = ExpressionEmittersCollection.Emit(right, context, returnDefaultValueLabel, out rightType);

            context.MarkLabelAndSurroundWithSP(valueIsNotNullLabel);
            resultType = node.Type;
            return(result);
            // ReSharper restore HeuristicUnreachableCode
        }
Exemple #11
0
 public int MarkLabel(GroboIL.Label label, ILInstructionComment comment)
 {
     if (labelLineNumbers.ContainsKey(label))
     {
         throw new InvalidOperationException(string.Format("The label '{0}' has already been marked", label.Name));
     }
     labelLineNumbers.Add(label, Count);
     instructions.Add(new ILInstruction(InstructionKind.Label, default(OpCode), new LabelILInstructionParameter(label), comment));
     return(Count++);
 }
        public static bool Emit(Expression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            IExpressionEmitter emitter;

            if (!expressionEmitters.TryGetValue(node.NodeType, out emitter))
            {
                throw new NotSupportedException("Node type '" + node.NodeType + "' is not supported");
            }
            return(emitter.Emit(node, context, returnDefaultValueLabel, whatReturn, extend, out resultType));
        }
Exemple #13
0
 /// <summary>
 ///     Checks whether <c>obj</c> is empty
 /// </summary>
 /// <param name="context">Current context</param>
 /// <param name="notEmptyLabel">Label where to go if <c>obj</c> is not empty</param>
 /// <returns>true if <c>obj</c> can be empty</returns>
 protected virtual bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     if (Type.IsValueType)
     {
         return(false);
     }
     context.LoadObj();                // stack: [obj]
     context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     return(true);
 }
        private static void EmitNullableEquals(GroboIL il, MethodInfo getMethod, GroboIL.Label returnFalse)
        {
            // a.Equals(b)
            var type  = getMethod.ReturnType;
            var local = il.DeclareLocal(type);

            il.Ldarg(0);
            il.Call(getMethod);
            il.Stloc(local);
            il.Ldloca(local);
            il.Ldarg(1);
            il.Call(getMethod);
            il.Box(type);
            il.Call(ObjectEquals, type);
            il.Brfalse(returnFalse);
        }
        private void Visit(ForStatement stmt)
        {
            var loopStartLabel = Generator.DefineLabel("loopstart");

            var indexLocal = Local(stmt.VarName);
            var toLocal    = Generator.DeclareLocal(typeof(ulong), "end");

            var previousEndLabel = CurrentLoopEndLabel;
            var endLabel         = CurrentLoopEndLabel = Generator.DefineLabel("forend");

            Visit(stmt.From);
            Generator.Dup();
            Generator.Ldobj(typeof(BitsValue));
            Generator.Stloc(indexLocal);

            Visit(stmt.To);
            BitsValueToNumber();
            Generator.Stloc(toLocal);

            BitsValueToNumber();

            Generator.MarkLabel(loopStartLabel);

            Visit(stmt.Body);

            // Increment index
            Generator.Ldc_I8(1);
            Generator.Conv <ulong>();
            Generator.Add();
            NumberToBitsValue();
            Generator.Ldobj(typeof(BitsValue));
            Generator.Stloc(indexLocal);

            // Check index == max, if true branch to end
            Generator.Ldloca(indexLocal);
            BitsValueToNumber();
            Generator.Dup();
            Generator.Ldloc(toLocal);
            Generator.Bne_Un(loopStartLabel);

            Generator.MarkLabel(endLabel);
            CurrentLoopEndLabel = previousEndLabel;

            Generator.Pop();
        }
Exemple #16
0
 protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);                                                           // if(obj == null) goto empty;
         context.LoadObj();                                                                        // stack: [obj]
         context.Il.Ldfld(Type.GetPrivateInstanceField(PlatformHelpers.HashtableCountFieldNames)); // stack: [obj.Count]
         context.Il.Brtrue(notEmptyLabel);                                                         // if(obj.Count != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
Exemple #17
0
 protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);                                                                         // if(obj == null) goto empty;
         context.LoadObj();                                                                                      // stack: [obj]
         context.Il.Call(Type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public).GetGetMethod()); // stack: [&result[index], obj.Count]
         context.Il.Brtrue(notEmptyLabel);                                                                       // if(obj.Count != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
 protected override bool CheckEmpty(SizeCounterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);                                                           // if(obj == null) goto empty;
         context.LoadObj();                                                                        // stack: [obj]
         context.Il.Ldfld(Type.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic)); // stack: [obj.Count]
         context.Il.Brtrue(notEmptyLabel);                                                         // if(obj.Count != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
Exemple #19
0
 protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
 {
     context.LoadObj(); // stack: [obj]
     if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
     {
         context.Il.Brtrue(notEmptyLabel); // if(obj != null) goto notEmpty;
     }
     else
     {
         var emptyLabel = context.Il.DefineLabel("empty");
         context.Il.Brfalse(emptyLabel);   // if(obj == null) goto empty;
         context.LoadObj();                // stack: [obj]
         context.Il.Ldlen();               // stack: [obj.Length]
         context.Il.Brtrue(notEmptyLabel); // if(obj.Length != 0) goto notEmpty;
         context.Il.MarkLabel(emptyLabel);
     }
     return(true);
 }
        private void Visit(WhileStatement stmt)
        {
            var previousEndLabel = CurrentLoopEndLabel;

            var loopStartLabel = Generator.DefineLabel("whilestart");
            var loopEndLabel   = CurrentLoopEndLabel = Generator.DefineLabel("whileend");

            Generator.MarkLabel(loopStartLabel);

            Visit(stmt.Condition);
            BitsValueToNumber();
            Generator.Brfalse(loopEndLabel);

            Visit(stmt.Body);
            Generator.Br(loopStartLabel);

            Generator.MarkLabel(loopEndLabel);

            CurrentLoopEndLabel = previousEndLabel;
        }
Exemple #21
0
        public static void WriteObjectNull(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset, GroboIL.Local typeSize)
        {
            var _null = il.DeclareLocal(typeof(bool));

            il.Ldnull();
            il.Ceq();
            il.Stloc(_null);

            il.Ldloc(buffer);
            il.Ldloc(offset);

            il.Ldloc(_null);

            il.Stelem(typeof(byte));

            WriteOffsetAppend(il, offset, 1);

            il.Ldloc(_null);
            il.Brtrue(finishMethod);
        }
        protected override bool CheckEmpty(WriterMethodBuilderContext context, GroboIL.Label notEmptyLabel)
        {
            var il = context.Il;

            context.LoadObjByRef(); // stack: [ref obj]
            il.Ldfld(arrayField);   // stack: [obj._array]
            if (context.Context.GroBufWriter.Options.HasFlag(GroBufOptions.WriteEmptyObjects))
            {
                il.Brtrue(notEmptyLabel); // if(obj._array != null) goto notEmpty;
            }
            else
            {
                var emptyLabel = il.DefineLabel("empty");
                il.Brfalse(emptyLabel);   // if(obj._array == null) goto empty;
                context.LoadObjByRef();   // stack: [ref obj]
                il.Ldfld(countField);     // stack: [obj._count]
                il.Brtrue(notEmptyLabel); // if(obj._count != 0) goto notEmpty;
                il.MarkLabel(emptyLabel);
            }
            return(true);
        }
        private static void EmitLoadIndex(Expression index, EmittingContext context, Type arrayType)
        {
            GroboIL il = context.Il;

            GroboIL.Label indexIsNullLabel = context.CanReturn ? il.DefineLabel("indexIsNull") : null;
            Type          indexType;
            bool          labelUsed = ExpressionEmittersCollection.Emit(index, context, indexIsNullLabel, out indexType); // stack: [array, index]

            if (indexType != typeof(int))
            {
                throw new InvalidOperationException("Unable to perform array index operator to type '" + arrayType + "'");
            }
            if (labelUsed && context.CanReturn)
            {
                var indexIsNotNullLabel = il.DefineLabel("indexIsNotNull");
                il.Br(indexIsNotNullLabel);
                context.MarkLabelAndSurroundWithSP(indexIsNullLabel);
                il.Pop();
                il.Ldc_I4(0);
                context.MarkLabelAndSurroundWithSP(indexIsNotNullLabel);
            }
        }
Exemple #24
0
        public static void WriteNullableType <T>(GroboIL il, GroboIL.Label finishMethod, GroboIL.Local buffer, GroboIL.Local offset)
            where T : struct
        {
            var _null = il.DeclareLocal(typeof(bool));

            il.Call(typeof(Nullable <T>).GetProperty("HasValue").GetGetMethod());
            il.Ldc_I4(0);
            //il.Ldnull();
            il.Ceq();
            il.Stloc(_null);

            il.Ldloc(buffer);
            il.Ldloc(offset);

            il.Ldloc(_null);

            il.Stelem(typeof(byte));

            WriteOffsetAppend(il, offset, 1);

            il.Ldloc(_null);
            il.Brtrue(finishMethod);
        }
 public bool EmitNullChecking(Type type, GroboIL.Label objIsNullLabel)
 {
     if (!type.IsValueType)
     {
         Il.Dup();                   // stack: [obj, obj]
         Il.Brfalse(objIsNullLabel); // if(obj == null) goto returnDefaultValue; stack: [obj]
         return(true);
     }
     if (type.IsNullable())
     {
         using (var temp = DeclareLocal(type.MakeByRefType()))
         {
             Il.Stloc(temp);
             Il.Ldnull();
             Il.Ldloc(temp);
             EmitHasValueAccess(type);
             Il.Brfalse(objIsNullLabel);
             Il.Pop();
             Il.Ldloc(temp);
         }
         return(true);
     }
     return(false);
 }
        protected override bool EmitInternal(TryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            var il = context.Il;

            il.BeginExceptionBlock();
            returnDefaultValueLabel = context.CanReturn ? il.DefineLabel("returnDefaultValue") : null;
            bool returnDefaultValueLabelUsed = ExpressionEmittersCollection.Emit(node.Body, context, returnDefaultValueLabel, whatReturn, extend, out resultType);

            EmittingContext.LocalHolder retValue = null;
            var doneLabel = il.DefineLabel("done");

            if (resultType == typeof(void))
            {
                if (returnDefaultValueLabelUsed)
                {
                    context.MarkLabelAndSurroundWithSP(returnDefaultValueLabel);
                }
                il.Leave(doneLabel);
            }
            else
            {
                retValue = context.DeclareLocal(resultType);
                il.Stloc(retValue);
                il.Leave(doneLabel);
                if (returnDefaultValueLabelUsed)
                {
                    context.MarkLabelAndSurroundWithSP(returnDefaultValueLabel);
                    if (resultType.IsValueType)
                    {
                        il.Ldloca(retValue);
                        il.Initobj(resultType);
                    }
                    else
                    {
                        il.Ldnull();
                        il.Stloc(retValue);
                    }
                    il.Leave(doneLabel);
                }
            }
            foreach (var catchBlock in node.Handlers)
            {
                bool disposeVariable = false;
                var  variable        = catchBlock.Variable;
                if (catchBlock.Filter == null)
                {
                    il.BeginCatchBlock(catchBlock.Test);
                    if (variable == null)
                    {
                        il.Pop();
                    }
                    else
                    {
                        // todo вызвать ф-цию из AssignExpressionEmitter
                        var index = Array.IndexOf(context.Parameters, variable);
                        if (index >= 0)
                        {
                            il.Starg(index);
                        }
                        else
                        {
                            GroboIL.Local local;
                            if (!context.VariablesToLocals.TryGetValue(variable, out local))
                            {
                                local = context.DeclareLocal(variable.Type);
                                context.VariablesToLocals.Add(variable, local);
                                context.Variables.Push(variable);
                                disposeVariable = true;
                            }
                            il.Stloc(local);
                        }
                    }
                }
                else
                {
                    il.BeginExceptFilterBlock();
                    il.Isinst(catchBlock.Test);
                    il.Dup();
                    var rightTypeLabel = il.DefineLabel("rightType");
                    il.Brtrue(rightTypeLabel);
                    il.Pop();
                    il.Ldc_I4(0);
                    var endFilterLabel = il.DefineLabel("endFilter");
                    il.Br(endFilterLabel);
                    context.MarkLabelAndSurroundWithSP(rightTypeLabel);
                    if (variable == null)
                    {
                        il.Pop();
                    }
                    else
                    {
                        // todo вызвать ф-цию из AssignExpressionEmitter
                        var index = Array.IndexOf(context.Parameters, variable);
                        if (index >= 0)
                        {
                            il.Starg(index);
                        }
                        else
                        {
                            GroboIL.Local local;
                            if (!context.VariablesToLocals.TryGetValue(variable, out local))
                            {
                                local = string.IsNullOrEmpty(variable.Name)
                                                ? context.Il.DeclareLocal(variable.Type)
                                                : context.Il.DeclareLocal(variable.Type, variable.Name, appendUniquePrefix: false);
                                if (context.DebugInfoGenerator != null)
                                {
                                    local.SetLocalSymInfo(local.Name);
                                }
                                context.VariablesToLocals.Add(variable, local);
                                context.Variables.Push(variable);
                                disposeVariable = true;
                            }
                            il.Stloc(local);
                        }
                    }
                    GroboIL.Label returnFalseLabel = context.CanReturn ? il.DefineLabel("returnFalse") : null;
                    Type          filterResultType;
                    bool          returnFalseLabelUsed = ExpressionEmittersCollection.Emit(catchBlock.Filter, context, returnFalseLabel, out filterResultType);
                    if (returnFalseLabelUsed)
                    {
                        il.Br(endFilterLabel);
                        context.MarkLabelAndSurroundWithSP(returnFalseLabel);
                        il.Pop();
                        il.Ldc_I4(0);
                    }
                    context.MarkLabelAndSurroundWithSP(endFilterLabel);
                    il.BeginCatchBlock(null);
                    il.Pop();
                }

                context.EmitLoadArguments(catchBlock.Body);
                if (catchBlock.Body.Type != typeof(void))
                {
                    il.Stloc(retValue);
                }

                if (disposeVariable)
                {
                    context.VariablesToLocals.Remove(variable);
                    context.Variables.Pop();
                }
            }

            if (node.Fault != null)
            {
                il.BeginFaultBlock();
                EmitExpressionAsVoid(node.Fault, context);
            }

            if (node.Finally != null)
            {
                il.BeginFinallyBlock();
                EmitExpressionAsVoid(node.Finally, context);
            }

            il.EndExceptionBlock();

            context.MarkLabelAndSurroundWithSP(doneLabel);
            if (retValue != null)
            {
                il.Ldloc(retValue);
                retValue.Dispose();
            }
            return(false);
        }
        protected override bool EmitInternal(UnaryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            Type    operandType;
            var     result = ExpressionEmittersCollection.Emit(node.Operand, context, returnDefaultValueLabel, ResultType.Value, extend, out operandType);
            GroboIL il     = context.Il;

            if (node.NodeType == ExpressionType.IsTrue || node.NodeType == ExpressionType.IsFalse)
            {
                if (!operandType.IsNullable())
                {
                    if (node.Method != null)
                    {
                        il.Call(node.Method);
                    }
                    else if (operandType == typeof(bool))
                    {
                        if (node.NodeType == ExpressionType.IsFalse)
                        {
                            il.Ldc_I4(1);
                            il.Xor();
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'");
                    }
                }
                else
                {
                    using (var temp = context.DeclareLocal(operandType))
                    {
                        il.Stloc(temp);
                        il.Ldloca(temp);
                        context.EmitHasValueAccess(operandType);
                        var returnFalseLabel = il.DefineLabel("returnFalse");
                        il.Brfalse(returnFalseLabel);
                        il.Ldloca(temp);
                        context.EmitValueAccess(operandType);
                        if (node.Method != null)
                        {
                            il.Call(node.Method);
                        }
                        else if (operandType == typeof(bool?))
                        {
                            if (node.NodeType == ExpressionType.IsFalse)
                            {
                                il.Ldc_I4(1);
                                il.Xor();
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a type '" + operandType + "'");
                        }
                        var doneLabel = il.DefineLabel("done");
                        il.Br(doneLabel);
                        context.MarkLabelAndSurroundWithSP(returnFalseLabel);
                        il.Ldc_I4(0);
                        context.MarkLabelAndSurroundWithSP(doneLabel);
                    }
                }
            }
            else
            {
                if (!operandType.IsNullable())
                {
                    if (node.Method != null)
                    {
                        il.Call(node.Method);
                    }
                    else
                    {
                        if (operandType.IsStruct())
                        {
                            throw new InvalidOperationException("Cannot perform operation '" + node.NodeType + "' to a struct '" + operandType + "'");
                        }
                        switch (node.NodeType)
                        {
                        case ExpressionType.UnaryPlus:
                            break;

                        case ExpressionType.Negate:
                            il.Neg();
                            break;

                        case ExpressionType.NegateChecked:
                            using (var temp = context.DeclareLocal(operandType))
                            {
                                il.Stloc(temp);
                                il.Ldc_I4(0);
                                context.EmitConvert(typeof(int), operandType);
                                il.Ldloc(temp);
                                il.Sub_Ovf(operandType.Unsigned());
                            }
                            break;

                        case ExpressionType.Increment:
                            il.Ldc_I4(1);
                            context.EmitConvert(typeof(int), operandType);
                            il.Add();
                            break;

                        case ExpressionType.Decrement:
                            il.Ldc_I4(1);
                            context.EmitConvert(typeof(int), operandType);
                            il.Sub();
                            break;

                        case ExpressionType.OnesComplement:
                            il.Not();
                            break;

                        default:
                            throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point");
                        }
                    }
                }
                else
                {
                    using (var temp = context.DeclareLocal(operandType))
                    {
                        il.Stloc(temp);
                        il.Ldloca(temp);
                        context.EmitHasValueAccess(operandType);
                        var returnNullLabel = il.DefineLabel("returnLabel");
                        il.Brfalse(returnNullLabel);
                        Type argumentType = operandType.GetGenericArguments()[0];
                        if (node.Method != null)
                        {
                            il.Ldloca(temp);
                            context.EmitValueAccess(operandType);
                            il.Call(node.Method);
                        }
                        else
                        {
                            switch (node.NodeType)
                            {
                            case ExpressionType.UnaryPlus:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                break;

                            case ExpressionType.Negate:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Neg();
                                break;

                            case ExpressionType.NegateChecked:
                                il.Ldc_I4(0);
                                context.EmitConvert(typeof(int), argumentType);
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Sub_Ovf(argumentType.Unsigned());
                                break;

                            case ExpressionType.Increment:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Ldc_I4(1);
                                context.EmitConvert(typeof(int), argumentType);
                                il.Add();
                                break;

                            case ExpressionType.Decrement:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Ldc_I4(1);
                                context.EmitConvert(typeof(int), argumentType);
                                il.Sub();
                                break;

                            case ExpressionType.OnesComplement:
                                il.Ldloca(temp);
                                context.EmitValueAccess(operandType);
                                il.Not();
                                break;

                            default:
                                throw new InvalidOperationException("Node type '" + node.NodeType + "' invalid at this point");
                            }
                        }
                        il.Newobj(operandType.GetConstructor(new[] { argumentType }));
                        var doneLabel = il.DefineLabel("done");
                        il.Br(doneLabel);
                        context.MarkLabelAndSurroundWithSP(returnNullLabel);
                        context.EmitLoadDefaultValue(operandType);
                        context.MarkLabelAndSurroundWithSP(doneLabel);
                    }
                }
            }
            resultType = node.Type;
            return(result);
        }
Exemple #28
0
        public int GetLabelLineNumber(GroboIL.Label label)
        {
            int result;

            return(labelLineNumbers.TryGetValue(label, out result) ? result : -1);
        }
 private static void EmitStatic(GroboIL il, MethodInfo getMethod, MethodInfo staticMethod, GroboIL.Label returnFalse)
 {
     // Equals(a.Property, b.Property)
     il.Ldarg(0);
     il.Call(getMethod);
     il.Ldarg(1);
     il.Call(getMethod);
     il.Call(staticMethod);
     il.Brfalse(returnFalse);
 }
        protected override bool EmitInternal(LambdaExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            var parameterTypes = node.Parameters.Select(parameter => parameter.Type).ToArray();

            Type[] constantTypes;
            var    compiledLambda = CompileAndLoadConstants(node, context, out constantTypes);

            var  il = context.Il;
            Type rawSubLambdaType;

            if (!Extensions.IsMono)
            {
                context.LoadCompiledLambdaPointer(compiledLambda);
                rawSubLambdaType = typeof(IntPtr);
            }
            else
            {
                rawSubLambdaType = Extensions.GetDelegateType(constantTypes.Concat(parameterTypes).ToArray(), node.ReturnType);
                context.LoadCompiledLambda(compiledLambda);
                il.Castclass(rawSubLambdaType);
            }

            resultType = Extensions.GetDelegateType(parameterTypes, node.ReturnType);
            var types            = constantTypes.Concat(new[] { rawSubLambdaType }).ToArray();
            var module           = (ModuleBuilder)(context.TypeBuilder == null ? null : context.TypeBuilder.Module);
            var subLambdaInvoker = DynamicMethodInvokerBuilder.BuildDynamicMethodInvoker(module, constantTypes, node.ReturnType, parameterTypes);

            il.Newobj(subLambdaInvoker.GetConstructor(types));
            il.Ldftn(subLambdaInvoker.GetMethod("Invoke"));
            il.Newobj(resultType.GetConstructor(new[] { typeof(object), typeof(IntPtr) }));
            return(false);
        }