static TypeSpec EmitCallInstance(EmitContext ec, Expression instance, TypeSpec declaringType, OpCode callOpcode) { var instance_type = instance.Type; // // Push the instance expression // if ((instance_type.IsStruct && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType.IsStruct))) || instance_type.IsGenericParameter || declaringType.IsNullableType) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf(ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary(instance_type); instance.Emit(ec); temp.Store(ec); temp.AddressOf(ec, AddressOp.Load); temp.Release(ec); } return(ReferenceContainer.MakeType(ec.Module, instance_type)); } if (instance_type.IsEnum || instance_type.IsStruct) { instance.Emit(ec); ec.Emit(OpCodes.Box, instance_type); return(ec.BuiltinTypes.Object); } instance.Emit(ec); return(instance_type); }
public void EmitLoad(EmitContext ec) { var instance_type = instance.Type; // // Push the instance expression // if (addressRequired) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf(ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary(instance_type); instance.Emit(ec); temp.Store(ec); temp.AddressOf(ec, AddressOp.Load); } return; } instance.Emit(ec); // Only to make verifier happy if (instance_type.IsGenericParameter && !(instance is This) && TypeSpec.IsReferenceType(instance_type)) { ec.Emit(OpCodes.Box, instance_type); } else if (instance_type.IsStructOrEnum) { ec.Emit(OpCodes.Box, instance_type); } }
public void EmitLoad(EmitContext ec, bool boxInstance) { var instance_type = instance.Type; // // Push the instance expression // if (addressRequired) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf(ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary(instance_type); instance.Emit(ec); temp.Store(ec); temp.AddressOf(ec, AddressOp.Load); } return; } instance.Emit(ec); // Only to make verifier happy if (boxInstance && RequiresBoxing()) { ec.Emit(OpCodes.Box, instance_type); } }
public void EmitLoad (EmitContext ec, bool boxInstance) { var instance_type = instance.Type; // // Push the instance expression // if (addressRequired) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf (ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary (instance_type); instance.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); } return; } instance.Emit (ec); // Only to make verifier happy if (boxInstance && RequiresBoxing ()) { ec.Emit (OpCodes.Box, instance_type); } }
static TypeSpec EmitCallInstance (EmitContext ec, Expression instance, TypeSpec declaringType, OpCode callOpcode) { var instance_type = instance.Type; // // Push the instance expression // if ((instance_type.IsStructOrEnum && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType.IsStruct))) || instance_type.IsGenericParameter || declaringType.IsNullableType) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf (ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary (instance_type); instance.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); } return ReferenceContainer.MakeType (ec.Module, instance_type); } if (instance_type.IsStructOrEnum) { instance.Emit (ec); ec.Emit (OpCodes.Box, instance_type); return ec.BuiltinTypes.Object; } instance.Emit (ec); return instance_type; }
protected void EmitInstance(EmitContext ec, bool prepare_for_load) { if (IsStatic) return; if (InstanceExpression == EmptyExpression.Null) { // FIXME: This should not be here at all SimpleName.Error_ObjectRefRequired (new ResolveContext (ec.MemberContext), loc, GetSignatureForError ()); return; } if (TypeManager.IsValueType (InstanceExpression.Type)) { if (InstanceExpression is IMemoryLocation) { ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore); } else { LocalTemporary t = new LocalTemporary (InstanceExpression.Type); InstanceExpression.Emit (ec); t.Store (ec); t.AddressOf (ec, AddressOp.Store); } } else InstanceExpression.Emit (ec); if (prepare_for_load) ec.Emit (OpCodes.Dup); }
protected void EmitInstance (EmitContext ec, bool prepare_for_load) { if (IsStatic) return; if (InstanceExpression == EmptyExpression.Null) { SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return; } if (InstanceExpression.Type.IsValueType) { if (InstanceExpression is IMemoryLocation) { ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore); } else { LocalTemporary t = new LocalTemporary (InstanceExpression.Type); InstanceExpression.Emit (ec); t.Store (ec); t.AddressOf (ec, AddressOp.Store); } } else InstanceExpression.Emit (ec); if (prepare_for_load) ec.ig.Emit (OpCodes.Dup); }
public void EmitLoad (EmitContext ec) { var instance_type = instance.Type; // // Push the instance expression // if (addressRequired) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. var iml = instance as IMemoryLocation; if (iml != null) { iml.AddressOf (ec, AddressOp.Load); } else { LocalTemporary temp = new LocalTemporary (instance_type); instance.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); } return; } instance.Emit (ec); // Only to make verifier happy if (instance_type.IsGenericParameter && !(instance is This) && TypeSpec.IsReferenceType (instance_type)) { ec.Emit (OpCodes.Box, instance_type); } else if (instance_type.IsStructOrEnum) { ec.Emit (OpCodes.Box, instance_type); } }
protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode) { LocalTemporary value_target = new LocalTemporary (type); if (is_type_parameter) { DoEmitTypeParameter (ec); value_target.Store (ec); value_target.AddressOf (ec, mode); return value_target; } if (!TypeManager.IsStruct (type)){ // // We throw an exception. So far, I believe we only need to support // value types: // foreach (int j in new StructType ()) // see bug 42390 // throw new Exception ("AddressOf should not be used for classes"); } value_target.AddressOf (ec, AddressOp.Store); if (method == null) { ec.ig.Emit (OpCodes.Initobj, type); } else { if (Arguments != null) Arguments.Emit (ec); ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method); } value_target.AddressOf (ec, mode); return value_target; }
bool DoEmitTypeParameter (EmitContext ec) { #if GMCS_SOURCE ILGenerator ig = ec.ig; // IMemoryLocation ml; MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod ( new Type [] { type }); GenericConstraints gc = TypeManager.GetTypeParameterConstraints (type); if (gc.HasReferenceTypeConstraint || gc.HasClassConstraint) { ig.Emit (OpCodes.Call, ci); return true; } // Allow DoEmit() to be called multiple times. // We need to create a new LocalTemporary each time since // you can't share LocalBuilders among ILGeneators. LocalTemporary temp = new LocalTemporary (type); Label label_activator = ig.DefineLabel (); Label label_end = ig.DefineLabel (); temp.AddressOf (ec, AddressOp.Store); ig.Emit (OpCodes.Initobj, type); temp.Emit (ec); ig.Emit (OpCodes.Box, type); ig.Emit (OpCodes.Brfalse, label_activator); temp.AddressOf (ec, AddressOp.Store); ig.Emit (OpCodes.Initobj, type); temp.Emit (ec); ig.Emit (OpCodes.Br_S, label_end); ig.MarkLabel (label_activator); ig.Emit (OpCodes.Call, ci); ig.MarkLabel (label_end); return true; #else throw new InternalErrorException (); #endif }
// `dup_args' leaves an extra copy of the arguments on the stack // `omit_args' does not leave any arguments at all. // So, basically, you could make one call with `dup_args' set to true, // and then another with `omit_args' set to true, and the two calls // would have the same set of arguments. However, each argument would // only have been evaluated once. public static void EmitCall (EmitContext ec, bool is_base, Expression instance_expr, MethodBase method, Arguments Arguments, Location loc, bool dup_args, bool omit_args) { ILGenerator ig = ec.ig; bool struct_call = false; bool this_call = false; LocalTemporary this_arg = null; Type decl_type = method.DeclaringType; if (IsMethodExcluded (method, loc)) return; bool is_static = method.IsStatic; if (!is_static){ this_call = instance_expr is This; if (TypeManager.IsStruct (decl_type) || TypeManager.IsEnumType (decl_type)) struct_call = true; // // If this is ourselves, push "this" // if (!omit_args) { Type t = null; Type iexpr_type = instance_expr.Type; // // Push the instance expression // if (TypeManager.IsValueType (iexpr_type) || TypeManager.IsGenericParameter (iexpr_type)) { // // Special case: calls to a function declared in a // reference-type with a value-type argument need // to have their value boxed. if (TypeManager.IsStruct (decl_type) || TypeManager.IsGenericParameter (iexpr_type)) { // // If the expression implements IMemoryLocation, then // we can optimize and use AddressOf on the // return. // // If not we have to use some temporary storage for // it. if (instance_expr is IMemoryLocation) { ((IMemoryLocation)instance_expr). AddressOf (ec, AddressOp.LoadStore); } else { LocalTemporary temp = new LocalTemporary (iexpr_type); instance_expr.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); } // avoid the overhead of doing this all the time. if (dup_args) t = TypeManager.GetReferenceType (iexpr_type); } else { instance_expr.Emit (ec); // FIXME: should use instance_expr is IMemoryLocation + constraint. // to help JIT to produce better code ig.Emit (OpCodes.Box, instance_expr.Type); t = TypeManager.object_type; } } else { instance_expr.Emit (ec); t = instance_expr.Type; } if (dup_args) { ig.Emit (OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { this_arg = new LocalTemporary (t); this_arg.Store (ec); } } } } if (!omit_args && Arguments != null) Arguments.Emit (ec, dup_args, this_arg); OpCode call_op; if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) { call_op = OpCodes.Call; } else { call_op = OpCodes.Callvirt; #if GMCS_SOURCE if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter)) ig.Emit (OpCodes.Constrained, instance_expr.Type); #endif } if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { Type[] varargs_types = GetVarargsTypes (method, Arguments); ig.EmitCall (call_op, (MethodInfo) method, varargs_types); return; } // // If you have: // this.DoFoo (); // and DoFoo is not virtual, you can omit the callvirt, // because you don't need the null checking behavior. // if (method is MethodInfo) ig.Emit (call_op, (MethodInfo) method); else ig.Emit (call_op, (ConstructorInfo) method); }
public override void Emit (EmitContext ec) { LocalTemporary temp_storage = new LocalTemporary(type); temp_storage.AddressOf(ec, AddressOp.LoadStore); ec.ig.Emit(OpCodes.Initobj, type); temp_storage.Emit(ec); }
public void AddressOf (EmitContext ec, AddressOp Mode) { if (is_type_parameter) { LocalTemporary temp = new LocalTemporary (type); DoEmitTypeParameter (ec); temp.Store (ec); temp.AddressOf (ec, Mode); return; } if (!type.IsValueType){ // // We throw an exception. So far, I believe we only need to support // value types: // foreach (int j in new StructType ()) // see bug 42390 // throw new Exception ("AddressOf should not be used for classes"); } LocalTemporary value_target = new LocalTemporary (type); IMemoryLocation ml = (IMemoryLocation) value_target; ml.AddressOf (ec, AddressOp.Store); if (method == null) { ec.ig.Emit (OpCodes.Initobj, type); } else { method.EmitArguments (ec, Arguments); ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method); } ((IMemoryLocation) value_target).AddressOf (ec, Mode); }