private void EmitVariableAssignment(BinaryExpression node, EmitAs emitAs)
        {
            var variable = (ParameterExpression)node.Left;

            EmitExpression(node.Right);
            if (emitAs != EmitAs.Void)
            {
                _ilg.Emit(OpCodes.Dup);
            }

            if (variable.IsByRef)
            {
                // Note: the stloc/ldloc pattern is a bit suboptimal, but it
                // saves us from having to spill stack when assigning to a
                // byref parameter. We already make this same tradeoff for
                // hoisted variables, see ElementStorage.EmitStore

                LocalBuilder value = _ilg.GetLocal(variable.Type);
                _ilg.Emit(OpCodes.Stloc, value);
                _scope.EmitGet(variable);
                _ilg.Emit(OpCodes.Ldloc, value);
                _ilg.FreeLocal(value);
                _ilg.EmitStoreValueIndirect(variable.Type);
            }
            else
            {
                _scope.EmitSet(variable);
            }
        }
        private void Emit(BlockExpression node, EmitAs emitAs) {
            EnterScope(node);

            int count = node.ExpressionCount;
            for (int index = 0; index < count - 1; index++) {
                var e = node.GetExpression(index);

                if (_emitDebugSymbols) {
                    //No need to emit a clearance if the next expression in the block is also a
                    //DebugInfoExprssion.
                    var debugInfo = e as DebugInfoExpression;
                    if (debugInfo != null && debugInfo.IsClear && node.GetExpression(index + 1) is DebugInfoExpression) {
                        continue;
                    }
                }
                EmitExpressionAsVoid(e);
            }

            // if the type of Block it means this is not a Comma
            // so we will force the last expression to emit as void.
            if (emitAs == EmitAs.Void || node.Type == typeof(void)) {
                EmitExpressionAsVoid(node.GetExpression(count - 1));
            } else {
                EmitExpressionAsType(node.GetExpression(count - 1), node.Type);
            }

            ExitScope(node);
        }
        private void EmitArrayIndexAssignment(BinaryExpression node, EmitAs emitAs)
        {
            Debug.Assert(node.NodeType == ExpressionType.ArrayIndex);
            var arrayIndex = (BinaryExpression)node.Left;

            // Emit array object
            EmitInstance(arrayIndex.Left, arrayIndex.Left.Type);

            // Emit index
            EmitExpression(arrayIndex.Right);

            // Emit value
            EmitExpression(node.Right);

            // Save the expression value, if needed
            LocalBuilder temp = null;

            if (emitAs != EmitAs.Void)
            {
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Stloc, temp = _ilg.GetLocal(node.Type));
            }

            _ilg.EmitStoreElement(arrayIndex.Type);

            // Restore the value
            if (emitAs != EmitAs.Void)
            {
                _ilg.Emit(OpCodes.Ldloc, temp);
                _ilg.FreeLocal(temp);
            }
        }
        private void Emit(BlockExpression node, EmitAs emitAs) {
            int count = node.ExpressionCount;

            // Labels defined immediately in the block are valid for the whole block

            for(int i = 0; i < count; i++) {
                Expression e = node.GetExpression(i);

                var label = e as LabelExpression;
                if (label != null) {
                    DefineLabel(label.Label);
                }
            }

            EnterScope(node);

            for (int index = 0; index < count - 1; index++) {
                EmitExpressionAsVoid(node.GetExpression(index));
            }

            // if the type of Block it means this is not a Comma
            // so we will force the last expression to emit as void.
            if (emitAs == EmitAs.Void || node.Type == typeof(void)) {
                EmitExpressionAsVoid(node.GetExpression(count - 1));
            } else {
                EmitExpression(node.GetExpression(count - 1));
            }

            ExitScope(node);
        }
        private void EmitThrow(UnaryExpression expr, EmitAs emitAs) {
            if (expr.Operand == null) {
                CheckRethrow();

                _ilg.Emit(OpCodes.Rethrow);
            } else {
                EmitExpression(expr.Operand);
                _ilg.Emit(OpCodes.Throw);
            }
            if (emitAs != EmitAs.Void && expr.Type != typeof(void)) {
                _ilg.EmitDefault(expr.Type);
            }
        }
        private void EmitMemberAssignment(BinaryExpression node, EmitAs emitAs)
        {
            MemberExpression lvalue = (MemberExpression)node.Left;
            MemberInfo       member = lvalue.Member;

            // emit "this", if any
            Type objectType = null;

            if (lvalue.Expression != null)
            {
                EmitInstance(lvalue.Expression, objectType = lvalue.Expression.Type);
            }

            // emit value
            EmitExpression(node.Right);

            LocalBuilder temp = null;

            if (emitAs != EmitAs.Void)
            {
                // save the value so we can return it
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Stloc, temp = _ilg.GetLocal(node.Type));
            }

            switch (member.MemberType)
            {
            case MemberTypes.Field:
                _ilg.EmitFieldSet((FieldInfo)member);
                break;

            case MemberTypes.Property:
                EmitCall(objectType, ((PropertyInfo)member).GetSetMethod(true));
                break;

            default:
                throw Error.InvalidMemberType(member.MemberType);
            }

            if (emitAs != EmitAs.Void)
            {
                _ilg.Emit(OpCodes.Ldloc, temp);
                _ilg.FreeLocal(temp);
            }
        }
