public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { var leftStack = _leftStack ?? dest; var rightStack = _rightStack ?? dest; if (_left.GetSingleType() != _type || _right.GetSingleType() != _type) { //Needs conversion in MOV and ISTC. throw new NotImplementedException(); } if (leftStack.Offset > 255 || rightStack.Offset > 255 || dest.Offset > 255) { throw new NotImplementedException(); } // emit leftStack = _left // ISFC/ISTC dest, leftStack, exitLabel // emit rightStack = _right // MOV dest, rightStack //exitLabel: var exitLabel = new LabelStatementSyntaxNode(); _left.EmitPrep(writer); _left.EmitGet(writer, leftStack); writer.WriteUUS(_opcode, dest.Offset, leftStack.Offset, 0); writer.AddLabelFix(exitLabel, InstructionWriter.FixUUSJump); _right.EmitPrep(writer); _right.EmitGet(writer, rightStack); //We already wrote to dest. No need to MOV. Debug.Assert(rightStack.Offset == dest.Offset); writer.MarkLabel(exitLabel); }
public override void Emit(InstructionWriter writer) { Debug.Assert(_firstLoopVarStack.Offset == _hiddenVariableStack.Offset + 3); _forBlock.EmitUpvalLists(writer); var exitLabel = new LabelStatementSyntaxNode(); var loopLabel = new LabelStatementSyntaxNode(); //Insert assignment and FORG instruction (call iterator function and check for exit condition). _assignment.Emit(writer); writer.MarkLabel(loopLabel); if (_hiddenVariableStack.Offset > 255 || _loopVarSig > 255) { throw new NotImplementedException(); } writer.WriteUUS(Opcodes.FORG, _hiddenVariableStack.Offset, _loopVarSig, 0); writer.AddLabelFix(exitLabel, InstructionWriter.FixUUSJump); //Emit inner block. _forBlock.EmitStatements(writer); //Jump back. writer.WriteUSx(Opcodes.JMP, 0, 0); writer.AddLabelFix(loopLabel, InstructionWriter.FixUSxJump); writer.MarkLabel(exitLabel); }
public override void EmitGet(InstructionWriter writer, IStackFragment sigBlock, StackSignature sigType, int sigIndex, bool keepSig) { Debug.Assert(_isVararg); if (sigIndex > 255 || sigBlock.Offset > 255 | sigType.FixedSize > 127) { throw new NotImplementedException(); } //Note that for VARG/VARGC, we are using a different version of R1-R3. See OpCodes doc for details. Debug.Assert(_funcVarargSig.FixedSize == 0); if (_funcVarargSig.IsCompatibleWith(sigType)) { writer.WriteUUS(keepSig ? OpCodes.VARG : OpCodes.VARGC, sigBlock.Offset, sigIndex, sigType.FixedSize); } else { writer.WriteUUS(keepSig ? OpCodes.VARG : OpCodes.VARGC, sigBlock.Offset, sigIndex, -1); } }
public override void Emit(InstructionWriter writer) { Debug.Assert(_firstLoopVarStack.Offset == _hiddenVariableStack.Offset + 3); _forBlock.EmitUpvalLists(writer); var exitLabel = new LabelStatementSyntaxNode(); var loopLabel = new LabelStatementSyntaxNode(); //Insert assignment and FORG instruction (call iterator function and check for exit condition). _assignment.Emit(writer); writer.MarkLabel(loopLabel); if (_hiddenVariableStack.Offset > 255 || _loopVarSig > 255 || _loopVarSigType.FixedSize > 127) { throw new NotImplementedException(); } writer.WriteUSx(OpCodes.FORG, _hiddenVariableStack.Offset, 0); writer.AddLabelFix(exitLabel, InstructionWriter.FixUSxJump); //Adjust right parameter: assume EmptyV. if (_loopVarSigType.IsCompatibleWith(StackSignature.EmptyV)) { writer.WriteUUS(OpCodes.FORG_CTN, _loopVarSig, (int)WellKnownStackSignature.EmptyV, _loopVarSigType.FixedSize); } else { writer.WriteUUS(OpCodes.FORG_CTN, _loopVarSig, 0, 0); } //Emit inner block. _forBlock.EmitStatements(writer); //Jump back. writer.WriteUSx(OpCodes.JMP, 0, 0); writer.AddLabelFix(loopLabel, InstructionWriter.FixUSxJump); writer.MarkLabel(exitLabel); }