public void Store(EmitContext ec) { if (builder == null) { builder = ec.GetTemporaryLocal(type); } ec.Emit(OpCodes.Stloc, builder); }
public void AddressOf(EmitContext ec, AddressOp mode) { if (builder == null) { builder = ec.GetTemporaryLocal(type); } if (builder.LocalType.IsByRef) { // // if is_address, than this is just the address anyways, // so we just return this. // ec.Emit(OpCodes.Ldloc, builder); } else { ec.Emit(OpCodes.Ldloca, builder); } }
public void Emit(EmitContext ec, bool conditionalAccess) { Label NullOperatorLabel; Nullable.Unwrap unwrap; if (conditionalAccess && Expression.IsNeverNull(instance)) { conditionalAccess = false; } if (conditionalAccess) { NullOperatorLabel = ec.DefineLabel(); unwrap = instance as Nullable.Unwrap; } else { NullOperatorLabel = new Label(); unwrap = null; } IMemoryLocation instance_address = null; bool conditional_access_dup = false; if (unwrap != null) { unwrap.Store(ec); unwrap.EmitCheck(ec); ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel); } else { if (conditionalAccess && addressRequired) { // // Don't allocate temp variable when instance load is cheap and load and load-address // operate on same memory // instance_address = instance as VariableReference; if (instance_address == null) { instance_address = instance as LocalTemporary; } if (instance_address == null) { EmitLoad(ec, false); ec.Emit(OpCodes.Dup); ec.EmitLoadFromPtr(instance.Type); conditional_access_dup = true; } else { instance.Emit(ec); } } else { EmitLoad(ec, !conditionalAccess); if (conditionalAccess) { conditional_access_dup = !IsInexpensiveLoad(); if (conditional_access_dup) { ec.Emit(OpCodes.Dup); } } } if (conditionalAccess) { if (instance.Type.Kind == MemberKind.TypeParameter) { ec.Emit(OpCodes.Box, instance.Type); } ec.Emit(OpCodes.Brtrue_S, NullOperatorLabel); if (conditional_access_dup) { ec.Emit(OpCodes.Pop); } } } if (conditionalAccess) { if (!ec.ConditionalAccess.Statement) { if (ec.ConditionalAccess.Type.IsNullableType) { Nullable.LiftedNull.Create(ec.ConditionalAccess.Type, Location.Null).Emit(ec); } else { ec.EmitNull(); } } ec.Emit(OpCodes.Br, ec.ConditionalAccess.EndLabel); ec.MarkLabel(NullOperatorLabel); if (instance_address != null) { 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); } else if (!conditional_access_dup) { instance.Emit(ec); } } }
void EmitMoveNext(EmitContext ec) { move_next_ok = ec.DefineLabel(); move_next_error = ec.DefineLabel(); if (resume_points == null) { EmitMoveNext_NoResumePoints(ec); return; } current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); Label[] labels = new Label[1 + resume_points.Count]; labels[0] = ec.DefineLabel(); bool need_skip_finally = false; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = resume_points[i]; need_skip_finally |= s is ExceptionStatement; labels[i + 1] = s.PrepareForEmit(ec); } if (need_skip_finally) { skip_finally = ec.GetTemporaryLocal(ec.BuiltinTypes.Bool); ec.EmitInt(0); ec.Emit(OpCodes.Stloc, skip_finally); } var async_init = this as AsyncInitializer; if (async_init != null) { ec.BeginExceptionBlock(); } ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error); ec.MarkLabel(labels[0]); BodyEnd = ec.DefineLabel(); block.EmitEmbedded(ec); ec.MarkLabel(BodyEnd); if (async_init != null) { async_init.EmitCatchBlock(ec); } ec.Mark(Block.Original.EndLocation); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); EmitMoveNextEpilogue(ec); ec.MarkLabel(move_next_error); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(0); ec.Emit(OpCodes.Ret); } ec.MarkLabel(move_next_ok); if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt(1); ec.Emit(OpCodes.Ret); } }
public void EmitDispose(EmitContext ec) { if (resume_points == null) { return; } Label end = ec.DefineLabel(); Label[] labels = null; for (int i = 0; i < resume_points.Count; ++i) { ResumableStatement s = resume_points[i]; Label ret = s.PrepareForDispose(ec, end); if (ret.Equals(end) && labels == null) { continue; } if (labels == null) { labels = new Label[resume_points.Count + 1]; for (int j = 0; j <= i; ++j) { labels[j] = end; } } labels[i + 1] = ret; } if (labels != null) { current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt); ec.EmitThis(); ec.Emit(OpCodes.Ldfld, storey.PC.Spec); ec.Emit(OpCodes.Stloc, current_pc); } ec.EmitThis(); ec.EmitInt(1); ec.Emit(OpCodes.Stfld, ((IteratorStorey)storey).DisposingField.Spec); ec.EmitThis(); ec.EmitInt((int)IteratorStorey.State.After); ec.Emit(OpCodes.Stfld, storey.PC.Spec); if (labels != null) { //SymbolWriter.StartIteratorDispatcher (ec.ig); ec.Emit(OpCodes.Ldloc, current_pc); ec.Emit(OpCodes.Switch, labels); //SymbolWriter.EndIteratorDispatcher (ec.ig); foreach (ResumableStatement s in resume_points) { s.EmitForDispose(ec, current_pc, end, true); } } ec.MarkLabel(end); }
public void Emit (EmitContext ec, bool conditionalAccess) { Label NullOperatorLabel; Nullable.Unwrap unwrap; if (conditionalAccess && Expression.IsNeverNull (instance)) conditionalAccess = false; if (conditionalAccess) { NullOperatorLabel = ec.DefineLabel (); unwrap = instance as Nullable.Unwrap; } else { NullOperatorLabel = new Label (); unwrap = null; } IMemoryLocation instance_address = null; bool conditional_access_dup = false; if (unwrap != null) { unwrap.Store (ec); unwrap.EmitCheck (ec); ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel); } else { if (conditionalAccess && addressRequired) { // // Don't allocate temp variable when instance load is cheap and load and load-address // operate on same memory // instance_address = instance as VariableReference; if (instance_address == null) instance_address = instance as LocalTemporary; if (instance_address == null) { EmitLoad (ec, false); ec.Emit (OpCodes.Dup); ec.EmitLoadFromPtr (instance.Type); conditional_access_dup = true; } else { instance.Emit (ec); } } else { EmitLoad (ec, !conditionalAccess); if (conditionalAccess) { conditional_access_dup = !IsInexpensiveLoad (); if (conditional_access_dup) ec.Emit (OpCodes.Dup); } } if (conditionalAccess) { if (instance.Type.Kind == MemberKind.TypeParameter) ec.Emit (OpCodes.Box, instance.Type); ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel); if (conditional_access_dup) ec.Emit (OpCodes.Pop); } } if (conditionalAccess) { if (!ec.ConditionalAccess.Statement) { if (ec.ConditionalAccess.Type.IsNullableType) Nullable.LiftedNull.Create (ec.ConditionalAccess.Type, Location.Null).Emit (ec); else ec.EmitNull (); } ec.Emit (OpCodes.Br, ec.ConditionalAccess.EndLabel); ec.MarkLabel (NullOperatorLabel); if (instance_address != null) { 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); } else if (!conditional_access_dup) { instance.Emit (ec); } } }
public void AddressOf (EmitContext ec, AddressOp mode) { if (builder == null) builder = ec.GetTemporaryLocal (type); if (builder.LocalType.IsByRef) { // // if is_address, than this is just the address anyways, // so we just return this. // ec.Emit (OpCodes.Ldloc, builder); } else { ec.Emit (OpCodes.Ldloca, builder); } }
public void Store (EmitContext ec) { if (builder == null) builder = ec.GetTemporaryLocal (type); ec.Emit (OpCodes.Stloc, builder); }