Exemple #7
0
        private void EmitThrow(UnaryExpression expr, EmitAs emitAs)
        {
            if (expr.Operand == null)
            {
                CheckRethrow();

                _ilg.Emit(OpCodes.Rethrow);
            }
            else
            {
                EmitExpression(expr.Operand);
                _ilg.Emit(OpCodes.Throw);
            }
            if (emitAs != EmitAs.Void && expr.Type != typeof(void))
            {
                _ilg.EmitDefault(expr.Type);
            }
        }
        private void EmitIndexAssignment(BinaryExpression node, EmitAs emitAs)
        {
            var index = (IndexExpression)node.Left;

            // Emit instance, if calling an instance method
            Type objectType = null;

            if (index.Object != null)
            {
                EmitInstance(index.Object, objectType = index.Object.Type);
            }

            // Emit indexes. We don't allow byref args, so no need to worry
            // about writebacks or EmitAddress
            foreach (var arg in index.Arguments)
            {
                EmitExpression(arg);
            }

            // Emit value
            EmitExpression(node.Right);

            // Save the expression value, if needed
            LocalBuilder temp = null;

            if (emitAs != EmitAs.Void)
            {
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Stloc, temp = _ilg.GetLocal(node.Type));
            }

            EmitSetIndexCall(index, objectType);

            // Restore the value
            if (emitAs != EmitAs.Void)
            {
                _ilg.Emit(OpCodes.Ldloc, temp);
                _ilg.FreeLocal(temp);
            }
        }
