⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codegen.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 3 页
字号:
			current_flow_branching = FlowBranching.CreateBranching (				CurrentBranching, type, block, block.StartLocation);			return current_flow_branching;		}		public FlowBranchingException StartFlowBranching (ExceptionStatement stmt)		{			FlowBranchingException branching = new FlowBranchingException (				CurrentBranching, stmt);			current_flow_branching = branching;			return branching;		}		// <summary>		//   Ends a code branching.  Merges the state of locals and parameters		//   from all the children of the ending branching.		// </summary>		public FlowBranching.UsageVector DoEndFlowBranching ()		{			FlowBranching old = current_flow_branching;			current_flow_branching = current_flow_branching.Parent;			return current_flow_branching.MergeChild (old);		}		// <summary>		//   Ends a code branching.  Merges the state of locals and parameters		//   from all the children of the ending branching.		// </summary>		public FlowBranching.Reachability EndFlowBranching ()		{			FlowBranching.UsageVector vector = DoEndFlowBranching ();			return vector.Reachability;		}		// <summary>		//   Kills the current code branching.  This throws away any changed state		//   information and should only be used in case of an error.		// </summary>		public void KillFlowBranching ()		{			current_flow_branching = current_flow_branching.Parent;		}		public void CaptureVariable (LocalInfo li)		{			capture_context.AddLocal (CurrentAnonymousMethod, li);			li.IsCaptured = true;		}		public void CaptureParameter (string name, Type t, int idx)		{			capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);		}		public void CaptureThis ()		{			capture_context.CaptureThis ();		}						//		// Use to register a field as captured		//		public void CaptureField (FieldExpr fe)		{			capture_context.AddField (this, CurrentAnonymousMethod, fe);		}		//		// Whether anonymous methods have captured variables		//		public bool HaveCapturedVariables ()		{			if (capture_context != null)				return capture_context.HaveCapturedVariables;			return false;		}		//		// Whether anonymous methods have captured fields or this.		//		public bool HaveCapturedFields ()		{			if (capture_context != null)				return capture_context.HaveCapturedFields;			return false;		}		//		// Emits the instance pointer for the host method		//		public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)		{			if (capture_context != null)				capture_context.EmitMethodHostInstance (target, am);			else if (IsStatic)				target.ig.Emit (OpCodes.Ldnull);			else				target.ig.Emit (OpCodes.Ldarg_0);		}		//		// Returns whether the `local' variable has been captured by an anonymous		// method		//		public bool IsCaptured (LocalInfo local)		{			return capture_context.IsCaptured (local);		}		public bool IsParameterCaptured (string name)		{			if (capture_context != null)				return capture_context.IsParameterCaptured (name);			return false;		}				public void EmitMeta (ToplevelBlock b, InternalParameters ip)		{			if (capture_context != null)				capture_context.EmitAnonymousHelperClasses (this);			b.EmitMeta (this);			if (HasReturnLabel)				ReturnLabel = ig.DefineLabel ();		}		//		// Here until we can fix the problem with Mono.CSharp.Switch, which		// currently can not cope with ig == null during resolve (which must		// be fixed for switch statements to work on anonymous methods).		//		public void EmitTopBlock (IMethodData md, ToplevelBlock block, InternalParameters ip)		{			if (block == null)				return;						bool unreachable;						if (ResolveTopBlock (null, block, ip, md, out unreachable)){				EmitMeta (block, ip);				current_phase = Phase.Emitting;				EmitResolvedTopBlock (block, unreachable);			}		}		bool resolved;		public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,					     InternalParameters ip, IMethodData md, out bool unreachable)		{			current_phase = Phase.Resolving;						unreachable = false;			if (resolved)				return true;			capture_context = block.CaptureContext;						if (!loc.IsNull)				CurrentFile = loc.File;#if PRODUCTION			try {#endif				if (!block.ResolveMeta (this, ip))					return false;				bool old_do_flow_analysis = DoFlowAnalysis;				DoFlowAnalysis = true;				if (anonymous_method_host != null)					current_flow_branching = FlowBranching.CreateBranching (						anonymous_method_host.CurrentBranching,						FlowBranching.BranchingType.Block, block, loc);				else 					current_flow_branching = block.TopLevelBranching;				if (!block.Resolve (this)) {					current_flow_branching = null;					DoFlowAnalysis = old_do_flow_analysis;					return false;				}				FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();				current_flow_branching = null;				DoFlowAnalysis = old_do_flow_analysis;				if (reachability.AlwaysReturns ||				    reachability.AlwaysThrows ||				    reachability.IsUnreachable)					unreachable = true;#if PRODUCTION			} catch (Exception e) {					Console.WriteLine ("Exception caught by the compiler while compiling:");					Console.WriteLine ("   Block that caused the problem begin at: " + loc);										if (CurrentBlock != null){						Console.WriteLine ("                     Block being compiled: [{0},{1}]",								   CurrentBlock.StartLocation, CurrentBlock.EndLocation);					}					Console.WriteLine (e.GetType ().FullName + ": " + e.Message);					throw;			}#endif			if (ReturnType != null && !unreachable) {				if (CurrentAnonymousMethod == null) {					Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());					return false;				} else if (!CurrentAnonymousMethod.IsIterator) {					Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",						CurrentAnonymousMethod.GetSignatureForError ());					return false;				}			}			block.CompleteContexts ();			resolved = true;			return true;		}		public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)		{			if (block != null)				block.Emit (this);						if (HasReturnLabel)				ig.MarkLabel (ReturnLabel);						if (return_value != null){				ig.Emit (OpCodes.Ldloc, return_value);				ig.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.				//				bool in_iterator = (CurrentAnonymousMethod != null) &&					CurrentAnonymousMethod.IsIterator && InIterator;				if ((block != null) && block.IsDestructor) {					// Nothing to do; S.R.E automatically emits a leave.				} else if (HasReturnLabel || (!unreachable && !in_iterator)) {					if (ReturnType != null)						ig.Emit (OpCodes.Ldloc, TemporaryReturn ());					ig.Emit (OpCodes.Ret);				}			}			//			// Close pending helper classes if we are the toplevel			//			if (capture_context != null && capture_context.ParentToplevel == null)				capture_context.CloseAnonymousHelperClasses ();		}		/// <summary>		///   This is called immediately before emitting an IL opcode to tell the symbol		///   writer to which source line this opcode belongs.		/// </summary>		public void Mark (Location loc, bool check_file)		{			if ((CodeGen.SymbolWriter == null) || loc.IsNull)				return;			if (check_file && (CurrentFile != loc.File))				return;			CodeGen.SymbolWriter.MarkSequencePoint (ig, loc.Row, loc.Column);		}		public void DefineLocalVariable (string name, LocalBuilder builder)		{			if (CodeGen.SymbolWriter == null)				return;			CodeGen.SymbolWriter.DefineLocalVariable (name, builder);		}		public void BeginScope ()		{			ig.BeginScope();			if (CodeGen.SymbolWriter != null)				CodeGen.SymbolWriter.OpenScope(ig);		}		public void EndScope ()		{			ig.EndScope();			if (CodeGen.SymbolWriter != null)				CodeGen.SymbolWriter.CloseScope(ig);		}		/// <summary>		///   Returns a temporary storage for a variable of type t as 		///   a local variable in the current body.		/// </summary>		public LocalBuilder GetTemporaryLocal (Type t)		{			LocalBuilder location = null;						if (temporary_storage != null){				object o = temporary_storage [t];				if (o != null){					if (o is ArrayList){						ArrayList al = (ArrayList) o;												for (int i = 0; i < al.Count; i++){							if (al [i] != null){								location = (LocalBuilder) al [i];								al [i] = null;								break;							}						}					} else						location = (LocalBuilder) o;					if (location != null)						return location;				}			}						return ig.DeclareLocal (t);		}		public void FreeTemporaryLocal (LocalBuilder b, Type t)		{			if (temporary_storage == null){				temporary_storage = new Hashtable ();				temporary_storage [t] = b;				return;			}			object o = temporary_storage [t];			if (o == null){				temporary_storage [t] = b;				return;			}			if (o is ArrayList){				ArrayList al = (ArrayList) o;				for (int i = 0; i < al.Count; i++){					if (al [i] == null){						al [i] = b;						return;					}				}				al.Add (b);				return;			}			ArrayList replacement = new ArrayList ();			replacement.Add (o);			temporary_storage.Remove (t);			temporary_storage [t] = replacement;		}		/// <summary>		///   Current loop begin and end labels.		/// </summary>		public Label LoopBegin, LoopEnd;		/// <summary>		///   Default target in a switch statement.   Only valid if		///   InSwitch is true		/// </summary>		public Label DefaultTarget;		/// <summary>		///   If this is non-null, points to the current switch statement		/// </summary>		public Switch Switch;		/// <summary>		///   ReturnValue creates on demand the LocalBuilder for the		///   return value from the function.  By default this is not		///   used.  This is only required when returns are found inside		///   Try or Catch statements.		///		///   This method is typically invoked from the Emit phase, so		///   we allow the creation of a return label if it was not		///   requested during the resolution phase.   Could be cleaned		///   up, but it would replicate a lot of logic in the Emit phase		///   of the code that uses it.		/// </summary>		public LocalBuilder TemporaryReturn ()		{			if (return_value == null){				return_value = ig.DeclareLocal (ReturnType);				if (!HasReturnLabel){					ReturnLabel = ig.DefineLabel ();					HasReturnLabel = true;				}			}			return return_value;		}		/// <summary>		///   This method is used during the Resolution phase to flag the		///   need to define the ReturnLabel		/// </summary>		public void NeedReturnLabel ()		{			if (current_phase != Phase.Resolving){				//				// The reason is that the `ReturnLabel' is declared between				// resolution and emission				// 				throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve");			}						if (!InIterator && !HasReturnLabel) 				HasReturnLabel = true;		}		//		// Emits the proper object to address fields on a remapped		// variable/parameter to field in anonymous-method/iterator proxy classes.		//		public void EmitThis ()		{			ig.Emit (OpCodes.Ldarg_0);			if (capture_context != null && CurrentAnonymousMethod != null){				ScopeInfo si = CurrentAnonymousMethod.Scope;				while (si != null){					if (si.ParentLink != null)						ig.Emit (OpCodes.Ldfld, si.ParentLink);					if (si.THIS != null){						ig.Emit (OpCodes.Ldfld, si.THIS);						break;					}					si = si.ParentScope;				}			} 		}		//		// Emits the code necessary to load the instance required		// to access the captured LocalInfo

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -