MarkLabel() public méthode

public MarkLabel ( Label label ) : void
label System.Reflection.Emit.Label
Résultat void
Exemple #1
0
		protected override void DoEmit (EmitContext ec)
		{
			if (!HasBeenReferenced)
				ec.Report.Warning (164, 2, loc, "This label has not been referenced");

			LabelTarget (ec);
			ec.MarkLabel (label);
		}
Exemple #2
0
		public override void Emit (EmitContext ec)
		{
			Label l_initialized = ec.DefineLabel ();

			if (mg_cache != null) {
				ec.Emit (OpCodes.Ldsfld, mg_cache.Spec);
				ec.Emit (OpCodes.Brtrue_S, l_initialized);
			}

			base.Emit (ec);

			if (mg_cache != null) {
				ec.Emit (OpCodes.Stsfld, mg_cache.Spec);
				ec.MarkLabel (l_initialized);
				ec.Emit (OpCodes.Ldsfld, mg_cache.Spec);
			}
		}
Exemple #3
0
		protected override void DoEmit (EmitContext ec)
		{
			if (empty) {
				expr.EmitSideEffect (ec);
				return;
			}

			Label old_begin = ec.LoopBegin;
			Label old_end = ec.LoopEnd;
			
			ec.LoopBegin = ec.DefineLabel ();
			ec.LoopEnd = ec.DefineLabel ();

			//
			// Inform whether we are infinite or not
			//
			if (expr is Constant){
				// expr is 'true', since the 'empty' case above handles the 'false' case
				ec.MarkLabel (ec.LoopBegin);
				expr.EmitSideEffect (ec);
				Statement.Emit (ec);
				ec.Emit (OpCodes.Br, ec.LoopBegin);
					
				//
				// Inform that we are infinite (ie, `we return'), only
				// if we do not `break' inside the code.
				//
				ec.MarkLabel (ec.LoopEnd);
			} else {
				Label while_loop = ec.DefineLabel ();

				ec.Emit (OpCodes.Br, ec.LoopBegin);
				ec.MarkLabel (while_loop);

				Statement.Emit (ec);
			
				ec.MarkLabel (ec.LoopBegin);
				ec.Mark (loc);

				expr.EmitBranchable (ec, while_loop, true);
				
				ec.MarkLabel (ec.LoopEnd);
			}	

			ec.LoopBegin = old_begin;
			ec.LoopEnd = old_end;
		}
Exemple #4
0
			protected override void DoEmit (EmitContext ec)
			{
				copy.EmitAssign (ec, for_each.expr);

				int rank = length_exprs.Length;
				Label[] test = new Label [rank];
				Label[] loop = new Label [rank];

				for (int i = 0; i < rank; i++) {
					test [i] = ec.DefineLabel ();
					loop [i] = ec.DefineLabel ();

					if (lengths != null)
						lengths [i].EmitAssign (ec, length_exprs [i]);
				}

				IntConstant zero = new IntConstant (0, loc);
				for (int i = 0; i < rank; i++) {
					variables [i].EmitAssign (ec, zero);

					ec.Emit (OpCodes.Br, test [i]);
					ec.MarkLabel (loop [i]);
				}

				variable.local_info.CreateBuilder (ec);
				variable.EmitAssign (ec, conv, false, false);

				statement.Emit (ec);

				ec.MarkLabel (ec.LoopBegin);

				for (int i = rank - 1; i >= 0; i--){
					counter [i].Emit (ec);

					ec.MarkLabel (test [i]);
					variables [i].Emit (ec);

					if (lengths != null)
						lengths [i].Emit (ec);
					else
						length_exprs [i].Emit (ec);

					ec.Emit (OpCodes.Blt, loop [i]);
				}

				ec.MarkLabel (ec.LoopEnd);
			}
