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