public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; // Labelled is now the root: Labelled.SetRoot(optimizationInfo); if (Labelled.DefaultBreakStatementBehaviour) { // Set up the information needed by the break statement. ILLabel endOfStatement = generator.CreateLabel(); optimizationInfo.PushBreakOrContinueInfo(labels, endOfStatement, null, true); Labelled.GenerateCode(generator, optimizationInfo); // Revert the information needed by the break statement. generator.DefineLabelPosition(endOfStatement); optimizationInfo.PopBreakOrContinueInfo(); } else { // Loop, For-In, For-Of or Switch only. optimizationInfo.Labels = labels; Labelled.GenerateCode(generator, optimizationInfo); } // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { List <string> labels = optimizationInfo.Labels; optimizationInfo.Labels = null; // We need a label for each case clause and one for the default case. var jumpTargets = new ILLabel[this.CaseClauses.Count]; int defaultIndex = -1; ILLabel endOfSwitch = generator.CreateLabel(); // Generate code for the switch value. var startOfSwitch = generator.CreateLabel(); this.Value.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.Value.GetResultType(optimizationInfo)); // Save the switch value in a variable. var switchValue = generator.CreateTemporaryVariable(typeof(object)); generator.StoreVariable(switchValue); for (int i = 0; i < this.CaseClauses.Count; i++) { var caseClause = this.CaseClauses[i]; // Create a label for each clause. jumpTargets[i] = generator.CreateLabel(); if (caseClause.Value == null) { // This is a default clause. defaultIndex = i; continue; } // TypeComparer.StrictEquals(switchValue, caseValue) generator.LoadVariable(switchValue); caseClause.Value.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, caseClause.Value.GetResultType(optimizationInfo)); generator.Call(ReflectionHelpers.TypeComparer_StrictEquals); // if (TypeComparer.StrictEquals(switchValue, caseValue) == true) // goto case i generator.BranchIfTrue(jumpTargets[i]); } // None of the cases matched, jump to the default clause or the end of the switch. if (defaultIndex >= 0) { generator.Branch(jumpTargets[defaultIndex]); } else { generator.Branch(endOfSwitch); } // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; for (int i = 0; i < this.CaseClauses.Count; i++) { // Define a label at the start of the case clause. generator.DefineLabelPosition(jumpTargets[i]); // Set up the information needed by the break statement. optimizationInfo.PushBreakOrContinueInfo(labels, endOfSwitch, null, false); // Emit the case clause statements. foreach (var statement in this.CaseClauses[i].BodyStatements) { // Mark as root: statement.SetRoot(optimizationInfo); // Emit: statement.GenerateCode(generator, optimizationInfo); } // Revert the information needed by the break statement. optimizationInfo.PopBreakOrContinueInfo(); } // Define a label for the end of the switch statement. generator.DefineLabelPosition(endOfSwitch); // Release the switch value variable for use elsewhere. generator.ReleaseTemporaryVariable(switchValue); // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; List <string> labels = optimizationInfo.Labels; optimizationInfo.Labels = null; // Construct a loop expression. // var enumerator = TypeUtilities.EnumeratePropertyNames(rhs).GetEnumerator(); // while (true) { // continue-target: // if (enumerator.MoveNext() == false) // goto break-target; // lhs = enumerator.Current; // // <body statements> // } // break-target: // Call IEnumerable<string> EnumeratePropertyNames(ScriptEngine engine, object obj) // optimizationInfo.MarkSequencePoint(generator, this.TargetObjectSourceSpan); EmitHelpers.LoadEngine(generator); this.TargetObject.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, this.TargetObject.GetResultType(optimizationInfo)); generator.Call(ReflectionHelpers.TypeUtilities_EnumeratePropertyNames); // Store the enumerator in a temporary variable. var enumerator = generator.CreateTemporaryVariable(typeof(IEnumerator <string>)); generator.StoreVariable(enumerator); var breakTarget = generator.CreateLabel(); var continueTarget = generator.DefineLabelPosition(); // Emit debugging information. // if (optimizationInfo.DebugDocument != null) // generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.VariableSourceSpan); // if (enumerator.MoveNext() == false) // goto break-target; generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_MoveNext); generator.BranchIfFalse(breakTarget); // lhs = enumerator.Current; this.Variable.GenerateSet(generator, optimizationInfo, false, typeof(string), delegate(bool two){ generator.LoadVariable(enumerator); generator.Call(ReflectionHelpers.IEnumerator_Current); if (two) { generator.Duplicate(); } }, false); // Emit the body statement(s). optimizationInfo.PushBreakOrContinueInfo(labels, breakTarget, continueTarget, false); // Mark the body as root: Body.SetRoot(optimizationInfo); Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); generator.Branch(continueTarget); generator.DefineLabelPosition(breakTarget); // Restore root: optimizationInfo.RootExpression = prevRoot; }
/// <summary> /// Generates CIL for the statement. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Get the previous root - we'll be changing it: Expression prevRoot = optimizationInfo.RootExpression; List <string> labels = optimizationInfo.Labels; optimizationInfo.Labels = null; // Emit the initialization statement. if (InitStatement != null) { // Init isn't in use. Mark it as root: InitStatement.SetRoot(optimizationInfo); InitStatement.GenerateCode(generator, optimizationInfo); // Restore root: optimizationInfo.RootExpression = prevRoot; } var startOfLoop = generator.DefineLabelPosition(); var continueTarget = generator.CreateLabel(); var endOfLoop = generator.CreateLabel(); bool conditionAtEnd = CheckConditionAtEnd; // AT END.. // top: // <body statements> // continue: // <increment> // if(condition) // <goto top> // break: // top: // if(!condition) // <goto break> // <body statements> // continue: // <increment> // <goto top> // break: if (!conditionAtEnd) { if (ConditionStatement != null) { Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo)); generator.BranchIfFalse(endOfLoop); } } // Emit the loop body. optimizationInfo.PushBreakOrContinueInfo(labels, endOfLoop, continueTarget, false); // Mark the body as root: Body.SetRoot(optimizationInfo); Body.GenerateCode(generator, optimizationInfo); optimizationInfo.PopBreakOrContinueInfo(); generator.DefineLabelPosition(continueTarget); // Increment the loop variable. if (IncrementStatement != null) { // Increment isn't in use. Mark it as root: IncrementStatement.SetRoot(optimizationInfo); IncrementStatement.GenerateCode(generator, optimizationInfo); } // Restore root: optimizationInfo.RootExpression = prevRoot; if (conditionAtEnd) { if (ConditionStatement != null) { // Emit now: Condition.GenerateCode(generator, optimizationInfo); EmitConversion.ToBool(generator, Condition.GetResultType(optimizationInfo)); generator.BranchIfTrue(startOfLoop); } } else { generator.Branch(startOfLoop); } generator.DefineLabelPosition(endOfLoop); }