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); } }
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); } }
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); } }