Bug fixes and a couple of optimizations (used a nice profiler to find
[mono.git] / mcs / mcs / expression.cs
index c491bc4d9cd5ed6da1bb5e061f9e8cb6c09ced06..bcb07955575522d34ff9611621962558a55ed8f6 100755 (executable)
@@ -125,7 +125,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Returns a stringified representation of the Operator
                /// </summary>
-               string OperName ()
+               static public string OperName (Operator oper)
                {
                        switch (oper){
                        case Operator.UnaryPlus:
@@ -159,10 +159,10 @@ namespace Mono.CSharp {
                        oper_names [(int) Operator.AddressOf] = "op_AddressOf";
                }
 
-               void error23 (Type t)
+               void Error23 (Type t)
                {
                        Report.Error (
-                               23, loc, "Operator " + OperName () +
+                               23, loc, "Operator " + OperName (oper) +
                                " cannot be applied to operand of type `" +
                                TypeManager.CSharpName (t) + "'");
                }
@@ -210,7 +210,7 @@ namespace Mono.CSharp {
                                
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
                                
@@ -223,7 +223,7 @@ namespace Mono.CSharp {
                                      (expr_type == TypeManager.int64_type) ||
                                      (expr_type == TypeManager.uint64_type) ||
                                      (expr_type.IsSubclassOf (TypeManager.enum_type)))){
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
 
@@ -244,9 +244,8 @@ namespace Mono.CSharp {
                                if (expr_type == TypeManager.uint64_type)
                                        return new ULongConstant (~ ((ULongConstant) e).Value);
 
-                               throw new Exception (
-                                       "FIXME: Implement constant OnesComplement of:" +
-                                       expr_type);
+                               Error23 (expr_type);
+                               return null;
                        }
                        throw new Exception ("Can not constant fold");
                }
@@ -263,17 +262,14 @@ namespace Mono.CSharp {
                        
                        op_name = oper_names [(int) oper];
 
-                       mg = MemberLookup (ec, expr_type, op_name, loc);
-                       
-                       if (mg == null && expr_type.BaseType != null)
-                               mg = MemberLookup (ec, expr_type.BaseType, op_name, loc);
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
                        
                        if (mg != null) {
                                Expression e = StaticCallExpr.MakeSimpleCall (
                                        ec, (MethodGroupExpr) mg, expr, loc);
 
                                if (e == null){
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
                                
@@ -294,7 +290,7 @@ namespace Mono.CSharp {
 
                        if (oper == Operator.LogicalNot){
                                if (expr_type != TypeManager.bool_type) {
-                                       error23 (expr.Type);
+                                       Error23 (expr.Type);
                                        return null;
                                }
                                
@@ -308,7 +304,7 @@ namespace Mono.CSharp {
                                      (expr_type == TypeManager.int64_type) ||
                                      (expr_type == TypeManager.uint64_type) ||
                                      (expr_type.IsSubclassOf (TypeManager.enum_type)))){
-                                       error23 (expr.Type);
+                                       Error23 (expr.Type);
                                        return null;
                                }
                                type = expr_type;
@@ -361,7 +357,7 @@ namespace Mono.CSharp {
                                        // -92233720368547758087 (-2^63) to be wrote as
                                        // decimal integer literal.
                                        //
-                                       error23 (expr_type);
+                                       Error23 (expr_type);
                                        return null;
                                }
 
@@ -391,7 +387,7 @@ namespace Mono.CSharp {
                                        return this;
                                }
 
-                               error23 (expr_type);
+                               Error23 (expr_type);
                                return null;
                        }
 
@@ -406,11 +402,19 @@ namespace Mono.CSharp {
                                        return null;
                                }
 
+                               if (!TypeManager.VerifyUnManaged (expr.Type, loc)){
+                                       return null;
+                               }
+                               
+                               //
+                               // This construct is needed because dynamic types
+                               // are not known by Type.GetType, so we have to try then to use
+                               // ModuleBuilder.GetType.
+                               //
                                string ptr_type_name = expr.Type.FullName + "*";
                                type = Type.GetType (ptr_type_name);
-                               if (type == null){
+                               if (type == null)
                                        type = RootContext.ModuleBuilder.GetType (ptr_type_name);
-                               }
                                
                                return this;
                        }
@@ -427,12 +431,15 @@ namespace Mono.CSharp {
                                                "The * or -> operator can only be applied to pointers");
                                        return null;
                                }
-                               
-                               type = expr_type.GetElementType ();
-                               return this;
+
+                               //
+                               // We create an Indirection expression, because
+                               // it can implement the IMemoryLocation.
+                               // 
+                               return new Indirection (expr);
                        }
                        
-                       Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+                       Error (187, loc, "No such operator '" + OperName (oper) + "' defined for type '" +
                               TypeManager.CSharpName (expr_type) + "'");
                        return null;
                }
@@ -474,12 +481,7 @@ namespace Mono.CSharp {
                                break;
                                
                        case Operator.AddressOf:
-                               ((IMemoryLocation)expr).AddressOf (ec);
-                               break;
-                               
-                       case Operator.Indirection:
-                               expr.Emit (ec);
-                               LoadFromPtr (ig, Type, false);
+                               ((IMemoryLocation)expr).AddressOf (ec, AddressOp.LoadStore);
                                break;
                                
                        default:
@@ -499,9 +501,56 @@ namespace Mono.CSharp {
 
                        expr.Emit (ec);
                }
+
+               public override string ToString ()
+               {
+                       return "Unary (" + oper + ", " + expr + ")";
+               }
                
        }
 
+       //
+       // Unary operators are turned into Indirection expressions
+       // after semantic analysis (this is so we can take the address
+       // of an indirection).
+       //
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+               Expression expr;
+               
+               public Indirection (Expression expr)
+               {
+                       this.expr = expr;
+                       this.type = expr.Type.GetElementType ();
+                       eclass = ExprClass.Variable;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       expr.Emit (ec);
+                       LoadFromPtr (ec.ig, Type, false);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       expr.Emit (ec);
+                       source.Emit (ec);
+                       StoreFromPtr (ec.ig, type);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       expr.Emit (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // Born fully resolved
+                       //
+                       return this;
+               }
+       }
+       
        /// <summary>
        ///   Unary Mutator expressions (pre and post ++ and --)
        /// </summary>
@@ -540,16 +589,16 @@ namespace Mono.CSharp {
                        expr = e;
                }
 
-               string OperName ()
+               static string OperName (Mode mode)
                {
                        return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
                                "++" : "--";
                }
                
-               void error23 (Type t)
+               void Error23 (Type t)
                {
                        Report.Error (
-                               23, loc, "Operator " + OperName () + 
+                               23, loc, "Operator " + OperName (mode) + 
                                " cannot be applied to operand of type `" +
                                TypeManager.CSharpName (t) + "'");
                }
@@ -592,10 +641,11 @@ namespace Mono.CSharp {
                        else 
                                op_name = "op_Decrement";
 
-                       mg = MemberLookup (ec, expr_type, op_name, loc);
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
 
                        if (mg == null && expr_type.BaseType != null)
-                               mg = MemberLookup (ec, expr_type.BaseType, op_name, loc);
+                               mg = MemberLookup (ec, expr_type.BaseType, op_name,
+                                                  MemberTypes.Method, AllBindingFlags, loc);
                        
                        if (mg != null) {
                                method = StaticCallExpr.MakeSimpleCall (
@@ -638,7 +688,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+                       Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
                               TypeManager.CSharpName (expr_type) + "'");
                        return null;
                }
@@ -1254,7 +1304,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Returns a stringified representation of the Operator
                /// </summary>
-               string OperName ()
+               static string OperName (Operator oper)
                {
                        switch (oper){
                        case Operator.Multiply:
@@ -1305,7 +1355,17 @@ namespace Mono.CSharp {
 
                        return ConvertImplicit (ec, expr, target_type, new Location (-1));
                }
-               
+
+               public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
+               {
+                       Report.Error (
+                               34, loc, "Operator `" + OperName (oper) 
+                               + "' is ambiguous on operands of type `"
+                               + TypeManager.CSharpName (l) + "' "
+                               + "and `" + TypeManager.CSharpName (r)
+                               + "'");
+               }
+
                //
                // Note that handling the case l == Decimal || r == Decimal
                // is taken care of by the Step 1 Operator Overload resolution.
@@ -1325,8 +1385,8 @@ namespace Mono.CSharp {
                                type = TypeManager.double_type;
                        } else if (l == TypeManager.float_type || r == TypeManager.float_type){
                                //
-                               // if either operand is of type float, th eother operand is
-                               // converd to type float.
+                               // if either operand is of type float, thother operand is
+                               // converted to type float.
                                //
                                if (r != TypeManager.double_type)
                                        right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
@@ -1382,15 +1442,8 @@ namespace Mono.CSharp {
                                if ((other == TypeManager.sbyte_type) ||
                                    (other == TypeManager.short_type) ||
                                    (other == TypeManager.int32_type) ||
-                                   (other == TypeManager.int64_type)){
-                                       string oper = OperName ();
-                                       
-                                       Error (34, loc, "Operator `" + OperName ()
-                                              + "' is ambiguous on operands of type `"
-                                              + TypeManager.CSharpName (l) + "' "
-                                              + "and `" + TypeManager.CSharpName (r)
-                                              + "'");
-                               }
+                                   (other == TypeManager.int64_type))
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
                                type = TypeManager.uint64_type;
                        } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
                                //
@@ -1481,15 +1534,25 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               void error19 ()
+               static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
                {
                        Error (19, loc,
-                              "Operator " + OperName () + " cannot be applied to operands of type `" +
-                              TypeManager.CSharpName (left.Type) + "' and `" +
-                              TypeManager.CSharpName (right.Type) + "'");
-                                                    
+                              "Operator " + name + " cannot be applied to operands of type `" +
+                              TypeManager.CSharpName (l) + "' and `" +
+                              TypeManager.CSharpName (r) + "'");
                }
                
+               void error19 ()
+               {
+                       Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
+               }
+
+               static bool is_32_or_64 (Type t)
+               {
+                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+                               t == TypeManager.int64_type || t == TypeManager.uint64_type);
+               }
+                                       
                Expression CheckShiftArguments (EmitContext ec)
                {
                        Expression e;
@@ -1528,15 +1591,14 @@ namespace Mono.CSharp {
                        
                        string op = "op_" + oper;
 
-                       left_expr = MemberLookup (ec, l, op, loc);
-                       if (left_expr == null && l.BaseType != null)
-                               left_expr = MemberLookup (ec, l.BaseType, op, loc);
-                       
-                       right_expr = MemberLookup (ec, r, op, loc);
-                       if (right_expr == null && r.BaseType != null)
-                               right_expr = MemberLookup (ec, r.BaseType, op, loc);
-                       
-                       MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
+                       MethodGroupExpr union;
+                       left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
+                       if (r != l){
+                               right_expr = MemberLookup (
+                                       ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
+                               union = Invocation.MakeUnionSet (left_expr, right_expr);
+                       } else
+                               union = (MethodGroupExpr) left_expr;
                        
                        if (union != null) {
                                Arguments = new ArrayList ();
@@ -1546,6 +1608,7 @@ namespace Mono.CSharp {
                                method = Invocation.OverloadResolve (ec, union, Arguments, loc);
                                if (method != null) {
                                        MethodInfo mi = (MethodInfo) method;
+
                                        type = mi.ReturnType;
                                        return this;
                                } else {
@@ -1566,6 +1629,12 @@ namespace Mono.CSharp {
                                // If any of the arguments is a string, cast to string
                                //
                                if (l == TypeManager.string_type){
+                                       
+                                       if (r == TypeManager.void_type) {
+                                               error19 ();
+                                               return null;
+                                       }
+                                       
                                        if (r == TypeManager.string_type){
                                                if (left is Constant && right is Constant){
                                                        StringConstant ls = (StringConstant) left;
@@ -1593,12 +1662,18 @@ namespace Mono.CSharp {
                                        
                                } else if (r == TypeManager.string_type){
                                        // object + string
+
+                                       if (l == TypeManager.void_type) {
+                                               error19 ();
+                                               return null;
+                                       }
+                                       
                                        method = TypeManager.string_concat_object_object;
+                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
                                        Arguments = new ArrayList ();
                                        Arguments.Add (new Argument (left, Argument.AType.Expression));
                                        Arguments.Add (new Argument (right, Argument.AType.Expression));
 
-                                       left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
                                        type = TypeManager.string_type;
 
                                        return this;
@@ -1622,6 +1697,38 @@ namespace Mono.CSharp {
                                        type = l;
                                        return this;
                                }
+
+                               //
+                               // Pointer arithmetic:
+                               //
+                               // T* operator + (T* x, int y);
+                               // T* operator + (T* x, uint y);
+                               // T* operator + (T* x, long y);
+                               // T* operator + (T* x, ulong y);
+                               //
+                               // T* operator + (int y,   T* x);
+                               // T* operator + (uint y,  T *x);
+                               // T* operator + (long y,  T *x);
+                               // T* operator + (ulong y, T *x);
+                               //
+                               // T* operator - (T* x, int y);
+                               // T* operator - (T* x, uint y);
+                               // T* operator - (T* x, long y);
+                               // T* operator - (T* x, ulong y);
+                               //
+                               // long operator - (T* x, T *y)
+                               //
+                               if (l.IsPointer){
+                                       if (r.IsPointer && oper == Operator.Subtraction){
+                                               if (r == l)
+                                                       return new PointerArithmetic (
+                                                               false, left, right, TypeManager.int64_type);
+                                       } else if (is_32_or_64 (r))
+                                               return new PointerArithmetic (
+                                                       oper == Operator.Addition, left, right, l);
+                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
+                                       return new PointerArithmetic (
+                                               true, right, left, r);
                        }
                        
                        //
@@ -1714,6 +1821,18 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       //
+                       // Pointer comparison
+                       //
+                       if (l.IsPointer && r.IsPointer){
+                               if (oper == Operator.Equality || oper == Operator.Inequality ||
+                                   oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
+                                   oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+                       }
+                       
                        //
                        // We are dealing with numbers
                        //
@@ -1759,56 +1878,6 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               /// <summary>
-               ///   Constant expression reducer for binary operations
-               /// </summary>
-               public Expression ConstantFold (EmitContext ec)
-               {
-                       object l = ((Constant) left).GetValue ();
-                       object r = ((Constant) right).GetValue ();
-                       
-                       if (l is string && r is string)
-                               return new StringConstant ((string) l + (string) r);
-
-                       Type result_type = null;
-
-                       //
-                       // Enumerator folding
-                       //
-                       if (left.Type == right.Type && left is EnumConstant)
-                               result_type = left.Type;
-
-                       switch (oper){
-                       case Operator.BitwiseOr:
-                               if ((l is int) && (r is int)){
-                                       IntConstant v;
-                                       int res = (int)l | (int)r;
-                                       
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               }
-                               break;
-                               
-                       case Operator.BitwiseAnd:
-                               if ((l is int) && (r is int)){
-                                       IntConstant v;
-                                       int res = (int)l & (int)r;
-                                       
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               }
-                               break;
-                       }
-                                       
-                       return null;
-               }
-               
                public override Expression DoResolve (EmitContext ec)
                {
                        left = left.Resolve (ec);
@@ -1829,10 +1898,8 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
 
                        if (left is Constant && right is Constant){
-                               //
-                               // This is temporary until we do the full folding
-                               //
-                               Expression e = ConstantFold (ec);
+                               Expression e = ConstantFold.BinaryFold (
+                                       ec, oper, (Constant) left, (Constant) right, loc);
                                if (e != null)
                                        return e;
                        }
@@ -2113,6 +2180,74 @@ namespace Mono.CSharp {
                }
        }
 
+       public class PointerArithmetic : Expression {
+               Expression left, right;
+               bool is_add;
+
+               //
+               // We assume that `l' is always a pointer
+               //
+               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t)
+               {
+                       type = t;
+                       eclass = ExprClass.Variable;
+                       left = l;
+                       right = r;
+                       is_add = is_addition;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Type op_type = left.Type;
+                       ILGenerator ig = ec.ig;
+                       int size = GetTypeSize (op_type.GetElementType ());
+                       
+                       if (right.Type.IsPointer){
+                               //
+                               // handle (pointer - pointer)
+                               //
+                               left.Emit (ec);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Sub);
+
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Div);
+                               }
+                               ig.Emit (OpCodes.Conv_I8);
+                       } else {
+                               //
+                               // handle + and - on (pointer op int)
+                               //
+                               left.Emit (ec);
+                               ig.Emit (OpCodes.Conv_I);
+                               right.Emit (ec);
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Mul);
+                               }
+                               if (is_add)
+                                       ig.Emit (OpCodes.Add);
+                               else
+                                       ig.Emit (OpCodes.Sub);
+                       }
+               }
+       }
+       
        /// <summary>
        ///   Implements the ternary conditiona operator (?:)
        /// </summary>
@@ -2160,21 +2295,32 @@ namespace Mono.CSharp {
                        if (expr == null || trueExpr == null || falseExpr == null)
                                return null;
 
+                       eclass = ExprClass.Value;
                        if (trueExpr.Type == falseExpr.Type)
                                type = trueExpr.Type;
                        else {
                                Expression conv;
+                               Type true_type = trueExpr.Type;
+                               Type false_type = falseExpr.Type;
 
+                               if (trueExpr is NullLiteral){
+                                       type = false_type;
+                                       return this;
+                               } else if (falseExpr is NullLiteral){
+                                       type = true_type;
+                                       return this;
+                               }
+                               
                                //
                                // First, if an implicit conversion exists from trueExpr
                                // to falseExpr, then the result type is of type falseExpr.Type
                                //
-                               conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
+                               conv = ConvertImplicit (ec, trueExpr, false_type, loc);
                                if (conv != null){
                                        //
                                        // Check if both can convert implicitl to each other's type
                                        //
-                                       if (ConvertImplicit (ec, falseExpr, trueExpr.Type, loc) != null){
+                                       if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){
                                                Report.Error (
                                                        172, loc,
                                                        "Can not compute type of conditional expression " +
@@ -2183,10 +2329,10 @@ namespace Mono.CSharp {
                                                        "' convert implicitly to each other");
                                                return null;
                                        }
-                                       type = falseExpr.Type;
+                                       type = false_type;
                                        trueExpr = conv;
-                               } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
-                                       type = trueExpr.Type;
+                               } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){
+                                       type = true_type;
                                        falseExpr = conv;
                                } else {
                                        Error (173, loc, "The type of the conditional expression can " +
@@ -2206,7 +2352,6 @@ namespace Mono.CSharp {
                                        return falseExpr;
                        }
 
-                       eclass = ExprClass.Value;
                        return this;
                }
 
@@ -2366,13 +2511,15 @@ namespace Mono.CSharp {
                        Store (ig, vi.Idx);
                }
                
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        VariableInfo vi = VariableInfo;
                        int idx = vi.Idx;
 
-                       vi.Used = true;
-                       vi.Assigned = true;
+                       if ((mode & AddressOp.Load) != 0)
+                               vi.Used = true;
+                       if ((mode & AddressOp.Store) != 0)
+                               vi.Assigned = true;
                        
                        if (idx <= 255)
                                ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
@@ -2415,7 +2562,7 @@ namespace Mono.CSharp {
                {
                        type = pars.GetParameterInfo (ec.TypeContainer, idx, out is_ref);
                        eclass = ExprClass.Variable;
-                       
+
                        return this;
                }
 
@@ -2480,26 +2627,9 @@ namespace Mono.CSharp {
                        
                        source.Emit (ec);
 
-                       if (is_ref){
-                               if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
-                                       ig.Emit (OpCodes.Stind_I4);
-                               else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
-                                       ig.Emit (OpCodes.Stind_I8);
-                               else if (type == TypeManager.char_type || type == TypeManager.short_type ||
-                                       type == TypeManager.ushort_type)
-                                       ig.Emit (OpCodes.Stind_I2);
-                               else if (type == TypeManager.float_type)
-                                       ig.Emit (OpCodes.Stind_R4);
-                               else if (type == TypeManager.double_type)
-                                       ig.Emit (OpCodes.Stind_R8);
-                               else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
-                                       type == TypeManager.bool_type)
-                                       ig.Emit (OpCodes.Stind_I1);
-                               else if (type == TypeManager.intptr_type)
-                                       ig.Emit (OpCodes.Stind_I);
-                               else
-                                       ig.Emit (OpCodes.Stind_Ref);
-                       } else {
+                       if (is_ref)
+                               StoreFromPtr (ig, type);
+                       else {
                                if (arg_idx <= 255)
                                        ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
                                else
@@ -2508,7 +2638,7 @@ namespace Mono.CSharp {
                        
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        int arg_idx = idx;
 
@@ -2609,15 +2739,22 @@ namespace Mono.CSharp {
                        // to pass just the value
                        //
                        if (ArgType == AType.Ref || ArgType == AType.Out){
+                               AddressOp mode = AddressOp.Store;
+
+                               if (ArgType == AType.Ref)
+                                       mode |= AddressOp.Load;
+                               
                                if (expr is ParameterReference){
                                        ParameterReference pr = (ParameterReference) expr;
 
                                        if (pr.is_ref)
                                                pr.EmitLoad (ec);
-                                       else
-                                               pr.AddressOf (ec);
+                                       else {
+                                               
+                                               pr.AddressOf (ec, mode);
+                                       }
                                } else
-                                       ((IMemoryLocation)expr).AddressOf (ec);
+                                       ((IMemoryLocation)expr).AddressOf (ec, mode);
                        } else
                                expr.Emit (ec);
                }
@@ -2824,25 +2961,32 @@ namespace Mono.CSharp {
                        else
                                argument_count = args.Count;
 
-                       if (candidate_pd.Count == 0 && argument_count == 0)
+                       int cand_count = candidate_pd.Count;
+
+                       if (cand_count == 0 && argument_count == 0)
                                return 1;
 
-                       if (candidate_pd.ParameterModifier (candidate_pd.Count - 1) != Parameter.Modifier.PARAMS)
-                               if (candidate_pd.Count != argument_count)
+                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+                               if (cand_count != argument_count)
                                        return 0;
                        
                        if (best == null) {
                                int x = 0;
+
+                               if (argument_count == 0 && cand_count == 1 &&
+                                   candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
+                                       return 1;
+                               
                                for (int j = argument_count; j > 0;) {
                                        j--;
-                                       
+
                                        Argument a = (Argument) args [j];
                                        Type t = candidate_pd.ParameterType (j);
 
                                        if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
                                                if (expanded_form)
                                                        t = t.GetElementType ();
-                                       
+
                                        x = BetterConversion (ec, a, t, null, loc);
                                        
                                        if (x <= 0)
@@ -2877,9 +3021,9 @@ namespace Mono.CSharp {
                                
                                x = BetterConversion (ec, a, ct, bt, loc);
                                y = BetterConversion (ec, a, bt, ct, loc);
-                                                     
+
                                if (x < y)
-                                       break;
+                                       return 0;
                                
                                rating1 += x;
                                rating2 += y;
@@ -3006,16 +3150,39 @@ namespace Mono.CSharp {
                        
                        if (pd_count - 1 > arg_count)
                                return false;
-
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               return true;
+                       
                        //
                        // If we have come this far, the case which remains is when the number of parameters
-                       // is less than or equal to the argument count. So, we now check if the element type
-                       // of the params array is compatible with each argument type
-                       //
+                       // is less than or equal to the argument count.
+
+                       for (int i = 0; i < pd_count - 1; ++i) {
+
+                               Argument a = (Argument) arguments [i];
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier ();
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i);
+
+                               if (a_mod == p_mod) {
+                                       
+                                       if (a_mod == Parameter.Modifier.NONE)
+                                               if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
+                                                       return false;
+                                                                               
+                                       if (a_mod == Parameter.Modifier.REF ||
+                                           a_mod == Parameter.Modifier.OUT)
+                                               if (pd.ParameterType (i) != a.Type)
+                                                       return false;
+                               } else
+                                       return false;
+                               
+                       }
 
                        Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
 
-                       for (int i = pd_count - 1; i < arg_count - 1; i++) {
+                       for (int i = pd_count - 1; i < arg_count; i++) {
                                Argument a = (Argument) arguments [i];
                                
                                if (!StandardConversionExists (a.Type, element_type))
@@ -3199,13 +3366,13 @@ namespace Mono.CSharp {
                                if (IsParamsMethodApplicable (Arguments, candidate) &&
                                    IsApplicable (Arguments, method))
                                        continue;
-
+                                       
                                int x = BetterFunction (ec, Arguments, method, candidate,
                                                        chose_params_expanded, loc);
 
                                if (x != 1) {
-                                       Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));
-                                       Console.WriteLine ("Best : " + FullMethodDesc (method));
+                                       //Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));
+                                       //Console.WriteLine ("Best : " + FullMethodDesc (method));
                                        Report.Error (
                                                121, loc,
                                                "Ambiguous call when selecting function due to implicit casts");
@@ -3459,7 +3626,7 @@ namespace Mono.CSharp {
                                                        // it.
                                                        if (instance_expr is IMemoryLocation){
                                                                ((IMemoryLocation)instance_expr).
-                                                                       AddressOf (ec);
+                                                                       AddressOf (ec, AddressOp.LoadStore);
                                                        }
                                                        else {
                                                                Type t = instance_expr.Type;
@@ -3642,7 +3809,7 @@ namespace Mono.CSharp {
                                        value_target = new LocalTemporary (ec, type);
 
                                ml = (IMemoryLocation) value_target;
-                               ml.AddressOf (ec);
+                               ml.AddressOf (ec, AddressOp.Store);
                        }
 
                        if (method != null)
@@ -4012,7 +4179,7 @@ namespace Mono.CSharp {
                {
                        int factor;
                        byte [] data;
-
+                       byte [] element;
                        int count = ArrayData.Count;
 
                        factor = GetTypeSize (underlying_type);
@@ -4054,35 +4221,20 @@ namespace Mono.CSharp {
                                                }
                                        }
                                } else if (underlying_type == TypeManager.float_type) {
-#if __MonoCS__
-#else
-                                       unsafe {
-                                               if (!(v is Expression)){
-                                                       float val = (float) v;
-
-                                                       byte *ptr = (byte *) &val;
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((float) v);
                                                        
-                                                       for (int j = 0; j < factor; ++j)
-                                                               data [idx + j] = (byte) ptr [j];
-                                               }
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
                                        }
-#endif
                                } else if (underlying_type == TypeManager.double_type) {
-#if __MonoCS__
-#else
-                                       unsafe {
-                                               if (!(v is Expression)){
-                                                       double val = (double) v;
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((double) v);
 
-                                                       byte *ptr = (byte *) &val;
-                                               
-                                                       for (int j = 0; j < factor; ++j)
-                                                               data [idx + j] = (byte) ptr [j];
-                                               }
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
                                        }
-#endif
                                } else if (underlying_type == TypeManager.char_type){
-
                                        if (!(v is Expression)){
                                                int val = (int) ((char) v);
                                                
@@ -4340,7 +4492,7 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Starg, 0);
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        ec.ig.Emit (OpCodes.Ldarg_0);
 
@@ -4557,7 +4709,8 @@ namespace Mono.CSharp {
                                        
                                        if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
                                                Expression enum_member = MemberLookup (
-                                                       ec, decl_type, "value__", loc); 
+                                                       ec, decl_type, "value__", MemberTypes.Field,
+                                                       AllBindingFlags, loc); 
 
                                                Enum en = TypeManager.LookupEnum (decl_type);
 
@@ -4780,8 +4933,12 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
-                       Expr = Expr.Resolve (ec);
+                       bool last_const_check = ec.ConstantCheckState;
 
+                       ec.ConstantCheckState = true;
+                       Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
+                       
                        if (Expr == null)
                                return null;
 
@@ -4793,10 +4950,13 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
                        
                        ec.CheckState = true;
+                       ec.ConstantCheckState = true;
                        Expr.Emit (ec);
                        ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
                }
                
        }
@@ -4815,7 +4975,11 @@ namespace Mono.CSharp {
 
                public override Expression DoResolve (EmitContext ec)
                {
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.ConstantCheckState = false;
                        Expr = Expr.Resolve (ec);
+                       ec.ConstantCheckState = last_const_check;
 
                        if (Expr == null)
                                return null;
@@ -4828,10 +4992,13 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
                        
                        ec.CheckState = false;
+                       ec.ConstantCheckState = false;
                        Expr.Emit (ec);
                        ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
                }
                
        }
@@ -4882,7 +5049,27 @@ namespace Mono.CSharp {
 
                        return true;
                }
-                               
+
+               Expression MakePointerAccess ()
+               {
+                       Type t = Expr.Type;
+
+                       if (t == TypeManager.void_ptr_type){
+                               Report.Error (
+                                       242, loc,
+                                       "The array index operation is not valid for void pointers");
+                               return null;
+                       }
+                       if (Arguments.Count != 1){
+                               Report.Error (
+                                       196, loc,
+                                       "A pointer must be indexed by a single value");
+                               return null;
+                       }
+                       Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t);
+                       return new Indirection (p);
+               }
+               
                public override Expression DoResolve (EmitContext ec)
                {
                        if (!CommonResolve (ec))
@@ -4894,8 +5081,12 @@ namespace Mono.CSharp {
                        //
                        // I am experimenting with this pattern.
                        //
-                       if (Expr.Type.IsSubclassOf (TypeManager.array_type))
+                       Type t = Expr.Type;
+
+                       if (t.IsSubclassOf (TypeManager.array_type))
                                return (new ArrayAccess (this)).Resolve (ec);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
                        else
                                return (new IndexerAccess (this)).Resolve (ec);
                }
@@ -4905,8 +5096,11 @@ namespace Mono.CSharp {
                        if (!CommonResolve (ec))
                                return null;
 
-                       if (Expr.Type.IsSubclassOf (TypeManager.array_type))
+                       Type t = Expr.Type;
+                       if (t.IsSubclassOf (TypeManager.array_type))
                                return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
                        else
                                return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
                }
@@ -4940,7 +5134,6 @@ namespace Mono.CSharp {
                        }
 
                        Type t = ea.Expr.Type;
-
                        if (t.GetArrayRank () != ea.Arguments.Count){
                                Report.Error (22, ea.loc,
                                              "Incorrect number of indexes for array " +
@@ -5140,7 +5333,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public void AddressOf (EmitContext ec)
+               public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        int rank = ea.Expr.Type.GetArrayRank ();
                        ILGenerator ig = ec.ig;
@@ -5398,7 +5591,7 @@ namespace Mono.CSharp {
                                return null;
                        }
                        
-                       member_lookup = MemberLookup (ec, base_type, "get_Item", loc);
+                       member_lookup = MemberLookup (ec, base_type, "get_Item", MemberTypes.Method, AllBindingFlags, loc);
                        if (member_lookup == null)
                                return null;
 
@@ -5484,7 +5677,6 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Call, (ConstructorInfo) method);
 
                }
-
        }
 
        // <summary>
@@ -5535,4 +5727,148 @@ namespace Mono.CSharp {
                        throw new Exception ("This should never be called");
                }
        }
+
+       //
+       // This class is used to represent the address of an array, used
+       // only by the Fixed statement, this is like the C "&a [0]" construct.
+       //
+       public class ArrayPtr : Expression {
+               Expression array;
+               
+               public ArrayPtr (Expression array)
+               {
+                       Type array_type = array.Type.GetElementType ();
+
+                       this.array = array;
+                       
+                       string array_ptr_type_name = array_type.FullName + "*";
+                       
+                       type = Type.GetType (array_ptr_type_name);
+                       if (type == null){
+                               ModuleBuilder mb = RootContext.ModuleBuilder;
+                               
+                               type = mb.GetType (array_ptr_type_name);
+                       }
+
+                       eclass = ExprClass.Value;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       array.Emit (ec);
+                       IntLiteral.EmitInt (ig, 0);
+                       ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+       }
+
+       //
+       // Used by the fixed statement
+       //
+       public class StringPtr : Expression {
+               LocalBuilder b;
+               
+               public StringPtr (LocalBuilder b)
+               {
+                       this.b = b;
+                       eclass = ExprClass.Value;
+                       type = TypeManager.char_ptr_type;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldloc, b);
+                       ig.Emit (OpCodes.Conv_I);
+                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
+                       ig.Emit (OpCodes.Add);
+               }
+       }
+       
+       //
+       // Implements the `stackalloc' keyword
+       //
+       public class StackAlloc : Expression {
+               Type otype;
+               string t;
+               Expression count;
+               Location loc;
+               
+               public StackAlloc (string type, Expression count, Location l)
+               {
+                       t = type;
+                       this.count = count;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       count = count.Resolve (ec);
+                       if (count == null)
+                               return null;
+                       
+                       if (count.Type != TypeManager.int32_type){
+                               count = ConvertImplicitRequired (ec, count, TypeManager.int32_type, loc);
+                               if (count == null)
+                                       return null;
+                       }
+
+                       if (ec.InCatch || ec.InFinally){
+                               Report.Error (255, loc,
+                                             "stackalloc can not be used in a catch or finally block");
+                               return null;
+                       }
+                       
+                       otype = RootContext.LookupType (ec.TypeContainer, t, false, loc);
+
+                       if (otype == null)
+                               return null;
+
+                       if (!TypeManager.VerifyUnManaged (otype, loc))
+                               return null;
+
+                       string ptr_name = otype.FullName + "*";
+                       type = Type.GetType (ptr_name);
+                       if (type == null){
+                               ModuleBuilder mb = RootContext.ModuleBuilder;
+                               
+                               type = mb.GetType (ptr_name);
+                       }
+                       eclass = ExprClass.Value;
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int size = GetTypeSize (otype);
+                       ILGenerator ig = ec.ig;
+                               
+                       if (size == 0)
+                               ig.Emit (OpCodes.Sizeof, otype);
+                       else
+                               IntConstant.EmitInt (ig, size);
+                       count.Emit (ec);
+                       ig.Emit (OpCodes.Mul);
+                       ig.Emit (OpCodes.Localloc);
+               }
+       }
 }