Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / ConstantExpression.cs
index 8679c1aae8590c2b33d1d85cce96351f93a5f179..38a7b3cab66116f54649681a2016c64a5b4de9af 100644 (file)
@@ -50,11 +50,33 @@ namespace System.Linq.Expressions {
                        this.value = value;
                }
 
+#if !FULL_AOT_RUNTIME
                internal override void Emit (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
+                       if (Type.IsNullable ()) {
+                               EmitNullableConstant (ec, Type, value);
+                               return;
+                       }
+
+                       EmitConstant (ec, Type, value);
+               }
 
-                       switch (Type.GetTypeCode (Type)){
+               void EmitNullableConstant (EmitContext ec, Type type, object value)
+               {
+                       if (value == null) {
+                               var local = ec.ig.DeclareLocal (type);
+                               ec.EmitNullableInitialize (local);
+                       } else {
+                               EmitConstant (ec, type.GetFirstGenericArgument (), value);
+                               ec.EmitNullableNew (type);
+                       }
+               }
+
+               void EmitConstant (EmitContext ec, Type type, object value)
+               {
+                       var ig = ec.ig;
+
+                       switch (Type.GetTypeCode (type)){
                        case TypeCode.Byte:
                                ig.Emit (OpCodes.Ldc_I4, (int) ((byte)value));
                                return;
@@ -129,17 +151,46 @@ namespace System.Linq.Expressions {
 
                                ig.Emit (OpCodes.Newobj, typeof (Decimal).GetConstructor (new Type [5] { ti, ti, ti, typeof(bool), typeof(byte) }));
                                return;
-                        }
+                       }
+
+                       case TypeCode.DateTime: {
+                               var date = (DateTime) value;
+                               var local = ig.DeclareLocal (typeof (DateTime));
+
+                               ig.Emit (OpCodes.Ldloca, local);
+                               ig.Emit (OpCodes.Ldc_I8, date.Ticks);
+                               ig.Emit (OpCodes.Ldc_I4, (int) date.Kind);
+                               ig.Emit (OpCodes.Call, typeof (DateTime).GetConstructor (new [] { typeof (long), typeof (DateTimeKind) }));
+                               ig.Emit (OpCodes.Ldloc, local);
+
+                               return;
+                       }
+
+                       case TypeCode.DBNull:
+                               ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value", BindingFlags.Public | BindingFlags.Static));
+                               return;
 
                        case TypeCode.String:
-                               ig.Emit (OpCodes.Ldstr, (string) value);
+                               EmitIfNotNull (ec, c => c.ig.Emit (OpCodes.Ldstr, (string) value));
                                return;
 
                        case TypeCode.Object:
-                               break;
+                               EmitIfNotNull (ec, c => c.EmitReadGlobal (value));
+                               return;
                        }
 
                        throw new NotImplementedException (String.Format ("No support for constants of type {0} yet", Type));
                }
+
+               void EmitIfNotNull (EmitContext ec, Action<EmitContext> emit)
+               {
+                       if (value == null) {
+                               ec.ig.Emit (OpCodes.Ldnull);
+                               return;
+                       }
+
+                       emit (ec);
+               }
+#endif
        }
 }