Exemple #5
0
		/// <summary>
		/// This method emits code for a lookup-based switch statement (non-string)
		/// Basically it groups the cases into blocks that are at least half full,
		/// and then spits out individual lookup opcodes for each block.
		/// It emits the longest blocks first, and short blocks are just
		/// handled with direct compares.
		/// </summary>
		/// <param name="ec"></param>
		/// <param name="val"></param>
		/// <returns></returns>
		void TableSwitchEmit (EmitContext ec, Expression val)
		{
			int element_count = Elements.Count;
			object [] element_keys = new object [element_count];
			Elements.Keys.CopyTo (element_keys, 0);
			Array.Sort (element_keys);

			// initialize the block list with one element per key
			var key_blocks = new List<KeyBlock> (element_count);
			foreach (object key in element_keys)
				key_blocks.Add (new KeyBlock (System.Convert.ToInt64 (key)));

			KeyBlock current_kb;
			// iteratively merge the blocks while they are at least half full
			// there's probably a really cool way to do this with a tree...
			while (key_blocks.Count > 1)
			{
				var key_blocks_new = new List<KeyBlock> ();
				current_kb = (KeyBlock) key_blocks [0];
				for (int ikb = 1; ikb < key_blocks.Count; ikb++)
				{
					KeyBlock kb = (KeyBlock) key_blocks [ikb];
					if ((current_kb.Size + kb.Size) * 2 >=  KeyBlock.TotalLength (current_kb, kb))
					{
						// merge blocks
						current_kb.last = kb.last;
						current_kb.Size += kb.Size;
					}
					else
					{
						// start a new block
						key_blocks_new.Add (current_kb);
						current_kb = kb;
					}
				}
				key_blocks_new.Add (current_kb);
				if (key_blocks.Count == key_blocks_new.Count)
					break;
				key_blocks = key_blocks_new;
			}

			// initialize the key lists
			foreach (KeyBlock kb in key_blocks)
				kb.element_keys = new List<object> ();

			// fill the key lists
			int iBlockCurr = 0;
			if (key_blocks.Count > 0) {
				current_kb = (KeyBlock) key_blocks [0];
				foreach (object key in element_keys)
				{
					bool next_block = (key is UInt64) ? (ulong) key > (ulong) current_kb.last :
						System.Convert.ToInt64 (key) > current_kb.last;
					if (next_block)
						current_kb = (KeyBlock) key_blocks [++iBlockCurr];
					current_kb.element_keys.Add (key);
				}
			}

			// sort the blocks so we can tackle the largest ones first
			key_blocks.Sort ();

			// okay now we can start...
			Label lbl_end = ec.DefineLabel ();	// at the end ;-)
			Label lbl_default = default_target;

			Type type_keys = null;
			if (element_keys.Length > 0)
				type_keys = element_keys [0].GetType ();	// used for conversions

			TypeSpec compare_type;
			
			if (TypeManager.IsEnumType (SwitchType))
				compare_type = EnumSpec.GetUnderlyingType (SwitchType);
			else
				compare_type = SwitchType;
			
			for (int iBlock = key_blocks.Count - 1; iBlock >= 0; --iBlock)
			{
				KeyBlock kb = ((KeyBlock) key_blocks [iBlock]);
				lbl_default = (iBlock == 0) ? default_target : ec.DefineLabel ();
				if (kb.Length <= 2)
				{
					foreach (object key in kb.element_keys) {
						SwitchLabel sl = (SwitchLabel) Elements [key];
						if (key is int && (int) key == 0) {
							val.EmitBranchable (ec, sl.GetILLabel (ec), false);
						} else {
							val.Emit (ec);
							EmitObjectInteger (ec, key);
							ec.Emit (OpCodes.Beq, sl.GetILLabel (ec));
						}
					}
				}
				else
				{
					// TODO: if all the keys in the block are the same and there are
					//       no gaps/defaults then just use a range-check.
					if (compare_type == TypeManager.int64_type ||
						compare_type == TypeManager.uint64_type)
					{
						// TODO: optimize constant/I4 cases

						// check block range (could be > 2^31)
						val.Emit (ec);
						EmitObjectInteger (ec, System.Convert.ChangeType (kb.first, type_keys));
						ec.Emit (OpCodes.Blt, lbl_default);
						val.Emit (ec);
						EmitObjectInteger (ec, System.Convert.ChangeType (kb.last, type_keys));
						ec.Emit (OpCodes.Bgt, lbl_default);

						// normalize range
						val.Emit (ec);
						if (kb.first != 0)
						{
							EmitObjectInteger (ec, System.Convert.ChangeType (kb.first, type_keys));
							ec.Emit (OpCodes.Sub);
						}
						ec.Emit (OpCodes.Conv_I4);	// assumes < 2^31 labels!
					}
					else
					{
						// normalize range
						val.Emit (ec);
						int first = (int) kb.first;
						if (first > 0)
						{
							ec.EmitInt (first);
							ec.Emit (OpCodes.Sub);
						}
						else if (first < 0)
						{
							ec.EmitInt (-first);
							ec.Emit (OpCodes.Add);
						}
					}

					// first, build the list of labels for the switch
					int iKey = 0;
					int cJumps = kb.Length;
					Label [] switch_labels = new Label [cJumps];
					for (int iJump = 0; iJump < cJumps; iJump++)
					{
						object key = kb.element_keys [iKey];
						if (System.Convert.ToInt64 (key) == kb.first + iJump)
						{
							SwitchLabel sl = (SwitchLabel) Elements [key];
							switch_labels [iJump] = sl.GetILLabel (ec);
							iKey++;
						}
						else
							switch_labels [iJump] = lbl_default;
					}
					// emit the switch opcode
					ec.Emit (OpCodes.Switch, switch_labels);
				}

				// mark the default for this block
				if (iBlock != 0)
					ec.MarkLabel (lbl_default);
			}

			// TODO: find the default case and emit it here,
			//       to prevent having to do the following jump.
			//       make sure to mark other labels in the default section

			// the last default just goes to the end
			if (element_keys.Length > 0)
				ec.Emit (OpCodes.Br, lbl_default);

			// now emit the code for the sections
			bool found_default = false;

			foreach (SwitchSection ss in Sections) {
				foreach (SwitchLabel sl in ss.Labels) {
					if (sl.Converted == SwitchLabel.NullStringCase) {
						ec.MarkLabel (null_target);
					} else if (sl.Label == null) {
						ec.MarkLabel (lbl_default);
						found_default = true;
						if (!has_null_case)
							ec.MarkLabel (null_target);
					}
					ec.MarkLabel (sl.GetILLabel (ec));
					ec.MarkLabel (sl.GetILLabelCode (ec));
				}
				ss.Block.Emit (ec);
			}
			
			if (!found_default) {
				ec.MarkLabel (lbl_default);
				if (!has_null_case) {
					ec.MarkLabel (null_target);
				}
			}
			
			ec.MarkLabel (lbl_end);
		}
Exemple #6
0
		protected override void DoEmit (EmitContext ec)
		{
			//
			// Needed to emit anonymous storey initialization
			// Otherwise it does not contain any statements for now
			//
			block.Emit (ec);

			default_target = ec.DefineLabel ();
			null_target = ec.DefineLabel ();

			// Store variable for comparission purposes
			// TODO: Don't duplicate non-captured VariableReference
			LocalTemporary value;
			if (HaveUnwrap) {
				value = new LocalTemporary (SwitchType);
				unwrap.EmitCheck (ec);
				ec.Emit (OpCodes.Brfalse, null_target);
				new_expr.Emit (ec);
				value.Store (ec);
			} else if (!is_constant) {
				value = new LocalTemporary (SwitchType);
				new_expr.Emit (ec);
				value.Store (ec);
			} else
				value = null;

			//
			// Setup the codegen context
			//
			Label old_end = ec.LoopEnd;
			Switch old_switch = ec.Switch;
			
			ec.LoopEnd = ec.DefineLabel ();
			ec.Switch = this;

			// Emit Code.
			if (is_constant) {
				if (constant_section != null)
					constant_section.Block.Emit (ec);
			} else if (string_dictionary != null) {
				DoEmitStringSwitch (value, ec);
			} else {
				TableSwitchEmit (ec, value);
			}

			if (value != null)
				value.Release (ec);

			// Restore context state. 
			ec.MarkLabel (ec.LoopEnd);

			//
			// Restore the previous context
			//
			ec.LoopEnd = old_end;
			ec.Switch = old_switch;
		}
