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
- ImageListUtils.cs
- TypeExtensionSerializer.cs
- log.cs
- SystemIPAddressInformation.cs
- ListViewContainer.cs
- RequestCachingSection.cs
- ByteStack.cs
- CardSpaceShim.cs
- AttributeInfo.cs
- TemplateBamlTreeBuilder.cs
- BypassElement.cs
- TextBox.cs
- ParameterCollection.cs
- NullableDecimalAverageAggregationOperator.cs
- COM2ColorConverter.cs
- ExpressionDumper.cs
- CustomUserNameSecurityTokenAuthenticator.cs
- ToolStripItemCollection.cs
- _LocalDataStore.cs
- Switch.cs
- LineGeometry.cs
- UrlPath.cs
- XmlAttributeProperties.cs
- WSSecurityOneDotZeroSendSecurityHeader.cs
- DropShadowBitmapEffect.cs
- TypedTableBase.cs
- XmlCharType.cs
- CodeMemberMethod.cs
- TagNameToTypeMapper.cs
- AttachedPropertyBrowsableWhenAttributePresentAttribute.cs
- SkinIDTypeConverter.cs
- LongValidatorAttribute.cs
- XamlTreeBuilderBamlRecordWriter.cs
- WindowInteropHelper.cs
- DLinqAssociationProvider.cs
- ObjectDataSourceView.cs
- MultiBindingExpression.cs
- DbReferenceCollection.cs
- ByteStream.cs
- Calendar.cs
- WindowsGraphics2.cs
- IApplicationTrustManager.cs
- ResourceCategoryAttribute.cs
- WindowsTab.cs
- FlowPanelDesigner.cs
- tibetanshape.cs
- OdbcCommandBuilder.cs
- CookielessData.cs
- EventSinkHelperWriter.cs
- CopyNodeSetAction.cs
- Help.cs
- SourceItem.cs
- SubordinateTransaction.cs
- HtmlMeta.cs
- SecurityPermission.cs
- StrongName.cs
- autovalidator.cs
- ToolStripDropTargetManager.cs
- PostBackTrigger.cs
- KnownTypeAttribute.cs
- XmlValueConverter.cs
- ValidationService.cs
- LookupBindingPropertiesAttribute.cs
- GraphicsContext.cs
- SequentialOutput.cs
- UnlockInstanceAsyncResult.cs
- HttpResponse.cs
- Visual3DCollection.cs
- IApplicationTrustManager.cs
- Journaling.cs
- DBConnection.cs
- QueryOperator.cs
- InheritanceContextHelper.cs
- CodeVariableReferenceExpression.cs
- _SslSessionsCache.cs
- ArgumentException.cs
- UnaryNode.cs
- ScaleTransform.cs
- DbgCompiler.cs
- Thickness.cs
- BinaryFormatter.cs
- SystemWebCachingSectionGroup.cs
- OdbcDataAdapter.cs
- XsdCachingReader.cs
- RouteParameter.cs
- StringArrayConverter.cs
- AutomationIdentifierGuids.cs
- CompressEmulationStream.cs
- RelativeSource.cs
- TextServicesHost.cs
- InvalidDataException.cs
- ListControl.cs
- BinaryOperationBinder.cs
- CriticalHandle.cs
- WebUtil.cs
- DynamicResourceExtension.cs
- Vector3DKeyFrameCollection.cs
- PageAsyncTaskManager.cs
- IRCollection.cs
- While.cs