public override Value EmitValue(EmitContext context) { var assignmentInterrupt = context.InterruptAssignmentScope(); Value conditionValue = context.EmitValue(ConditionExpression); assignmentInterrupt.Dispose(); JumpLabel conditionJump = context.Module.CreateLabel(); JumpLabel exitTrueJump = context.Module.CreateLabel(); Value returnValue = context.GetReturnValue(ValueType); // We don't want any references outside the flow control to be dirtied conditionally context.TopTable.DirtyAllValues(); context.Module.AddJumpIfFalse(conditionJump, conditionValue); context.EmitValueAssignment(returnValue, TrueExpression); context.Module.AddJump(exitTrueJump); context.Module.LabelJump(conditionJump); context.EmitValueAssignment(returnValue, FalseExpression); context.Module.LabelJump(exitTrueJump); return(returnValue); }
public JumpLabel PushContinueLabel() { JumpLabel continueLabel = Module.CreateLabel(); _continueLabelStack.Push(continueLabel); return(continueLabel); }
public override Value EmitValue(EmitContext context) { // We don't want any references outside the flow control to be dirtied conditionally context.TopTable.DirtyAllValues(); Value returnValue = context.GetReturnValue(ValueType); context.EmitValueAssignment(returnValue, Lhs); TypeSymbol systemObjectType = context.GetTypeSymbol(SpecialType.System_Object); MethodSymbol objectEquality = new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.Equality, systemObjectType, context); Value conditionCheck = context.EmitValue(BoundInvocationExpression.CreateBoundInvocation(context, null, objectEquality, null, new BoundExpression[] { BoundAccessExpression.BindAccess(returnValue), BoundAccessExpression.BindAccess(context.GetConstantValue(systemObjectType, null)) })); JumpLabel notNullLabel = context.Module.CreateLabel(); context.Module.AddJumpIfFalse(notNullLabel, conditionCheck); context.EmitValueAssignment(returnValue, Rhs); context.Module.LabelJump(notNullLabel); return(returnValue); }
public JumpLabel PushBreakLabel() { JumpLabel breakLabel = Module.CreateLabel(); _breakLabelStack.Push(breakLabel); return(breakLabel); }
public override void Emit(EmitContext context) { Value conditionValue = context.EmitValue(ConditionExpression); JumpLabel exitLabel = context.Module.CreateLabel(); JumpLabel failLabel = context.Module.CreateLabel(); context.Module.AddJumpIfFalse(failLabel, conditionValue); if (BodyStatement != null) { context.Emit(BodyStatement); } if (ElseStatement != null) { context.Module.AddJump(exitLabel); } context.Module.LabelJump(failLabel); if (ElseStatement != null) { context.Emit(ElseStatement); } context.Module.LabelJump(exitLabel); }
/// <summary> /// Hole die relative Sprungadresse des Rückwärtsprungs. /// </summary> /// <returns>Relative Sprungadresse</returns> public int GetJumpBackwardAddress() { // Label holen. JumpLabel jumpLabel = jumpLabelStack.Pop(); // Relative Sprungadresse berechnen (Ziel - Start ... ergibt negative Zahl bspw. 21 - 42 = -21 = 0xFF FF FF EB) // Bei der Startadresse muss noch die Länge des Sprungbefehls (3) aufgerechnet werden. // Berechnete Adresse zurück geben. return(jumpLabel.jumpTo - (currentCodePosition + 3)); }
/// <summary> /// Aktualisiere relative Sprungadresse im Bytecode. /// </summary> /// <param name="commandSize">Bytes die auf relative Sprungadresse addiert werden müssen</param> public void UpdateJumpFoward(int commandSize = 0) { // Label holen. JumpLabel jumpLabel = jumpLabelStack.Pop(); // Relative Sprungadresse berechnen (Ziel - Start). Wobei das Ziel die nächste Adresse ist (diese ist abhängig von der Größe des Befehls). int targetAddress = (currentCodePosition + commandSize) - jumpLabel.jumpFrom; // Sprungadresse an entsprechende Stelle nachtragen. byte[] byteArray = BitConverter.GetBytes(targetAddress); codeBuffer[jumpLabel.jumpLabelPosition] = byteArray[0]; codeBuffer[jumpLabel.jumpLabelPosition + 1] = byteArray[1]; }
/// <summary> /// Generates the code for a JumpLabel node. /// </summary> /// <param name="jl">The JumpLabel node.</param> /// <returns>String containing C# code for JumpLabel jl.</returns> private void GenerateJumpLabel(JumpLabel jl, StringBuilder sb) { string labelStatement; if (m_insertCoopTerminationChecks) { labelStatement = m_coopTerminationCheck; } else { labelStatement = "NoOp();"; } GenerateLine(String.Format("{0}: {1}", CheckName(jl.LabelName), labelStatement), jl, sb); }
public void AddJumpLabel(JumpLabel jumpLabel, string comment = "") { if (jumpLabel.IsResolved) { throw new System.Exception($"Target jump label {jumpLabel.uniqueName} has already been used!"); } jumpLabel.resolvedAddress = (uint)programCounter; #if USE_UDON_LABELS AppendCommentedLine($"{jumpLabel.uniqueName}:", comment); #endif //AppendCommentedLine("NOP", comment); //programCounter += UdonSharpUtils.GetUdonInstructionSize("NOP"); }
public void AddJumpIfFalse(JumpLabel jumpTarget, string comment = "") { #if USE_UDON_LABELS AppendCommentedLine($"JUMP_IF_FALSE, {jumpTarget.uniqueName}", comment); #else if (jumpTarget.IsResolved) { AppendCommentedLine($"JUMP_IF_FALSE, {jumpTarget.AddresStr()}", comment); } else { AppendCommentedLine($"JUMP_IF_FALSE_LABEL, [{jumpTarget.uniqueName}]", comment); } #endif programCounter += UdonSharpUtils.GetUdonInstructionSize("JUMP_IF_FALSE"); }
public override void Emit(EmitContext context) { JumpLabel continueLabel = context.PushContinueLabel(); JumpLabel breakLabel = context.PushBreakLabel(); context.Module.LabelJump(continueLabel); context.Emit(Body); context.Module.AddJumpIfFalse(breakLabel, context.EmitValue(Condition)); context.Module.AddJump(continueLabel); context.Module.LabelJump(breakLabel); context.PopBreakLabel(); context.PopContinueLabel(); }
JumpLabel GetLabel(string labelName, int fileCount) { if (!_kuexok.ContainsKey(labelName)) { labelName = $"{labelName}@{fileCount}"; } if (_labels.ContainsKey(labelName)) { return(_labels[labelName]); } else { var jumpLabel = new JumpLabel(); _labels.Add(labelName, jumpLabel); return(jumpLabel); } }
public override void Emit(EmitContext context) { using (context.OpenBlockScope()) { if (Declaration != null) { context.Emit(Declaration); } foreach (var initializer in Initializers) { context.Emit(initializer); } JumpLabel continueLabel = context.PushContinueLabel(); JumpLabel breakLabel = context.PushBreakLabel(); JumpLabel loopLabel = context.Module.CreateLabel(); context.Module.LabelJump(loopLabel); if (Condition != null) { context.Module.AddJumpIfFalse(breakLabel, context.EmitValue(Condition)); } context.Emit(Body); context.Module.LabelJump(continueLabel); foreach (var incrementor in Incrementors) { context.Emit(incrementor); } context.Module.AddJump(loopLabel); context.Module.LabelJump(breakLabel); context.PopBreakLabel(); context.PopContinueLabel(); } }
public override Value EmitValue(EmitContext context) { // We don't want any references outside the flow control to be dirtied conditionally context.TopTable.DirtyAllValues(); Value resultValue = context.CreateInternalValue(ValueType); if (OperatorType == BuiltinOperatorType.LogicalAnd) { JumpLabel failLabel = context.Module.CreateLabel(); context.EmitValueAssignment(resultValue, Lhs); context.Module.AddJumpIfFalse(failLabel, resultValue); context.EmitValueAssignment(resultValue, Rhs); context.Module.LabelJump(failLabel); } else if (OperatorType == BuiltinOperatorType.LogicalOr) { JumpLabel failLabel = context.Module.CreateLabel(); JumpLabel exitLabel = context.Module.CreateLabel(); context.EmitValueAssignment(resultValue, Lhs); context.Module.AddJumpIfFalse(failLabel, resultValue); context.Module.AddJump(exitLabel); context.Module.LabelJump(failLabel); context.EmitValueAssignment(resultValue, Rhs); context.Module.LabelJump(exitLabel); } else { throw new InvalidOperationException("Invalid operator type"); } return(resultValue); }
private string ReplaceLabels(string assemblyString, LabelTable labelTable) { StringBuilder newAssemblyBuilder = new StringBuilder(); using (StringReader reader = new StringReader(assemblyString)) { string currentLine = reader.ReadLine(); while (currentLine != null) { string line = currentLine.TrimStart(_trimChars); if (line.StartsWith("JUMP_LABEL,", StringComparison.Ordinal)) { int startIdx = line.IndexOf('[') + 1; int endIdx = line.IndexOf(']'); string labelName = line.Substring(startIdx, endIdx - startIdx); JumpLabel label = labelTable.GetLabel(labelName); newAssemblyBuilder.AppendFormat(" JUMP, {0}\n", label.AddresStr()); } else if (line.StartsWith("JUMP_IF_FALSE_LABEL,", StringComparison.Ordinal)) { int startIdx = line.IndexOf('[') + 1; int endIdx = line.IndexOf(']'); string labelName = line.Substring(startIdx, endIdx - startIdx); JumpLabel label = labelTable.GetLabel(labelName); newAssemblyBuilder.AppendFormat(" JUMP_IF_FALSE, {0}\n", label.AddresStr()); } else { newAssemblyBuilder.Append(currentLine); newAssemblyBuilder.Append("\n"); } currentLine = reader.ReadLine(); } } return(newAssemblyBuilder.ToString()); }
public void AddJumpIfFalse(JumpLabel jumpTarget, SymbolDefinition conditionSymbol, string comment = "") { AddPush(conditionSymbol); AddJumpIfFalse(jumpTarget, comment); }
public JumpInstruction(JumpLabel jumpTarget) { JumpTarget = jumpTarget; }
public JumpIfFalseInstruction(JumpLabel jumpTarget, Value conditionValue) { JumpTarget = jumpTarget; ConditionValue = conditionValue; }
protected void CheckStackSize(Value valueCount, EmitContext context) { using (context.InterruptAssignmentScope()) { Value stack = context.RecursiveStackValue; BoundAccessExpression stackAccess = BoundAccessExpression.BindAccess(stack); Value stackAddr = context.RecursiveStackAddressValue; BoundAccessExpression stackAddrAccess = BoundAccessExpression.BindAccess(stackAddr); TypeSymbol arrayType = context.GetTypeSymbol(SpecialType.System_Array); context.Module.AddCommentTag("Stack size check"); // Check stack size and double it if it's not enough // We know that doubling once will always be enough since the default size of the stack is the max number of stack values pushed in any method PropertySymbol arraySizeProperty = arrayType.GetMember <PropertySymbol>("Length", context); TypeSymbol intType = context.GetTypeSymbol(SpecialType.System_Int32); Value arraySize = context.EmitValue(BoundAccessExpression.BindAccess(context, SyntaxNode, arraySizeProperty, stackAccess)); BoundAccessExpression arraySizeAccess = BoundAccessExpression.BindAccess(arraySize); Value targetSize = context.EmitValue(CreateBoundInvocation(context, SyntaxNode, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.Addition, intType, context), null, new BoundExpression[] { stackAddrAccess, BoundAccessExpression.BindAccess(valueCount) })); Value isSizeGreaterThan = context.EmitValue(CreateBoundInvocation(context, SyntaxNode, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.GreaterThanOrEqual, intType, context), null, new BoundExpression[] { BoundAccessExpression.BindAccess(targetSize), arraySizeAccess, })); JumpLabel skipResizeLabel = context.Module.CreateLabel(); context.Module.AddJumpIfFalse(skipResizeLabel, isSizeGreaterThan); // Resize logic Value constantTwo = context.GetConstantValue(intType, 2); Value newSize = context.EmitValue(CreateBoundInvocation(context, SyntaxNode, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.Multiplication, intType, context), null, new BoundExpression[] { arraySizeAccess, BoundAccessExpression.BindAccess(constantTwo), })); Value newArray = context.EmitValue(new BoundArrayCreationExpression(SyntaxNode, context, context.GetTypeSymbol(SpecialType.System_Object).MakeArrayType(context), new BoundExpression[] { BoundAccessExpression.BindAccess(newSize) }, null)); MethodSymbol arrayCopyMethod = arrayType.GetMembers <MethodSymbol>("Copy", context) .First(e => e.Parameters.Length == 3 && e.Parameters[2].Type == intType); context.Emit(CreateBoundInvocation(context, null, arrayCopyMethod, null, new BoundExpression[] { stackAccess, BoundAccessExpression.BindAccess(newArray), BoundAccessExpression.BindAccess(arraySize) })); context.Module.AddCopy(newArray, stack); context.Module.LabelJump(skipResizeLabel); context.Module.AddCommentTag("Stack size check end"); } }
public override Value EmitValue(EmitContext context) { JumpLabel returnPoint = context.Module.CreateLabel(); Value returnPointVal = context.CreateGlobalInternalValue(context.GetTypeSymbol(SpecialType.System_UInt32)); context.Module.AddPush(returnPointVal); var linkage = context.GetMethodLinkage(Method, !IsBaseCall); Value[] parameterValues = GetParameterValues(context); Value[] recursiveValues = null; bool isRecursiveCall = context.IsRecursiveMethodEmit; Value stackSizeCheckVal = null; if (isRecursiveCall) { EmitContext.MethodLinkage selfLinkage = context.GetMethodLinkage(context.CurrentEmitMethod, false); recursiveValues = selfLinkage.ParameterValues; stackSizeCheckVal = context.CreateGlobalInternalValue(context.GetTypeSymbol(SpecialType.System_Int32)); CheckStackSize(stackSizeCheckVal, context); PushRecursiveValues(selfLinkage.ParameterValues, context); } ReleaseCowReferences(context); if (isRecursiveCall) { Value.CowValue[] paramCows = parameterValues.Select(e => e.GetCowValue(context)).ToArray(); for (int i = 0; i < linkage.ParameterValues.Length; ++i) { context.EmitValueAssignment(linkage.ParameterValues[i], BoundAccessExpression.BindAccess(paramCows[i])); } foreach (var paramCow in paramCows) { paramCow.Dispose(); } } else { for (int i = 0; i < linkage.ParameterValues.Length; ++i) { context.Module.AddCopy(parameterValues[i], linkage.ParameterValues[i]); } } context.TopTable.DirtyAllValues(); if (isRecursiveCall) { Value[] collectedValues = context.CollectRecursiveValues().Where(e => !recursiveValues.Contains(e)).ToArray(); PushRecursiveValues(collectedValues, context); recursiveValues = recursiveValues.Concat(collectedValues).ToArray(); stackSizeCheckVal.DefaultValue = recursiveValues.Length; context.UpdateRecursiveStackMaxSize(recursiveValues.Length); } context.Module.AddCommentTag($"Calling {Method}"); context.Module.AddJump(linkage.MethodLabel); context.Module.LabelJump(returnPoint); returnPointVal.DefaultValue = returnPoint.Address; Value recursiveRet = null; if (isRecursiveCall) { if (linkage.ReturnValue != null) { recursiveRet = context.CreateInternalValue(linkage.ReturnValue.UserType); context.Module.AddCopy(linkage.ReturnValue, recursiveRet); } PopRecursiveValues(recursiveValues, context); } // Handle out/ref parameters for (int i = 0; i < Method.Parameters.Length; ++i) { if (!Method.Parameters[i].IsOut) { continue; } if (isRecursiveCall) { throw new CompilerException("U# does not yet support calling user methods with ref/out parameters from methods marked with RecursiveMethod"); } BoundAccessExpression paramAccess = (BoundAccessExpression)ParameterExpressions[i]; paramAccess.EmitSet(context, BoundAccessExpression.BindAccess(linkage.ParameterValues[i])); } // Properties need to return the value that they are set to for assignment expressions if (IsPropertySetter) { return(parameterValues.Last()); } if (Method.ReturnType != null) { if (isRecursiveCall) { return(recursiveRet); } return(linkage.ReturnValue); } return(null); }
public LoopData(JumpLabel continueLabel, JumpLabel breakLabel) { ContinueLabel = continueLabel; BreakLabel = breakLabel; }
static LkAssembler() { FASAL_LABEL = new JumpLabel(); }
/// <summary> /// Generates the code for a JumpLabel node. /// </summary> /// <param name="jl">The JumpLabel node.</param> /// <returns>String containing C# code for JumpLabel jl.</returns> private string GenerateJumpLabel(JumpLabel jl) { return GenerateLine(Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();"); }
public SymbolDefinition Invoke(SymbolDefinition[] invokeParams) { SymbolDefinition methodResult = null; System.Type resultSymbolType = null; string lookupSymbolName = null; switch (captureFunc) { case InternalFunc.TypeIDInstance: case InternalFunc.TypeIDGeneric: resultSymbolType = typeof(long); lookupSymbolName = "udonTypeID"; break; case InternalFunc.TypeNameInstance: case InternalFunc.TypeNameGeneric: resultSymbolType = typeof(string); lookupSymbolName = "udonTypeName"; break; default: throw new System.ArgumentException("Invalid internal method invocation"); } methodResult = visitorContext.topTable.CreateUnnamedSymbol(resultSymbolType, SymbolDeclTypeFlags.Internal); if (captureFunc == InternalFunc.TypeIDInstance || captureFunc == InternalFunc.TypeNameInstance) { SymbolDefinition invokeSymbol = captureScope.accessSymbol; using (ExpressionCaptureScope resultSetterScope = new ExpressionCaptureScope(visitorContext, null)) { resultSetterScope.SetToLocalSymbol(methodResult); using (ExpressionCaptureScope getInvokeScope = new ExpressionCaptureScope(visitorContext, null)) { getInvokeScope.SetToLocalSymbol(invokeSymbol); getInvokeScope.ResolveAccessToken(nameof(VRC.Udon.UdonBehaviour.GetProgramVariable)); string symbolName = visitorContext.topTable.GetReflectionSymbol(lookupSymbolName, resultSymbolType).symbolUniqueName; SymbolDefinition invokeResult = getInvokeScope.Invoke(new SymbolDefinition[] { visitorContext.topTable.CreateConstSymbol(typeof(string), symbolName) }); JumpLabel exitBranchJump = visitorContext.labelTable.GetNewJumpLabel("exitUdonTypeIdLoc"); JumpLabel falseBranchLoc = visitorContext.labelTable.GetNewJumpLabel("falseUdonTypeIdLoc"); SymbolDefinition nullCheckSymbol = null; using (ExpressionCaptureScope nullCheckCondition = new ExpressionCaptureScope(visitorContext, null)) { nullCheckCondition.SetToMethods(UdonSharpUtils.GetOperators(typeof(object), BuiltinOperatorType.Inequality)); nullCheckSymbol = nullCheckCondition.Invoke(new SymbolDefinition[] { invokeResult, visitorContext.topTable.CreateConstSymbol(typeof(object), null) }); } visitorContext.uasmBuilder.AddJumpIfFalse(falseBranchLoc, nullCheckSymbol); resultSetterScope.ExecuteSet(captureScope.CastSymbolToType(invokeResult, resultSymbolType, true)); visitorContext.uasmBuilder.AddJump(exitBranchJump); // If the value is null visitorContext.uasmBuilder.AddJumpLabel(falseBranchLoc); if (captureFunc == InternalFunc.TypeIDInstance) { resultSetterScope.ExecuteSet(visitorContext.topTable.CreateConstSymbol(typeof(long), 0L)); } else { resultSetterScope.ExecuteSet(visitorContext.topTable.CreateConstSymbol(typeof(string), "UnknownType")); } visitorContext.uasmBuilder.AddJumpLabel(exitBranchJump); } } } else { object resultSymbolValue = null; if (captureFunc == InternalFunc.TypeIDGeneric) { resultSymbolValue = Internal.UdonSharpInternalUtility.GetTypeID(genericType); } else if (captureFunc == InternalFunc.TypeNameGeneric) { resultSymbolValue = Internal.UdonSharpInternalUtility.GetTypeName(genericType); } methodResult = visitorContext.topTable.CreateConstSymbol(resultSymbolType, resultSymbolValue); } using (ExpressionCaptureScope propagateScope = new ExpressionCaptureScope(visitorContext, visitorContext.topCaptureScope)) { propagateScope.SetToLocalSymbol(methodResult); } return(methodResult); }
private IList <LkCode> Analyze(IList <string> wordList, int fileCount, out bool isMain) { List <LkCode> codeList = new List <LkCode>(); bool isCI = false; isMain = true; for (int i = 0; i < wordList.Count; i++) { var str = wordList[i]; if (str == "'c'i") { isCI = true; } else if (str == "'i'c") { isCI = false; } else { string label; string head, middle, tail; switch (str) { case "nll": label = wordList[++i]; codeList.Add(new LkCode { Mnemonic = LkMnemonic.NLL, Head = GetLabel(label, fileCount), Tail = ZERO, }); if (wordList[i + 1] == "l'") { throw new ApplicationException($"Wrong label nll {wordList[i]} l'"); } break; case "l'": if (i == 0) { throw new ApplicationException($"Wrong label l'"); } label = wordList[++i]; codeList.Insert(codeList.Count - 1, new LkCode { Mnemonic = LkMnemonic.NLL, Head = GetLabel(label, fileCount), Tail = ZERO, }); break; case "kue": ++i; isMain = false; break; case "xok": ++i; break; case "lifem": case "lifem8": case "lifem16": Operand opd = Convert(wordList[++i], fileCount); if (opd is JumpLabel jumpLabel) { var lifemValueLabel = new JumpLabel(); codeList.Add(new LkCode { Mnemonic = LkMnemonic.NLL, Head = lifemValueLabel, Tail = ZERO, }); codeList.Add(new LkCode { Mnemonic = Enum.Parse <LkMnemonic>(str, true), Head = ZERO, Tail = ZERO, }); _labelLifemList.Add(new LkCode { Mnemonic = str switch { "lifem8" => LkMnemonic.KRZ8C, "lifem16" => LkMnemonic.KRZ16C, _ => LkMnemonic.KRZ, }, Head = jumpLabel, Tail = Seti(lifemValueLabel), });
/// <summary> /// Generates the code for a JumpLabel node. /// </summary> /// <param name="jl">The JumpLabel node.</param> /// <returns>String containing C# code for JumpLabel jl.</returns> private string GenerateJumpLabel(JumpLabel jl) { return(Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();\n"); }
public override void Emit(EmitContext context) { var blockScope = context.OpenBlockScope(); TypeSymbol intType = context.GetTypeSymbol(SpecialType.System_Int32); MethodSymbol toCharArrayMethod = context.GetTypeSymbol(SpecialType.System_String).GetMembers <MethodSymbol>("ToCharArray", context).First(e => e.Parameters.Length == 0); PropertySymbol lengthProperty = context.GetTypeSymbol(SpecialType.System_Array).GetMember <PropertySymbol>("Length", context); Value iteratorValue = context.EmitValue(BoundInvocationExpression.CreateBoundInvocation(context, SyntaxNode, toCharArrayMethod, IteratorSource, new BoundExpression[] {})); iteratorValue.MarkUsedRecursively(); var iteratorAccess = BoundAccessExpression.BindAccess(iteratorValue); Value arraySize = context.CreateInternalValue(intType); arraySize.MarkUsedRecursively(); BoundAccessExpression getLength = BoundAccessExpression.BindAccess(context, SyntaxNode, lengthProperty, iteratorAccess); context.EmitValueAssignment(arraySize, getLength); // Declare and reset incrementor value Value incrementorValue = context.CreateInternalValue(intType); incrementorValue.MarkUsedRecursively(); context.EmitValueAssignment(incrementorValue, BoundAccessExpression.BindAccess(context.GetConstantValue(intType, 0))); JumpLabel loopLabel = context.Module.CreateLabel(); context.Module.LabelJump(loopLabel); var incrementorAccess = BoundAccessExpression.BindAccess(incrementorValue); BoundExpression increment = new BoundInvocationExpression.BoundPrefixOperatorExpression(context, SyntaxNode, incrementorAccess, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.Addition, intType, context)); var lengthCheck = BoundInvocationExpression.CreateBoundInvocation(context, SyntaxNode, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.LessThan, intType, context), null, new BoundExpression[] { incrementorAccess, BoundAccessExpression.BindAccess(arraySize) }); JumpLabel exitLoopLabel = context.PushBreakLabel(); JumpLabel continueLabel = context.PushContinueLabel(); Value lengthCheckResult = context.EmitValue(lengthCheck); context.Module.AddJumpIfFalse(exitLoopLabel, lengthCheckResult); context.EmitValueAssignment(context.GetUserValue(ValueSymbol), BoundAccessExpression.BindElementAccess(context, SyntaxNode, iteratorAccess, new BoundExpression[] { incrementorAccess })); context.Emit(BodyStatement); context.Module.LabelJump(continueLabel); context.Emit(increment); context.Module.AddJump(loopLabel); context.Module.LabelJump(exitLoopLabel); context.PopBreakLabel(); context.PopContinueLabel(); blockScope.Dispose(); }