if (sf.IsHiddenLocation (loc))
return false;
-#if NET_4_0
methodSymbols.MarkSequencePoint (ig.ILOffset, sf.SourceFileEntry, loc.Row, loc.Column, false);
-#endif
return true;
}
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 ()
if ((flags & Options.OmitDebugInfo) != 0)
return;
-#if NET_4_0
methodSymbols.EndBlock (ig.ILOffset);
-#endif
}
public void CloseConditionalAccess (TypeSpec type)
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);
}
EmitLoad (ec, !conditionalAccess);
if (conditionalAccess) {
- conditional_access_dup = !IsInexpensiveLoad ();
+ conditional_access_dup = !ExpressionAnalyzer.IsInexpensiveLoad (instance);
if (conditional_access_dup)
ec.Emit (OpCodes.Dup);
}
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);
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);
}
instance.Emit (ec);
// Only to make verifier happy
- if (boxInstance && RequiresBoxing ()) {
+ if (boxInstance && ExpressionAnalyzer.RequiresBoxing (instance)) {
ec.Emit (OpCodes.Box, instance_type);
}
}
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))
//
// 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;