Exemple #9
0
        private void Emit(BlockExpression node, EmitAs emitAs)
        {
            int count = node.ExpressionCount;

            // Labels defined immediately in the block are valid for the whole block

            for (int i = 0; i < count; i++)
            {
                Expression e = node.GetExpression(i);

                var label = e as LabelExpression;
                if (label != null)
                {
                    DefineLabel(label.Label);
                }
            }

            EnterScope(node);

            for (int index = 0; index < count - 1; index++)
            {
                EmitExpressionAsVoid(node.GetExpression(index));
            }

            // if the type of Block it means this is not a Comma
            // so we will force the last expression to emit as void.
            if (emitAs == EmitAs.Void || node.Type == typeof(void))
            {
                EmitExpressionAsVoid(node.GetExpression(count - 1));
            }
            else
            {
                EmitExpression(node.GetExpression(count - 1));
            }

            ExitScope(node);
        }
        private void EmitAssign(BinaryExpression node, EmitAs emitAs)
        {
            switch (node.Left.NodeType)
            {
            case ExpressionType.Index:
                EmitIndexAssignment(node, emitAs);
                return;

            case ExpressionType.MemberAccess:
                EmitMemberAssignment(node, emitAs);
                return;

            case ExpressionType.Parameter:
                EmitVariableAssignment(node, emitAs);
                return;

            case ExpressionType.ArrayIndex:
                EmitArrayIndexAssignment(node, emitAs);
                return;

            default:
                throw Error.InvalidLvalue(node.Left.NodeType);
            }
        }
        private void EmitMemberAssignment(BinaryExpression node, EmitAs emitAs) {
            MemberExpression lvalue = (MemberExpression)node.Left;
            MemberInfo member = lvalue.Member;

            // emit "this", if any
            Type objectType = null;
            if (lvalue.Expression != null) {
                EmitInstance(lvalue.Expression, objectType = lvalue.Expression.Type);
            }

            // emit value
            EmitExpression(node.Right);

            LocalBuilder temp = null;
            if (emitAs != EmitAs.Void) {
                // save the value so we can return it
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Stloc, temp = _ilg.GetLocal(node.Type));
            }

            switch (member.MemberType) {
                case MemberTypes.Field:
                    _ilg.EmitFieldSet((FieldInfo)member);
                    break;
                case MemberTypes.Property:
                    EmitCall(objectType, ((PropertyInfo)member).GetSetMethod(true));
                    break;
                default:
                    throw Error.InvalidMemberType(member.MemberType);
            }

            if (emitAs != EmitAs.Void) {
                _ilg.Emit(OpCodes.Ldloc, temp);
                _ilg.FreeLocal(temp);
            }
        }
 private void EmitAssign(BinaryExpression node, EmitAs emitAs) {
     switch (node.Left.NodeType) {
         case ExpressionType.Index:
             EmitIndexAssignment(node, emitAs);
             return;
         case ExpressionType.MemberAccess:
             EmitMemberAssignment(node, emitAs);
             return;
         case ExpressionType.Parameter:
             EmitVariableAssignment(node, emitAs);
             return;
         case ExpressionType.ArrayIndex:
             EmitArrayIndexAssignment(node, emitAs);
             return;
         default:
             throw Error.InvalidLvalue(node.Left.NodeType);
     }
 }
        private void EmitVariableAssignment(BinaryExpression node, EmitAs emitAs) {
            var variable = (ParameterExpression)node.Left;

            EmitExpression(node.Right);
            if (emitAs != EmitAs.Void) {
                _ilg.Emit(OpCodes.Dup);
            }

            if (variable.IsByRef) {
                // Note: the stloc/ldloc pattern is a bit suboptimal, but it
                // saves us from having to spill stack when assigning to a
                // byref parameter. We already make this same tradeoff for
                // hoisted variables, see ElementStorage.EmitStore

                LocalBuilder value = _ilg.GetLocal(variable.Type);
                _ilg.Emit(OpCodes.Stloc, value);
                _scope.EmitGet(variable);
                _ilg.Emit(OpCodes.Ldloc, value);
                _ilg.FreeLocal(value);
                _ilg.EmitStoreValueIndirect(variable.Type);
            } else {
                _scope.EmitSet(variable);
            }
        }
        private void EmitArrayIndexAssignment(BinaryExpression node, EmitAs emitAs) {
            Debug.Assert(node.NodeType == ExpressionType.ArrayIndex);
            var arrayIndex = (BinaryExpression)node.Left;

            // Emit array object
            EmitInstance(arrayIndex.Left, arrayIndex.Left.Type);

            // Emit index
            EmitExpression(arrayIndex.Right);

            // Emit value
            EmitExpression(node.Right);

            // Save the expression value, if needed
            LocalBuilder temp = null;
            if (emitAs != EmitAs.Void) {
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Stloc, temp = _ilg.GetLocal(node.Type));
            }

            _ilg.EmitStoreElement(arrayIndex.Type);

            // Restore the value
            if (emitAs != EmitAs.Void) {
                _ilg.Emit(OpCodes.Ldloc, temp);
                _ilg.FreeLocal(temp);
            }
        }
        private void EmitIndexAssignment(BinaryExpression node, EmitAs emitAs) {
            var index = (IndexExpression)node.Left;

            // Emit instance, if calling an instance method
            Type objectType = null;
            if (index.Object != null) {
                EmitInstance(index.Object, objectType = index.Object.Type);
            }

            // Emit indexes. We don't allow byref args, so no need to worry
            // about writebacks or EmitAddress
            foreach (var arg in index.Arguments) {
                EmitExpression(arg);
            }

            // Emit value
            EmitExpression(node.Right);

            // Save the expression value, if needed
            LocalBuilder temp = null;
            if (emitAs != EmitAs.Void) {
                _ilg.Emit(OpCodes.Dup);
                _ilg.Emit(OpCodes.Stloc, temp = _ilg.GetLocal(node.Type));
            }

            EmitSetIndexCall(index, objectType);

            // Restore the value
            if (emitAs != EmitAs.Void) {
                _ilg.Emit(OpCodes.Ldloc, temp);
                _ilg.FreeLocal(temp);
            }
        }