Exemple #7
0
        public void EmitPrologue(EmitContext ec)
        {
            awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(expr.Type);

            var fe_awaiter = new FieldExpr(awaiter, loc);

            fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc);

            Label skip_continuation = ec.DefineLabel();

            using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) {
                //
                // awaiter = expr.GetAwaiter ();
                //
                fe_awaiter.EmitAssign(ec, expr, false, false);

                Expression completed_expr;
                if (IsDynamic)
                {
                    var rc = new ResolveContext(ec.MemberContext);

                    Arguments dargs = new Arguments(1);
                    dargs.Add(new Argument(fe_awaiter));
                    completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc);

                    dargs = new Arguments(1);
                    dargs.Add(new Argument(completed_expr));
                    completed_expr = new DynamicConversion(ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve(rc);
                }
                else
                {
                    var pe = PropertyExpr.CreatePredefined(awaiter_definition.IsCompleted, loc);
                    pe.InstanceExpression = fe_awaiter;
                    completed_expr        = pe;
                }

                completed_expr.EmitBranchable(ec, skip_continuation, true);
            }

            base.DoEmit(ec);

            //
            // The stack has to be empty before calling await continuation. We handle this
            // by lifting values which would be left on stack into class fields. The process
            // is quite complicated and quite hard to test because any expression can possibly
            // leave a value on the stack.
            //
            // Following assert fails when some of expression called before is missing EmitToField
            // or parent expression fails to find await in children expressions
            //
            ec.AssertEmptyStack();

            var storey = (AsyncTaskStorey)machine_initializer.Storey;

            if (IsDynamic)
            {
                storey.EmitAwaitOnCompletedDynamic(ec, fe_awaiter);
            }
            else
            {
                storey.EmitAwaitOnCompleted(ec, fe_awaiter);
            }

            // Return ok
            machine_initializer.EmitLeave(ec, unwind_protect);

            ec.MarkLabel(resume_point);
            ec.MarkLabel(skip_continuation);
        }
Exemple #8
0
                protected override void DoEmit(EmitContext ec)
                {
                    Label label_init = ec.DefineLabel ();

                    ec.Emit (OpCodes.Ldarg_0);
                    ec.Emit (OpCodes.Ldflda, host.PC.Spec);
                    ec.EmitInt ((int) Iterator.State.Start);
                    ec.EmitInt ((int) Iterator.State.Uninitialized);
                    ec.Emit (OpCodes.Call, TypeManager.int_interlocked_compare_exchange);

                    ec.EmitInt ((int) Iterator.State.Uninitialized);
                    ec.Emit (OpCodes.Bne_Un_S, label_init);

                    ec.Emit (OpCodes.Ldarg_0);
                    ec.Emit (OpCodes.Ret);

                    ec.MarkLabel (label_init);

                    new_storey.Emit (ec);
                    ec.Emit (OpCodes.Ret);
                }
Exemple #9
0
        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);
            }
        }
Exemple #10
0
        void EmitMoveNext(EmitContext ec)
        {
            move_next_ok    = ec.DefineLabel();
            move_next_error = ec.DefineLabel();

            if (resume_points == null)
            {
                EmitMoveNext_NoResumePoints(ec, block);
                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();
            }

            SymbolWriter.StartIteratorDispatcher(ec);
            ec.Emit(OpCodes.Ldloc, current_pc);
            ec.Emit(OpCodes.Switch, labels);

            ec.Emit(async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error);
            SymbolWriter.EndIteratorDispatcher(ec);

            ec.MarkLabel(labels[0]);

            iterator_body_end = ec.DefineLabel();

            SymbolWriter.StartIteratorBody(ec);
            block.Emit(ec);
            SymbolWriter.EndIteratorBody(ec);

            SymbolWriter.StartIteratorDispatcher(ec);

            ec.MarkLabel(iterator_body_end);

            if (async_init != null)
            {
                var catch_value = LocalVariable.CreateCompilerGenerated(ec.Module.Compiler.BuiltinTypes.Exception, block, Location);

                ec.BeginCatchBlock(catch_value.Type);
                catch_value.EmitAssign(ec);

                ec.EmitThis();
                ec.EmitInt((int)IteratorStorey.State.After);
                ec.Emit(OpCodes.Stfld, storey.PC.Spec);

                ((AsyncTaskStorey)async_init.Storey).EmitSetException(ec, new LocalVariableReference(catch_value, Location));

                ec.Emit(OpCodes.Leave, move_next_ok);
                ec.EndExceptionBlock();
            }

            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);
            }

            SymbolWriter.EndIteratorDispatcher(ec);
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        public void EmitPrologue(EmitContext ec)
        {
            var fe_awaiter = new FieldExpr(awaiter, loc);

            fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc);

            //
            // awaiter = expr.GetAwaiter ();
            //
            fe_awaiter.EmitAssign(ec, expr, false, false);

            Label skip_continuation = ec.DefineLabel();

            Expression completed_expr;

            if (IsDynamic)
            {
                var rc = new ResolveContext(ec.MemberContext);

                Arguments dargs = new Arguments(1);
                dargs.Add(new Argument(fe_awaiter));
                completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc);
            }
            else
            {
                var pe = PropertyExpr.CreatePredefined(is_completed, loc);
                pe.InstanceExpression = fe_awaiter;
                completed_expr        = pe;
            }

            completed_expr.EmitBranchable(ec, skip_continuation, true);

            base.DoEmit(ec);

            //
            // The stack has to be empty before calling await continuation. We handle this
            // by lifting values which would be left on stack into class fields. The process
            // is quite complicated and quite hard to test because any expression can possibly
            // leave a value on the stack.
            //
            // Following assert fails when some of expression called before is missing EmitToField
            // or parent expression fails to find await in children expressions
            //
            ec.AssertEmptyStack();

            var storey     = (AsyncTaskStorey)machine_initializer.Storey;
            var cont_field = storey.EmitContinuationInitialization(ec);

            var args = new Arguments(1);

            args.Add(new Argument(cont_field));

            if (IsDynamic)
            {
                var rc      = new ResolveContext(ec.MemberContext);
                var mg_expr = new Invocation(new MemberAccess(fe_awaiter, "OnCompleted"), args).Resolve(rc);

                ExpressionStatement es = (ExpressionStatement)mg_expr;
                es.EmitStatement(ec);
            }
            else
            {
                var mg_completed = MethodGroupExpr.CreatePredefined(on_completed, fe_awaiter.Type, loc);
                mg_completed.InstanceExpression = fe_awaiter;

                //
                // awaiter.OnCompleted (continuation);
                //
                mg_completed.EmitCall(ec, args);
            }

            // Return ok
            machine_initializer.EmitLeave(ec, unwind_protect);

            ec.MarkLabel(resume_point);
            ec.MarkLabel(skip_continuation);
        }
