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, AllocatedLocal dest) { if (dest.Offset > 255 || _constIndex > 255) { throw new NotImplementedException(); } writer.WriteUUU(OpCodes.K, dest.Offset, _constIndex, 0); }
public override void EmitGet(InstructionWriter writer, IStackFragment sigBlock, int sigIndex, bool keepSig) { Debug.Assert(_isVararg); if (sigIndex > 255 || sigBlock.Offset > 255) { throw new NotImplementedException(); } writer.WriteUUU(keepSig ? Opcodes.VARG : Opcodes.VARGC, sigIndex, sigBlock.Offset, 0); }
protected virtual void EmitInstruction(InstructionWriter writer, AllocatedLocal dest, AllocatedLocal leftStack, AllocatedLocal rightStack) { if (dest.Offset > 255 || leftStack.Offset > 255 || rightStack.Offset > 255) { throw new NotImplementedException(); } writer.WriteUUU(_opcode, dest.Offset, leftStack.Offset, rightStack.Offset); }
public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { Debug.Assert(!_isVararg); if (dest.Offset > 255) { throw new NotImplementedException(); } writer.WriteUUU(OpCodes.VARG1, dest.Offset, 0, 0); }
public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { var destIndex = dest.Offset; var listOffset = _upvalList.Offset; if (destIndex > 255 | listOffset > 255 | _index > 255) { throw new NotImplementedException(); } writer.WriteUUU(OpCodes.UGET, destIndex, listOffset, _index); }
public override void EmitPrep(InstructionWriter writer) { if (_tableStack.HasValue) { _table.EmitGet(writer, _tableStack.Value); } if (_keyStack.HasValue) { _key.EmitGet(writer, _keyStack.Value); } }
public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { var destIndex = dest.Offset; var offset = _localInfo.Offset; if (offset > 255 || destIndex > 255) { throw new NotImplementedException(); } writer.WriteUUU(Opcodes.MOV, destIndex, offset, 0); }
public override void Emit(InstructionWriter writer) { var restartLabel = new LabelStatementSyntaxNode(); writer.MarkLabel(restartLabel); _cond.Emit(writer); _block.Emit(writer); writer.WriteUSx(OpCodes.JMP, 0, 0); writer.AddLabelFix(restartLabel, InstructionWriter.FixUSxJump); writer.MarkLabel(_exitLabel); }
public override void EmitSet(InstructionWriter writer, AllocatedLocal src, VMSpecializationType type) { if (type != _type) { throw new NotImplementedException(); } var srcIndex = src.Offset; var listOffset = _upvalList.Offset; if (srcIndex > 255 | listOffset > 255 | _index > 255) { throw new NotImplementedException(); } writer.WriteUUU(OpCodes.USET, srcIndex, listOffset, _index); }
public override void EmitSet(InstructionWriter writer, AllocatedLocal src, VMSpecializationType type) { if (type != _type) { throw new NotImplementedException(); } var srcIndex = src.Offset; var offset = _localInfo.Offset; if (offset > 255 || srcIndex > 255) { throw new NotImplementedException(); } writer.WriteUUU(Opcodes.MOV, offset, srcIndex, 0); }
public override void EmitSet(InstructionWriter writer, AllocatedLocal src, VMSpecializationType type) { if (!_table.TryGetFromStack(out var tableStack)) { tableStack = _tableStack.Value; } if (!_key.TryGetFromStack(out var keyStack)) { keyStack = _keyStack.Value; } if (tableStack.Offset > 255 || keyStack.Offset > 255 || src.Offset > 255) { throw new NotImplementedException(); } writer.WriteUUU(Opcodes.TSET, src.Offset, tableStack.Offset, keyStack.Offset); }
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); }
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) { int operand; if (_tmpSlot.HasValue) { _operand.EmitGet(writer, _tmpSlot.Value); operand = _tmpSlot.Value.Offset; } else { var onStack = _operand.TryGetFromStack(out var s); Debug.Assert(onStack); operand = s.Offset; } var destIndex = dest.Offset; if (operand > 255 || destIndex > 255) { throw new NotImplementedException(); } switch (_operator) { case UnaryOperator.Neg: writer.WriteUUU(OpCodes.NEG, destIndex, operand, 0); break; case UnaryOperator.Not: writer.WriteUUU(OpCodes.NOT, destIndex, operand, 0); break; case UnaryOperator.Num: writer.WriteUUU(OpCodes.LEN, destIndex, operand, 0); break; } }
public override void Emit(InstructionWriter writer) { writer.WriteUUU(Opcodes.RET0, 0, 0, 0); }
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; } } }
//For variables: set the value of the variable to the value at src. //EmitPrep will be called before this. public virtual void EmitSet(InstructionWriter writer, AllocatedLocal src, VMSpecializationType type) { throw new NotSupportedException(); }
//For expressions with side effects: perform the expression's side effect without saving the value. //EmitPrep will NOT be called before this. public virtual void EmitDiscard(InstructionWriter writer) { EmitPrep(writer); EmitGet(writer, _null); }
public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { throw new NotSupportedException(); }
public override void Emit(InstructionWriter writer) { writer.WriteUSx(Opcodes.JMP, 0, 0); writer.AddLabelFix(_label, InstructionWriter.FixUSxJump); }
public override void Emit(InstructionWriter writer) { _expr.EmitPrep(writer); _expr.EmitDiscard(writer); }
//For vararg expr: calculate the value and write to stack at sigblock's location, with the given sig index. //The sigIndex is the index into proto's signature list. This should be the out signature of function calls. //sigType is the instance at sig index. It is needed by the new sig adjustment method. //EmitPrep will be called before this. public virtual void EmitGet(InstructionWriter writer, IStackFragment sigBlock, StackSignature sigType, int sigIndex, bool keepSig) { throw new NotSupportedException(); }
public override void Emit(InstructionWriter writer) { writer.MarkLabel(_label); }
public override void EmitDiscard(InstructionWriter writer) { }
public abstract void Emit(InstructionWriter writer);
public override void Emit(InstructionWriter writer) { writer.MarkLabel(_repeatLabel); _block.Emit(writer); _cond.Emit(writer); }
public override void EmitDiscard(InstructionWriter writer) { throw new NotSupportedException(); }