Changeset 64 for trunk/UTarget.pas
- Timestamp:
- Dec 4, 2014, 2:59:28 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UTarget.pas
r63 r64 66 66 end; 67 67 68 TBrainFuckCommand = (cmNoOperation, cmInc, cmDec, cmPointerInc, cmPointerDec, 69 cmOutput, cmInput, cmLoopStart, cmLoopEnd, cmDebug); 68 TMachineCommand = (cmNoOperation, cmInc, cmDec, cmPointerInc, cmPointerDec, 69 cmOutput, cmInput, cmLoopStart, cmLoopEnd, cmDebug, cmSet); 70 71 TMachineOperation = record 72 Command: TMachineCommand; 73 Parameter: Integer; 74 end; 70 75 71 76 TLogEvent = procedure (Lines: TStrings) of object; … … 80 85 function SourceReadNext: Char; 81 86 function CheckClear: Boolean; 82 function CheckOccurence(C: TBrainFuckCommand): Integer; 87 function CheckOccurenceSumParam(C: TMachineCommand): Integer; 88 function CheckOccurence(C: TMachineCommand): Integer; 89 procedure OptimizeAddSub; 90 procedure OptimizeMerge; 91 procedure OptimizeZeroInitMemory; 83 92 protected 84 93 FSourceCode: string; 85 FProgram: array of T BrainFuckCommand;94 FProgram: array of TMachineOperation; 86 95 FProgramIndex: Integer; 87 96 FTargetCode: string; … … 101 110 ProgramName: string; 102 111 ImageIndex: Integer; 103 Optimization : TCompilerOptimization;112 OptimizationLevel: TCompilerOptimization; 104 113 CompilerPath: string; 105 114 ExecutorPath: string; … … 367 376 begin 368 377 inherited; 369 Optimization := coNormal;378 OptimizationLevel := coNormal; 370 379 BreakPoints := TBreakPointList.Create; 371 380 DebugSteps := TDebugStepList.Create; … … 387 396 388 397 procedure TTarget.OptimizeSource; 389 begin 390 // Remove redundand code 391 398 var 399 OldLength: Integer; 400 begin 401 OptimizeAddSub; 402 repeat 403 OldLength := Length(FProgram); 404 OptimizeMerge; 405 until Length(FProgram) = OldLength; 406 OptimizeZeroInitMemory; 392 407 end; 393 408 … … 395 410 begin 396 411 LoadProgram; 412 if OptimizationLevel = coNormal then OptimizeSource; 397 413 Compiled := True; 398 414 end; … … 528 544 end; 529 545 530 function TTarget.CheckOccurence(C: T BrainFuckCommand): Integer;546 function TTarget.CheckOccurence(C: TMachineCommand): Integer; 531 547 begin 532 548 Result := 1; 533 if Optimization = coNormal then 534 while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1] = C) do begin 549 while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1].Command = C) do begin 535 550 Inc(Result); 536 551 Inc(FProgramIndex); 537 552 end; 553 end; 554 555 function TTarget.CheckOccurenceSumParam(C: TMachineCommand): Integer; 556 begin 557 Result := FProgram[FProgramIndex].Parameter; 558 while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1].Command = C) do begin 559 Inc(Result, FProgram[FProgramIndex + 1].Parameter); 560 Inc(FProgramIndex); 561 end; 562 end; 563 564 procedure TTarget.OptimizeAddSub; 565 var 566 NewProgram: array of TMachineOperation; 567 NewProgramIndex: Integer; 568 begin 569 NewProgramIndex := 0; 570 SetLength(NewProgram, Length(FProgram)); 571 572 FProgramIndex := 0; 573 while (FProgramIndex < Length(FProgram)) do begin 574 case FProgram[FProgramIndex].Command of 575 cmPointerInc: begin 576 NewProgram[NewProgramIndex].Command := cmPointerInc; 577 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmPointerInc); 578 end; 579 cmPointerDec: begin 580 NewProgram[NewProgramIndex].Command := cmPointerDec; 581 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmPointerDec); 582 end; 583 cmInc: begin 584 NewProgram[NewProgramIndex].Command := cmInc; 585 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmInc); 586 end; 587 cmDec: begin 588 NewProgram[NewProgramIndex].Command := cmDec; 589 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmDec); 590 end; 591 else begin 592 NewProgram[NewProgramIndex].Command := FProgram[FProgramIndex].Command; 593 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 594 end; 595 end; 596 Inc(FProgramIndex); 597 Inc(NewProgramIndex); 598 end; 599 SetLength(NewProgram, NewProgramIndex); 600 601 // Replace old program by new program 602 SetLength(FProgram, Length(NewProgram)); 603 Move(NewProgram[0], FProgram[0], SizeOf(TMachineOperation) * Length(NewProgram)); 604 end; 605 606 procedure TTarget.OptimizeMerge; 607 var 608 NewProgram: array of TMachineOperation; 609 NewProgramIndex: Integer; 610 PreviousCommand: TMachineCommand; 611 begin 612 // Merge together cmInc, cmDec, cmSet 613 // Merge together cmPointerInc, cmPointerDec 614 PreviousCommand := cmNoOperation; 615 NewProgramIndex := 0; 616 SetLength(NewProgram, Length(FProgram)); 617 618 FProgramIndex := 0; 619 while (FProgramIndex < Length(FProgram)) do begin 620 case FProgram[FProgramIndex].Command of 621 cmPointerInc: begin 622 if PreviousCommand in [cmPointerInc, cmPointerDec] then begin 623 if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then 624 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter + 625 FProgram[FProgramIndex].Parameter 626 else if NewProgram[NewProgramIndex - 1].Command = cmPointerDec then 627 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter - 628 FProgram[FProgramIndex].Parameter; 629 // If value negative then change command 630 if NewProgram[NewProgramIndex - 1].Parameter < 0 then begin 631 NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter; 632 if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then 633 NewProgram[NewProgramIndex - 1].Command := cmPointerDec 634 else NewProgram[NewProgramIndex - 1].Command := cmPointerInc; 635 end; 636 if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex); 637 Dec(NewProgramIndex); 638 end else begin 639 NewProgram[NewProgramIndex].Command := cmPointerInc; 640 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 641 end; 642 end; 643 cmPointerDec: begin 644 if PreviousCommand in [cmPointerInc, cmPointerDec] then begin 645 if NewProgram[NewProgramIndex - 1].Command = cmPointerDec then 646 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter + 647 FProgram[FProgramIndex].Parameter 648 else if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then 649 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter - 650 FProgram[FProgramIndex].Parameter; 651 // If value negative then change command 652 if NewProgram[NewProgramIndex - 1].Parameter < 0 then begin 653 NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter; 654 if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then 655 NewProgram[NewProgramIndex - 1].Command := cmPointerDec 656 else NewProgram[NewProgramIndex - 1].Command := cmPointerInc; 657 end; 658 if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex); 659 Dec(NewProgramIndex); 660 end else begin 661 NewProgram[NewProgramIndex].Command := cmPointerDec; 662 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 663 end; 664 end; 665 cmInc: begin 666 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 667 if NewProgram[NewProgramIndex - 1].Command in [cmInc, cmSet] then 668 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter + 669 FProgram[FProgramIndex].Parameter 670 else if NewProgram[NewProgramIndex - 1].Command = cmDec then 671 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter - 672 FProgram[FProgramIndex].Parameter; 673 // If value negative then change command 674 if (NewProgram[NewProgramIndex - 1].Parameter < 0) and (NewProgram[NewProgramIndex - 1].Command <> cmSet) then begin 675 NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter; 676 if NewProgram[NewProgramIndex - 1].Command = cmInc then 677 NewProgram[NewProgramIndex - 1].Command := cmDec 678 else NewProgram[NewProgramIndex - 1].Command := cmInc; 679 end; 680 if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex); 681 Dec(NewProgramIndex); 682 end else begin 683 NewProgram[NewProgramIndex].Command := cmInc; 684 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 685 end; 686 end; 687 cmDec: begin 688 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 689 if NewProgram[NewProgramIndex - 1].Command = cmDec then 690 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter + 691 FProgram[FProgramIndex].Parameter 692 else if NewProgram[NewProgramIndex - 1].Command in [cmInc, cmSet] then 693 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter - 694 FProgram[FProgramIndex].Parameter; 695 // If value negative then change command 696 if (NewProgram[NewProgramIndex - 1].Parameter < 0) and (NewProgram[NewProgramIndex - 1].Command <> cmSet) then begin 697 NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter; 698 if NewProgram[NewProgramIndex - 1].Command = cmInc then 699 NewProgram[NewProgramIndex - 1].Command := cmDec 700 else NewProgram[NewProgramIndex - 1].Command := cmInc; 701 end; 702 if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex); 703 Dec(NewProgramIndex); 704 end else begin 705 NewProgram[NewProgramIndex].Command := cmDec; 706 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 707 end; 708 end; 709 cmSet: begin 710 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 711 // Set overrides value of previous commands 712 Dec(NewProgramIndex); 713 NewProgram[NewProgramIndex].Command := cmSet; 714 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 715 end else begin 716 NewProgram[NewProgramIndex].Command := cmSet; 717 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 718 end; 719 end; 720 cmLoopStart: begin 721 if CheckClear then begin 722 NewProgram[NewProgramIndex].Command := cmSet; 723 NewProgram[NewProgramIndex].Parameter := 0; 724 Inc(FProgramIndex, 2); 725 end else begin 726 NewProgram[NewProgramIndex].Command := FProgram[FProgramIndex].Command; 727 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 728 end; 729 end; 730 else begin 731 NewProgram[NewProgramIndex].Command := FProgram[FProgramIndex].Command; 732 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 733 end; 734 end; 735 PreviousCommand := FProgram[FProgramIndex].Command; 736 Inc(FProgramIndex); 737 Inc(NewProgramIndex); 738 end; 739 SetLength(NewProgram, NewProgramIndex); 740 741 // Replace old program by new program 742 SetLength(FProgram, Length(NewProgram)); 743 Move(NewProgram[0], FProgram[0], SizeOf(TMachineOperation) * Length(NewProgram)); 744 end; 745 746 procedure TTarget.OptimizeZeroInitMemory; 747 begin 748 // Here optimization related to assumption that initial memory is filled with zeroes 749 // Then code for constants preparation can be translated to cmSet commands 750 // To eliminate also loops for building constants code need to be somehow interpretted partialy 538 751 end; 539 752 … … 549 762 case FSourceCode[I] of 550 763 '+': begin 551 FProgram[FProgramIndex] := cmInc; 764 FProgram[FProgramIndex].Command := cmInc; 765 FProgram[FProgramIndex].Parameter := 1; 552 766 DebugSteps.AddStep(I - 1, FProgramIndex, soNormal); 553 767 end; 554 768 '-': begin 555 FProgram[FProgramIndex] := cmDec; 769 FProgram[FProgramIndex].Command := cmDec; 770 FProgram[FProgramIndex].Parameter := 1; 556 771 DebugSteps.AddStep(I - 1, FProgramIndex, soNormal); 557 772 end; 558 773 '>': begin 559 FProgram[FProgramIndex] := cmPointerInc; 774 FProgram[FProgramIndex].Command := cmPointerInc; 775 FProgram[FProgramIndex].Parameter := 1; 560 776 DebugSteps.AddStep(I - 1, FProgramIndex, soNormal); 561 777 end; 562 778 '<': begin 563 FProgram[FProgramIndex] := cmPointerDec; 779 FProgram[FProgramIndex].Command := cmPointerDec; 780 FProgram[FProgramIndex].Parameter := 1; 564 781 DebugSteps.AddStep(I - 1, FProgramIndex, soNormal); 565 782 end; 566 783 ',': begin 567 FProgram[FProgramIndex] := cmInput; 784 FProgram[FProgramIndex].Command := cmInput; 785 FProgram[FProgramIndex].Parameter := 0; 568 786 DebugSteps.AddStep(I - 1, FProgramIndex, soNormal); 569 787 end; 570 788 '.': begin 571 FProgram[FProgramIndex] := cmOutput; 789 FProgram[FProgramIndex].Command := cmOutput; 790 FProgram[FProgramIndex].Parameter := 0; 572 791 DebugSteps.AddStep(I - 1, FProgramIndex, soNormal); 573 792 end; 574 793 '[': begin 575 FProgram[FProgramIndex] := cmLoopStart; 794 FProgram[FProgramIndex].Command := cmLoopStart; 795 FProgram[FProgramIndex].Parameter := 0; 576 796 DebugSteps.AddStep(I - 1, FProgramIndex, soStepIn); 577 797 end; 578 798 ']': begin 579 FProgram[FProgramIndex] := cmLoopEnd; 799 FProgram[FProgramIndex].Command := cmLoopEnd; 800 FProgram[FProgramIndex].Parameter := 0; 580 801 DebugSteps.AddStep(I - 1, FProgramIndex, soStepOut); 581 802 end … … 594 815 function TTarget.CheckClear: Boolean; 595 816 begin 596 Result := (FProgram[FProgramIndex] = cmLoopStart) and (Length(FProgram) >= FProgramIndex + 2) and 597 (FProgram[FProgramIndex + 1] = cmDec) and (FProgram[FProgramIndex + 2] = cmLoopEnd); 817 Result := (FProgram[FProgramIndex].Command = cmLoopStart) and (Length(FProgram) >= FProgramIndex + 2) and 818 (((FProgram[FProgramIndex + 1].Command = cmDec) and (FProgram[FProgramIndex + 1].Parameter = 1)) or 819 ((FProgram[FProgramIndex + 1].Command = cmInc) and (FProgram[FProgramIndex + 1].Parameter = -1))) 820 and (FProgram[FProgramIndex + 2].Command = cmLoopEnd); 598 821 end; 599 822
Note:
See TracChangeset
for help on using the changeset viewer.