OSDN Git Service

elccコンパイラの最適化機能を向上。
authorhikarupsp <hikarupsp@users.sourceforge.jp>
Sat, 25 Jan 2014 15:42:33 +0000 (00:42 +0900)
committerhikarupsp <hikarupsp@users.sourceforge.jp>
Sat, 25 Jan 2014 15:42:33 +0000 (00:42 +0900)
ai.js
elcc/elcc.js
elcc/elccide.html
webcpu/webcpu.js

diff --git a/ai.js b/ai.js
index 5cb6d73..8bf3e29 100644 (file)
--- a/ai.js
+++ b/ai.js
@@ -147,22 +147,22 @@ AI.prototype = {
                //表示処理
                if(this.messageBox && this.messageBoxBuffer != ""){
                        //messageBox
-                       var str = this.messageBox.innerHTML + this.messageBoxBuffer;
+                       var str = this.messageBox.value + this.messageBoxBuffer;
                        this.messageBoxBuffer = "";
                        if(str.length > this.maxMessageStringLength){
                                str = str.slice(str.length - (this.maxMessageStringLength >> 1));
                        }
-                       this.messageBox.innerHTML = str;
+                       this.messageBox.value = str;
                        this.messageBox.scrollTop = this.messageBox.scrollHeight;
                }
                if(this.debugBox && this.debugBoxBuffer != ""){
                        //debugBox
-                       var str = this.debugBox.innerHTML + this.debugBoxBuffer;
+                       var str = this.debugBox.value + this.debugBoxBuffer;
                        this.debugBoxBuffer = "";
                        if(str.length > this.maxDebugStringLength){
                                str = str.slice(str.length - (this.maxDebugStringLength >> 1));
                        }
-                       this.debugBox.innerHTML = str;
+                       this.debugBox.value = str;
                        this.debugBox.scrollTop = this.debugBox.scrollHeight;
                }
        },
