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) { var restartLabel = new LabelStatementSyntaxNode(); var exitLabel = new LabelStatementSyntaxNode(); if (_e1Stack.Offset > 255 || _loopVar.Offset > 255) { throw new NotImplementedException(); } //Calc expressions. _e1.EmitPrep(writer); _e1.EmitGet(writer, _e1Stack); _e2.EmitPrep(writer); _e2.EmitGet(writer, _e2Stack); _e3.EmitPrep(writer); _e3.EmitGet(writer, _e3Stack); //Init instruction (check type, check exit condition). writer.WriteUSx(_initOp, _e1Stack.Offset, 0); writer.AddLabelFix(exitLabel, InstructionWriter.FixUSxJump); //This is where we restart. writer.MarkLabel(restartLabel); //Start of the actual block (creates upvals). _forBlock.EmitUpvalLists(writer); //Copy hidden control variable to the visible loop var. writer.WriteUUU(Opcodes.MOV, _loopVar.Offset, _e1Stack.Offset, 0); //Emit inner aux block. _forBlock.EmitStatements(writer); //Loop instruction. writer.WriteUSx(_loopOp, _e1Stack.Offset, 0); writer.AddLabelFix(restartLabel, InstructionWriter.FixUSxJump); writer.MarkLabel(exitLabel); }
public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { //The two special cases. if (_mode == CalcMode.LeftToDest) { if (_right.TryGetFromStack(out var rightStack) && rightStack.Offset == dest.Offset) { _left.EmitPrep(writer); _left.EmitGet(writer, _rightTemp.Value); EmitInstruction(writer, dest, _rightTemp.Value, rightStack); return; } } else if (_mode == CalcMode.RightToDest) { if (_left.TryGetFromStack(out var leftStack) && leftStack.Offset == dest.Offset) { _right.EmitPrep(writer); _right.EmitGet(writer, _leftTemp.Value); EmitInstruction(writer, dest, leftStack, _leftTemp.Value); return; } } switch (_mode) { case CalcMode.LeftToDest: { _left.EmitPrep(writer); _left.EmitGet(writer, dest); if (!_right.TryGetFromStack(out var rightStack)) { rightStack = _rightTemp.Value; _right.EmitPrep(writer); _right.EmitGet(writer, rightStack); } EmitInstruction(writer, dest, dest, rightStack); break; } case CalcMode.RightToDest: { if (!_left.TryGetFromStack(out var leftStack)) { leftStack = _leftTemp.Value; _left.EmitPrep(writer); _left.EmitGet(writer, leftStack); } _right.EmitPrep(writer); _right.EmitGet(writer, dest); EmitInstruction(writer, dest, leftStack, dest); break; } case CalcMode.Normal: { if (!_left.TryGetFromStack(out var leftStack)) { leftStack = _leftTemp.Value; _left.EmitPrep(writer); _left.EmitGet(writer, leftStack); } if (!_right.TryGetFromStack(out var rightStack)) { rightStack = _rightTemp.Value; _right.EmitPrep(writer); _right.EmitGet(writer, rightStack); } EmitInstruction(writer, dest, leftStack, rightStack); break; } } }
public override void Emit(InstructionWriter writer) { _expr.EmitPrep(writer); _expr.EmitDiscard(writer); }