「10日くらいでできる!プログラミング言語自作入門」の続編#1-2

(1) HL-12

(前略)

unsigned char *ic, *icq; // ic[]:内部コード、icq:ic[]への書き込み用ポインタ. [この行は前からある]
unsigned char *dump0, *dump1; // codedumpのための変数(HL-12aから使います). [この行追加]
unsigned char *icq0, *icq1; // 最適化のための変数(HL-15から使います). [この行追加]
int jmps[10000], jp; // ジャンプ命令の場所を記憶しておくためのもの. [この行追加]

void putIc(int op, IntP p0, IntP p1, IntP p2, IntP p3) → HL-11と同じなので省略

int getHex(int c) → HL-11と同じなので省略

int get32(unsigned char *p) → HL-11と同じなので省略

void put32(unsigned char *p, int i) → HL-11と同じなので省略

void putIcX86_sub(String s, IntP a[])
{
    int i, j, k;
    for (i = 0; s[i] != 0; ) {
        if (s[i] == ' ' || s[i] == '\t' || s[i] == '_' || s[i] == ':' || s[i] == ';') {
            i++;
        } else if (getHex(s[i]) >= 0 && getHex(s[i + 1]) >= 0) { // 16進数2桁.
            (中略)
        } else if (s[i] == '%') {
            (中略)
            if (s[i + 2] == 'r') {	// relative.
                put32(icq, (int) a[j] - (int) (icq + 4));
                icq += 4;
            }
+           if (s[i + 2] == 'l') {	// label.
+               put32(icq, (int) a[j]);
+               jmps[jp] = icq - ic; // ジャンプ命令のラベル番号を書いた場所を記憶.
+               jp++;
+               icq += 4;
+           }
            i += 3;
        } else {
            printf("putIcX86: error: '%s'\n", s);
            exit(1);
        }
    }
}

void putIcX86(String s, IntP p0, IntP p1, IntP p2, IntP p3) → HL-11と同じなので省略

///////////////////////////////////////////////////////////////////////////////

(中略)

///////////////////////////////////////////////////////////////////////////////

void sub_print(int i)
{
    printf("%d\n", i);
}

clock_t t0; [この行追加]

void sub_time() [この関数追加]
{
    printf("time: %.3f[sec]\n", (clock() - t0) / (double) CLOCKS_PER_SEC);
}

///////////////////////////////////////////////////////////////////////////////

(中略)

///////////////////////////////////////////////////////////////////////////////

(中略)

int tmpLabelAlloc() → HL-8と同じなので省略

void defLabel(int i) [この関数追加]
{
    var[i] = icq - ic;
}

#define BInfSiz		10

int binf[BInfSiz * 100], bd, lbd; // binf:block-info, bd:block-depth, lbd:loop-block-depth

(中略)

///////////////////////////////////////////////////////////////////////////////

int compile(String s)
{
    int pc, pc1, i, j;
    unsigned char *icq1, *icp;
    pc1 = lexer(s, tc);
    tc[pc1++] = TcSemi;	// 末尾に「;」を付け忘れることが多いので、付けてあげる.
    tc[pc1] = tc[pc1 + 1] = tc[pc1 + 2] = tc[pc1 + 3] = TcDot;	// エラー表示用のために末尾にピリオドを登録しておく.
    icq = ic;
+   jp = 0;
    putIcX86("60; 83_ec_7c;", 0, 0, 0, 0); // PUSHAD(); SUB(ESP,124);
    (中略)
        } else if (phrCmp(10, "!!*0 = !!*1 + 1; if (!!*2 < !!*3) goto !!*4;", pc) && tc[wpc[0]] == tc[wpc[1]] && tc[wpc[0]] == tc[wpc[2]]) {
!           putIcX86("8b_%1m0; 40; 89_%1m0; 3b_%2m0; 0f_8c_%0l;", &var[tc[wpc[4]]], &var[tc[wpc[0]]], &var[tc[wpc[3]]], 0);
        (中略)
        } else if (phrCmp( 0, "!!*0:", pc)) {	// ラベル定義命令.
!           defLabel(tc[wpc[0]]); // ラベルに対応するicqを記録しておく.
        (中略)
!       } else if (phrCmpPutIcX86( 7, "time;", pc, 0, 0, sub_time, &e0)) {
    (中略)
    putIcX86("83_c4_7c; 61; c3;", 0, 0, 0, 0); // ADD(ESP,124); POPAD(); RET();
    icq1 = icq;
+   for (i = 0; i < jp; i++) { // ジャンプ命令の最適化.
+       icq = jmps[i] + ic; // icq=飛び先のラベル番号を書いておいた場所.
+       j = *(IntP) get32(icq); // ラベル番号を取得.
+       icp = j + ic; // icp=飛び先の命令列の先頭.
+       while (*icp == 0xe9) {  // 飛び先がジャンプ命令だったら、さらにその先を読む.
+           j = *(IntP) get32(icp + 1);
+           icp = j + ic;
+           put32(icq, j);	// 飛び先のラベル番号を上書きする.
+       }
+   }
+   for (i = 0; i < jp; i++) { // ジャンプ先の設定(相対値にする).
+       icq = jmps[i] + ic;
+       j = *(IntP) get32(icq); // ラベル番号を取得.
+       icp = j + ic; // icp=飛び先の命令列の先頭.
+       put32(icq, icp - (icq + 4));
+   }
    return icq1 - ic;
err:
    printf("syntax error : %s %s %s %s\n", ts[tc[pc]], ts[tc[pc + 1]], ts[tc[pc + 2]], ts[tc[pc + 3]]);
    return -1;
}

int run(String s)
{
    if (compile(s) < 0)
        return 1;
    void (*func)() = (void (*)()) ic;
+   t0 = clock();
    func();
    return 0;
}

(後略)

次回に続く

こめんと欄


コメントお名前NameLink

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS