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
- SafeEventLogWriteHandle.cs
- DataKeyArray.cs
- TreeNodeMouseHoverEvent.cs
- TextEditorTyping.cs
- XmlAttributeHolder.cs
- TdsParameterSetter.cs
- XD.cs
- altserialization.cs
- TargetException.cs
- PtsHelper.cs
- HttpHandlerActionCollection.cs
- ActivitySurrogate.cs
- ComponentGuaranteesAttribute.cs
- XmlAttributes.cs
- srgsitem.cs
- EnumDataContract.cs
- MenuItem.cs
- LinqDataSourceDeleteEventArgs.cs
- IgnoreSectionHandler.cs
- BaseHashHelper.cs
- PropertyPathConverter.cs
- InstanceCollisionException.cs
- InstancePersistenceContext.cs
- _NegotiateClient.cs
- EditorPartDesigner.cs
- StylusShape.cs
- WindowAutomationPeer.cs
- MultiPartWriter.cs
- DeviceSpecificChoiceCollection.cs
- CTreeGenerator.cs
- RulePatternOps.cs
- SecurityKeyType.cs
- ResXBuildProvider.cs
- StringInfo.cs
- ConstraintManager.cs
- ModulesEntry.cs
- RestHandlerFactory.cs
- ItemCheckedEvent.cs
- ObjectQuery.cs
- EnvelopedPkcs7.cs
- InvalidFilterCriteriaException.cs
- TypefaceCollection.cs
- EndpointFilterProvider.cs
- WebControlAdapter.cs
- DataRelationPropertyDescriptor.cs
- ImageAutomationPeer.cs
- JournalEntryListConverter.cs
- ComponentChangingEvent.cs
- ValidationVisibilityAttribute.cs
- DataGrid.cs
- WorkflowRuntimeSection.cs
- PaginationProgressEventArgs.cs
- ExternalFile.cs
- UniqueSet.cs
- BitmapMetadataEnumerator.cs
- CroppedBitmap.cs
- ToolBarButtonClickEvent.cs
- StreamUpgradeBindingElement.cs
- AlternateView.cs
- Pkcs7Recipient.cs
- EditableRegion.cs
- GregorianCalendarHelper.cs
- OdbcParameter.cs
- ImagingCache.cs
- WebPartManagerInternals.cs
- ReflectTypeDescriptionProvider.cs
- MemberInfoSerializationHolder.cs
- DataRow.cs
- ObjectResult.cs
- Win32KeyboardDevice.cs
- SectionUpdates.cs
- DataContractSerializerOperationBehavior.cs
- ChoiceConverter.cs
- FontStyleConverter.cs
- SmiEventSink_Default.cs
- WorkflowInstanceExtensionCollection.cs
- SslStreamSecurityUpgradeProvider.cs
- OptionUsage.cs
- PrePrepareMethodAttribute.cs
- AutoSizeToolBoxItem.cs
- ColumnMap.cs
- Suspend.cs
- Nullable.cs
- CapabilitiesState.cs
- StaticFileHandler.cs
- XmlSignatureProperties.cs
- CssTextWriter.cs
- Component.cs
- StreamWithDictionary.cs
- TabControlEvent.cs
- AdornerDecorator.cs
- PeoplePickerWrapper.cs
- ReceiveMessageRecord.cs
- DbConnectionOptions.cs
- Serializer.cs
- Claim.cs
- GACIdentityPermission.cs
- Vector3DCollection.cs
- Page.cs
- TrustSection.cs