Exemple #13
0
        void EmitMoveNext(EmitContext ec)
        {
            move_next_ok    = ec.DefineLabel();
            move_next_error = ec.DefineLabel();

            if (resume_points == null)
            {
                EmitMoveNext_NoResumePoints(ec, block);
                return;
            }

            current_pc = ec.GetTemporaryLocal(ec.BuiltinTypes.UInt);
            ec.Emit(OpCodes.Ldarg_0);
            ec.Emit(OpCodes.Ldfld, IteratorHost.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.Emit(OpCodes.Ldarg_0);
            ec.EmitInt((int)State.After);
            ec.Emit(OpCodes.Stfld, IteratorHost.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.Emit(OpCodes.Ldc_I4_0);
                ec.Emit(OpCodes.Stloc, skip_finally);
            }

            SymbolWriter.StartIteratorDispatcher(ec);
            ec.Emit(OpCodes.Ldloc, current_pc);
            ec.Emit(OpCodes.Switch, labels);

            ec.Emit(OpCodes.Br, move_next_error);
            SymbolWriter.EndIteratorDispatcher(ec);

            ec.MarkLabel(labels [0]);

            SymbolWriter.StartIteratorBody(ec);
            block.Emit(ec);
            SymbolWriter.EndIteratorBody(ec);

            SymbolWriter.StartIteratorDispatcher(ec);

            ec.Emit(OpCodes.Ldarg_0);
            ec.EmitInt((int)State.After);
            ec.Emit(OpCodes.Stfld, IteratorHost.PC.Spec);

            ec.MarkLabel(move_next_error);
            ec.EmitInt(0);
            ec.Emit(OpCodes.Ret);

            ec.MarkLabel(move_next_ok);
            ec.Emit(OpCodes.Ldc_I4_1);
            ec.Emit(OpCodes.Ret);

            SymbolWriter.EndIteratorDispatcher(ec);
        }
Exemple #14
0
        public void EmitDispose(EmitContext ec)
        {
            Label end = ec.DefineLabel ();

            Label [] labels = null;
            int n_resume_points = resume_points == null ? 0 : resume_points.Count;
            for (int i = 0; i < n_resume_points; ++i) {
                ResumableStatement s = (ResumableStatement) 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 (TypeManager.uint32_type);
                ec.Emit (OpCodes.Ldarg_0);
                ec.Emit (OpCodes.Ldfld, IteratorHost.PC.Spec);
                ec.Emit (OpCodes.Stloc, current_pc);
            }

            ec.Emit (OpCodes.Ldarg_0);
            ec.EmitInt ((int) State.After);
            ec.Emit (OpCodes.Stfld, IteratorHost.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, this, end, true);
            }

            ec.MarkLabel (end);
        }
Exemple #15
0
        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 = !ExpressionAnalyzer.IsInexpensiveLoad(instance);
                        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);
                    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);
                }
            }
        }
Exemple #16
0
        internal void EmitMoveNext(EmitContext ec, Block original_block)
        {
            move_next_ok = ec.DefineLabel ();
            move_next_error = ec.DefineLabel ();

            if (resume_points == null) {
                EmitMoveNext_NoResumePoints (ec, original_block);
                return;
            }

            current_pc = ec.GetTemporaryLocal (TypeManager.uint32_type);
            ec.Emit (OpCodes.Ldarg_0);
            ec.Emit (OpCodes.Ldfld, IteratorHost.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.Emit (OpCodes.Ldarg_0);
            ec.EmitInt ((int) State.After);
            ec.Emit (OpCodes.Stfld, IteratorHost.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 (TypeManager.bool_type);
                ec.Emit (OpCodes.Ldc_I4_0);
                ec.Emit (OpCodes.Stloc, skip_finally);
            }

            SymbolWriter.StartIteratorDispatcher (ec);
            ec.Emit (OpCodes.Ldloc, current_pc);
            ec.Emit (OpCodes.Switch, labels);

            ec.Emit (OpCodes.Br, move_next_error);
            SymbolWriter.EndIteratorDispatcher (ec);

            ec.MarkLabel (labels [0]);

            SymbolWriter.StartIteratorBody (ec);
            original_block.Emit (ec);
            SymbolWriter.EndIteratorBody (ec);

            SymbolWriter.StartIteratorDispatcher (ec);

            ec.Emit (OpCodes.Ldarg_0);
            ec.EmitInt ((int) State.After);
            ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec);

            ec.MarkLabel (move_next_error);
            ec.EmitInt (0);
            ec.Emit (OpCodes.Ret);

            ec.MarkLabel (move_next_ok);
            ec.Emit (OpCodes.Ldc_I4_1);
            ec.Emit (OpCodes.Ret);

            SymbolWriter.EndIteratorDispatcher (ec);
        }
