private Operand MakeVariableAssignment(VariableAssignmentNode node, ILGenerator generator) { SymbolOperand leftHandSide = node.Accessor.Visit(generator) as SymbolOperand; Operand rightHandSide = node.Right.Visit(generator); // If right-hand side exists and has a type, do some type checking /*if (rightHandSide.Type != leftHandSide.Type) * throw new AstWalkerException($"Cannot convert {rightHandSide.Type} to {leftHandSide.Type} ('{leftHandSide.Name}')");*/ if (node.Operator.Type == TokenType.Assignment) { generator.Emmit(new StoreInstruction(leftHandSide, rightHandSide)); return(leftHandSide); } Instruction instr = null; switch (node.Operator.Type) { case TokenType.IncrementAndAssign: instr = new AddInstruction(leftHandSide, leftHandSide, rightHandSide); break; case TokenType.DecrementAndAssign: instr = new SubInstruction(leftHandSide, leftHandSide, rightHandSide); break; case TokenType.MultAndAssign: instr = new MultInstruction(leftHandSide, leftHandSide, rightHandSide); break; case TokenType.DivideAndAssign: instr = new DivInstruction(leftHandSide, leftHandSide, rightHandSide); break; default: throw new InvalidInstructionException($"Unsupported operation: {node.Operator.Value} ({node.Operator.Type})"); } generator.Emmit(instr); return(leftHandSide); }
public override IEnumerable<MilocInstruction> Mult(MultInstruction s, InstructionStream<MilocInstruction> stream) { var d0 = constantValue(s, s.RegSource0); var d1 = constantValue(s, s.RegSource1); if (d0.HasValue == d1.HasValue) { yield return s; yield break; } if (d0.HasValue) { yield return new SllInstruction(s.RegSource1, d0.Value, s.RegDest0); } else { yield return new SllInstruction(s.RegSource0, d1.Value, s.RegDest0); } }
public Operand Visit(ILGenerator generator, BinaryNode binary) { Operand left = binary.Left.Visit(generator); Operand right = binary.Right.Visit(generator); SymbolOperand tmpname = generator.SymbolTable.NewTempSymbol(OperandType.Auto); Instruction instr = null; switch (binary.Operator.Type) { case TokenType.Addition: instr = new AddInstruction(tmpname, left, right); break; case TokenType.Minus: instr = new SubInstruction(tmpname, left, right); break; case TokenType.Multiplication: instr = new MultInstruction(tmpname, left, right); break; case TokenType.Division: instr = new DivInstruction(tmpname, left, right); break; case TokenType.Or: instr = new OrInstruction(tmpname, left, right); break; case TokenType.And: instr = new AndInstruction(tmpname, left, right); break; case TokenType.GreatThan: instr = new CgtInstruction(tmpname, left, right); break; case TokenType.GreatThanEqual: instr = new CgteInstruction(tmpname, left, right); break; case TokenType.LessThan: instr = new CltInstruction(tmpname, left, right); break; case TokenType.LessThanEqual: instr = new ClteInstruction(tmpname, left, right); break; case TokenType.Equal: case TokenType.NotEqual: // Use NOT instruction instr = new CeqInstruction(tmpname, left, right); break; } generator.Emmit(new VarInstruction(tmpname, null)); generator.Emmit(instr); if (binary.Operator.Type == TokenType.NotEqual) { SymbolOperand notname = generator.SymbolTable.NewTempSymbol(OperandType.Auto); generator.Emmit(new VarInstruction(notname, null)); generator.Emmit(new NotInstruction(notname, tmpname)); return(notname); } return(tmpname); }