Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Compiler / LambdaCompiler.ControlFlow.cs / 1305376 / LambdaCompiler.ControlFlow.cs
/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ using System.Diagnostics; using System.Dynamic.Utils; namespace System.Linq.Expressions.Compiler { // The part of the LambdaCompiler dealing with low level control flow // break, contiue, return, exceptions, etc partial class LambdaCompiler { private LabelInfo EnsureLabel(LabelTarget node) { LabelInfo result; if (!_labelInfo.TryGetValue(node, out result)) { _labelInfo.Add(node, result = new LabelInfo(_ilg, node, false)); } return result; } private LabelInfo ReferenceLabel(LabelTarget node) { LabelInfo result = EnsureLabel(node); result.Reference(_labelBlock); return result; } private LabelInfo DefineLabel(LabelTarget node) { if (node == null) { return new LabelInfo(_ilg, null, false); } LabelInfo result = EnsureLabel(node); result.Define(_labelBlock); return result; } private void PushLabelBlock(LabelScopeKind type) { _labelBlock = new LabelScopeInfo(_labelBlock, type); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kind")] private void PopLabelBlock(LabelScopeKind kind) { Debug.Assert(_labelBlock != null && _labelBlock.Kind == kind); _labelBlock = _labelBlock.Parent; } private void EmitLabelExpression(Expression expr, CompilationFlags flags) { var node = (LabelExpression)expr; Debug.Assert(node.Target != null); // If we're an immediate child of a block, our label will already // be defined. If not, we need to define our own block so this // label isn't exposed except to its own child expression. LabelInfo label = null; if (_labelBlock.Kind == LabelScopeKind.Block) { _labelBlock.TryGetLabelInfo(node.Target, out label); // We're in a block but didn't find our label, try switch if (label == null && _labelBlock.Parent.Kind == LabelScopeKind.Switch) { _labelBlock.Parent.TryGetLabelInfo(node.Target, out label); } // if we're in a switch or block, we should've found the label Debug.Assert(label != null); } if (label == null) { label = DefineLabel(node.Target); } if (node.DefaultValue != null) { if (node.Target.Type == typeof(void)) { EmitExpressionAsVoid(node.DefaultValue, flags); } else { flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart); EmitExpression(node.DefaultValue, flags); } } label.Mark(); } private void EmitGotoExpression(Expression expr, CompilationFlags flags) { var node = (GotoExpression)expr; var labelInfo = ReferenceLabel(node.Target); var tailCall = flags & CompilationFlags.EmitAsTailCallMask; if (tailCall != CompilationFlags.EmitAsNoTail) { // Since tail call flags are not passed into EmitTryExpression, CanReturn // means the goto will be emitted as Ret. Therefore we can emit the goto's // default value with tail call. This can be improved by detecting if the // target label is equivalent to the return label. tailCall = labelInfo.CanReturn ? CompilationFlags.EmitAsTail : CompilationFlags.EmitAsNoTail; flags = UpdateEmitAsTailCallFlag(flags, tailCall); } if (node.Value != null) { if (node.Target.Type == typeof(void)) { EmitExpressionAsVoid(node.Value, flags); } else { flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart); EmitExpression(node.Value, flags); } } labelInfo.EmitJump(); EmitUnreachable(node, flags); } // We need to push default(T), unless we're emitting ourselves as // void. Even though the code is unreachable, we still have to // generate correct IL. We can get rid of this once we have better // reachability analysis. private void EmitUnreachable(Expression node, CompilationFlags flags) { if (node.Type != typeof(void) && (flags & CompilationFlags.EmitAsVoidType) == 0) { _ilg.EmitDefault(node.Type); } } private bool TryPushLabelBlock(Expression node) { // Anything that is "statement-like" -- e.g. has no associated // stack state can be jumped into, with the exception of try-blocks // We indicate this by a "Block" // // Otherwise, we push an "Expression" to indicate that it can't be // jumped into switch (node.NodeType) { default: if (_labelBlock.Kind != LabelScopeKind.Expression) { PushLabelBlock(LabelScopeKind.Expression); return true; } return false; case ExpressionType.Label: // LabelExpression is a bit special, if it's directly in a // block it becomes associate with the block's scope. Same // thing if it's in a switch case body. if (_labelBlock.Kind == LabelScopeKind.Block) { var label = ((LabelExpression)node).Target; if (_labelBlock.ContainsTarget(label)) { return false; } if (_labelBlock.Parent.Kind == LabelScopeKind.Switch && _labelBlock.Parent.ContainsTarget(label)) { return false; } } PushLabelBlock(LabelScopeKind.Statement); return true; case ExpressionType.Block: if (node is SpilledExpressionBlock) { // treat it as an expression goto default; } PushLabelBlock(LabelScopeKind.Block); // Labels defined immediately in the block are valid for // the whole block. if (_labelBlock.Parent.Kind != LabelScopeKind.Switch) { DefineBlockLabels(node); } return true; case ExpressionType.Switch: PushLabelBlock(LabelScopeKind.Switch); // Define labels inside of the switch cases so theyare in // scope for the whole switch. This allows "goto case" and // "goto default" to be considered as local jumps. var @switch = (SwitchExpression)node; foreach (SwitchCase c in @switch.Cases) { DefineBlockLabels(c.Body); } DefineBlockLabels(@switch.DefaultBody); return true; // Remove this when Convert(Void) goes away. case ExpressionType.Convert: if (node.Type != typeof(void)) { // treat it as an expression goto default; } PushLabelBlock(LabelScopeKind.Statement); return true; case ExpressionType.Conditional: case ExpressionType.Loop: case ExpressionType.Goto: PushLabelBlock(LabelScopeKind.Statement); return true; } } private void DefineBlockLabels(Expression node) { var block = node as BlockExpression; if (block == null || block is SpilledExpressionBlock) { return; } for (int i = 0, n = block.ExpressionCount; i < n; i++) { Expression e = block.GetExpression(i); var label = e as LabelExpression; if (label != null) { DefineLabel(label.Target); } } } // See if this lambda has a return label // If so, we'll create it now and mark it as allowing the "ret" opcode // This allows us to generate better IL private void AddReturnLabel(LambdaExpression lambda) { var expression = lambda.Body; while (true) { switch (expression.NodeType) { default: // Didn't find return label return; case ExpressionType.Label: // Found the label. We can directly return from this place // only if the label type is reference assignable to the lambda return type. var label = ((LabelExpression)expression).Target; _labelInfo.Add(label, new LabelInfo(_ilg, label, TypeUtils.AreReferenceAssignable(lambda.ReturnType, label.Type))); return; case ExpressionType.Block: // Look in the last significant expression of a block var body = (BlockExpression)expression; // omit empty and debuginfo at the end of the block since they // are not going to emit any IL for (int i = body.ExpressionCount - 1; i >= 0; i--) { expression = body.GetExpression(i); if (Significant(expression)) { break; } } continue; } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WeakReadOnlyCollection.cs
- DocumentPageHost.cs
- RectangleConverter.cs
- Literal.cs
- SerializerDescriptor.cs
- XmlSerializerVersionAttribute.cs
- BreadCrumbTextConverter.cs
- TraceXPathNavigator.cs
- sqlser.cs
- ApplicationServiceManager.cs
- SrgsElementList.cs
- StreamGeometry.cs
- InputReferenceExpression.cs
- ToolStripContainer.cs
- ProgressBar.cs
- SettingsPropertyValue.cs
- parserscommon.cs
- XmlSchemaType.cs
- TreeNodeCollection.cs
- BuildProvider.cs
- CustomWebEventKey.cs
- XPathParser.cs
- DataServiceProcessingPipeline.cs
- EventDriven.cs
- ProcessInfo.cs
- XamlInterfaces.cs
- SmiRecordBuffer.cs
- ExcCanonicalXml.cs
- WebPartTracker.cs
- ListControl.cs
- TemplateBuilder.cs
- ConfigXmlReader.cs
- FocusManager.cs
- InputScope.cs
- NamespaceListProperty.cs
- CaseStatement.cs
- sitestring.cs
- ImageInfo.cs
- ControlAdapter.cs
- _LocalDataStore.cs
- HttpRequestWrapper.cs
- FormClosingEvent.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- FileChangesMonitor.cs
- ArithmeticException.cs
- PageOutputQuality.cs
- SimpleLine.cs
- MobileControlsSection.cs
- DynamicRendererThreadManager.cs
- KeysConverter.cs
- WriteTimeStream.cs
- ActiveDocumentEvent.cs
- PriorityRange.cs
- RadioButton.cs
- LinkedResource.cs
- TraceHwndHost.cs
- GroupByQueryOperator.cs
- ColorKeyFrameCollection.cs
- ByteRangeDownloader.cs
- SpecialNameAttribute.cs
- CodeBlockBuilder.cs
- BaseParser.cs
- InstanceHandleConflictException.cs
- WinInetCache.cs
- StrokeDescriptor.cs
- FixedDocument.cs
- SelectionRange.cs
- ZipIOLocalFileDataDescriptor.cs
- PrintingPermissionAttribute.cs
- PointConverter.cs
- GeometryValueSerializer.cs
- StyleSheetDesigner.cs
- ProviderException.cs
- InstanceOwner.cs
- BindingMemberInfo.cs
- FamilyMapCollection.cs
- XsltLoader.cs
- GridViewRowPresenter.cs
- SchemeSettingElement.cs
- XamlToRtfWriter.cs
- TextWriter.cs
- RowCache.cs
- SystemIPAddressInformation.cs
- ActivationServices.cs
- WorkflowRuntimeServiceElementCollection.cs
- ItemsControlAutomationPeer.cs
- AndCondition.cs
- IndependentlyAnimatedPropertyMetadata.cs
- PropertyBuilder.cs
- TextContainerChangedEventArgs.cs
- BinaryMessageEncoder.cs
- CursorEditor.cs
- DataGrid.cs
- WinEventTracker.cs
- TypeLibConverter.cs
- UrlPropertyAttribute.cs
- ExceptionUtil.cs
- ZipIOLocalFileHeader.cs
- IPGlobalProperties.cs
- FileLevelControlBuilderAttribute.cs