From: hikarupsp Date: Sat, 25 Jan 2014 15:42:33 +0000 (+0900) Subject: elccコンパイラの最適化機能を向上。 X-Git-Url: http://git.osdn.jp/view?p=chnosproject%2FAI004.git;a=commitdiff_plain;h=4ef3a606f5f103f185a612fd65d236acc433fdb9 elccコンパイラの最適化機能を向上。 --- diff --git a/ai.js b/ai.js index 5cb6d73..8bf3e29 100644 --- 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(); } diff --git a/elcc/elcc.js b/elcc/elcc.js index a5c00e6..3bb66e1 100644 --- a/elcc/elcc.js +++ b/elcc/elcc.js @@ -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 = "ダウンロード"; + this.downloadBoxDOMObject.innerHTML = "右クリックしてダウンロード"; } else{ this.debug("BinarySaved: " + url + "\n"); } diff --git a/elcc/elccide.html b/elcc/elccide.html index c206b20..622dc27 100755 --- a/elcc/elccide.html +++ b/elcc/elccide.html @@ -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){

ELCC-IDE

-

mainWindow

+

MainWindow

-

Internal Information

- message
+

Message

+ -
+ +
+
+ +
+

Downloads

+

Code

@@ -197,7 +211,6 @@ procedure main() }
Drop SourceCode.elc here
-
\ No newline at end of file diff --git a/webcpu/webcpu.js b/webcpu/webcpu.js index e347883..f610284 100755 --- a/webcpu/webcpu.js +++ b/webcpu/webcpu.js @@ -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){ - //プログラム末尾のラベル命令は削除しないようにする + //プログラム末尾のラベル命令は削除しない。 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; + } + } + } + }, } //数値計算