public virtual void Emit(EmitContext ec) { if (!IsByRef) { Expr.Emit(ec); return; } AddressOp mode = AddressOp.Store; if (ArgType == AType.Ref) { mode |= AddressOp.Load; } IMemoryLocation ml = (IMemoryLocation)Expr; ParameterReference pr = ml as ParameterReference; // // ParameterReferences might already be references, so we want // to pass just the value // if (pr != null && pr.IsRef) { pr.EmitLoad(ec); } else { ml.AddressOf(ec, mode); } }
public virtual void Emit(EmitContext ec) { if (!IsByRef) { if (ArgType == AType.ExtensionTypeConditionalAccess) { var ie = new InstanceEmitter(Expr, false); ie.Emit(ec, true); } else { Expr.Emit(ec); } return; } AddressOp mode = AddressOp.Store; if (ArgType == AType.Ref) { mode |= AddressOp.Load; } IMemoryLocation ml = (IMemoryLocation)Expr; ml.AddressOf(ec, mode); }
public void AddressOf(EmitContext ec, AddressOp mode) { IMemoryLocation ml = expr as VariableReference; if (ml != null) { ml.AddressOf(ec, mode); } else { LocalVariable.AddressOf(ec, mode); } }
public virtual void Emit(EmitContext ec) { if (!IsByRef) { Expr.Emit(ec); return; } AddressOp mode = AddressOp.Store; if (ArgType == AType.Ref) { mode |= AddressOp.Load; } IMemoryLocation ml = (IMemoryLocation)Expr; ml.AddressOf(ec, mode); }
public void Emit(EmitContext ec, bool conditionalAccess) { Label NullOperatorLabel; Nullable.Unwrap unwrap; if (conditionalAccess && Expression.IsNeverNull(instance)) { conditionalAccess = false; } if (conditionalAccess) { NullOperatorLabel = ec.DefineLabel(); unwrap = instance as Nullable.Unwrap; } else { NullOperatorLabel = new Label(); unwrap = null; } IMemoryLocation instance_address = null; bool conditional_access_dup = false; if (unwrap != null) { unwrap.Store(ec); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel); } else { if (conditionalAccess && addressRequired) { // // Don't allocate temp variable when instance load is cheap and load and load-address // operate on same memory // instance_address = instance as VariableReference; if (instance_address == null) { instance_address = instance as LocalTemporary; } if (instance_address == null) { EmitLoad(ec, false); ec.Emit(OpCodes.Dup); ec.EmitLoadFromPtr(instance.Type); conditional_access_dup = true; } else { instance.Emit(ec); } } else { EmitLoad(ec, !conditionalAccess); if (conditionalAccess) { conditional_access_dup = !IsInexpensiveLoad(); if (conditional_access_dup) { ec.Emit(OpCodes.Dup); } } } if (conditionalAccess) { if (instance.Type.Kind == MemberKind.TypeParameter) { ec.Emit(OpCodes.Box, instance.Type); } ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel); if (conditional_access_dup) { ec.Emit(OpCodes.Pop); } } } if (conditionalAccess) { if (!ec.ConditionalAccess.Statement) { if (ec.ConditionalAccess.Type.IsNullableType) { Nullable.LiftedNull.Create(ec.ConditionalAccess.Type, Location.Null).Emit(ec); } else { ec.EmitNull(); } } ec.Emit(OpCodes.Br, ec.ConditionalAccess.EndLabel); ec.MarkLabel(NullOperatorLabel); if (instance_address != null) { instance_address.AddressOf(ec, AddressOp.Load); } else if (unwrap != null) { unwrap.Emit(ec); var tmp = ec.GetTemporaryLocal(unwrap.Type); ec.Emit(OpCodes.Stloc, tmp); ec.Emit(OpCodes.Ldloca, tmp); ec.FreeTemporaryLocal(tmp, unwrap.Type); } else if (!conditional_access_dup) { instance.Emit(ec); } } }
public override bool Emit (EmitContext ec, IMemoryLocation target) { bool left_on_stack = base.Emit (ec, target); if (initializers.IsEmpty) return left_on_stack; LocalTemporary temp = target as LocalTemporary; if (temp == null) { if (!left_on_stack) { VariableReference vr = target as VariableReference; // FIXME: This still does not work correctly for pre-set variables if (vr != null && vr.IsRef) target.AddressOf (ec, AddressOp.Load); ((Expression) target).Emit (ec); left_on_stack = true; } temp = new LocalTemporary (type); } instance = temp; if (left_on_stack) temp.Store (ec); initializers.Emit (ec); if (left_on_stack) { temp.Emit (ec); temp.Release (ec); } return left_on_stack; }
// // This Emit can be invoked in two contexts: // * As a mechanism that will leave a value on the stack (new object) // * As one that wont (init struct) // // If we are dealing with a ValueType, we have a few // situations to deal with: // // * The target is a ValueType, and we have been provided // the instance (this is easy, we are being assigned). // // * The target of New is being passed as an argument, // to a boxing operation or a function that takes a // ValueType. // // In this case, we need to create a temporary variable // that is the argument of New. // // Returns whether a value is left on the stack // // *** Implementation note *** // // To benefit from this optimization, each assignable expression // has to manually cast to New and call this Emit. // // TODO: It's worth to implement it for arrays and fields // public virtual bool Emit (EmitContext ec, IMemoryLocation target) { bool is_value_type = TypeManager.IsValueType (type); ILGenerator ig = ec.ig; VariableReference vr = target as VariableReference; if (target != null && is_value_type && (vr != null || method == null)) { target.AddressOf (ec, AddressOp.Store); } else if (vr != null && vr.IsRef) { vr.EmitLoad (ec); } if (Arguments != null) Arguments.Emit (ec); if (is_value_type) { if (method == null) { ig.Emit (OpCodes.Initobj, type); return false; } if (vr != null) { ig.Emit (OpCodes.Call, (ConstructorInfo) method); return false; } } if (is_type_parameter) return DoEmitTypeParameter (ec); ConstructorInfo ci = (ConstructorInfo) method; #if MS_COMPATIBLE if (TypeManager.IsGenericType (type) && type.IsGenericTypeDefinition) ci = TypeBuilder.GetConstructor (type, ci); #endif ig.Emit (OpCodes.Newobj, ci); return true; }