Exemple #17
0
		//
		// Called back from Yield
		//
		public void MarkYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point)
		{
			// Store the new current
			ec.Emit (OpCodes.Ldarg_0);
			expr.Emit (ec);
			ec.Emit (OpCodes.Stfld, IteratorHost.CurrentField.Spec);

			//
			// Guard against being disposed meantime
			//
			Label disposed = ec.DefineLabel ();
			ec.Emit (OpCodes.Ldarg_0);
			ec.Emit (OpCodes.Ldfld, IteratorHost.DisposingField.Spec);
			ec.Emit (OpCodes.Brtrue_S, disposed);

			//
			// store resume program-counter
			//
			ec.Emit (OpCodes.Ldarg_0);
			ec.EmitInt (resume_pc);
			ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec);
			ec.MarkLabel (disposed);

			// mark finally blocks as disabled
			if (unwind_protect && skip_finally != null) {
				ec.EmitInt (1);
				ec.Emit (OpCodes.Stloc, skip_finally);
			}

			// Return ok
			ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok);

			ec.MarkLabel (resume_point);
		}
Exemple #18
0
        protected override void EmitFinallyBody(EmitContext ec)
        {
            if (!TypeManager.IsStruct (expr_type)) {
                Label skip = ec.DefineLabel ();
                local_copy.Emit (ec);
                ec.Emit (OpCodes.Brfalse, skip);
                local_copy.Emit (ec);
                ec.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                ec.MarkLabel (skip);
                return;
            }

            MethodSpec ms = MemberCache.FindMember (expr_type,
                MemberFilter.Method ("Dispose", 0, ParametersCompiled.EmptyReadOnlyParameters, TypeManager.void_type),
                BindingRestriction.InstanceOnly) as MethodSpec;

            if (ms == null) {
                local_copy.Emit (ec);
                ec.Emit (OpCodes.Box, expr_type);
                ec.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
                return;
            }

            local_copy.AddressOf (ec, AddressOp.Load);
            ec.Emit (OpCodes.Call, ms);
        }
Exemple #19
0
		public void EmitResultLift (EmitContext ec, TypeSpec type, bool statement)
		{
			if (!NullShortCircuit)
				throw new InternalErrorException ();

			bool value_rt = TypeSpec.IsValueType (type);
			TypeSpec lifted;
			if (value_rt) {
				if (type.IsNullableType)
					lifted = type;
				else {
					lifted = Nullable.NullableInfo.MakeType (ec.Module, type);
					ec.Emit (OpCodes.Newobj, Nullable.NullableInfo.GetConstructor (lifted));
				}
			} else {
				lifted = null;
			}

			var end = ec.DefineLabel ();
			if (value_on_stack || !statement) {
				ec.Emit (OpCodes.Br_S, end);
			}

			ec.MarkLabel (NullOperatorLabel);

			if (value_on_stack)
				ec.Emit (OpCodes.Pop);

			if (!statement) {
				if (value_rt)
					Nullable.LiftedNull.Create (lifted, Location.Null).Emit (ec);
				else
					ec.EmitNull ();
			}

			ec.MarkLabel (end);
		}
Exemple #20
0
		void DoEmitStringSwitch (LocalTemporary value, EmitContext ec)
		{
			Label l_initialized = ec.DefineLabel ();

			//
			// Skip initialization when value is null
			//
			value.EmitBranchable (ec, null_target, false);

			//
			// Check if string dictionary is initialized and initialize
			//
			switch_cache_field.EmitBranchable (ec, l_initialized, true);
			string_dictionary.EmitStatement (ec);
			ec.MarkLabel (l_initialized);

			LocalTemporary string_switch_variable = new LocalTemporary (TypeManager.int32_type);

			ResolveContext rc = new ResolveContext (ec.MemberContext);

			if (TypeManager.generic_ienumerable_type != null) {
				Arguments get_value_args = new Arguments (2);
				get_value_args.Add (new Argument (value));
				get_value_args.Add (new Argument (string_switch_variable, Argument.AType.Out));
				Expression get_item = new Invocation (new MemberAccess (switch_cache_field, "TryGetValue", loc), get_value_args).Resolve (rc);
				if (get_item == null)
					return;

				//
				// A value was not found, go to default case
				//
				get_item.EmitBranchable (ec, default_target, false);
			} else {
				Arguments get_value_args = new Arguments (1);
				get_value_args.Add (new Argument (value));

				Expression get_item = new ElementAccess (switch_cache_field, get_value_args, loc).Resolve (rc);
				if (get_item == null)
					return;

				LocalTemporary get_item_object = new LocalTemporary (TypeManager.object_type);
				get_item_object.EmitAssign (ec, get_item, true, false);
				ec.Emit (OpCodes.Brfalse, default_target);

				ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable,
					new Cast (new TypeExpression (TypeManager.int32_type, loc), get_item_object, loc)).Resolve (rc);

				get_item_int.EmitStatement (ec);
				get_item_object.Release (ec);
			}

			TableSwitchEmit (ec, string_switch_variable);
			string_switch_variable.Release (ec);
		}
