Merge pull request #2869 from BrzVlad/feature-mod-union-opt
[mono.git] / mcs / mcs / codegen.cs
index 6dfe7b6ce6b6e47574e132822483c1b3b2e099af..d5ba75c12813af9d07e4b3182134f82cc3e557f9 100644 (file)
@@ -262,9 +262,7 @@ namespace Mono.CSharp
                        if (sf.IsHiddenLocation (loc))
                                return false;
 
-#if NET_4_0
                        methodSymbols.MarkSequencePoint (ig.ILOffset, sf.SourceFileEntry, loc.Row, loc.Column, false);
-#endif
                        return true;
                }
 
@@ -319,24 +317,20 @@ namespace Mono.CSharp
                        ig.BeginFinallyBlock ();
                }
 
-               public void BeginScope ()
+               public void BeginScope (int scopeIndex)
                {
                        if ((flags & Options.OmitDebugInfo) != 0)
                                return;
 
-#if NET_4_0
-                       methodSymbols.StartBlock (CodeBlockEntry.Type.Lexical, ig.ILOffset);
-#endif
+                       methodSymbols.StartBlock (CodeBlockEntry.Type.Lexical, ig.ILOffset, scopeIndex);
                }
 
-               public void BeginCompilerScope ()
+               public void BeginCompilerScope (int scopeIndex)
                {
                        if ((flags & Options.OmitDebugInfo) != 0)
                                return;
 
-#if NET_4_0
-                       methodSymbols.StartBlock (CodeBlockEntry.Type.CompilerGenerated, ig.ILOffset);
-#endif
+                       methodSymbols.StartBlock (CodeBlockEntry.Type.CompilerGenerated, ig.ILOffset, scopeIndex);
                }
 
                public void EndExceptionBlock ()
@@ -349,9 +343,7 @@ namespace Mono.CSharp
                        if ((flags & Options.OmitDebugInfo) != 0)
                                return;
 
-#if NET_4_0
                        methodSymbols.EndBlock (ig.ILOffset);
-#endif
                }
 
                public void CloseConditionalAccess (TypeSpec type)
@@ -398,6 +390,22 @@ namespace Mono.CSharp
                        if (IsAnonymousStoreyMutateRequired)
                                type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type);
 
+                       if (pinned) {
+                               //
+                               // This is for .net compatibility. I am not sure why pinned
+                               // pointer temps are converted to & even if they are pointers to
+                               // pointers.
+                               //
+                               var pt = type as PointerContainer;
+                               if (pt != null) {
+                                       type = pt.Element;
+                                       if (type.Kind == MemberKind.Void)
+                                               type = Module.Compiler.BuiltinTypes.IntPtr;
+                                       
+                                       return ig.DeclareLocal (type.GetMetaInfo ().MakeByRefType (), true);
+                               }
+                       }
+
                        return ig.DeclareLocal (type.GetMetaInfo (), pinned);
                }
 
@@ -896,6 +904,9 @@ namespace Mono.CSharp
 
                                ig.Emit (OpCodes.Stobj, type.GetMetaInfo ());
                                break;
+                       case MemberKind.PointerType:
+                               ig.Emit (OpCodes.Stind_I);
+                               break;
                        default:
                                ig.Emit (OpCodes.Stind_Ref);
                                break;
@@ -1233,7 +1244,7 @@ namespace Mono.CSharp
                                        EmitLoad (ec, !conditionalAccess);
 
                                        if (conditionalAccess) {
-                                               conditional_access_dup = !IsInexpensiveLoad ();
+                                               conditional_access_dup = !ExpressionAnalyzer.IsInexpensiveLoad (instance);
                                                if (conditional_access_dup)
                                                        ec.Emit (OpCodes.Dup);
                                        }
@@ -1252,10 +1263,15 @@ namespace Mono.CSharp
 
                        if (conditionalAccess) {
                                if (!ec.ConditionalAccess.Statement) {
-                                       if (ec.ConditionalAccess.Type.IsNullableType)
-                                               Nullable.LiftedNull.Create (ec.ConditionalAccess.Type, Location.Null).Emit (ec);
-                                       else
+                                       var t = ec.ConditionalAccess.Type;
+                                       if (t.IsNullableType)
+                                               Nullable.LiftedNull.Create (t, Location.Null).Emit (ec);
+                                       else {
                                                ec.EmitNull ();
+
+                                               if (t.IsGenericParameter)
+                                                       ec.Emit (OpCodes.Unbox_Any, t);
+                                       }
                                }
 
                                ec.Emit (OpCodes.Br, ec.ConditionalAccess.EndLabel);
@@ -1265,10 +1281,12 @@ namespace Mono.CSharp
                                        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);
+                                       if (addressRequired) {
+                                               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);
                                }
@@ -1306,7 +1324,7 @@ namespace Mono.CSharp
                        instance.Emit (ec);
 
                        // Only to make verifier happy
-                       if (boxInstance && RequiresBoxing ()) {
+                       if (boxInstance && ExpressionAnalyzer.RequiresBoxing (instance)) {
                                ec.Emit (OpCodes.Box, instance_type);
                        }
                }
@@ -1324,7 +1342,12 @@ namespace Mono.CSharp
                        return instance_type;
                }
 
-               bool RequiresBoxing ()
+
+       }
+
+       static class ExpressionAnalyzer
+       {
+               public static bool RequiresBoxing (Expression instance)
                {
                        var instance_type = instance.Type;
                        if (instance_type.IsGenericParameter && !(instance is This) && TypeSpec.IsReferenceType (instance_type))
@@ -1339,12 +1362,12 @@ namespace Mono.CSharp
                //
                // Returns true for cheap race-free load, where we can avoid using dup
                //
-               bool IsInexpensiveLoad ()
+               public static bool IsInexpensiveLoad (Expression instance)
                {
                        if (instance is Constant)
                                return instance.IsSideEffectFree;
 
-                       if (RequiresBoxing ())
+                       if (RequiresBoxing (instance))
                                return false;
 
                        var vr = instance as VariableReference;