Merge pull request #1936 from esdrubal/DotNetRelativeOrAbsolute
[mono.git] / mcs / mcs / codegen.cs
index 55a061cf034c4191e9aef92ed25b9228a8e3582b..429c3b9d3b0d1f23db2fb66109e2d5ab93f6ca03 100644 (file)
@@ -222,6 +222,8 @@ namespace Mono.CSharp
 
                public List<TryFinally> TryFinallyUnwind { get; set; }
 
+               public Label RecursivePatternLabel { get; set; }
+
                #endregion
 
                public void AddStatementEpilog (IExpressionCleanup cleanupExpression)
@@ -260,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;
                }
 
@@ -322,9 +322,7 @@ namespace Mono.CSharp
                        if ((flags & Options.OmitDebugInfo) != 0)
                                return;
 
-#if NET_4_0
                        methodSymbols.StartBlock (CodeBlockEntry.Type.Lexical, ig.ILOffset);
-#endif
                }
 
                public void BeginCompilerScope ()
@@ -332,9 +330,7 @@ namespace Mono.CSharp
                        if ((flags & Options.OmitDebugInfo) != 0)
                                return;
 
-#if NET_4_0
                        methodSymbols.StartBlock (CodeBlockEntry.Type.CompilerGenerated, ig.ILOffset);
-#endif
                }
 
                public void EndExceptionBlock ()
@@ -347,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)
@@ -547,13 +541,10 @@ namespace Mono.CSharp
                        switch (type.BuiltinType) {
                        case BuiltinTypeSpec.Type.Bool:
                                //
-                               // Workaround MSIL limitation. Load bool element as single bit,
-                               // bool array can actually store any byte value
+                               // bool array can actually store any byte value in underlying byte slot
+                               // and C# spec does not specify any normalization rule, except the result
+                               // is undefined
                                //
-                               ig.Emit (OpCodes.Ldelem_U1);
-                               ig.Emit (OpCodes.Ldc_I4_0);
-                               ig.Emit (OpCodes.Cgt_Un);
-                               break;
                        case BuiltinTypeSpec.Type.Byte:
                                ig.Emit (OpCodes.Ldelem_U1);
                                break;
@@ -769,12 +760,8 @@ namespace Mono.CSharp
                                ig.Emit (OpCodes.Ldind_U1);
                                break;
                        case BuiltinTypeSpec.Type.SByte:
-                               ig.Emit (OpCodes.Ldind_I1);
-                               break;
                        case BuiltinTypeSpec.Type.Bool:
                                ig.Emit (OpCodes.Ldind_I1);
-                               ig.Emit (OpCodes.Ldc_I4_0);
-                               ig.Emit (OpCodes.Cgt_Un);
                                break;
                        case BuiltinTypeSpec.Type.ULong:
                        case BuiltinTypeSpec.Type.Long:
@@ -901,6 +888,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;
@@ -1064,7 +1054,7 @@ namespace Mono.CSharp
                                        var ie = new InstanceEmitter (instance_copy, IsAddressCall (instance_copy, call_op, method.DeclaringType));
 
                                        if (Arguments == null) {
-                                               ie.EmitLoad (ec);
+                                               ie.EmitLoad (ec, true);
                                        }
                                } else if (!InstanceExpressionOnStack) {
                                        var ie = new InstanceEmitter (InstanceExpression, IsAddressCall (InstanceExpression, call_op, method.DeclaringType));
@@ -1226,7 +1216,7 @@ namespace Mono.CSharp
                                                instance_address = instance as LocalTemporary;
 
                                        if (instance_address == null) {
-                                               EmitLoad (ec);
+                                               EmitLoad (ec, false);
                                                ec.Emit (OpCodes.Dup);
                                                ec.EmitLoadFromPtr (instance.Type);
 
@@ -1234,11 +1224,8 @@ namespace Mono.CSharp
                                        } else {
                                                instance.Emit (ec);
                                        }
-
-                                       if (instance.Type.Kind == MemberKind.TypeParameter)
-                                               ec.Emit (OpCodes.Box, instance.Type);
                                } else {
-                                       EmitLoad (ec);
+                                       EmitLoad (ec, !conditionalAccess);
 
                                        if (conditionalAccess) {
                                                conditional_access_dup = !IsInexpensiveLoad ();
@@ -1248,6 +1235,9 @@ namespace Mono.CSharp
                                }
 
                                if (conditionalAccess) {
+                                       if (instance.Type.Kind == MemberKind.TypeParameter)
+                                               ec.Emit (OpCodes.Box, instance.Type);
+
                                        ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel);
 
                                        if (conditional_access_dup)
@@ -1280,7 +1270,7 @@ namespace Mono.CSharp
                        }
                }
 
-               public void EmitLoad (EmitContext ec)
+               public void EmitLoad (EmitContext ec, bool boxInstance)
                {
                        var instance_type = instance.Type;
 
@@ -1311,8 +1301,9 @@ namespace Mono.CSharp
                        instance.Emit (ec);
 
                        // Only to make verifier happy
-                       if (RequiresBoxing ())
+                       if (boxInstance && RequiresBoxing ()) {
                                ec.Emit (OpCodes.Box, instance_type);
+                       }
                }
 
                public TypeSpec GetStackType (EmitContext ec)
@@ -1340,6 +1331,9 @@ namespace Mono.CSharp
                        return false;
                }
 
+               //
+               // Returns true for cheap race-free load, where we can avoid using dup
+               //
                bool IsInexpensiveLoad ()
                {
                        if (instance is Constant)
@@ -1349,8 +1343,10 @@ namespace Mono.CSharp
                                return false;
 
                        var vr = instance as VariableReference;
-                       if (vr != null)
-                               return !vr.IsRef;
+                       if (vr != null) {
+                               // Load from captured local would be racy without dup
+                               return !vr.IsRef && !vr.IsHoisted;
+                       }
 
                        if (instance is LocalTemporary)
                                return true;