Exemple #21
0
				protected override void DoEmit (EmitContext ec)
				{
					Label label_init = ec.DefineLabel ();

					ec.Emit (OpCodes.Ldarg_0);
					ec.Emit (OpCodes.Ldflda, host.PC.Spec);
					ec.EmitInt ((int) Iterator.State.Start);
					ec.EmitInt ((int) Iterator.State.Uninitialized);

					var m = ec.Module.PredefinedMembers.InterlockedCompareExchange.Resolve (loc);
					if (m != null)
						ec.Emit (OpCodes.Call, m);

					ec.EmitInt ((int) Iterator.State.Uninitialized);
					ec.Emit (OpCodes.Bne_Un_S, label_init);

					ec.Emit (OpCodes.Ldarg_0);
					ec.Emit (OpCodes.Ret);

					ec.MarkLabel (label_init);

					new_storey.Emit (ec);
					ec.Emit (OpCodes.Ret);
				}
Exemple #22
0
		protected sealed override void DoEmit (EmitContext ec)
		{
			EmitPreTryBody (ec);

			if (resume_points != null) {
				ec.EmitInt ((int) Iterator.State.Running);
				ec.Emit (OpCodes.Stloc, iter.CurrentPC);
			}

			ec.BeginExceptionBlock ();

			if (resume_points != null) {
				ec.MarkLabel (resume_point);

				// For normal control flow, we want to fall-through the Switch
				// So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above
				ec.Emit (OpCodes.Ldloc, iter.CurrentPC);
				ec.EmitInt (first_resume_pc);
				ec.Emit (OpCodes.Sub);

				Label [] labels = new Label [resume_points.Count];
				for (int i = 0; i < resume_points.Count; ++i)
					labels [i] = resume_points [i].PrepareForEmit (ec);
				ec.Emit (OpCodes.Switch, labels);
			}

			EmitTryBody (ec);

			ec.BeginFinallyBlock ();

			Label start_finally = ec.DefineLabel ();
			if (resume_points != null) {
				ec.Emit (OpCodes.Ldloc, iter.SkipFinally);
				ec.Emit (OpCodes.Brfalse_S, start_finally);
				ec.Emit (OpCodes.Endfinally);
			}

			ec.MarkLabel (start_finally);
			EmitFinallyBody (ec);

			ec.EndExceptionBlock ();
		}
Exemple #23
0
		protected override void EmitFinallyBody (EmitContext ec)
		{
			//
			// if (lock_taken) Monitor.Exit (expr_copy)
			//
			Label skip = ec.DefineLabel ();

			if (lock_taken != null) {
				lock_taken.Emit (ec);
				ec.Emit (OpCodes.Brfalse_S, skip);
			}

			expr_copy.Emit (ec);
			ec.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
			ec.MarkLabel (skip);
		}
Exemple #24
0
		public override void EmitForDispose (EmitContext ec, Iterator iterator, Label end, bool have_dispatcher)
		{
			if (emitted_dispose)
				return;

			emitted_dispose = true;

			Label end_of_try = ec.DefineLabel ();

			// Ensure that the only way we can get into this code is through a dispatcher
			if (have_dispatcher)
				ec.Emit (OpCodes.Br, end);

			ec.BeginExceptionBlock ();

			ec.MarkLabel (dispose_try_block);

			Label [] labels = null;
			for (int i = 0; i < resume_points.Count; ++i) {
				ResumableStatement s = (ResumableStatement) resume_points [i];
				Label ret = s.PrepareForDispose (ec, end_of_try);
				if (ret.Equals (end_of_try) && labels == null)
					continue;
				if (labels == null) {
					labels = new Label [resume_points.Count];
					for (int j = 0; j < i; ++j)
						labels [j] = end_of_try;
				}
				labels [i] = ret;
			}

			if (labels != null) {
				int j;
				for (j = 1; j < labels.Length; ++j)
					if (!labels [0].Equals (labels [j]))
						break;
				bool emit_dispatcher = j < labels.Length;

				if (emit_dispatcher) {
					//SymbolWriter.StartIteratorDispatcher (ec.ig);
					ec.Emit (OpCodes.Ldloc, iterator.CurrentPC);
					ec.EmitInt (first_resume_pc);
					ec.Emit (OpCodes.Sub);
					ec.Emit (OpCodes.Switch, labels);
					//SymbolWriter.EndIteratorDispatcher (ec.ig);
				}

				foreach (ResumableStatement s in resume_points)
					s.EmitForDispose (ec, iterator, end_of_try, emit_dispatcher);
			}

			ec.MarkLabel (end_of_try);

			ec.BeginFinallyBlock ();

			EmitFinallyBody (ec);

			ec.EndExceptionBlock ();
		}
Exemple #25
0
		protected override void EmitFinallyBody (EmitContext ec)
		{
			Label skip = ec.DefineLabel ();

			bool emit_null_check = !TypeManager.IsValueType (var.Type);
			if (emit_null_check) {
				var.Emit (ec);
				ec.Emit (OpCodes.Brfalse, skip);
			}

			Invocation.EmitCall (ec, var, TypeManager.void_dispose_void, null, loc);

			if (emit_null_check)
				ec.MarkLabel (skip);
		}
