public UpvalueExpressionGenerator(AllocatedLocal upvalList, int index, LocalVariableDefinitionSyntaxNode definition) : base(0) { _upvalList = upvalList; _index = index; _type = definition.Specialization.GetVMSpecializationType(); }
public ConditionGenerator(GeneratorFactory factory, BlockGenerator block, ExpressionSyntaxNode expr, LabelStatementSyntaxNode falseLabel, bool reverseCondition) { while (expr is UnaryExpressionSyntaxNode unary && unary.Operator == UnaryOperator.Not) { expr = unary.Operand; reverseCondition = !reverseCondition; } if (expr is BinaryExpressionSyntaxNode bin && IsComparisonExpr(bin, out _opcode, out _exchangeComparison)) { _isComparison = true; //Normally, reverse the cmp (jump to false label if condition is not met). if (!reverseCondition) { ReverseComparisonResult(ref _opcode); } _expr1 = factory.CreateExpression(block, bin.Left); _expr2 = factory.CreateExpression(block, bin.Right); if (!_expr1.TryGetFromStack(out _)) { _expr1Stack = block.TempAllocator.Allocate(_expr1.GetSingleType()); } if (!_expr2.TryGetFromStack(out _)) { _expr2Stack = block.TempAllocator.Allocate(_expr2.GetSingleType()); } }
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 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, AllocatedLocal dest) { Debug.Assert(!_isVararg); if (dest.Offset > 255) { throw new NotImplementedException(); } writer.WriteUUU(OpCodes.VARG1, dest.Offset, 0, 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) { 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 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 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 (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 (!_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 NumericForStatementGenerator(GeneratorFactory factory, BlockGenerator block, NumericForBlockSyntaxNode stat) { var stack = new GroupStackFragment(); block.Stack.Add(stack); _e1 = factory.CreateExpression(block, stat.From); _e2 = factory.CreateExpression(block, stat.To); var stepExpr = stat.Step ?? new LiteralExpressionSyntaxNode() { DoubleValue = 1 }; _e3 = factory.CreateExpression(block, stepExpr); var e1t = _e1.GetSingleType(); var e2t = _e2.GetSingleType(); var e3t = _e3.GetSingleType(); if (e1t == VMSpecializationType.Polymorphic && e2t == VMSpecializationType.Polymorphic && e3t == VMSpecializationType.Polymorphic) { _initOp = Opcodes.FORI; _loopOp = Opcodes.FORL; } else { throw new NotImplementedException(); } var ctrlStack = new BlockStackFragment(); stack.Add(ctrlStack); _e1Stack = ctrlStack.AddSpecializedType(e1t); _e2Stack = ctrlStack.AddSpecializedType(e2t); _e3Stack = ctrlStack.AddSpecializedType(e3t); //Use stack (so it's after control variables). //This will also handle the aux block for us. _forBlock = new BlockGenerator(factory, stack, stat); var loopVar = factory.Function.Locals[stat.Variable]; var loopVarOnStack = loopVar.TryGetFromStack(out _loopVar); Debug.Assert(loopVarOnStack); }
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 bool TryGetFromStack(out AllocatedLocal stackOffset) { stackOffset = default; return(false); }
protected ExpressionGenerator(GeneratorFactory factory) { _null = factory.Function.NullSlot; }
//For all expressions: get the single value and write to dest. //EmitPrep will be called before this. public abstract void EmitGet(InstructionWriter writer, AllocatedLocal dest);
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(); }
public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { throw new NotSupportedException(); }
//For locals & arguments: provide the slot it occupies on stack. //This might be called before and during the emit stage. //EmitPrep will NOT be called before this. public abstract bool TryGetFromStack(out AllocatedLocal stackOffset);
public override bool TryGetFromStack(out AllocatedLocal stackOffset) { stackOffset = _localInfo; return(true); }
public LocalVariableExpressionGenerator(BlockStackFragment stack, LocalVariableDefinitionSyntaxNode definition) : base(0) { _type = definition.Specialization.GetVMSpecializationType(); _localInfo = stack.AddSpecializedType(_type); }