@@ -250,7 +250,7 @@ AI.prototype = {
                
                var that = this;
                var cc = new ELCHNOSCompiler(function(s){ that.debug(s); }, this.downloadBox);
-               if(cc.compile(str) == null){
+               if(cc.compile(str) != null){
                        cc.saveBinary();
                }
                
index a5c00e6..3bb66e1 100644 (file)
@@ -87,10 +87,11 @@ ELCHNOSCompiler.prototype = {
                "-",
                "*",
                "/",
+               "#",
        ],
        errorMessageList: [
                "Trap.",
-               "Incompatible value attribute.",
+               "Incompatible attribute.",
                "Unexpected identifier.",
                "Unknown assembly language type.",
                "Invalid expression of OSECPU Binary.",
@@ -114,7 +115,7 @@ ELCHNOSCompiler.prototype = {
                this.pointerRegisterAllocationTable = new Array();
        },
        compile: function(str){
-               //戻り値nullでコンパイル成功
+               //戻り値はコンパイルされたバイナリのHex文字列。nullの場合コンパイル失敗。
                this.reset();
                //
                this.line = str.split("\n");
@@ -496,26 +497,27 @@ ELCHNOSCompiler.prototype = {
                        this.expandBinaryString();
                        this.assignRegister();
                        this.bin.logAsHexByte(this.debug);
-                       this.debug("\n");
+                       this.debug("(" + this.bin.length + "Bytes)\n");
                        //
-                       
+                       //最適化(試験中)
                        //
                        var cpu = new WebCPU();
                        cpu.loadBinaryText(this.bin.stringAsHexByte());
                        cpu.staticOptimize();
-                       this.debug(cpu.createBackendBinaryString());
-                       this.debug("\n");
+                       var binStr = cpu.createBackendBinaryString();
+                       this.debug(binStr);
+                       this.debug("(" + (binStr.length >> 1) + "Bytes)\n");
                        //
                } catch(e){
                        //全エラー処理
                        if(e instanceof ELCHNOSCompiler_CompileException){
                                this.debug(e.getMessageString());
-                               return e;
+                               return null;
                        } else{
                                throw e;
                        }
                }
-               return null;
+               return binStr;
        },
        compile_removeComment: function(){
                //コメント削除
@@ -527,7 +529,7 @@ ELCHNOSCompiler.prototype = {
                for(var i = 0, iLen = this.separated.length; i < iLen; i++){
                        var s = this.separated[i];
                        if(commentLineStartIndex == -1){
-                               if(s == "//"){
+                               if(s == "//" || s == "#"){
                                        //行コメント開始
                                        commentLineStartIndex = i;
                                }
@@ -713,6 +715,7 @@ ELCHNOSCompiler.prototype = {
                }
        },
        expandBinaryString: function(){
+               //入れ子構造になっている配列を一次元配列に展開して返す。
                var ary = this.bin;
                var b = new Array();
                var aryStack = new Array();
@@ -767,7 +770,7 @@ ELCHNOSCompiler.prototype = {
                        }
                        if(url){
                                if(this.downloadBoxDOMObject){
-                                       this.downloadBoxDOMObject.innerHTML = "<a href='" + url + "' target='_blank'>ダウンロード</a>";
+                                       this.downloadBoxDOMObject.innerHTML = "<a href='" + url + "' target='_blank'>右クリックしてダウンロード</a>";
                                } else{
                                        this.debug("BinarySaved: " + url + "\n");
                                }
index c206b20..622dc27 100755 (executable)
@@ -34,7 +34,7 @@ var binStr = null;
 onload = function(){
        debugMessageTextArea = document.getElementById('debugMessageText');
        mainCPU = new WebCPU();
-       mainCompiler = new ELCHNOSCompiler(messageOut);
+       mainCompiler = new ELCHNOSCompiler(messageOut, document.getElementById('downloadBox'));
 
        mainCPU.setMainWindowCanvasDOMObject("mainWindowCanvas");
        enableDebugMode();
@@ -71,12 +71,11 @@ function messageOut(s){
 
 function compile(){
        debugMessageTextArea.value += "****Compile Started****\n";
-       if(mainCompiler.compile(codeTextArea.value) == null){
+       binStr = mainCompiler.compile(codeTextArea.value);
+       if(binStr != null){
                messageOut("*\n****Compile Succeeded!****\n*\n");
-               binStr = mainCompiler.bin.stringAsHexByte()
        } else{
                messageOut("*\n****Compile Failed...****\n*\n");
-               binStr = null;
        }
 }
 
@@ -84,6 +83,16 @@ function run(){
        if(binStr){
                mainCPU.loadBinaryText(binStr);
                mainCPU.execute();
+       } else{
+               messageOut("run: No available binary.\n");
+       }
+}
+
+function showAssembly(){
+       if(binStr){
+               mainCPU.loadBinaryText(binStr);
+       } else{
+               messageOut("showAssembly: No available binary.\n");
        }
 }
 
@@ -111,11 +120,10 @@ function handleFileSelect(evt){
                var r = new FileReader();
                r.onload = (function(file){
                        return function(e){
-                               var a = r.result;
-                               codeTextArea.value = a;
+                               codeTextArea.value = r.result;
                        }
                })(f);
-               r.readAsArrayBuffer(f);
+               r.readAsText(f);
        }
 }
 
@@ -129,18 +137,24 @@ function handleDragOver(evt){
 <body>
 <h1>ELCC-IDE</h1>
 <div style="float:left;">
-       <h2>mainWindow</h2>
+       <h2>MainWindow</h2>
        <canvas id="mainWindowCanvas" width="640" height="480" style="border:1px solid #000000;"></canvas>
-       <h2>Internal Information</h2>
-       <input type="checkbox" onchange="">message</input><br />
+       <h3>Message</h3>
        <textarea id="debugMessageText" cols="66" rows="16"></textarea>
        <form onsubmit="return false;">
                <button onclick="compile();">Compile</button>
+               <button onclick="showAssembly();">Show Assembly</button>
                <button onclick="run();">Run</button>
-               <button onclick="mainCPU.stopFlag = true;">Break</button><br />
+               <button onclick="mainCPU.stopFlag = true;">Break</button>
+               <br />
                <button onclick="enableDebugMode();">EnableDebugMode</button>
                <button onclick="disableDebugMode();">DisableDebugMode</button>
+               <br />
+               <button onclick="if(binStr){ mainCompiler.saveBinary(); }">Create bin.ose</button>
+               
        </form>
+       <h3>Downloads</h3>
+       <div id="downloadBox"></div>
 </div>
 <div style="float:left;">
        <h2>Code</h2>
@@ -197,7 +211,6 @@ procedure main()
 }
        </textarea>
        <div id="fileDropZone">Drop SourceCode.elc here</div>
-       <div id="fileList"></div>
 </div>
 </body>
 </html>
\ No newline at end of file
index e347883..f610284 100755 (executable)
@@ -255,7 +255,7 @@ WebCPU.prototype = {
                        for(var i = 0; i < this.registers.Pointer[0x02].addressOffset; i++){
                                binStr += ("00" + binData.data[i].toString(16)).slice(-2);
                        }
-                       this.message("[" + binStr + "]\n");
+                       this.message("[" + binStr + "](" + (binStr.length >> 1) + "Bytes)\n");
                        this.loadBackEndBinaryText(binStr);
                        this.reset();
                } else{
@@ -398,12 +398,12 @@ WebCPU.prototype = {
        },
        debugShowTick: function(){
                if(this.debugMessageText && this.debugMessageBuffer != ""){
-                       var str = this.debugMessageText.innerHTML + this.debugMessageBuffer;
+                       var str = this.debugMessageText.value + this.debugMessageBuffer;
                        this.debugMessageBuffer = "";
                        if(str.length > WebCPU.maxDebugStringLength){
                                str = str.slice(str.length - (WebCPU.maxDebugStringLength >> 1));
                        }
-                       this.debugMessageText.innerHTML = str;
+                       this.debugMessageText.value = str;
                        this.debugMessageText.scrollTop = this.debugMessageText.scrollHeight;
                }
                this.refreshDebugIntegerRegisterText();
@@ -443,20 +443,20 @@ WebCPU.prototype = {
        },
        refreshDebugIntegerRegisterText: function(){
                if(this.debugIntegerRegisterText != null){
-                       this.debugIntegerRegisterText.innerHTML = "";
+                       this.debugIntegerRegisterText.value = "";
                        for(var i = 0; i < this.registers.Integer.length; i++){
-                               this.debugIntegerRegisterText.innerHTML += "R" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":0x" + this.registers.Integer[i].toString(16).toUpperCase() + "\n";
+                               this.debugIntegerRegisterText.value += "R" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":0x" + this.registers.Integer[i].toString(16).toUpperCase() + "\n";
                        }
                }
        },
        refreshDebugPointerRegisterText: function(){
                if(this.debugPointerRegisterText != null){
-                       this.debugPointerRegisterText.innerHTML = "";
+                       this.debugPointerRegisterText.value = "";
                        for(var i = 0; i < this.registers.Pointer.length; i++){
                                if(this.registers.Pointer[i]){
-                                       this.debugPointerRegisterText.innerHTML += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":" + this.registers.Pointer[i].toString() + "\n";
+                                       this.debugPointerRegisterText.value += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":" + this.registers.Pointer[i].toString() + "\n";
                                } else{
-                                       this.debugPointerRegisterText.innerHTML += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":(null)\n";
+                                       this.debugPointerRegisterText.value += "P" +  ("00" + i.toString(16)).slice(-2).toUpperCase() + ":(null)\n";
                                }
                        }
                }
@@ -494,6 +494,11 @@ WebCPU.prototype = {
        },
        staticOptimize: function(){
                //静的最適化
+               this.staticOptimize_RemoveDuplicatedLabelNumber();
+               this.staticOptimize_CMPxx_CND_PLIMM_PLIMM_LB();
+               this.staticOptimize_RemoveUnusedLabelNumber();
+       },
+       staticOptimize_RemoveDuplicatedLabelNumber: function(){
                //連続するラベル命令の削除
                //一つのメモリページにラベル命令のみがある場合は、それを次のメモリページのラベル名に置換する
                var mpage;
@@ -527,7 +532,7 @@ WebCPU.prototype = {
                        }
                }
                if(labelIDStack.length != 0){
-                       //ã\83\97ã\83­ã\82°ã\83©ã\83 æ\9c«å°¾ã\81®ã\83©ã\83\99ã\83«å\91½ä»¤ã\81¯å\89\8aé\99¤ã\81\97ã\81ªã\81\84ã\82\88ã\81\86ã\81«ã\81\99ã\82\8b
+                       //ã\83\97ã\83­ã\82°ã\83©ã\83 æ\9c«å°¾ã\81®ã\83©ã\83\99ã\83«å\91½ä»¤ã\81¯å\89\8aé\99¤ã\81\97ã\81ªã\81\84ã\80\82
                        newLabelID = labelIDStack.pop();
                        for(;;){
                                labelID = labelIDStack.pop();
@@ -541,6 +546,7 @@ WebCPU.prototype = {
                }
        },
        staticOptimize_ReplaceLabelNumber: function(from, to){
+               //PLIMM命令のラベル番号がfromのものをtoに変更する。
                var mpage;
                var instr;
                for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
@@ -554,7 +560,128 @@ WebCPU.prototype = {
                                }
                        }
                }
-       }
+       },
+       staticOptimize_RemoveUnusedLabelNumber: function(){
+               var usedLabelNumberList = new Array();
+               var mpage;
+               var instr;
+               //使われているラベル番号のリスト生成
+               for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
+                       mpage = this.mainMemory.root[i];
+                       for(var j = 0, jLen = mpage.data.length; j < jLen; j++){
+                               instr = mpage.data[j];
+                               if(instr instanceof WebCPU_Instruction_PLIMM){
+                                       usedLabelNumberList.pushUnique(instr.imm32);
+                               }
+                       }
+               }
+               //ラベルを走査し、不要なラベル番号を削除
+               for(var i = 0; i < this.mainMemory.root.length; i++){
+                       mpage = this.mainMemory.root[i];
+                       if(mpage instanceof WebCPU_MemoryPage && mpage.data[0] instanceof WebCPU_Instruction_LB){
+                               if(mpage.data[0].opt == 1 || usedLabelNumberList.isIncluded(mpage.data[0].imm32)){
+                                       //使われている、もしくはグローバルなラベル番号
+                               } else{
+                                       //未参照のローカルラベル番号
+                                       //ひとまずラベル命令削除
+                                       mpage.data.splice(0, 1);
+                                       if(i != 0){
+                                               //一つ前のページに統合
+                                               this.mainMemory.root[i - 1].data = this.mainMemory.root[i - 1].data.concat(mpage.data);
+                                               //このページを削除
+                                               this.mainMemory.root.splice(i, 1);
+                                               i--;
+                                       }
+                               }
+                       }
+               }
+       },
+       staticOptimize_CMPxx_CND_PLIMM_PLIMM_LB: function(){
+               //From:
+               //>CMPxx(Ra, --, --);
+               //CND(Ra);
+               //>PLIMM(P3F, b);
+               //PLIMM(P3F, --);
+               //----
+               //LB(opt:--, b);
+               //
+               //To:
+               //>CMP!(xx)(Ra, --, --);
+               //CND(Ra);
+               //PLIMM(P3F, --);
+               //----
+               //LB(opt:--, b);
+               
+               //これより後にstaticOptimize_RemoveUnusedLabelNumberを実行することを推奨する。
+               //CMP系命令は、InstrIDが偶数の場合+1, 奇数の場合-1することで逆の条件になる。
+               //CMP系:20-2D
+               var mode = 0;
+               var rega;
+               var immb;
+               //0:次は CMPxx(Ra, --, --);
+               //1:次は CND(Ra);
+               //2:次は PLIMM(P3F, b);
+               //3:次は PLIMM(P3F, --);
+               //4:次は LB(opt:--, b);
+               for(var i = 0, iLen = this.mainMemory.root.length; i < iLen; i++){
+                       mpage = this.mainMemory.root[i];
+                       for(var j = 0, jLen = mpage.data.length; j < jLen; j++){
+                               instr = mpage.data[j];
+                               switch(mode){
+                                       case 0:
+                                               if(instr instanceof WebCPU_Instruction_TernaryOperation && 0x20 <= instr.instrID && instr.instrID <= 0x2D){
+                                                       //CMPxx(Ra, --, --);
+                                                       rega = instr.reg0;
+                                                       mode++;
+                                               }
+                                               break;
+                                       case 1:
+                                               if(instr instanceof WebCPU_Instruction_CND && instr.reg0R == rega){
+                                                       //CND(Ra);
+                                                       mode++;
+                                               } else{
+                                                       mode = 0;
+                                               }
+                                               break;
+                                       case 2:
+                                               if(instr instanceof WebCPU_Instruction_PLIMM && instr.reg0 == 0x3f){
+                                                       //PLIMM(P3F, b);
+                                                       immb = instr.imm32;
+                                                       mode++;
+                                               } else{
+                                                       mode = 0;
+                                               }
+                                               break;
+                                       case 3:
+                                               if(instr instanceof WebCPU_Instruction_PLIMM && instr.reg0 == 0x3f){
+                                                       //PLIMM(P3F, --);
+                                                       mode++;
+                                               } else{
+                                                       mode = 0;
+                                               }
+                                               break;
+                                       case 4:
+                                               if(instr instanceof WebCPU_Instruction_LB && instr.imm32 == immb){
+                                                       //LB(opt:--, b);
+                                                       //置換対象確定
+                                                       mpage = this.mainMemory.root[i - 1];
+                                                       //CMPxx(Ra, --, --); -> CMP!(xx)(Ra, --, --);
+                                                       instr = mpage.data[mpage.data.length - 4];
+                                                       if((instr.instrID & 0x01) == 0){
+                                                               instr.instrID++;
+                                                       } else{
+                                                               instr.instrID--;
+                                                       }
+                                                       instr.setParameter(instr.reg0, instr.reg1, instr.reg2);
+                                                       //Remove PLIMM(P3F, b);
+                                                       mpage.data.splice(mpage.data.length - 2, 1);
+                                               }
+                                               mode = 0;
+                                               break;
+                               }
+                       }
+               }
+       },
 }
 
 //数値計算