Exemple #26
0
		protected override void DoEmit (EmitContext ec)
		{
			if (InitStatement != null)
				InitStatement.Emit (ec);

			if (empty) {
				Test.EmitSideEffect (ec);
				return;
			}

			Label old_begin = ec.LoopBegin;
			Label old_end = ec.LoopEnd;
			Label loop = ec.DefineLabel ();
			Label test = ec.DefineLabel ();

			ec.LoopBegin = ec.DefineLabel ();
			ec.LoopEnd = ec.DefineLabel ();

			ec.Emit (OpCodes.Br, test);
			ec.MarkLabel (loop);
			Statement.Emit (ec);

			ec.MarkLabel (ec.LoopBegin);
			Increment.Emit (ec);

			ec.MarkLabel (test);
			//
			// If test is null, there is no test, and we are just
			// an infinite loop
			//
			if (Test != null){
				//
				// The Resolve code already catches the case for
				// Test == Constant (false) so we know that
				// this is true
				//
				if (Test is Constant) {
					Test.EmitSideEffect (ec);
					ec.Emit (OpCodes.Br, loop);
				} else {
					Test.EmitBranchable (ec, loop, true);
				}
				
			} else
				ec.Emit (OpCodes.Br, loop);
			ec.MarkLabel (ec.LoopEnd);

			ec.LoopBegin = old_begin;
			ec.LoopEnd = old_end;
		}
Exemple #27
0
				protected override void EmitFinallyBody (EmitContext ec)
				{
					Label call_dispose = ec.DefineLabel ();
					if (dispose != null) {
						local_copy.Emit (ec, false);
						ec.Emit (OpCodes.Isinst, dispose.Type);
						dispose.Store (ec);
					}

					base.EmitFinallyBody (ec);

					if (dispose != null) {
						ec.MarkLabel (call_dispose);
						dispose.Release (ec);
					}
				}
Exemple #28
0
		protected void EmitConditionalAccess (EmitContext ec)
		{
			var a_expr = arguments [0].Expr;

			var des = a_expr as DynamicExpressionStatement;
			if (des != null) {
				des.EmitConditionalAccess (ec);
			}

			if (HasConditionalAccess ()) {
				var NullOperatorLabel = ec.DefineLabel ();

				if (ExpressionAnalyzer.IsInexpensiveLoad (a_expr)) {
					a_expr.Emit (ec);
				} else {
					var lt = new LocalTemporary (a_expr.Type);
					lt.EmitAssign (ec, a_expr, true, false);

					Arguments [0].Expr = lt;
				}

				ec.Emit (OpCodes.Brtrue_S, NullOperatorLabel);

				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);

				return;
			}

			if (a_expr.HasConditionalAccess ()) {
				var lt = new LocalTemporary (a_expr.Type);
				lt.EmitAssign (ec, a_expr, false, false);

				Arguments [0].Expr = lt;
			}
		}
Exemple #29
0
		protected override void DoEmit (EmitContext ec)
		{
			LabelTarget (ec);
			ec.MarkLabel (label);
		}
Exemple #30
0
		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);
				}
			}
		}
Exemple #31
0
		protected override void DoEmit (EmitContext ec)
		{
			Label false_target = ec.DefineLabel ();
			Label end;

			//
			// If we're a boolean constant, Resolve() already
			// eliminated dead code for us.
			//
			Constant c = expr as Constant;
			if (c != null){
				c.EmitSideEffect (ec);

				if (!c.IsDefaultValue)
					TrueStatement.Emit (ec);
				else if (FalseStatement != null)
					FalseStatement.Emit (ec);

				return;
			}			
			
			expr.EmitBranchable (ec, false_target, false);
			
			TrueStatement.Emit (ec);

			if (FalseStatement != null){
				bool branch_emitted = false;
				
				end = ec.DefineLabel ();
				if (!is_true_ret){
					ec.Emit (OpCodes.Br, end);
					branch_emitted = true;
				}

				ec.MarkLabel (false_target);
				FalseStatement.Emit (ec);

				if (branch_emitted)
					ec.MarkLabel (end);
			} else {
				ec.MarkLabel (false_target);
			}
		}
Exemple #32
0
        //
        // Called back from Yield
        //
        public void MarkYield(EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point)
        {
            // Store the new current
            ec.Emit (OpCodes.Ldarg_0);
            expr.Emit (ec);
            ec.Emit (OpCodes.Stfld, IteratorHost.CurrentField.Spec);

            // store resume program-counter
            ec.Emit (OpCodes.Ldarg_0);
            ec.EmitInt (resume_pc);
            ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec);

            // mark finally blocks as disabled
            if (unwind_protect && skip_finally != null) {
                ec.EmitInt (1);
                ec.Emit (OpCodes.Stloc, skip_finally);
            }

            // Return ok
            ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok);

            ec.MarkLabel (resume_point);
        }
Exemple #33
0
		public override void Emit (EmitContext ec)
		{
			if (Report.Errors > 0)
				return;

#if PRODUCTION
			try {
#endif
			if (ec.HasReturnLabel)
				ec.ReturnLabel = ec.DefineLabel ();

			base.Emit (ec);

			ec.Mark (EndLocation);

			if (ec.HasReturnLabel)
				ec.MarkLabel (ec.ReturnLabel);

			if (ec.return_value != null) {
				ec.Emit (OpCodes.Ldloc, ec.return_value);
				ec.Emit (OpCodes.Ret);
			} else {
				//
				// If `HasReturnLabel' is set, then we already emitted a
				// jump to the end of the method, so we must emit a `ret'
				// there.
				//
				// Unfortunately, System.Reflection.Emit automatically emits
				// a leave to the end of a finally block.  This is a problem
				// if no code is following the try/finally block since we may
				// jump to a point after the end of the method.
				// As a workaround, we're always creating a return label in
				// this case.
				//

				if (ec.HasReturnLabel || !unreachable) {
					if (ec.ReturnType != TypeManager.void_type)
						ec.Emit (OpCodes.Ldloc, ec.TemporaryReturn ());
					ec.Emit (OpCodes.Ret);
				}
			}

#if PRODUCTION
			} catch (Exception e){
				Console.WriteLine ("Exception caught by the compiler while emitting:");
				Console.WriteLine ("   Block that caused the problem begin at: " + block.loc);
					
				Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
				throw;
			}
#endif
		}
