private void EmitSwitchExpression(Expression expr) { SwitchExpression node = (SwitchExpression)expr; LabelInfo breakTarget = DefineLabel(node.BreakLabel); Label defaultTarget = breakTarget.Label; Label[] labels = new Label[node.SwitchCases.Count]; // Create all labels for (int i = 0; i < node.SwitchCases.Count; i++) { labels[i] = _ilg.DefineLabel(); // Default case. if (node.SwitchCases[i].IsDefault) { // Set the default target defaultTarget = labels[i]; } } // Emit the test value EmitExpression(node.Test); // Check if jmp table can be emitted if (!TryEmitJumpTable(node, labels, defaultTarget)) { // There might be scenario(s) where the jmp table is not emitted // Emit the switch as conditional branches then EmitConditionalBranches(node, labels); } // If "default" present, execute default code, else exit the switch _ilg.Emit(OpCodes.Br, defaultTarget); // Emit the bodies for (int i = 0; i < node.SwitchCases.Count; i++) { // First put the corresponding labels _ilg.MarkLabel(labels[i]); // And then emit the Body!! EmitExpressionAsVoid(node.SwitchCases[i].Body); } breakTarget.Mark(); }
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 EmitLoopExpression(Expression expr) { LoopExpression node = (LoopExpression)expr; PushLabelBlock(LabelBlockKind.Block); LabelInfo breakTarget = DefineLabel(node.BreakLabel); LabelInfo continueTarget = DefineLabel(node.ContinueLabel); continueTarget.Mark(); EmitExpressionAsVoid(node.Body); _ilg.Emit(OpCodes.Br, continueTarget.Label); PopLabelBlock(LabelBlockKind.Block); breakTarget.Mark(); }