Exemple #34
0
        void EmitMoveNext_NoResumePoints(EmitContext ec, Block original_block)
        {
            ec.Emit (OpCodes.Ldarg_0);
            ec.Emit (OpCodes.Ldfld, IteratorHost.PC.Spec);

            ec.Emit (OpCodes.Ldarg_0);
            ec.EmitInt ((int) State.After);
            ec.Emit (OpCodes.Stfld, IteratorHost.PC.Spec);

            // We only care if the PC is zero (start executing) or non-zero (don't do anything)
            ec.Emit (OpCodes.Brtrue, move_next_error);

            SymbolWriter.StartIteratorBody (ec);
            original_block.Emit (ec);
            SymbolWriter.EndIteratorBody (ec);

            ec.MarkLabel (move_next_error);
            ec.Emit (OpCodes.Ldc_I4_0);
            ec.Emit (OpCodes.Ret);
        }
Exemple #35
0
		protected override void DoEmit (EmitContext ec)
		{
			Label loop = ec.DefineLabel ();
			Label old_begin = ec.LoopBegin;
			Label old_end = ec.LoopEnd;
			
			ec.LoopBegin = ec.DefineLabel ();
			ec.LoopEnd = ec.DefineLabel ();
				
			ec.MarkLabel (loop);
			EmbeddedStatement.Emit (ec);
			ec.MarkLabel (ec.LoopBegin);

			//
			// Dead code elimination
			//
			if (expr is Constant){
				bool res = !((Constant) expr).IsDefaultValue;

				expr.EmitSideEffect (ec);
				if (res)
					ec.Emit (OpCodes.Br, loop); 
			} else
				expr.EmitBranchable (ec, loop, true);
			
			ec.MarkLabel (ec.LoopEnd);

			ec.LoopBegin = old_begin;
			ec.LoopEnd = old_end;
		}
Exemple #36
0
		public override void Emit (EmitContext ec)
		{
			//
			// Use same anonymous method implementation for scenarios where same
			// code is used from multiple blocks, e.g. field initializers
			//
			if (method == null) {
				//
				// Delay an anonymous method definition to avoid emitting unused code
				// for unreachable blocks or expression trees
				//
				method = DoCreateMethodHost (ec);
				method.Define ();
			}

			bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
			if (is_static && am_cache == null) {
				//
				// Creates a field cache to store delegate instance if it's not generic
				//
				if (!method.MemberName.IsGeneric) {
					var parent = method.Parent.PartialContainer;
					int id = parent.AnonymousMethodsCounter++;
					var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type;

					am_cache = new Field (parent, new TypeExpression (cache_type, loc),
						Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
						new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "am$cache", id), loc), null);
					am_cache.Define ();
					parent.AddField (am_cache);
				} else {
					// TODO: Implement caching of generated generic static methods
					//
					// Idea:
					//
					// Some extra class is needed to capture variable generic type
					// arguments. Maybe we could re-use anonymous types, with a unique
					// anonymous method id, but they are quite heavy.
					//
					// Consider : "() => typeof(T);"
					//
					// We need something like
					// static class Wrap<Tn, Tm, DelegateType> {
					//		public static DelegateType cache;
					// }
					//
					// We then specialize local variable to capture all generic parameters
					// and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
					//
				}
			}

			Label l_initialized = ec.DefineLabel ();

			if (am_cache != null) {
				ec.Emit (OpCodes.Ldsfld, am_cache.Spec);
				ec.Emit (OpCodes.Brtrue_S, l_initialized);
			}

			//
			// Load method delegate implementation
			//

			if (is_static) {
				ec.EmitNull ();
			} else if (storey != null) {
				Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
				if (e != null) {
					e.Emit (ec);
				}
			} else {
				ec.EmitThis ();

				//
				// Special case for value type storey where this is not lifted but
				// droped off to parent class
				//
				for (var b = Block.Parent; b != null; b = b.Parent) {
					if (b.ParametersBlock.StateMachine != null) {
						ec.Emit (OpCodes.Ldfld, b.ParametersBlock.StateMachine.HoistedThis.Field.Spec);
						break;
					}
				}
			}

			var delegate_method = method.Spec;
			if (storey != null && storey.MemberName.IsGeneric) {
				TypeSpec t = storey.Instance.Type;

				//
				// Mutate anonymous method instance type if we are in nested
				// hoisted generic anonymous method storey
				//
				if (ec.IsAnonymousStoreyMutateRequired) {
					t = storey.Mutator.Mutate (t);
				}

				ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ()));
			} else {
				if (delegate_method.IsGeneric)
					delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters);

				ec.Emit (OpCodes.Ldftn, delegate_method);
			}

			var constructor_method = Delegate.GetConstructor (type);
			ec.Emit (OpCodes.Newobj, constructor_method);

			if (am_cache != null) {
				ec.Emit (OpCodes.Stsfld, am_cache.Spec);
				ec.MarkLabel (l_initialized);
				ec.Emit (OpCodes.Ldsfld, am_cache.Spec);
			}
		}
Exemple #37
0
                protected override void EmitFinallyBody(EmitContext ec)
                {
                    Expression instance = parent.enumerator;
                    if (!TypeManager.IsValueType (parent.enumerator_type)) {

                        parent.enumerator.Emit (ec);

                        Label call_dispose = ec.DefineLabel ();

                        if (!implements_idisposable) {
                            ec.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
                            LocalTemporary temp = new LocalTemporary (TypeManager.idisposable_type);
                            temp.Store (ec);
                            temp.Emit (ec);
                            instance = temp;
                        }

                        ec.Emit (OpCodes.Brtrue_S, call_dispose);

                        // using 'endfinally' to empty the evaluation stack
                        ec.Emit (OpCodes.Endfinally);
                        ec.MarkLabel (call_dispose);
                    }

                    Invocation.EmitCall (ec, false, instance, TypeManager.void_dispose_void, null, loc);
                }