view Changes @ 877:6955ee41688f

non parse mode struct initialization passed.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 02 Apr 2014 17:44:57 +0900
parents f93bf97bbd1f
children f915d5ba033e
line wrap: on
line source

Thu Nov 25 17:27:12 JST 1999

subroutine call がない
局所変数もない
その代わり、大域変数を多用する
大域変数のスコープは局所的
Fortran の用に局所変数は静的に取る
recursion する時には、自分で保存する
subroutine call時のレジスタのセーブも局所的に行う
それは、ちょっと変じゃない?
やっぱりデフォルトのフレームは持ち歩くか?

recursive call とそうでないのを区別するか? 

fp は用意する方が良い

関数定義と同時に、それ専用のfpの構造体を用意する

C をcompileする時には、stackを持ち歩く
    fp = (struct func_state *)stack 
えっと、どこに代入するの? そういう問題もあるわけね。
じゃあ、fpは特別? それは気に入らないな。static 
なfpにすれば良いわけね。

func(void *stack) {
    static struct func_state {
	static struct func_state *fp;
	int local1;
	brahbrah...
    } func_state;     // ここまで hidden
    func_state.fp = (stack -= sizeof(struct func_state));
}

func_state をとってくる演算子があった方が良い? そうね。
    func.state
ぐらい?

fp->local1 みたいなことだけするなら、C と同じになる。

call する時のargument も、
    static な func_state に置く
    stack 上の func_state に置く
という二通りの選択肢がある。Cと互換なら、当然、後者。

Recursive なら後者だが、この言語は状態遷移を記述するから、static
なものでも良いはず。

Internal function は? あってもいいんだけど...

Recursive call する時には、 fp をsaveする必要があるね。
    (--(struct func_state *)stack) = fp;
    call callee(&fp->arg,continuation,stack);
call しても、戻って来ないから... continuation は一般的にはcode
だから... それは Internal function にするか。

continuation に一般的にcompileする方法を考えないといけないか。
self は必要なわけね?

言語の名前も考えないといかんなぁ。

C からのコンパイラも書かないといけないのか...

Mon Dec 13 18:53:04 JST 1999

compiler based で、内部で partial evaluation できる?

func をdatabaseとして扱えないなら、それはできない。

しかし、状態遷移としては取り扱える。

    func.state
    func.code

みたいな形にしてpartial evaluationすれば良い

でも止まるのか?

textual でない、中間的なコード表現があった方が良い? <-> interpreter?

Prolog ではなんでいけないの? --> Unification が重いから

Sat Nov 27 13:50:41 JST 1999

func.state とか作るのだったら、
    struct {
	struct {
	    int i;
	} state;
	state *code = {
	    i = i+1;
	};
    } name;
みたいな形で、それ自体を構造化すれば? で、代入すると部分評価される。
代入も可能。なるほど。
	*name.code;
値はあるわけ? 値は &state でしょうね。
self があれば、
    struct {
	struct {
	    int i;
	} state,
	*code = {
	    self->i = self->i+1;
	};
    } name;
かな。self = state だよね。

union の拡張もあわせて議論すると...

Partial evaluator をセマンティクスや実行系にいれておくことは可能か?

byte code とか仮想マシンだったら可能。そうでない場合は?

いずれにせよ、構造体のタグのunique性を修正しないとだめだな。

ヘッダファイルはどうするの?

Mon Dec 13 18:53:18 JST 1999

library との整合性は?

exec sequence では、
    (--(struct func_state *)stack) = fp;
    call callee(&fp->arg);
という形でpointerだけ渡すの? それは変だよね。

値渡しにするとすれば、複数の値を渡せたほうが良い。

    func(void *stack) {
	static struct func_state {
	    static struct func_state *fp;
	    int local1;
	    brahbrah...
	} func_state;     // ここまで hidden
	func_state.fp = (stack -= sizeof(struct func_state));
    }

の引数自体が、構造体であるべき。

    func(
	struct void *stack
	) {
	static struct func_state {
	    static struct func_state *fp;
	    int local1;
	    brahbrah...
	} func_state;     // ここまで hidden
	func_state.fp = (stack -= sizeof(struct func_state));
    }

で、構造体に register storage を許す。

    func(
	static struct argument {
	    register void *stack;
	    register void *continuation;
	}
	) {
	static struct func_state {
	    static struct func_state *fp;
	    int local1;
	    brahbrah...
	} func_state;     // ここまで hidden
	func_state.fp = (stack -= sizeof(struct func_state));
    }

すると、caller の方も、構造体を引数とするのが自然。

    call caller(
	static struct argument {
	    register void *stack;
	    register void *continuation;
	} arg = {a,b};
    )

みたいな。もちろん、この構造体はインタフェースと呼ばれる。

argument は、callee にあった方が良いけど、caller 側にあっても
良い。register なんかは、そう。

	caller(interface caller_arg = {a,b,c})
みたいなsyntax かな。
	caller->interface = {a,b,c};
	*caller->code;
を、
	caller(a,b,c);
と称する。

function には、interface と code と state があることになる。

state にアクセスする時のlockは? protected state? synchronized state かな?
もちろん、sequential implementationでは、そんなものはいらない。

function {
    interface:
	register int a;
	register struct self self;
    state:
	int b;
	serialized int c;
    code:
	b  = a;
}

int にvoid value を定義する。実装は重くなるけど...

serialized の semantics は?

もう少しmicro-Cに近く! 

carrying state と static state。

Mon Dec 13 19:42:41 JST 1999

interface に register keyword を使うのは、あまりに
実装よりすぎる。でも、でないと状態にできない?
そんなことはないか。やっぱりcaller側のstatic 領域に
直接書き込む?

だとCより遅そう。でも、引数に40個とかかかれたら...

Wed Dec 15 14:09:49 JST 1999

C と互換にする?
	goto function(arguments);
	goto *continuation(arguments);
みたいな感じで。

stackの管理は? どうせ、library との互換はとらないと
いけないんだから...

local 変数がある場合は stack を動かす。でも、戻す奴がいない。
closure 化するか?

return した時の挙動が複雑になる。大域returnするわけだら。

arguments をstatic 領域にかきこむ方式だと互換性がとれない。
stack 上の frame pointer 上にないとダメだから。

両立させるのは無理か? つまり、これだと、呼び出された方の
frame semantics は、C と互換になる。だから、stackの直後に
frame pointer があると思っている (そうか? ) frame pointer
stack pointer に沿って移動した直後に、そこからのoffset
で引数を操作することになる。

つまり、それはだめだったことじゃない? つまり、goto だと、
frame pointer は、stack の直後とは限らないから。前の
frame pointer 相対に引数にアクセスしてくれれば別だけどね。

stack に引数を積むのは容認して、goto の場合は、向こう側で
stack を畳むってのは?  ということは、普通の関数と定義の
方法を変えるってことか。ま、悪くはないか。

すると、goto のsemantics は、C と互換になる。それを受ける
方が異なることをする。それは、なんかおかしいな。それに、
それだと関数呼び出しが軽くならない...

ということは、やはり、C のcall は、call function で
実現して、その他の呼び出しは、すべて、goto 扱いに
する方が正しいだろう。

問題は、この言語の関数をcallされた時だな。dual entry にして、
call の時と、goto の時を区別するか。
	func:	stack processing
	func_goto: normal processing
         ...
みたいな感じ。でも、return はないから...

このあたりも自分で記述できる言語であるべきだよね。その通り。
つまり、C とのstub も自分で記述すると言うことか。

protocol function {
    interface c {
	register "%esp" struct {
	    entry code ret(int);
	    void *fp;
	} *sp;
	register "%ebp" void *fp;
    };
    code function_code {
	fp = sp;
	sp += sizeof(struct local);
	struct local *local = sp;

	local->i = 1;
	goto *fp->ret(local->i),sp=fp;  // return(local->i);
    };
}

みたいな感じでさ。さっすが、アセンブラ。いまいちreturnが汚いけど。
まぁ、return はそのままreturnでもいいけどさ。

あ、これは良いかも知れない。code が複数かけるから。

state 以外は、consistent state であることを保証しない。ってのは?
local 変数は使っても良いけど、call/goto の前後で、値を保証しないか...

うーん、だんだん炸裂してるなぁ。

だから、レジスタに対するマッピングの記述と、そうでない部分の
記述は分離するべきでしょうね。


全部一辺に実装するわけにはいかないからぁ...

Thu Dec 16 13:44:21 JST 1999

lock は状態遷移レベルで実現するのだから、self などを
使ってlockする必要はないはず。

全体の直列化は、状態遷移レベルで、
	lock(storage) -> transition
みたいな形で記述すれば良い。この当たりを、どのように記述するかは
もう少し先送りしよう。


引数はレジスタ渡しにしよう。長い引数は、呼び出し側の領域への
ポインタとする。実装を規定しても良い。そうすれば、varargs
みたいなものはなくなる。だいたい、なんで、そんなものがいるんだろう?
配列を渡せばいいじゃん。

なので、引数は一つ(or 二つ)に限るという方法もある。

とすると、やはり、前もって静的領域や動的領域を確保することは
できない。

この言語では動的領域は自分で確保するわけだから、その点は問題ない。

Thu Dec 16 20:24:55 JST 1999

とすると関数呼び出しは、
	# register save
	# set 1st argument in register %eax
	# set 2nd argument in register %ecx
	# set extra arguments in save area
	# set extra argument pointer in %edx
	    jmp function
という形式になるわけね。second を処理するのはめんどくさいから一つ
にしよう。

えーと、frame pointer はないけど、コンパイルの手順からすると
あった方が良い。しかし、frame pointer そのものをstatic
にとるのはまずい。だから、frame pointer がfirst argument
ということにする方が正しい。とすると引数は、さらに、その
後と言うわけか。
	f(fp,argument)
fp を渡すのにさらにargument をレジスタで渡すのはおかしい。おかしいけど、
ま、良いか。

return しないなら、return type の定義をとるのは変だな。

f(fp,arg1,arg2,arg3) とすると、それぞれが決まったレジスタに入って、
多い分は配列にあると思われる。ふむふむ...
    fp->xx 
でアクセスすれば、そのまま局所変数になる。全部、配列で
送っても良い。

  .set label,value

で as は値をセットするようですね。

関数コールの後は戻って来ないから後始末の心配はしなくてよい。
frame pointer を使ったら自分で面倒を見ること。

だと
	a = atoi(s);
みたいなことはできない...

普通のCの定義と交じると間違いやすい。

とすると、struct と同様に、
	protocol
	code
	interface
	state
を用意するわけね。時間あるのかぁ?

とりあえず、register 渡しのfunction 定義とgoto文を実装する。

code name(register "%ebp" void *arg) {
    goto name(arg);
}
 
ぐらいかな? で、first argument が必ずregisterにのるようにしないと
いけない。register storage class を入れて、
    register "%ebp" void *arg
とかするわけね。

ってことは、まず、レジスタを実装しないといけないわけね。

で、stack を使った演算は、一応、そのままにする? それでも動くはず。
式の途中でgotoは使えないんだから、それでいいはず。

で、それから、これを拡張していく。

interface c {
    register "%ebp" void *arg;
}
code name(interface c) {
    goto name(c.arg);  // c. は省略可能
}

とかね。さらに、

protocol name {
    interface c {
	register "%ebp" void *arg;
    }
    code name(interface c) {
	goto name(arg);
    }
    code name1(interface c) {
	goto name(arg);
    }
}

などとするわけか。なんと、これが C と共存するわけね。うーん。

Fri Dec 31 11:44:03 JST 1999

code でなくて、別な名前のほうが良くない? segment? action?

レジスタ名が入るのは、やっぱりいや。optionalには許す。

interface は構造体のようなものだから... 構造体でいいんじゃない?
構造体の場合は... malloc する? う、うーん。malloc するとして、
いつfree するの?

再入するときには、壊れてていいんじゃない? multi-thread でなければね。
multi thread では、状態は、レジスタ経由または、thread local に持つ
必要がある。static は、だから thread local に持たなくてはならない。
大域変数に割り振っちゃだめ。でも、いまは、やめて

interface は、とりあえず、二つまでの値渡しにしよう。
	self と arg
ですね。

もう少し拡張しやすいコンパイラがいいなぁ。

    code name (c,a)
    struct state *c; struct arg *a;
    {
	goto name(arg);
    }

local 変数は? この互換性の問題かぁ。

KL/1 を意識して、interface は heap に置くことにしても良い。
GC は言語に入れておくべきだが、interfaceは machine independent
であるべき。だとすれば use/forget みたいものはいるだろう。
でも今のところは考える必要はない。

えーと、
    code name (c,a)
    struct state *c; struct arg *a;
    {
	int i;
	goto name(arg);
    }
の時の一時変数iはどうするの? 基本的にはレジスタ割り当てだけど...
使用させない? んー、大胆な御意見。まぁ、やっぱりheapに割り当てちゃう
のが簡単か。でも、どうせ抜ける時にはいらなくなるわけだから...

ほんらい、この変数は、次のcallでは必要無くなるのが普通。

とにかく、レジスタ変数は必要なんでしょう?

だから、GC と合わせて言語を設計すべきだよね。API を規定して、
異なるGCを選択できるようにする。

Sat Jan  1 22:40:22 JST 2000

とーにかく、 storage class register を実装しよう。

    stmode=REGISTER

で、local storage とおなじ扱いとする
	static register? は、ない。

symbol table に storage class をたせば? dsp==EXTRN で判定しているから、
local 変数が36以上あるとおかしくなるぞ?

sc  は GVAR/LVAR だけど、register は LVAR の特殊な奴だから、
sc に入れるほうが正しいか...

Sun Jan  2 01:47:17 JST 2000

register 変数はできました。けど、register を二つ使うと、
一杯になってしまうので、REGISTER6 でコンパイルしないと
結構ひどい。が、register 変数を%esi,%edi に割り当てれば
いいか。

Sun Jan  2 04:43:04 JST 2000

で、
    code name (c,a)
    struct state *c; struct arg *a;
    {
	goto name(c);
    }
の一時変数無しは実装できます。引数は二つまでね。

	.file "tmp.c"
	.version	"01.01"
gcc2_compiled.:
.text
# 
# code name(c,a)
	.align 2
.globl code
code:
	.type	code,@function
#    struct state *c; struct arg *a;
# {
#	goto name(c);
	movl %esi,%esi
	jmp	name
_5:
	.size	code,_5-code
	.ident "Micro-C compiled"

う、すごい。

goto 文がめんどくさい。stack をたたんで、jmp すれば
よいだけだが..

Sun Jan  2 11:17:50 JST 2000

普通のcallをcontinuation baseにすることができる?

Sun Jan  2 20:28:45 JST 2000

goto 文だけど、やはり、一度、expr で生成してから、top level
で jump code を生成しよう。

Tue Jan  4 03:32:55 JST 2000

code をtypeにしないと、
	code *p;
とか書けないね。
	int *p();
と同じだけどさ。


    main(ac,av)
    int ac;
    char *av[];
    {
	goto code1(ac,av);
    }

    code code1(ac,av)
    int ac;
    char *av[];
    {
	if (ac)
	    goto code1(ac,av);
	else
	    goto ac(ac,av);
    }

Tue Jan  4 04:56:56 JST 2000

うーん、なんかレジスタにつむ順序が違う
これは、adecl がreverseにつむから。

code のreturn

やはりcodeはtypeにしないとだめ。

main()
{
    goto code1();
}

とかだと、main に戻って来れない。もちろん、code1() 以降で、
return するわけにはいかない。(main の disp をcode1 は知り得ない)
goto label をcode1の引数に送れば?

main()
{
    goto code1(ret);
ret:
}

これだと、ret がforward labelかどうか分からないけど?

code1 中で使う中間変数を stack 上にとるのは悪くない。しかし、それを
%ebp 経由でアクセスするということは、main の中間変数を壊すということ。
それを防ぐには、main 中のgoto codeで、%ebp を修正してやれば良い。
(今は戻って来ないので問題ない)

code1 のgoto では、戻って来ないから、その必要はない。しかし、
label をcode1 中で渡されると、ちょっと気まずい。

とすると、それは禁止して、main() 中でstackをたたんでからgotoするか?
そうすると、無限後退して、結局、帰れないことになる... うーん。

main() 中のlocal code を許せば、それは解決するが..

main()
{
    goto code1(code2);
    code code2() {
	return;
    }
}

みたいな感じ。でも、そうするとscope rule を変える必要があるので厳しい。
ま、悪くはないけどね。

continuation を明示する方法もある。

main()
{
    goto code1(continuation);
}
code code1(ret) 
code (*ret)();
{
    goto *ret;
}

かな? call/cc ?

label へのgotoを許すのもいいけど、
でも、label を許すと、すごくspaghettiにならない?


Tue Jan  4 11:47:24 JST 2000

continuation じゃなくて、return keyword を使おう。
(実際、continuation と少し違うし)
type が少し変になるけど、まあ良い。

int
main()
{
    goto code1(return);
}
code code1(ret) 
code (*ret)(int);
{
    goto *ret(3);
}

だな。prototype も付けないといけないか。

Tue Jan  4 12:21:44 JST 2000

これだとmethodがすべてstatic になってしまう。dynamic なmethod
呼び出しにするには? dispatcher を自分で作ることになる。かなり
めんどくさいが...

code method(obj,arg)
{
}

か、あるいは、inline にするか... #define のかわりに inline ねぇ。
これはあとで考えて良い。

Tue Jan  4 14:22:19 JST 2000

main の変数を書き潰すのと、goto (*reg)(123) での値は、
register 渡しで、current register にのらないので、
結局、return label は専用に作る必要がある。

Tue Jan  4 18:14:07 JST 2000

stack を継ぎ足して、呼び出す方式を取れば、call by value
のregister 渡しを制限する必要は無くなる。

複数の値を返すことも容易だ。

	.file "tmp.c"
	.version	"01.01"
gcc2_compiled.:
.text
# 
# code name(a,b,c,d,e,f)
	.align 2
.globl code
code:
	.type	code,@function
#    struct arg *a,*b,*c,*d,*e,*f;
# {
#	int g;
#	goto name(a,b,d,e,f);
	jmp	name
_5:
	.size	code,_5-code
	.ident "Micro-C compiled"

おお?!
	%esp  new %esp = old %esp - 12 -4
	%ebp-4     = g
        %esi       = a
        %edi       = b
        %ebp = old %esp   0
        %ebp+4     = c       code_arg_offset=0
        %ebp+8     = d
        %ebp+12    = e
        %ebp+16    = f

interface は付けよう! というか、
	goto name(struct {xxxx})
みたいな感じで良いわけね。どれをregisterにいれるかと言う問題はあるが。

で、どうやってcallすればいいわけ? emit_pushするかわりにpush
する?

うう、これでは、だめか。code argument の数が変わると、
ebp をいちいち動かすことになる。そこにはold sp があるから
そいつもコピーする必要がある。

	%esp  new %esp = old %esp - 20
	%ebp-20   = g
        %esi      = a
        %edi      = b
        %ebp-16   = c code_arg_offset= -16 ((nargs-max_reg)*int_size)
        %ebp-12   = d
        %ebp-8    = e
        %ebp-4    = f
        %ebp = old %esp   0

そうか、function からcallする時には、local 変数を書き潰して良い。

#	goto name(a,b,d,e,f);

	%esp  new %esp = old %esp - 20
	%ebp-20   = g
        %esi      = a
        %edi      = b
        %ebp-16   = c code_arg_offset= -16 ((nargs-max_reg)*int_size)
        %ebp-12   = d
        %ebp-8    = e
        %ebp-4    = f
        %ebp = old %esp   0      disp=0 (*)
         local1 <----16 local variable      
        %edx        -12   <- disp_offset
        %ecx         -8
        %ebx         -4
        %ebp = %esp   0
        %eip          4   <- arg_offset

となる。ということは、pushl %ebp は、間違い。

だけど、%ebp をそのまま使うのは良くない。disp_offset がかかっているから。
だから、もう一度 pushl %ebp したほうがよい。しかし、push する先は、
上の、(*)。
	leave           movl %ebp,%esp
			popl %ebp
じゃなかったか?

Thu Jan  6 13:00:33 JST 2000

できたね。これでとりあえず動くはず。速度は問題だが...
あとは、
	ANSI-C prototype
	ANSI-C prototype check
	Interface Definition
	GC support
	Direct handling of Frame
だね。簡単に出来そう? たぶん...

Fri Jan  7 09:42:53 JST 2000

goto 文が動いてなかった。あと peep hole optimization version も
作るか?

continuation として label を送れるようにするべきか?
そうすると便利なんだけど、ちょっと、汚いプログラムが
出来るようになる。あと、送り側の環境(frame)を維持する
必要がある。ま、できなくはないか...

そうすると、label が値を持つようになる。
	a = label:;
とか。うーん。label:(a,b,c) {}; みたいな形で、parallel 代入を許すと言う
手もあるね。

こちらの方がCとの相性は良いが... main() { label:(){ ... } }
みたいなnestを許すかどうかと言う問題がある。
変数の参照を許さなければ、特に問題はない。

a = label: は、二重の意味があるなぁ。

言語の名前。DinnerBell II とか? join も入れる?
	code entry_a().entry_b() {}
ですか? parallel call も?

Fri Jan  7 19:53:53 JST 2000

いまのままだと return が環境を持ってないから、大域脱出できない。
まぁ、環境を入れてもいいんだけど、どこに置くかと言う問題が
あるね。

そうじゃなくて、return 側で判断するか? 
	return(ID)
みたいな形でIDで判断する。そうすれば、return 側でID
を見て判断できる。けど...

まぁ、はやり、環境を持って歩く方がいいかなぁ。でも、
引き渡しているから、二つ引き渡して、片方を使われたときに、
反対側が消えてしまうのはいたいよね。今のままならば、
そういうことは起こらない。

continuation 特有の問題を避けるなら、このままでもいいんだが...
continuation や環境は、このシステムでは自分で作ることが
できるからね。

そうなんだけど.... retlabel や retcont は実はオブジェクト
全体に一つあれば良い。

引数を渡すときに、そこに環境へのポインタをいれてやれば良いので、
解決は割と簡単だが、そうすると、例の構造体を引数で渡すと言う
問題を解決する必要がある。

でも、今の実装ならば、まったく同じ変数の構成ならばコピーは
実際には起こらないわけだから問題ないはず。特に、それを保証するために、
interface を実装する必要がある。

return ->
	(void *)old bp
	return address

bp を直接操作できるようにするといいんだけど.... 

Sat Jan  8 08:49:59 JST 2000

今は、code 内ではreturnできないわけだけど。実は、return って、
	code return0(i) int i; { return(i); }
か? 今は禁止してないから書けちゃうよね。どういうcodeが出るんだろう?

doreturn() では retpending をセットしているだけだから、control=1
のまま。で、code の終りにくるのでエラーになる。checkret は、
statement の引数で判断するようにしたほうが合理的だろう。

大域脱出は結構根が深いよね。途中をスキップされてうれしいか?
destructor と同じで、途中のcodeは全部呼びたいのが普通だろう。

bp が同じになるまで return すれば良いわけだよね。
return と同じで、明示的に環境を引き渡すようにするか。
type は void * で良い?

return する時にstackの上限を越えているかどうかを自分でチェックする
必要があるね。誰にreturnするかをcodeで明示すれば良いわけだけど。

	code return0(i) int i; { return(i); }

を許して、そこで、frame pointer を大域あるいは渡した引数と
比較して処理する?
	code return0(i,env) int i; env *env; { 
		if (env==self) return(i); 
	}
あれ? これはおかしいよね。
	code return0(i,env) int i; env *env; { 
		if (env!=self) {
		    env->return();
		    return(i); 
		}
	}
も、なんか変だよなぁ。呼び出しと逆順に帰りたいわけだが...
実際、逆順には帰っているわけだよね。

return の中でこそこそ比較するという技もあるけど。

問題は、destructor に渡す情報だよね。もちろん、self で良いわけだが、
このあたりは、言語外の問題で、それを明示的にしたいから、この言語を
作っているわけなのだから、これを内部で処理するのはおかしい。

	code return0(i) int i; { return(i); }

これだと、return の型が合わないと言う問題が生じるな。簡単には
チェックできない。
	int
	main() {
	    code a() {
	    }
	    code b() {
		return(i);
	    }
	}
にすれば、check はできるようになる。でも、これだと、
	int
	main() {
	    a: {
	    }
	    b: {
		return(i);
	    }
	}
と差がない。module 化を言語外でやるというのが主旨なのだから、これでは
まずい。これは高級アセンブラなのだから。

あそうか、return と、大域脱出時のabortとは、状況が違う。だから、
別なcode を呼び出さないとだめ。あるいは、値で区別するか。これは、
logic programming のfail/success と似ている。
	main() { } abort { ... }
でもいいけど?
	main() {  code abort { ... }; code return { ... }}
かな?

本来、subroutine call自体が、かなりの省略形なわけだから、これは
仕方がない。今のままで通常のsubroutine callをシミュレートできるのか?
	code (struct arg {...},void *sp) {
	    struct env;
	    push(sp,arg);
	    push(env,arg);
	}
できるけど、ちょっと重い。やはり、frame pointer を直接操作しないと
だめ。

goto 文のほうに、env を一緒に送るものを作ったほうがいいのかも。
	goto (*ret)(),environment;
かな。type は? (void *)?
	goto ret(),environment;
にはならないの? そうすれば、自分でthreadを制御できる。environment
の正当性を評価しなくて良いの? まぁ、ねぇ。

これは実装は容易だが... goto といちいち書くのが本当にいいのか?
env に対するoperationがあった方がいいなぁ。push とか?

	code return0(i) int i; { return(i); }

を認めれば、return 擬変数はいらなくなる。

でも、実は、return は、caller の引数の数と一致してないといけない
わけだから、 code return0(i) int i; { return(i); } はだめ。env
と一致してないといけない。ということは分離するとまずいんじゃない?
あれ? そんなはずないな。

Sun Jan  9 01:15:56 JST 2000

やはり、分離してはまずい。もともと、
	goto func(arg);
自体が、
	goto func(arg) with current.env
みたいなものだ。つまり、これは、DinnerBell の、
	self message: arg
と同じ。self->func(arg); でも良い。が、function callと区別が付かないのは
良くない。

そうすると、type code はsize int でなくなる。
	code *p = func;
ではいけなくて、
	code p = {func,env};
でないといけない。実際、
	goto func(arg)
では、current environment を pushl %ebp でstack = current env
に積んでいるわけだから。

いずれにせよ、
	struct p = q;
は実装する必要がある。localな、
	code p = {func,env};
も動くはずだが...

	code (*p)();
	goto (*p)(arg);

はだから少しおかしい。これは、goto がenv を補っていると考えるべき。

このようにすると、常に、
	func,env
の組をcodeとみなすことになる。これは、object と呼ぶべきだ。
ただ、既存のobjectとは別だよな。actor の方が良い?

うーん、これでjoinを入れれば、完璧なDinnerBellだな。並列送信はないけど。

Sun Jan  9 01:40:05 JST 2000

local 変数の初期化はallocation の後に遅らせる必要がある。
nptr に入れられるはずだよね? nptr に初期化フラグを足すか?

文途中で出現するlocal変数の初期化。ちゃんと動いているの?

構造体のcopyは、lcheck を修正すべきでない。

Sun Jan  9 08:49:43 JST 2000

うーん、なんか修正が多いなぁ。あと、関数呼び出し、goto 文の
構造体への対応か。

	goto (*code)();

が、self env を使うのか、code の先の値を使うのかを区別する
必要がある。もし*を使わないとするとlabel(FNAME)との区別が
つかないぞ。あ、でも、環境を持ち歩くことにしたから、label
へもjumpしようと思えばできるね。

並列送信はなくても、この構成ならばstatement単位の並列性を検出するのは
容易だろう。

やればできるけど、この修正の量だと1日じゃ終らないかなぁ。
浮動小数点も入れるのでしょう?

Mon Jan 10 09:00:12 JST 2000

引数に構造体を許すには、必ずANSI-Cにする必要がある。難しくは
ないが...

goto 文には label, code, continuation の3つが来る。
	continuation = code + env
			| label +env
なのだが、code/label では、env の内容が異なる。できれば面白いが、
その価値はあるのか?

しかし、code , env を分離するとあまりに危険すぎる。どうせgoto
が危険なんだからいいか? その方が簡単。簡単なら、そっちの方法を
とるべきじゃない? うーん。

return の関数依存性はなくした方が良い。
一つにするのは、pop の問題があるので良くないが...

そうか、ret をenvを指定して戻るようにしたから、leave する必要は
なくなった。そして、push %ebp に相当する部分は、lea -disp(%ebp),%sp
で消去されている。ということは、jump のfunction依存部分はいらない
ということだね。

でも、汚いなぁ。read only属性をhardware supportできればなあ。

sched_yields() 相当を書けるかな? lock は?

一応、できたけど、やっぱり汚い。

Wed Jan 12 16:12:27 JST 2000

あは。ANSI prototype はめんどい。
	bexpr()
で、関数での引数の順序と、そのあとの宣言の順序が変わることがある。
そうすると、うしろの方が優先されてしまう。これは、こまる。

そうか、code_arg_offset のような方法だと、ANSI style では、
困ってしまう。

Thu Jan 13 04:46:12 JST 2000

#       goto name(a,b,d,e,f);
        code name { int g; ...

        %esp  new %esp = old %esp - 20
        %ebp-20   = g code's local variable
        %ebp-12   = f <- new_disp
        %ebp-8    = d
        %ebp-4    = d
        %ebp-0    = c
        %edi      = b
        %esi      = a
        %ebp = old %esp   0      disp=0 new env
         local1 <----16 old local variable       ( to be erased )
        %edx        -12   <- disp_offset
        %ecx         -8
        %ebx         -4
        %ebp = %esp   0   <- old env
        %eip          4   <- arg_offset


Thu Jan 13 13:38:24 JST 2000

だいたいできたけど、test/tmp7.c のprintf のtype mismatch は
なんなんだろう?  ANSI の副作用だろうなぁ。

これだと、プロセスの切替えのときには、結構な量のデータを
コピーすることになる。それでもいいんだけど...

それごと、どっかにとって置く。continuationへの参照みたいなもの
ができないかな。

コピーができれば、environment/return の組は動くわけだから、
それへの参照と切替えがあっても良いよね。

Fri Jan 14 12:03:35 JST 2000

Libretto のkeyboardが壊れた... control key が効かない...

printf の参照の問題は解決しました。list2 がlocalなheap
に割り当てているのがいけなかったね。

return の処理は、goto 文で処理するより、environment に
returnto する方が良くはないか?

environment は実は送り先でそれなりの準備が必要。
new-environment() みたいなlibrary があれば、thread にできる。

join は?

funcall を用意すると良いね。

Mon Jan 17 15:23:34 JST 2000

    struct aa f1() {
	return bb;
    }

みたいなのは? 関数の型か代入の型を見て、crn にpointerを渡して、
あとでcopyしてから stack を畳む。

    # 	bb=f1(aaa);
	    movl $bb,%eax
	    pushl %eax
	    movl $aaa,%eax
	    pushl %eax
	    call	main2
	    popl %edx
	    copy %eax,%edx,$400
	    addl $400,%esp
    #     return a1;

あ、でも、それだと、local変数を返したときに困るね。leave; ret;
してはいけなくて...

あ、やっぱり、こういう場合はコピー先をmain2に引き渡しているみたいね。
    void f1(struct aa *ret) {
	*ret = bb ;
	return;
    }
と同じか。これは簡単。
	f1().a[55]
みたいな場合は、局所変数に強制的に取ってしまうみたいね。それはそうだ...
が、うちの実装だとちょっと厳しいか。
	leal $-sizeof(struct),%esp
	pushl %esp
なんだけど、関数呼び出しの途中ではできないから....

    # main(ac,av)
    # int ac;
	    .align 2
    .globl main
    main:
	    .type	main,@function
	    pushl %ebp
	    movl %esp,%ebp
	    pushl %ebx
	    pushl %ecx
	    pushl %edx
    # char *av[];
    # {
    #     register int i;
    #     register char *p;
    #     int j = 3;
    #     struct { int b; void (*c)(struct aa); } q = {3,main1},r;
    # 
    #     j = 3;
	    subl $20,%esp

このsublを後から指定してやればOk。

でも、それだと jump の時にずれない? ずれるか? ずれるね。うーん。
実行時にチェックしてやるのも変だし。

まぁ、それほど必要な機能ではないんだけど。

これもcontinuationを渡してやると言う手法が使えないことはないんだが...

関数呼び出しの最初にやってやればいいか。それでできるかな?


Sun Feb 20 23:59:16 JST 2000

MIPS のcall frame

	$sp = $fp 
			local variables
        		saved register (including $31 = return address)

mask  は使用したレジスタのbit pattern
 -4 は何?

  18                            .mask   0xc0000000,-4
  19                            .fmask  0x00000000,0
  20 0000 D0FFBD27              subu    $sp,$sp,48
  21 0004 2C00BFAF              sw      $31,44($sp)
  22 0008 2800BEAF              sw      $fp,40($sp)
  23 000c 0000000C              move    $fp,$sp
  24 0010 21F0A003              jal     __main
  25 0014 03000224              li      $2,0x00000003           # 3
  26 0018 000082AF              sw      $2,a
  27 001c 04000224              li      $2,0x00000004           # 4
  28 0020 00C082AF              sw      $2,b
  29 0024 05000224              li      $2,0x00000005           # 5
  30 0028 000082A3              sb      $2,c
  31 002c 06000224              li      $2,0x00000006           # 6
  32 0030 08C082A3              sb      $2,d
  33                    $L1:
  34 0034 21E8C003              move    $sp,$fp                 # sp not trusted
 here
  35 0038 2C00BF8F              lw      $31,44($sp)
  36 003c 2800BE8F              lw      $fp,40($sp)
  37 0040 0800E003              addu    $sp,$sp,48
  38 0044 3000BD27              j       $31
  39                            .end    main

これと同じようにするならば、registerの使用数を最初に調べる必要が
あるのだけど、one path compiler である micro-C では、それは
できない。したがって、enter は後ろでする方が良い。

Mon Jan 20 18:25:27 JST 2003

3年間さわってないのかよ。何やってんだ?

goto 文のバグをとらないといけない。

まず、関数引数の構造体の展開。これは、どうってことないはず。

   goto (*code)(i+1,j,...)

まず、いじらなくてすむ変数を摘出する。

   foreach arg 
      compare

単純演算 ( op+const , pointer , const assign ) などは、ここで検出する。
大半は、そのようになるはず。
レジスタに乗せる分があるから... それには触らないとして...

複雑なものは、前もって計算しておく。(get_register する)
スタック上かレジスタ上に作る。

残りは並列代入となる。再帰的に計算する。

えーと、大きな順にやるんだっけ? 小さな順にやるんだっけ?
    code f( int a, int b, int c ) {
        goto g(b,c,a);
    }
みたいなやつだよね。

    移動するものを一つ検出する。
    そのために移動が必要なものを移動しておく(再帰)
    代入する

こんなんでいいのか? ループしない? するよね。ループしたら
get_register する。

前の例だと、

    g(b,c,a) のbに着目する。
    bに代入するコードを出すと、a が壊れる。
    a が必要かどうかを調べる。それは、引数のリストを見ればわかる。
    その前に、a を移動する。a の移動先を見て、
       空いていれば、移動してOk。しかし、c 
    なので、 c を見る。と b になるので、ループするのがわかるので、
    b を get_register する。
    で、c が移動できる。で、aを移動して、とっておいたbを代入。

Tue Jan 21 22:45:09 JST 2003

とりあえず、jump は複雑すぎる。もっと簡単にすることを考える。
parser 側である程度処理できない?

     goto f(a+3,b(),c);

などを、

     a = a+3;
     b = b();
     goto f(a,b,c);

程度に簡略化する。この時、f(a,b,c) は(できるだけ)、元の
関数の引数リストに近付ける。のは無理なので、単純変数
まで落す。

あまり関係ないか。一時変数はどうせいるわけだし。ってこと
みたいね。

だとすると、元のコードと、そう変わらんね。前のも、そんなに
悪くないってことか。

Wed Jan 22 14:33:12 JST 2003

やっぱり、途中で局所変数を増やしたいよね。

Fri Jan 31 20:30:36 JST 2003

なんか #ifdef / #if がないとだめだな。実装する?
しました。

Tue Feb  4 01:04:12 JST 2003

##      while ((*chptr++ = c = getc(filep->fcb)) != '\n') { 
_1120:
        movl $10,%eax
        movl $8,%ecx
        movl filep,%edx
        addl %ecx,%edx
        movl (%edx),%edx
        pushl %edx
        xchg %edx,%eax     .... edx に$10が入る (なんでxchg?)
        call    getc
        addl $4,%esp
        movl %eax,-20(%ebp)  c に代入
        movl $chptr,%ecx
        pushl %ecx
        popl %ebx
        movl (%ebx),%ecx      ecx にchptrの中身
        addl $1,(%ebx)
        movb %al,(%ecx)
        subl %edx,%eax         eax-edx ($10)
        je      _1119

が壊れる理由なんだけど...

edx,ecx が破壊されちゃうみたいね。

Tue Feb  4 12:17:07 JST 2003

ようやっと直したよ...

use_pointer って、なにもしなくていいんだよね? eax,ebx を避ける
ってことらしいけど。

inline/引数付き #define 欲しくない? 置き換えは、local name stack に積んじゃう。
展開は function  で行う。

getch を工夫する必要はあるが。置き換えスタックが必要。


Wed Feb  5 01:16:00 JST 2003

大域で定義された struct field が大域変数と重なっていると落ちる。
そりゃそうだけど。どうするの? (直した記憶があるんだけどなぁ...)
struct 毎に field 名とoffset/type の組を持てばい良いんだよね。

なんだけど、タグ無しの構造体もあるから、型名の方に付ける必要
もある。というのは、型名のない構造体もあるから。タグ名には、
一応、リストがついている。なんかに使う必要があったんでしょう
ね。あ、めんどう。無条件にやっても大域変数名を汚すのを直すの
が難しい。

ちょっと、あれだけど、「型名.フィールド名」で登録してしまうのはどう?
型名が後で出て来るところが気まずいが...

def で登録するときに、nptrにdispを代入せずに、struct field list
(大域変数) に入れて、type の方に、field list (list3(nptr,offset,
type)) を入れれば良い。

あとは、strop の方でtypeのlistを見るようにすれば良いわけだ。

これなら、簡単に直せるはず。LUSTR/GUSTRなどの区別もなくなるし。

Wed Feb  5 02:10:14 JST 2003

浮動小数点ねぇ。完全なANSI Cにするのは大変。でも、
浮動小数点ぐらいないと。

code generation part を、さらに分割して、
複数のコード対応にしやすいようにする。
おそらく、それほど共有する部分はないけどね。

Sample C code をコンパイルして、その結果から(半分手動で)
Micro CbC code generation part を生成する方法を用意する。



Thu Feb  6 11:47:03 JST 2003

Code Segment を単位として使うときに、大域変数はどういう
ように分けるの? static なんかは意味ないよね。

もちろん、自然にグループ分けされるわけだけど。

あとデータフローだよね。データフローに関しては、
あんまりやってないなぁ

Fri Feb  7 14:36:15 JST 2003

inline では、必らず、局所変数の増加がある。また、inline
は普通の関数として展開しておく必要もあるらしい。(何故?)

#define ねぇ。

   #define c(a,b)  g(a+1,b+1)
   #define g(a,b)  printf("%d %d\n",a+1,b+1);

   main() {
       int a,b;
       a =1; b = 3;
       c(a,b);
   }

local #define がいるんだよね。g の中で a が出て来た時には、
c のa の置き換えは起こってはいけない。ということは、c
の置き換えはg が始まる前に終っている必要がある。dynamic
scope なんだから、assoc の上乗せで良いはず。
macro のlevelを定義して、あるレベルでは、それ以前の展開
を行わないという手法が良いかな。

   c(a,b) =>  a=>"a+1", b=>"b+1"
   g(a,b) =>  (a=>"a+1+1",a=>"a+1"), (b=>"b+1+1",a=>"a+1")

みたいな感じ?

やっぱり関数解析でマクロ処理をやらせるのは無理かな? 先読みされちゃうし。

Sat Feb  8 00:53:52 JST 2003

macro は途中まで書きました。置き換えをマクロが呼び出された
時点で cheap に置くと、それを解消するタイミングがない。
ここだけmallocしても良いが..

chptrsave はlistにする必要がある。list で良い。

やっぱりmacro levelを見て、自分と一致したassoc valueまで
手繰って置換するんでしょう。そうすれば、置き換える必要は無い。
ということは、local_define にmflagsを格納する必要がある。

   c(a,b) =>  a=>"a", b=>"b"
        a=>"a" .. mflag == 1
   g(a,b) =>  (a=>"a+1+1",a=>"a+1"), (b=>"b+1+1",a=>"a+1")
        a=>"a+1" .. mflag == 2
        
macro のもとのnptr が残ってないと、オリジナルを返せない。オ
リジナルは、sc などが破壊されてしまう。ってことは、local macro
は、local table を汚してはいけないってことだよね。ってことは、
macro table は、もとのとは別に用意する必要がある。

#define c(a,b)  g(a+1,b+1)
#define g(a,b)  printf("%d %d\n",a+2,b+2);

main() {
   int a,b;                  a ... local
   a =1; b = 3;
#ifndef a
   c(a,                 a = "a".. macro mflag==1
                        g(a,
                               a="a+1"  mflag==2
                                  ^  a = "a" mflag==1
                        While replacing a in g's body, a should not
                           be replaced to  (original) "a", should be c's a.
      b);                
   /* 3,5 expected */
#endif
}

うーむ。ややこしい。

    main() 
	c(a,b)    mflag++
                         a=>"a" mflag ==1
           g(a,b) mflag++;
                         a=>"a+1" mflag ==2
                             ^ is replaced by c's "a" not g's a;
いったん mflag level n で展開したら、それは mflag level n-1 となる。

Sat Feb  8 18:13:43 JST 2003

いちおう、mflag まではデバッグしたが....  mflag を戻してないんじゃないの?

     ---c(a,b)-----------------------  mflag ==1
          a=>hoge, b=>hoga (mflag==1)
        ----g(ac,bc)-----------------  mflag ==2
              ac=>goge, bc=>goga(mflag==2)
            ----printf(a,b)----------  mflag ==3
                a=>poge, b=>poga(mflag==3)

g が呼び出されると、ac,bc は mflag==1 でのみ置換される。

あるテキストを置き換えると、それは置き換えたマクロのmflag level
(つまり一つ少ないレベル)になる。
置き換え終ったら、元のlevelに戻す。

mflag==2のlevel では、mflag==2のlocal macroの展開しかしない。

置き換えると、mflag level 1 になるので、そこで mflag==1 のlocal
macro を展開する。mflag==0 は常に展開を行う。

Sun Feb  9 11:35:23 JST 2003

うーん、なんかtypeが、list とCHARなどと入混じっているじゃん。
    int save = chptrsave;
で、chptrsave が、$chptrsave になってしまう。

Sun Feb  9 22:33:36 JST 2003


#define car(e) (heap[(int)(e)])
#define cadr(e) (heap[((int)(e))+1])
    car(cadr(e))

だろ。
    car ->  
       #define e cadr(e) (mleve=1)
    cadr ->  
       #define e e (mleve=2)

むぅ。これ、うまくいかないんじゃん。こまったなぁ。

#define c(a,b)  g(a+1,b+1)
#define g(a,b)  printf("%d %d\n",a+1,b+1);
   c(a, b);

こっちもだめじゃん。ふーむ。lisp interpreter のように
作ればいいはずなんだけど。

Mon Feb 10 08:10:25 JST 2003

結局、list base のinterpreter を実装しました。きちゃないが。
前の方法でも、頑張ればできるんでしょうけどね。

Tue Feb 11 13:50:03 JST 2003

struct copy だけど... 関数がstructを返すときに、引数に前もって
積んでおくのでは、そこに値がコピーされてしまうし、あとで、
スタックをたたんで置くときにきまずい。

function call の時に、引数の型のチェックをしてない

type に -1 とheapの引数が混在しているやつだけど..
やっぱまずいんじゃないか?

temporal struct は再利用できるんだけど、dispの変更ができないので
新しく作るしかない。大きいときだけ新しく作るなんていうセコイ
技はあるけど。(そうすると、帰って来た値へのポインタを使えなく
なるが.... 別にいいよね。戻り値それ自身を直接 return する
時もだいじょうぶなはず)

結局、呼出側で、領域を確保して引き渡すことにしました。この方法だと、
代入のときに二度コピーする必要もない。

register  を使用しているかだけじゃなくて、実際にcreg/dregに
値があるかどうかを記憶する必要がある。

Wed Feb 12 11:09:22 JST 2003

それだけどさ... やっぱりアドホックに実現するのは難しいんじゃないの?

まぁねぇ。register の場所の確保と、寿命は別だから、それで
いいんだけど、regs flag だけでなんとかならないのかな。
こういう変更ははまるが虚しい。

Thu Feb 13 18:37:36 JST 2003

さて、そろそろ jump  にとりかかりますか。

構造体の引き渡しのシークエンスに使う局所変数の位置がgccと違う...

そろそろ register は構造体にすべきだね。
    struct register {
        int used;
        int valued;
        char *name;
        char *wname;
        char *bname;
        int type; /* register variable or not */
        int number;
    }
virtual/real は、どうする。

Sat Feb 15 14:00:03 JST 2003

fdecl_struct を構文的に引数が出現するときに行うと、int *f(int
a) などで、* の評価が終る前に、int aが評価されしまう。*obj 
のobj を評価し終らないとfのタイプが確定しない。int*f()[] み
たいな場合があるから。(?) なので、gcc と、そろえるためには、
arg の先頭で fdecl_struct を行う方法ではだめで、fdecl 中であ
とから修正する方が良い。

fix しようにも引数リストなんて、存在しないじゃん!

varargs を実装するのはめんどくさかろう...

rvalue(expr(),type) では、expr() のtypeをrvalueに引き渡せな
い。でも、type を大域変数にすると、rvalueを異なるタイプで呼
び出すときにtypeを変更する必要がある。このrvalueのtype の扱
いは、かなりはまったことがあるので、rvalue(int e,int type)の
方が良いことは確かなんだが... 

struct_push のregisterの扱いが複雑すぎ。なんか、もっと
簡単にならないの?

Sun Feb 16 07:58:23 JST 2003

代入しなくて良いからと言って、ソース
のリストから除いては、上書きを防げない。

Sun Feb 16 22:55:58 JST 2003

vdisp ってなんだったんだ?

Mon Feb 17 12:35:39 JST 2003

並列代入は出来たみたい。代入は小さいものを先にすべきなのか?
まぁ、できりゃいいんだけど、横に避けるものが大きいのはいや
だよね。

Tue Feb 18 11:56:10 JST 2003

overlapped 用の emit_copy
float/double
long long

Tue Feb 18 19:34:31 JST 2003

code argument の符号を反転させると、list2(LVAR,offset)
のoffsetがアドレスの方向と一致しているという前提が
崩れる。それで、構造体の格納順序がずれてしまう...

ということは... def(n) でcodeの時はargumentは、局所変数と同じ
扱いでマイナス符号で処理した方が良い。

できたみたい。でもさ、
   
int main( int ac, char *av[])
{
    int n;
    goto arg1(0,1,2,3,4,return,environment);
}

って、きっと return 文がないと、文句を
言われるよね。むむむ。

post processing する時にoverlapしてないという保証がない。

Wed Feb 19 15:38:55 JST 2003

自分自身とのoverlapを見てないので、
    struct a a,int i
    int i,struct a a
みたいな時に自分自身を壊してしまう。なので、emit_copy
が、ちゃんと方向を見て壊さないように処理する必要がある。

call bcopy でいいじゃん。まね。

Wed Feb 19 20:42:07 JST 2003

楊さんの C2CbC と CbC2C を、micro C に取り込む。各所に、
conv->func(); を埋め込む。conv は、構造体。

    conv:   original
            c2cbc
            cbc2c

とする。なるほど。

Thu Feb 20 05:34:58 JST 2003

むぅ。code-ia32 で結構はまった。あと、stack のアライメントが
ずれるみたい。6809では問題にならなかったんだけどね。
leave で調整するべき。


Thu Feb 20 14:42:46 JST 2003

c2cbc,cbc2c なんだけど、いったん、構文木にしてから変換すると、
結構失われる情報があるけど、いいの? 特に局所変数の名前とか型
の情報とか。macro もそうだけど。 indent ぐらい保存できないか
なぁ。式の途中でfunction callする場合も取り扱う必要があるの
で、構文木にしてから計算するしかないかな。gexpr の代わりに生
成するようにするか。そうすると、修正するのは、statement と、
gexpr になる。でも、結局、構文木で型を持ち歩くしかないんじゃ
ないの? やっぱり変だよ。型の情報がないのは。

そうではなくて、exprN() で変換していく方法もある。この方が
情報が欠落しないので楽だろう。そうすると、修正するのは、
    exprN(),doXXXX()
となる。これは、量は多い。けど、まぁ、それだけ。この方が
オリジナルを保存しやすい。

中間変数を途中で追加すると、宣言部を前もって出力できなく
なる。{int a;...} を認めれば良いわけだど。実装は難しくない。
じゃ、やれば? でも、汚くなるなあ。出力をいったんバッファ
に貯めれば? どこに? cheapp ですか? 中間変数はいらないん
じゃないの?
     a = g(i)+a;
でしょ。
     goto g_1(i,f_1,save_a); }
     code g_1(i,f_1,save_a) { .... goto f_1(ret_value,save_a); }
     code f_1(ret_value,save_a) { a = ret_value+a; ...}
じゃん。いらないじゃん。。


型を表示するルーチンが必要だね。

めんどくさいなぁ。CbCのProlog version とかほしいなぁ。そうすれば、
変換は簡単。でも、やろうとしてできなかったことでもあるな。


Thu Feb 20 21:13:23 JST 2003

MC6809 の mc-codegen.c version は? (ちょっと虚しすぎる?)
X と D で、use_data_register, use_pointer してやる。
tosop で、X と D の間の足し算を特別扱いする。
(なるほど...) MAX_MAX=0でうまく動くのか? やっぱり、1は
いるよね。できれば、2だよね。

結構、浮動小数点も簡単かも。

汎用の書き換えツールも便利そう。

でも、Prolog version ってのも面白そう。
   code(name,interface(....)) :- 
     p()....,goto(name,interface(....)).
みたいな感じ? 結構、簡単にinterpreterを書けるかも知れない。
これは、あれだね。thread diagram interpreter と似ている。

Fri Feb 21 13:34:17 JST 2003

構文要素での書き換えだけど、どれくらいの能力があるの?
その場での書き換えだけだと、ちょっと低すぎない? それで、
cbc2c,c2cbc はできるとは思う。

まぁいいけど.. chk を無視しているところが結構あるんですけど。
jmp,enter,leave ...

Sat Feb 22 13:05:04 JST 2003

type の印刷かぁ...

conv 系は大半はdefault convが呼ばれる。なので、c.c
っていうよりは、default.cだよね。必要なところだけ、
自分で代入すると言う方法が良いだろう。その方が
ヘッダも一つで済むし。もちろん、object 指向なら
簡単なんだが...


Sun Feb 23 19:47:41 JST 2003

struct のtypeを印刷するんだけど、一回印刷したら、あとは印刷
しない方が良い。逆に毎回書くなら、tag名type名は、いらないの
か。

とするとtypeの解釈はやめてndeclで処理する? 印刷では、それで
いいわけだけど。

このタイプの印刷だと再帰型は印刷が終了しないんじゃないか?
しないね。

Mon Feb 24 02:31:06 JST 2003

strings の\nなどを元に戻す必要がある。

なんか括弧がわやになってるな。

Mon Feb 24 11:02:07 JST 2003

typedef されたタイプは、そちらを使う方が良い。けど、情報が失
われてしまっているので、どこかにとっておかないとだめだね。dsp
? 

うーむ、これはなかなか難しい。全サーチしてもいいんじゃないか
な。遅いけど。少なくともgnptrで定義されたものはサーチすべき
でしょう。

indirect function type の表現がなぁ....

sdecl ではconv を行うので、type_print ではsdeclを経由した場
合に表示を行ってはいけない。

なんか関数の引数の型の値が微妙に変わるんですけど... やだなぁ...

まだ、関数定義のtypedefがstructに変わってしまう。gtypedefed
がうまく動いていない?

Mon Feb 24 17:24:31 JST 2003

まぁねぇ。やっぱり完全に構文木から再構成した方が
便利ではあるよね。特に getsym (空白など)と conv->x_()
との総合作用はめんどくさい。

そのためには、局所変数名をtree上で持ち歩く必要がある。
まぁ、そうすれば良いだけだけど。

実際、今のセットで出来るかどうかは、ちょっと怪しい。
たぶん、buffer に出力するってのをいれればおそらくは
変換できるだろう。

式の途中での呼び出しとかを考えると、やっぱり
構文式から生成しないとだめだろうね。
(ってことは、まだ、かなりの作業があるってこと.... むぅ...)
tmp2.c は、通らないし...

Fri Feb 28 20:32:46 JST 2003

で、c2cbc は、途中で float の方を先にやるわけ?

Sat Mar  1 22:05:43 JST 2003

creg_destroy は、ぜんぜんだめ。これは基本的なアイデアがだめ。

long long はstructでいいんじゃない? だめ? で struct 演算を別に
定義してやる。これは、実装にもよるか。

float,long longなんだけど、
    FRGVAR DRGVAR LRGVAR
などを作る。さらに、
    FMUL DMUL LMUL
などもいる。型の変換は binop で解釈する。変換も演算になる。
    D2F, D2I, F2D, F2I, I2D, I2F, U2D, U2F
ぐらいですか?

emit_pushは、型を必要とするけど? そうだねぇ。emit_fpush, emit_dpush
かな?

creg にfloat register(or stack) の値を入れればいいんじゃないの?
それを見て、emit_pushの型を決める。creg は、けっこう、いろんあ
ものが見ているので、いじらない方がいいじゃないかなぁ。
そうね。FMULとかがあるなら、それで判断できそう。

構文木には型を含めないってのは不便。型を入れれば? そうすれば、
    RGVAR CRGVAR FRGVAR DRGVAR LRGVAR
ではなく、
    RGVAR
ですむし。その方が変形も楽だしね。型は、
   CHAR,UNSIGNED, UNSIGNED CHAR, INT, FLOAT, DOUBLE, LONGLONG
ぐらいですか。

emit_data

とすると、書き換えが結構あるけど。

Sun Mar  2 12:58:38 JST 2003

あとはconstantだね。FCONT,DCONSTかな。binopでは
変換とかも必要なわけだけど。

そういえば、shot のload/storeもないね。SRGVAR,SASSとかですか? SASS
は、すでにあるなぁ。

Sun Mar  2 22:01:58 JST 2003

あれ?
       conv->_sm();
       (*conv->_sm)();
の場合は、
       *conv->_sm の値へcallする
んだけど、
       goto exit1();
       goto (*exit1)();
の場合は、
       exit1
の値へjumpするんだよね? およ? なんか勘違いしてる? なんでexit1()
だとindirectが出て、(*exit1)だと出ないんだろう?

この宣言は、
    void (*_sm)();
であって、
    void _sm();
はできない? なんで?

あぁ、まぁ、いろいろ、めんどくさい。

やっぱり、arglist の再帰的扱いがちゃんとしてないとだめ。

うーむ、 enum なんてのもあるのね。やさしいけど、いるのか?

code (code *) * みたいなのがあるので、conv は手直しが必要。

Mon Mar  3 12:38:08 JST 2003

float/double は順調に進んでるけど、3日はかかるでしょう。

binop を書いちゃうとmc-parse.c は、ほとんど終り?!
代入と関数呼び出しが残っているか。あと single もあるね。

emit_push base で書くんだけど、他のCPUではだいぶ様相が
違うんだろうな。

dreg/creg のfloating versionが必要です。( です? )

Tue Mar  4 14:56:28 JST 2003

double のcurrent register は387のスタックを使う。(?)
関数呼び出し時に387のスタックが保存されるという
保証は無いので、emit_dpushでは、%esp に保存する。

でも、そうすると、代入の後などで387のスタックが
常に残ることになる。こいつをクリアするコードは
どこにいれる? free_register でもいいんだけど....
ううーむ、つかいずらいやつ。ld じゃなくて、
stack top に代入するオペレーションはないの?

(あぁ、でも、なんか、floatは、もうすぐ終っちゃうな... なんか、
さびし...)

Tue Mar  4 23:58:07 JST 2003

fmulp とかでは、fpp のstackのつじつまはあう。fstl とかだと、
合わない。fstpl すればいいんだが、そうすると連続代入でまずくなる。
値を使うかどうかを代入時に知ることができれば良いんだが。
(use flag で判断することにした)

結局、freg は、使わなかったね。0が、入っているので直さないとまずいか。
fregを見て、stack を直すってのは、やっぱり、まずいよな...

でも、浮動小数点レジスタを持つCPUの場合はいるんじゃないの?

Wed Mar  5 11:25:11 JST 2003

printf では 引数はdoubleで統一する必要がある。goto() では、
それをするのはまずい。局所変数と同等だから。ってことは、

関数の引数はdoubleにしないとだめなのね。プロトタイプが
ある時は、その限りでない。(うーむ...)

   (くそ、こいつの副作用が結構出るな...)

あと、fpp のスタックに頼っているので、overflowした時に
困らないか? ほとんどの場合でだいじょうぶだが、だめだった
時にerrorぐらい出せば? でも実行時にしかわからないか...

I2D でさ、signed/unsigned の区別がいるね。

やっぱり FCONST いるんじゃないの?

Wed Mar  5 19:51:59 JST 2003

副作用以外は終ったけど.... あと、name space が結構重なっている
んだよね。
          struct tag, struct field
が重なっているのは結構うっとうしい。gsearc/lsearch のあたりも
書き直さないとだめかも。

あと、list もなぁ。mode の作り方にもよるんでしょうけど。

あと、結構、汚いよな...

Wed Mar  5 21:15:34 JST 2003

できたよ。まだ、テストしてない部分はあるけど。局所変数の初期化とか。
FCONST とか。3日で出来たね。

(gcc の方をやった方がいいかなぁ...)
 goto.c が通らなくなってるな。

Thu Mar  6 14:00:13 JST 2003

PowerPCのnon-lazy pointerって、テーブルに入っていてそれを読
み込む形式なのね。いったん、レジスタに読み込んだら、それを再
利用する形が良いらしい。ということは、code_gvar にキャッシュ
を作らないといけない。しかも RLU ですか? (めんどくさ〜)
でも、そうしないと、
   i = i+1;
なんてのでも、ひどい目にあってしまう。

local variable も最初に move multiple register で大半は
レジスタに読み込んじゃうみたいね。pointer で参照されると
困るんでしょうけど。まぁ、31個もあれば、そういうことを
してもあまり問題ないのかも知れないけど。

creg を破壊しない実装にすれば、少しはましになるんじゃない?
(IA32では、それは難しいけど)

Thu Mar  6 20:50:24 JST 2003

やっぱり、使った分だけregisterを保存するようなコードに
なるみたい。one path で、それをするためには、
        .align 2
_main0__:
        lwz r5,2136(r1)
        addi r1,r1,2128
        lmw r23,-36(r1)
        mtlr r5
        blr
        .align 2
        .globl _main0
_main0:
        mflr r2
        stmw r30,-8(r1)
        stw r2,8(r1)
        li r11,0
        stwu r1,-480(r1)
        li r2,100
        mtctr r2
        mr r30,r3
        addi r0,r1,64
        mr r9,r0
        b _main0__;
とかいう感じにするしかないね。

あと引数は、レジスタに積むようになっているみたいだけど... r3 から?

        mflr r31
        li r0,7
        stw r0,56(r1)

だから8個まではレジスタに積むみたいね。
r3-r10 だね。

構造体もregisterにコピーされるのか。そして、向う側で受取の
コピーを行うわけだね。先頭にreturn structへのポインタがあるのも
同じ。

(うう、memcpyしまくりだ...)

浮動小数点もレジスタ渡し見たい。f1から。(なるほど)

saveFPってのを呼び出して、 f24-f31をsaveするらしい。
(31-24)*8 数合わないな?

pointer のことを考えると、レジスタだとまずいものもある
わけだけど。アドレスを取られてからで間に合うんじゃない?
配列などは、もともとだめだし。場所と値(?)は確保するとして。

そうか、逆に、r3-r10 は引数でなければ壊しても良いわけか。
(それでr9とか良く使われているわけか...)
ということは足りなくなったら、引数をセーブすれば良いわけね。
(ってことは、LVAR かつ REGISTER っていう状況があるんじゃん...
まぁ、そうだけどさ...)
これは get_register がめんどくさそ。

どうも、r11-r12  あたりは自由に使っているらしい。

引数を作っている途中で関数呼出しするときは、どうするの?
r30などに移動するのか?

なんか知らんけど、in file call name と out file call name が
違うみたいね。(sigh...) こんなのなんとかなるのかなぁ。
全部、stub にしておいて、.set で書き換えるという手もあるけど。

(さすがに一日ではできないか...)

なんか整数から浮動小数点への変換はじぶんでやらないとだめなのね。
これはサブルーチンを呼んだ方がましだ。

get_register は絶対失敗しないようにできるんじゃないか?

label があると、code_base cache はclearしないといけない。
それを判断するには fwddef をhookする必要があるけど。

Fri Mar  7 09:17:10 JST 2003

問題は、
       register allocation

       function call/goto call
の構成だな。goto の方は machine dependentなところは
ほとんどない。register のsaveさえ必要ないから。

register allocation だけど。
     r0
     r1      frame pointer (or stack pointer )
     r30     jj
     r31     relocation register
     r0,r1,r2    システムで使う
     r0-r10  引数
             引数でないところは優先的に使う
     r20-r29 セーブして使う領域

r10-r19 はどうなんだろう? セーブしないのか?

ia32 の方でもfppのスタックを関数呼び出しのときに吐き出した方が
良い。

r0 r1 r2 r3 r4 r5 r6 r7 r8 r9
r10 r11 r12 r13 r14 r15 r16
r28 r29 r30 r31

なので、もののみごとに、17-27 までが使われてないね。

ということは、関す呼出し時には、保存されるレジスタはないと
思った方が良いってこと? あるいは、r17-r28 は保存されると
思って良いのかな。

Sat Mar  8 19:28:42 JST 2003

関数呼び出し時のレジスタセーブを避けるためには、関数呼び出し
を優先して実行してやれば良い。関数呼び出しの結果は局所変数に
セーブする。
     f(g(h(a)+1)+2)
は、
    a1=h(a)
    a2=g(a1+1)
    f(a1+2)
となる。そうすれば、関数呼び出しのときのスタックはかならず0になる。

でも、結局、引数は関数呼び出しの前にセーブするのね。だったら、
そんなことしないで、セーブすれば良いのか。

Mon Mar 10 11:42:40 JST 2003

で、レジスタのセーブなんだけど、mc-codegen.c を変更しない
とすれば、引数のリストを使って変更していくのが良い。
関数呼び出しは基本的には並列代入になる。並列代入でき
てもできなくても、セーブする必要はある。今の並列代入
ルーチンのできは良くないので、「同じかどうか」だけ
判断するのが良いのではないか?

関数呼び出しの前に式用にレジスタに積まれた値はセーブした
方が良い。セーブした後はlvarとしてアクセスすることになる。
スタックでもいいけど。
そうすると、stack 配列には、

     レジスタ   レジスタ番号 (>0)
     スタック   -1
     lvar       lvar番号

の三種類が入ることになる。それに合わせてtosop/assopを書き直
す必要がある。emit_pop だけでいいかも。スタックを止めちまう
のも手ではあるが、ia32の方で効率が悪い。やっぱり三種類サポー
トするのが良いだろう。

(けっこういろいろあるなぁ... どこから手を付けるか...) 

Tue Mar 11 14:23:57 JST 2003

save_stacks すると、レジスタはほとんど使われなくなって
しまう。が、コードの見通しは良くなる。

定数を右辺に持って行くとsave_stacksでsaveする量が減る。が以
外にめんどくさいね。反射律が成り立たない演算子に関しては。tosop
の定数版とか作ることになるので... あとスタックに積む順序が逆
になってしまう。まぁ、もとの版では行われていたことだが... 
CMPではrexpr で反転して論理を逆転させる方が簡単か。SUBでは、
ADD + (-CONST) にする方が良いね。

      je _xxx
したあと、current register のregv[]が残ってしまう。これは、
変だよね。gexpr_init で regv が残るのは、case 文の比較だけ。
あとは全部0にして良い。(まぁ、害は無いんだけど)

(case 文のjumpは、switch 文が終る時に処理すれば、index jump
にすることができるね)

Wed Mar 12 12:58:47 JST 2003

比較で入れ換えるとの否定は若干違うよね。

Thu Mar 13 19:39:48 JST 2003

そういえば、doif で条件が定数だったときとかの最適化は
してないんだね。やさしいけど。chk を使えば良いので。

   f(g(1,2,3),g(1,2,3),g(1,2,3))

とかだと、結局、g の返り値は一旦メモリに入れないとだめじゃん。
なんだけど、実際は、r29-r22 を使っているようですね。

ってことは、function call の時に、r3-r10 が前の引数かどうかを
チェックして、引数だったらr29-r22に移す作業がいるわけだよね。
いったんr3とかに入れてしまった後だと、重複してしまうが...
前もって関数呼出しがあるかどうかは、調べることができるから、
関数呼び出しがあったら、そうするようにする?

いろいろめんどくさいなぁ... (いったい、いつなったらできるんだ?)

Fri Mar 14 10:38:25 JST 2003

function の dsp が、arglist と extern flag の両方を入れてしまっている。
本来は sc で区別するべき物だよね。

なんか、emit_pop_free のxregがLVARの時のバグを取るのに苦労した...
gdb は top level でのwhile を受け付けなくて、define してやなんないと
だめみたいね。

Fri Mar 14 15:50:28 JST 2003

なぁ... 書いても書いても書いても、終らん!

Fri Mar 14 19:43:44 JST 2003

jump の中で input register を割り振るときに floating point register の
ことを考えてなかった。これは  register_var とは異なるので異なる
仕組みで割り振る必要がある。ってことは、get_input_register_var
が要るってこと?


0x9001a544 <saveFP+4>:  stfd    f15,-136(r1)
0x9001a548 <saveFP+8>:  stfd    f16,-128(r1)
0x9001a54c <saveFP+12>: stfd    f17,-120(r1)
0x9001a550 <saveFP+16>: stfd    f18,-112(r1)
0x9001a554 <saveFP+20>: stfd    f19,-104(r1)
0x9001a558 <saveFP+24>: stfd    f20,-96(r1)
0x9001a55c <saveFP+28>: stfd    f21,-88(r1)
0x9001a560 <saveFP+32>: stfd    f22,-80(r1)
0x9001a564 <saveFP+36>: stfd    f23,-72(r1)
0x9001a568 <saveFP+40>: stfd    f24,-64(r1)
0x9001a56c <saveFP+44>: stfd    f25,-56(r1)
0x9001a570 <saveFP+48>: stfd    f26,-48(r1)
0x9001a574 <saveFP+52>: stfd    f27,-40(r1)
0x9001a578 <saveFP+56>: stfd    f28,-32(r1)
0x9001a57c <saveFP+60>: stfd    f29,-24(r1)
0x9001a580 <saveFP+64>: stfd    f30,-16(r1)
0x9001a584 <saveFP+68>: stfd    f31,-8(r1)
0x9001a588 <saveFP+72>: stw     r0,8(r1)
0x9001a58c <saveFP+76>: blr

なのか。ということは、
      f%d に対して、"saveFP+%d",68-(31-f)*4
かな?

うーん、これで、全部書いた気がする。でも、ほとんど全部の
関数にバグがあるだろうなぁ。一つ一つ取っていくしかないか。

Sat Mar 15 16:04:09 JST 2003

やぁ...  まぁ.... バグだらけだな。

function call のレジスタの処理がでたらめ。RISCの場合は、parallel_assign
した方がいいんじゃないか?

Sun Mar 16 20:59:10 JST 2003

あぁ、まだまだ、かかりそうだ....

定義されてない関数/定数をextern扱いにする必要がある。(なんで、PICなの?)

function は c0(n->ty)==FUNCTION で識別する。n->sc には、FUNCTION/EXTRN[1]
が入る。だよね。(CODE)も。だけど、n->ty に戻り型が入っている場合が
けっこうあるらしい。

(しかし、これは、結構かかるな...)

Mon Mar 17 12:02:22 JST 2003

function のnptrだけど、
    nptr->ty  function の return type
         list3(FUNCTION,return_type,arg_type_list);
    nptr->sc  本来はFUNCTION/CODE (EXTRN/EXTRN1)
    nptr->dsp 引数のリスト
と言う構成なわけだよね。で、引数のリストとtypeは重複している。

他のnptrとの整合性を考えると、
    nptr->ty  return type
    nptr->sc  FUNCTION/CODE
    nptr->dsp 引数のリスト
が良い。で、引数のリストにEXTRNの情報を入れる方がいいんじゃないか?
(どっちにするんだよ...)

プロトタイプと実際の引数リストの整合性はチェックしなくちゃ
いけないわけだから、別な方がいいんじゃないか? とすると、
やっぱり前者か...


extern と、そうでないものとの呼出しを、呼出しの時点で
区別しないといけない。しかし、prototype で定義されている
ものと default extern の区別は、最終の時点でしか判別できない。
できないよね。定義されてないものが default extern なんだから。
ってことは、最後に、.set で定義するしかないか。(sigh...)

Mon Mar 17 14:34:12 JST 2003

えーと、input register に regv/regs をセットしないとだめ。
関数呼び出しの引数を評価する前に save する必要がある。
さらに、引数の評価の後に、save された変数を呼び出す必要が
ある。(ってことは、いままでのは、まったくのでたらめか..)

register 変数の場合は、問題ない。ってことは、ia32 側も
変更してしまったので、おかしくなっているね。もっとも、
code の場合は、そういうsaveとかは必要ないから良いのか。

(11日目か...)

    mr creg,hoge
    mr hoge2,creg 

とかは、g_expr_u で最適化するべし。set_freg/set_creg でレジ
スタ変数に割り振ると、set_freg でfreeされてしまう。

浮動小数点定数の共有はやった方が良い?

input register のsaveを忘れている。
input register の割当が逆順。

Mon Mar 17 23:38:14 JST 2003

あぁ、そうか。input-register のアドレスを取ったときは、
それをLVARに変えないとだめ。

なんだけど、途中で分かっても、loop で前に戻ることがあるので、
手遅れです。ということは、one path ではできないね。

むぅ... function call の save_input_register も同じ「手遅れ」
の問題があるのね。function argument は、すでに parse されて
いて、その引数は、register に固定されてしまっている。
save_input_register で、save するコードを出しても、
そちらを見るようには出来てない。(どうすればいいんだ?)

function callの先頭で、引数を全部stackにsaveしてしまえば、
このあたりの問題は解決する。けど、あんまりな気もするね。
でも、stmw も使えるしな...

結局、input_register は、LVAR のまま処理して、可能ならば
register を使うって方がいいんじゃないかなぁ.... でも、
そうすると、今まで書いたコードは、ほとんど無駄かぁ...

いずれにせよ、あんまり簡単な解決はないね。

Tue Mar 18 10:46:48 JST 2003

結局、全部 stack にsave しました。そうすれば、変更は1行。

やっぱり、関数全体を構文木に落してからgexprするべきだよね。
それ自体は、そんなに難しくないが。

Tue Mar 18 12:41:42 JST 2003

COND(三項演算子)で使うレジスタが関数の引数を破壊してしまう。
input register にならない値を使えば良いんだけど。r15
を使っているんだけど、それでいいの?

virtual を使っていたときは、use_register で何も破壊されなかった
んだけど、使わないとすると、結構破壊されてしまう。なので、
ちょっと奥の深い問題かもね。三項演算子の型はチェックしてなかったし。

まぁ、それは、一時レジスタを使えば良いとして...

時々呼び出す、u2d とか bcopy とかで破壊されるinput レジスタ
はどうする? これは、予測は困難だよね。使う分だけsaveするって
言う手もあるけど。うー、どうしよう... 検出できるようにするっ
ていう手もある。(と、思ったら、get_register_var が間違ってい
るみたいね) 検出はちょっと重いか。二乗のアルゴリズムは、あま
り使いたくない。といっても、定数乗になるだけか。呼出側でsave
する? bcopy がどれくらい使うか割りと曖昧。

もっと積極的にget_register_var するっていう手もあるよね。そ
うすれば、あまり気にすること無く library call できる。(ちょ
っと、書き換えが多いが...) その方が筋かな。使うレジスタを減
らそうと思うと、それは検出するのと、それほど差はないわけか。

このあたりも構文木を全部持っていれば解決できるんだよな。

うーん、まだまだ、だな。

関数が関数呼び出しで決まる場合の input register の破壊を考えて
ませんでした。これも、どうすればいいんだ... まぁ、get_register_var
するのが簡単だよね。

save register が狂っているようだね。max_register_var あたり?

Wed Mar 19 02:22:51 JST 2003

なんだか、struct のtag listが、int a,b,c; のようになっているのを
一つと数えているらしい。困ったものだ。前に言ったのをちゃんと
実装しよう。

macro のバグも見つけちゃったよ... むぅ。

でも、とりあえず、a.out は動きました。

Wed Mar 19 12:59:01 JST 2003

なんか、浮動小数点をprintfに引き渡すときは、rnレジスタにも
値をいれていて、しかも、そっちを見るみたいね。これは、
めんどくさい....
   r4,r5   ... f1
   r6,r7   ... f2
   r8,r9   ... f3
   f4 からは単独
(あぁ、なんか、これは異常にめんどくさいぞ... こんなことするなら
f0 から r0 にコピーさせてよ...)

40(r1)とかをprintfは、派手にぶっこわすようですね。いったい
どれだけ取れば良いんだろう?

-112 ぐらい? 今は-72程度か。

(なんか風邪ひいた... 家内がくるというのに...)

浮動小数点のバグも順調に取れています。

なんか、save_stack が余計なsaveしてない?
まぁ、一時変数を良く使うのでfree listを作った方が良いかもね。

その前に整数演算のチェックが必要だな。

Thu Mar 20 12:06:27 JST 2003

まだ、save したレジスタを破壊しているな。
    set L_98,244
    stw r15,lo16(-44+L_98)(r1)
ぐらいで、もう壊れちゃうみたい。ってことは、L_98 がもっと
大きくないとダメなのか。

 
Thu Mar 20 23:43:42 JST 2003

ようやっと、self compile が通りそう。register save 系が
やっぱり難しいみたいだね。dynamic loader を壊したりするし。

あとmodがおかしいみたいで、hashの値が違うらしい。マイナスの値
になるunsignedのかけ算ねぇ。int.c のrecursionが通らない。
まだ、offset がおかしいらしい。

macro のバグもとれたし。

一応は、self compile は通りました。

Fri Mar 21 03:18:26 JST 2003

やっぱり、r1 と x(r30) の計算が合わない。きっと、
呼出側で、引数の分のoffset を用意しているのだろう。
だから、どれくらいの引数の関数を呼び出したかという
値がいるのではないか?


Fri Mar 21 12:22:11 JST 2003

                       <------r1_offset------------------------------>
                                      <------------lvar_offset------->
 r+  +------------+---+---------------+----------+--------------+----+    -
      caller arg   xx   register save   local      callee arg     xx
                          reg_save      disp       max_func_args*size_of_int

ということだったみたいね。ようやっと self compile が通りました。

free_glist を作るか....

Sat Mar 22 11:17:41 JST 2003

creg/freg を g_expr の引数にした方が、レジスタマシン系では、素直な
みたい。そうすれば、
##              conv->static_();
        addis r15,r31,ha16(_conv-L_242)
        la r15,lo16(_conv-L_242)(r15)
        lwz r3,0(r15)
        lwz r3,244(r3)
        mr r29,r3
        mtctr r29
みたいな mr は減るね。もっとも一命令だけどさ。3% もあるみたい。
ちょっと多いか... 386 での use_register もなくなるしなぁ。
(あぁ、でも大半はポインタキャッシュだな。こっちを直す方が
簡単か)

まぁ、そういう最適化をしないっていうのが、このコンパイラの立場
なわけだけど。


構造体の引数渡しでは、構造体そのものをレジスタに載せて
引き渡しているみたいだね。まったく... それで、あわてて
メモリに代入しているわけか。

なんか  mtctr r2; bdn Lxx とかいうのがあるのね。main frame っぽい!
これはベンチマーク用って感じだね。


Sun Mar 23 16:06:29 JST 2003

Breakpoint 3, get_register () at mc-code-powerpc.c:235
235         for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) {
(gdb) c 9999
Will ignore next 9998 crossings of breakpoint 3.  Continuing.
test/basic.c:67:Bug of compiler

Breakpoint 2, errmsg () at mc-parse.c:214
214         if(lineno==0) return;
(gdb) info b
Number Type           Disposition Enabled Address    WhatStackFrame Condition IgnoreCount Commands 
2      breakpoint     keep        y   0x0000ca08 in errmsg at mc-parse.c :214       
        breakpoint already hit 1            time
3      breakpoint     keep        y   0x000028e4 in get_register at mc-code-powerpc.c :235       
        breakpoint already hit 69           times
        ignore next 9930      hits
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /Users/kono/src/device/mc -s test/basic.c
[Switching to process 24650 thread 0x2307]
test/basic.c:67:Bug of compiler

Breakpoint 2, errmsg () at mc-parse.c:214
214         if(lineno==0) return;
(gdb) c 69

うまくいかんね。

a+a+a....a で落ちてしまう。まぁねぇ。

結局、stack frame の問題か。

Mon Mar 24 03:06:32 JST 2003

Intel 側にもだいぶ embug してしまったようだ。

basicとかfloatの難易度を上げすぎたか?

mc-code-power.c のlvar は、
     input arg > 0
     local var < 0
     output arg > ARG_OFF
とするべきだね。

Mon Mar 24 12:08:43 JST 2003

        addi r27,r1,56
        addi r29,r28,28
        mr r3,r27
        mr r4,r29
        li r5,372
        bl L_memcpy$stub
        lwz r4,0(r28)
        lwz r5,4(r28)
        lwz r6,8(r28)
        lwz r7,12(r28)
        lwz r8,16(r28)
        lwz r9,20(r28)
        lwz r10,24(r28)
        mr r3,r28
        bl _main3


うーむ、最低な奴。最初の28byteだけレジスタ渡しなのか。アドレス
は変わらないんでしょうけど。まぁ、合わせなくても害は無いけどさ。
そのうちね。(そんなに難しくは無いが... また、function が複雑
怪奇になるな) しかし浮動小数点レジスタも使うとかそんなんじゃなくて
良かったかも。


        stwu r1,lo16(-L_9)(r1)
とかしているから、局所変数は64k以内ってことだね。haしてもいいんだけどさ。

Mon Mar 24 17:07:59 JST 2003

さて、ようやっと fact-a.c に取り掛かれるわけだけど、今のままだと、
    input register -> メモリへのsave
ってのがあるんだよね。これはいただけない。sub routine call すると、
r0-r10 は破壊されちゃうし。ということは、code segment の引数は、
r29-r20 が良いんじゃないか? 浮動小数点f31-f20を含めて。

問題は、どこでinput register を指定するかだけど、get_input_register_var
で code 用かどうかを指定するのが良いかな。fnptr ではダメなので明示した
方が良いだろう。

r31, r1 の設定があるのはやむを得まい。r1=r30であった方が良いのだろうか?
その方がfunction calll の時の変更が少ないだろう。

メモリとinput register (この場合はr29-r20,f21-f20だけど)の対応は
どうする? 通常だと呼出側が確保するわけだけど、そうはいかないね。
レジスタもsaveする必要が無いから、いろいろ簡単でよろしい。

あとは、return/environment の扱いだけど。ia32 の方でもいろいろ
動かなくなっているようだな。

Mon Mar 24 21:56:47 JST 2003

うーん、別にフレームを変えないで、そのままでいいか。
その方が楽だよね。return しようと思うといちいち
frame をうごかさないといけないけど、return は
別処理するんだから、いらないか。

Wed Mar 26 14:29:21 JST 2003

で、フレームを変えないとすると、
    
                       <------r1_offset------------------------------>
                      *               <------------lvar_offset------->
 r+  +------------+---+---------------+----------+--------------+----+    -
      callee arg   xx   register save ! local      caller arg     xx
                          reg_save      disp       max_func_args*size_of_int
        lvar>0                         lvar<0       lvar>0x1000 0000

なので、r1/r30 を常に移動させる必要がある。前のcode segment/
function がどこにr1/r30を持っていたかを知る手段はないので、
jump する前に糢とに戻す必要がある。r30が固定ならばr1のみの
修正で良く、前に戻す必要はない。

でも、r1_offset 分を戻せば良いだけなんだから、r30を * に固定
しても良いんじゃないか? ! でもいいんだけど。こっちの方が簡単
かな? code の場合は register_save は 0 (つまり、マイナス)な
わけだから。(まぁ、穴を開けておいても良いけど) 

Intel の場合はどうして、こうしなかったのか? (でも、最後にチェック
した時にはcore dumpしていたが...)

                      ebp                        <-----esp----------->
                       <------r1_offset------------------------------>
                      *               <------------lvar_offset------->
 r+  +------------+---+---------------+----------+--------------+----+    -
      callee arg   xx   register save ! local      caller arg     xx
                          reg_save      disp       max_func_args*size_of_int
        lvar>0                         lvar<0       lvar>0x1000 0000

というわけなので、* にそろえる方が Intel 版とも一致する。
ってことは、ebp の移動は Intel でもやっていたってこと?
いやfunctionではこうなっているんだけど、code では違う。


     ebp                                         <-----esp----------->
                       <------r1_offset------------------------------>
                      *               <------------lvar_offset------->
 r+  +------------+---+---------------+----------+--------------+----+    -
      callee arg   xx   register save ! local      caller arg     xx
                          reg_save      disp       max_func_args*size_of_int
        lvar>0                         lvar<0       lvar>0x1000 0000

ってわけか。とすると powerpc では、

     r30               <------r1_offset------------------------------> r1
     #                *               <------------lvar_offset------->
 r+  +------------+---+---------------+----------+--------------+----+    -
  xx  callee arg   zz   register save ! local      caller arg     zz
                          reg_save      disp       max_func_args*size_of_int
        lvar>0                         lvar<0       lvar>0x1000 0000

の#にr30を固定してr1をずらすことになる。やっぱ、こっちだよね。
zz はから。xx に、base  となる関数呼び出しが来る。から、
callee arg は破壊される。

どっちも可能だな。両方実装する? やっぱり後者からかな。gcc は
前者の方が簡単だろう。

入力変数をレジスタに割り振ってしまうと、その範囲では
簡単に動いてしまう。(そりゃ、そうだ...)

goto with environment で構造体を返すのには注意が必要。
どこでコピーする? goto した場所? return-continuation?
そうねぇ。return-continuation 側が普通でしょう。あぁ、
でも返し先は元の関数呼び出しの引数上だから壊れちゃって
いるかもね。だから、とっておく実装の方が良いわけね。

(なんか -O3 にすると、mc1 が落ちるな...)

Sat Mar 29 16:35:18 JST 2003

     r30               <------r1_offset------------------------------> r1
     #                *               <------------lvar_offset------->
 r+  +------------+---+---------------+----------+--------------+----+    -
  xx  callee arg   zz   register save ! local      caller arg     zz
                          reg_save      disp       max_func_args*size_of_int
        lvar>0                         lvar<0       lvar>0x1000 0000

このままだと、* が previous r1/r30 になるので、function から
goto する時に戻り番地やzzにあるはずのsaved r31/r30が破壊されて
しまう。それは、ちょっと困るということは、一旦、dummy subroutine
(普通はstub っていうか)を呼び出す方が良い? 戻り番地とprevious r1/r30
は持ち歩いているわけだけど... また、r20-r29はつぶされてしまう
ので、前もってsaveする必要もある。f31-f20も。(結構多いな...)

   #  *          r30 <--------------r1_offset-----------> r1
r+ +--+----------+----------+-----------+----------+----+
xx  zz  reg save !callee arg!code local  caller arg  xx
         r20-r29 

これだと environment は持ち運ぶ必要はない? いや、ある?
逆に戻り番地を持ち運ぶ必要はなくなるわけね。そっちの
方がきれいかな。goto-continuation みたいな感じか。

返り側は、

  lwz r1,continuation
  lwz r1,0(r1)
  lwz r0,8(r1)
  mtlr r0
  lmw r30,-8(r1)
  blr

程度で良い? このr30ってのはgoto先では知り得ない。いや、待てよ、
この場合は、r20-r29って決まっているわけか。

  lwz r1,continuation
  set r3/f1 as a return value
  lwz r1,0(r1)
  lwz r0,8(r1)
  mtlr r0
  lmw r20,-148(r1) (?!)
  blr

で良いわけか。構文は同じでreturn addressは無視することにするか。
呼出側は、

  通常の関数呼び出し (引数0) (は、手間0だから..)
  bl L_stub_NN
L_return:        (普通のretrunもあるから、必要な場合がある)
  lwz r1,0(r1)
  lwz r0,8(r1)
  mtlr r0
  lmw r20,-8(r1)
  blr
L_stub_NN:
  mflr r0
  bl L_61
L_65:
  lwz r1,0(r1)
  lmw r23,-108(r1)
  b restFP+36 ; restore f23-f31
L_61:
  stmw r23,-108(r1)
  stw r0,8(r1)
  b saveFP+36 ; save f23-f31

ちょっと複雑すぎるかな。特に gcc では、こういう操作は難しいかも。

あ、そうか。register saveは、このy関数が呼び出された時点で
やってしまえば良い。そうすれば必要ない。戻り番地も既に xx
に入っている。だよね。

                 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
   #             *                           r30<--r1_offset-------------> r1
r+ +----------+--+----------+----------------+-----------+----------+----+
    cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                   r20-r29     lvar>0         lvar<0      lvar>0x1000 000
                   f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
                              *size_of_int                  *size_of_int

とすれば stub は必要ない。cousin arg も保存されている。goto の
引数のみがlocal変数を上書きする形で格納される。これで、original
のIA32実装と一致することになる。(引数の保存を除いて。いや、
元のも保存されているんじゃないの?)

それで、code segment から関数呼出しするときは? (ってことは、
それようのテストも必要なわけか...)

Wed Apr  2 17:40:32 JST 2003

register 変数が既に使われていても、わざわざsaveする必要はない。
戻って来ないから。register を使ったことにするには、used_max_register_var
を設定してやれば良い。

Intel版で goto が動かなくなったのは、arg_offset が、register 変数分
も取るようになったから。save することを考えると、その方が良い。実際、
function call があるとsaveされてしまう。ということは、別に r20-r29
である必要はないってことか。通常のinput register varで良い。とすると、
register変数をsaveする必要もないね。
ただ、input register var は、function callの前には saveする必要が
ある。でも、これは、やっぱり手遅れか。ってことは、やっぱり、
r20-r29が良いってことか。

jump() では、呼出し引数は、-arg_size つまり、局所変数と
同じ扱いになっている。ってことは、

                 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
   #             *                           r30<----r1_offset---------> r1
r+ +----------+--+----------+----------------+-----------+----------+----+
    cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                   r20-r29     lvar >0        lvar<0      lvar>0x1000 000
                   f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
                              *size_of_int                  *size_of_int

                  r1 <----------------------r30 (return continuation)

で、callee arg は保存されたまま、code local だけ変わるってことだね。

return continuation で、構造体を返そうと思うと難しい。そもそも、
浮動小数点が、ちゃんと返るのか?

Thu Apr  3 13:47:23 JST 2003

r1 は stack top に保存してあるものを、そのままenvironment
として渡すのが良い。

stack 上のデータが64kbyteなのは制限だが、やむをえまい。

というわけで、powerpc 版の CwC はできあがり。

    return continuation での構造体の引渡し
    function のprototypeでの重複した引数の省略

あたりが、まだ、テストしていない。あと、

    関数単位での構文木の作成
    従来のフレーム構造の再利用バージョン

も課題ではある。


Fri Apr  4 10:41:22 JST 2003

おいぉい、-O3 にすると、mc-codegen.c の arg_register は
r14 まで使うよ。それは、まずいんでないかい? 困ったなぁ。

Mon Apr  7 14:29:51 JST 2003

そういえば、unsigned char は処理してんの? crgvar はあるけど、
curgvar とかはないみたいだけど。

あと、-1.0 とかが d2i とかを生成するのを直してないんでないかい?

MIPS の比較命令は、

        beq     $2,$3,$L18

        slt     $2,$2,$3
        bne     $2,$0,$L17

という感じなわけね。(signed less than か?)

だとすると今の方法ではうまくないかも。

PS2Linuxのアセンブラが低能すぎて、forward reference を全然
解決してくれない。どうすりゃいいんだ?

.include を使うと良いらしい。(そんなんでいいのか?!)

csvalue() で取って来たregisterを誰がfreeするの?

Tue Apr  8 14:52:06 JST 2003

MIPSには bgez とか bgtz とかいう命令があるのね。なんかに
使えるの? 使えるけどさ。今のコンパイラで使う方法は?

gccが浮動小数点レジスタを避けるようにコンパイルしている
のは何故だろう? 遅いから? jal dcmp とかは、やっぱり変。

double と float の差が良くわからない。

Wed Apr  9 16:20:00 JST 2003

LOR LAND の定数の扱いを追加

配列の処理があるから、変数*定数ぐらいのh最適化は
入れた方が良いかも。その方がレジスタも少なく使うし。
(また?)

授業で使うように、また、最適化を落したものが必要かな。

MIPSの浮動小数点ってさ、single precision しか機械語命令が
ない? dpsub とかを呼び出すのっておかしくない? (まぁ、
いいんだけどさ)

Fri Apr 11 14:36:33 JST 2003

(二日酔だ...)

要するに、
     浮動小数点レジスタは single float しか使えない
     double は、すべて、汎用レジスタに置き、計算はすべて、 subroutine 
ってことだよね。(あ〜、やだやだ)

single float だけでの演算を導入するためには、DSUBの他にFSUB 
などを導入する必要がある。これは「うざい」。不可能じゃないけ
ど、かなりめんどくさいね。浮動小数点誤差の問題もあるし。全部
double に変換してから計算すれば問題ないかと言うと、そんなこ
とはないわけだが。せめて、浮動小数点レジスタ上での演算をおこ
なうsubroutineはないの? (あるかも知れない) 

まぁなぁ。FCOMPとかやればいいだけなんだけど。

Sat Apr 12 13:30:07 JST 2003

jal dpadd は、やっぱり、かなり複雑な浮動小数点演算だというが
わかった。IEEEの形式と合わないとかとかでそうなったんじゃなか
ろうか? もっとも、PlayStation に合わせてあるのかも知れないけ
ど。

ということで、single float 計算を入れないと、もとのgcc との
差が大きすぎるだろうと思う。ってことは、fmachineop とか FSUB
を入れないとだめってことか。まぁ、やれば、いいだけなんだけど、
他のCPUとの調節がなぁ... 

今は、float の演算もpipeline上では1clockなんだろうから、
できればdouble でやって欲しいけどね。とはいえ、double/float
の変換が不要になるので、float base だとMIPSの方が速い
ってことにはなるかも知れない。

gdb のdisass を見ると、jal bpadd とかは特定レジスタ
を使った間接代入になっているらしい。また、disass の
レジスタ表示が、

    $a0 $a2 $a3 $at $f0 $gp $ra $s0 $s1 $sp $t9 $zero $v1 $f12 $at

とかなので、よくわからん。こまったものだ。これも、
ちょっと時間かかるのかな?


まぁ、なぁ... ANSI-C に従おうと思うと、このあたりのfloat/double
はうっとうしいよね。でも、とりあえず動けば良い?

expr の引数として「output type」を入れるか? 基本的には assign
で決まるtypeを要求する。やっぱり、C の規格書がいるんだろうなぁ。
(それは嫌だな...) CbC として、そういうものを入れるのが本当に
正しいの? (さぁねぇ...)
    float  = float op float
は良いんだけど、
    double = float op float
の時に、必要な精度を確保できない。cast すれば良いんだけど、それは
ANSI-C とは異なる挙動になってしまう。ま、いいか。

MIPSはdouble=float ということにするっていう手もあるね。
その方がきれいか。でも、どうせ、他のCPUもあることを考えると、
fbinop するんじゃないの? lbinop も出さないとだめだろうし。
short とかunsigned char の扱いもね。(sigh...)

まぁ、時間の問題だから、やれば良いだけなんだけど。めんどい!

(せめてdoubleのルーチンが浮動小数点レジスタを使ってくれれば
楽だったのに〜)

Mon Apr 14 23:29:37 JST 2003

やっぱり、ちょっと変更大きいなぁ。

Fri May  2 14:53:16 JST 2003

なんでもいいけど、power-pc の test/basic が通らなくなってる。
(ま、そうだよな....) struct-pushと args-works の途中で
動かなくなったらしい。

あと、引数の引渡しだけど、printf (...) だけ特別扱いしたら?
プロトタイプがあるのを特別扱いする必要はないんじゃない?

Sat May  3 18:38:57 JST 2003

わかりました。contains_in_list を修正するのを忘れているね。
あと、get_register は、どうせ足りなくなるわけだろ? その
時はどうするの? 足りなくなるのは関数呼び出しの時だけ?
(かな?)

だとすれば、関数呼び出しのsaveの変数を局所変数も使えるように
すれば良いだけだね。

Sun May  4 09:18:32 JST 2003

関数呼び出し時の浮動小数点を格納する、r8,r9 の扱いが
おかしい。

emit_push / tosop で局所変数だけは特別扱い
した方がいいんじゃない? register full だと、

     register にload (emit_push)
     register full でそれを局所変数に代入 (*)
     演算時にregisterに再代入

まぁねぇ。それだと、mc-code-386.c の時代に戻るわけ
だけど。まぁ、その方がいいのかな。もっとも、(*)
が起こらなければ、特に問題はないんだけどね。

局所変数、大域変数、定数の足し算とかは処理した方がいいのかなぁ。

Sun May  4 15:10:48 JST 2003

たぶん、oprt とかは、それほど効果は無いよ。効くのは、
register full の時だけだろ?

MIPS version は、まだまだ全然と言う感じ。ゆっくり
片付けて行くしかないね。

Sun May  4 18:29:26 JST 2003

d50 では、引数はレジスタに $4,$5,$6,$7 の double 二つしかのらない。

f50 では、引数は
        $f12,$f14,$6,$7
というように4つ乗るらしい。(こまったもんだ...)

i50では、$4,$5,$6,$7 だね。

あとはstackに積むみたいね。

これらを get_input_register_var で処理するわけか。

Mon May  5 15:28:07 JST 2003

code_fconst/code_dconst と code_drgvar(e4,d,reg) みたいなのが
入混じってるな。ま、いいんだけど。

やっぱり、後者に統一。(めんどさ〜) free で d を指定するのはまずい。

Thu May  8 11:02:42 JST 2003

regs/fregs の複数は必要ないんじゃないか? 一つで良い? 外から
は見えないから、mc-code-mips だけでそうするのが良い。

register のやり方を工夫しないとだめか。

あーめんどい.... 本当に動くのか?

double のライブラリ呼び出しで$3,$4,$5,$6 を使うわけだけど、
ここは必ずあけておかなければいけないわけだよね。でも、実際に
は、ライブラリの呼び出し後には$3,$4 が使われてしまう。ここで、
emit_push されると気まずいが... 

本当のfunction callと同じ扱いでもいいんだけど、それだと
ちょっときつくない?

なんか浮動小数点レジスタ変数へのdpreinc/dpostinc を定義して
ないんじゃない? それは、まずいんじゃないの? dassop もそうか?
あれ? なんか何もしてないみたいだな。Intel 版にはレジスタ変数
がないから、テストしなかったのか。code の引数はレジスタに割
り当てられるから、そのあたりでテストすることは可能だろうね。
まぁ、これ自体は難しくはないが... 

code segment では浮動小数点レジスタに割り振られてしまうので、
実はエラーが出ていたんじゃないかな。これはテストプログラム
を書くべきでしょうね。

あるいは#define REG register でテストする必要があるわけね。

MIPSでは、$4,$5,$6,$7 は、本当に特別扱いしないとだめだね。

Thu May 15 21:25:45 JST 2003

fregv は、やっぱりサブルーチン・コールにするんだろ?
(さすがに授業が始まってしまうと、なかなか進まない...)

Sat May 17 13:57:12 JST 2003

$4,$5 を常に creg または、double のfregとして使う。
$f12 はfloating 用。

もちろん、emit_pushすればずれちゃうけどね。rename するべきか?
そもそもrenameは必要ないんじゃないの?

あともう少しなんだけどねぇ。やる気がでん...

Tue May 20 11:08:44 JST 2003

freg と同じように dreg を作る? (そうすると ia32
の書き直しがあるが、それは良いとして...)

でも、mc-codegen.c が creg/freg に依存しているから、
それを書き直すのが結構めんどくさい。書き直して
大丈夫なのか? ううーん...

逆にcreg/dreg/freg を無くすってのは? 全部、creg で
やるわけだな。ちょっと書き直しが多いけど。原理的には
それでいいはずだけど。着目しているcurrent register
は一つのはずだから。
(1)
   creg int
   freg double/float

ってなっているからおかしいのであって、
(2)
   creg int/double/float
か、
(3)
   creg int
   freg double
   greg float
だよねぇ。

やっぱり(2)かなぁ。long long のことをとかを考えると。
でも、とりあえず(1)でやるか。

いずれにせよ、fregv を追放することからはじめるんじゃない?

それはできました。

Thu May 22 23:40:13 JST 2003

3808                macro = (char *)car(nptrm->dsp);
3809                if (nptrm->sc==MACRO) {
3810                    while((*macropp++ = *macro++));
3811                    macropp[-1]=c;
(gdb) 
3812                } else if (nptrm->sc==FMACRO) {
3813                    if(c!='(') error(MCERR);
3814                    *macropp++=0;
3815                    macrop = macro_function(macrop,&body,nptrm,
3816                            list2((int)macro,history));

MACRO の場合のrecursive な処理を忘れいているみたいだけど。
それでも良かったはずなんだけど、macro_buf がstatic なので
不都合が出ているみたいね。

recursive に処理すると、
   #deifne car(e) heap[e]
   car(e)
みたいな時にまずい。これは、どうするんだっけ?

LMACRO ってのがあったみたいね。

Sun May 25 21:48:46 JST 2003

macro_eval がまだおかしいのは置いといて...

単純にcreg/fregを統一してしまうと、
     fdecl で creg をセット
した時に、float/double/int にどれかに固定される。そのまま、
coce_rlvar(creg) とかを呼ばれてしまうので、ちょっと困る。
code_rlvar で、if(!is_int_reg(creg)) creg = ireg;
とかすればいいんだけど、それは、ちょっと変だよね?

そもそも、mc-codgen.c でcregを持ち歩いている理由は?
なんかあったような気がするが...

そうか、
   use_int_reg()
とかしてやれば良いわけね。(rname を使うかどうかはともかく)

code_rlvar とかで設定するregisterを勝手に変えられると
うれしくない。(よね?) codegen 側で use_int_reg()とか
できればいいんじゃないの?

Mon May 26 21:06:14 JST 2003

code_* 側でやるか、mc-codegen 側で行うか? どっちかなぁ。
code_* 側の方が良いような気もするけど。

Thu May 29 10:30:09 JST 2003

freg/creg の区別は mc-codegen 側でやっていたんだから、
mc-codegen 側でやらないと、mc-cdoe-* 側での動的
チェックが増えすぎてしまう。

creg/freg を共有するのは良いのだが、その設定は
mc-codegen 側ですべきなんじゃないの?

mc-code-* 側を修正するとバグが取り切れない...
(といいつつ、もう、すぐなんだろうけど... でも、なぁ)

cast を自分で定義できる言語なら簡単なんだろうけど。

Tue Jun  3 13:03:41 JST 2003

あぁ、なんか乗り切れない。CONV の直前でcregが不定だ。
どっかで use_float を忘れているんだろうな。

Wed Jun 11 12:27:58 JST 2003

なんか、ようやっと creg/ireg/freg が片付いたよ。
creg を変更したときに、ireg を変更し忘れることが多かった
みたい。set_creg を必ず使うようにすれば良いだけだと思う
のだが。

Thu Jun 12 19:34:48 JST 2003

まぁ、MIPS用のレジスタ割り当てを書かないとだめだね。
ちゃんと書いてもいいんだけどさ。なんか one path に
するのが面白いんでしょ?

Sun Jul 13 18:26:29 JST 2003

また、一カ月なにも書かなかったのか。 mips は、mc-code-power.c
から書き直した方が良さそうだね。

   regs/regv は、i/f/d のすべてのレジスタに関して一つ

でないと stack に積むのを統一できないから。そういう意味では、
reg_stack と freg_stack を区別する意味はないわけね。でもstack
は型付けした方が良いから。でも、区別しておくと、long を増や
した時にも、stack を増やさないとだめなんじゃない? なので区別
しない方が良い。でも、それに手をつけると、また時間かかるんじ
ゃないの? そのためにはスタックそのものに型付けしないとだめだ
から結局同じか。

mips の double を格納するためのregister pairは、regs に
格納する。regs にアクセスには必ずアクセス関数を通す。
なるほど。

get_input_dregister_var なんだけど、dregister pair の
場合は、常にpairが決まった値になる必要があるよね。
この分はどうする? 前もってとっておくか?

あ、そうか、任意のregister pairを許さなくても良いよ。input register
に対応する連続したregister pair だけを許そう。そうすれば、あ
まり気にしなくても良くなるから。でも、gcc が奇数pairを許して
いたら気まずくない? 

regv は、register rename がなければいらないんじゃない?

Mon Jul 14 10:54:46 JST 2003

なんかなぁ... creg/ireg/freg/dreg は、あんまり良いアイデア
では、なかったみたい。creg は、このうちのどれかでなくては
ならないんだが、それを保証できない。

前と同じで、creg を廃止して、ireg/freg/dreg/lreg とするか?

Mon Jul 14 14:25:23 JST 2003

なんか unsigned が通らなくなっているみたい。

Sun Jul 20 17:37:34 JST 2003

やっぱり dictionary は、書き直さないとだめだよな。
それに関して、heap も修正した方が良い。このコード
はあんまりだものなぁ。

さて、あとは、オフセットだけど... めんど...

Mon Jul 21 15:12:56 JST 2003

Frame pointer は使うの? 使った方がいいんじゃない?
PowerPC は使わなかったけど。

Tue Jul 22 08:12:48 JST 2003

switch 文をtableにコンパイルするには...

最初の比較の行き先を後で指定するようにする
        cmp reg,case_value
        bne L_NEXT
   ....
   L_NEXT:
を、
        cmp reg,case_value
        bne L_CASE
   ....
   L_NEXT:
      ....
   L_CASE 
で、case 文が終ったらtableを作る。table がいらないようだったら、
   L_CASE = L_NEXT

各caseの入口は覚えておく。
      (list of (value, label))

table は、どうやって作るかと言うと、

   まず、値の分布をチェックする
   密度の高い表を作る(端のいくつかを除いて連続していること)
   というか、(定差分で)連続している部分にだけ表を作れば良いか。
   table は8entry以上。それ以下は、2分法に負ける。
       (list of (number of entry, diff, (list of (value,label))))

512 or 128kbyte まで容認する。限度はなくても良いか。連続している
部分にしか表は作らない。

連続してない部分は、2分法にする。

2 分法でもいいけど。2分法にする? その方が簡単かな。最後のス
テージは、(順序が一致していれば...) 元のコードが使えるし。そ
うすると、sort して、真中かから比較して行けば良い。そうすれ
ば表の分布とか考えなくても良いからいいかもね。

簡単じゃん。

まぁ、やっぱり、構文木の先読みをするんじゃないの? そうすれば
reference のとられてない変数もわかるし。

Wed Jul 23 16:21:12 JST 2003

やっぱり構造体のタグの名前はname tableにいれちゃだめだね。
まぁ、いれなきゃいけないんだけどさ。どうする?
どうするっていっても...

Thu Jul 31 15:07:08 JST 2003

C から変換したコードは動いたけど。まぁ、cast は動くのは
良いんだけど、こういうのじゃなくて、link を使った変換
でもいいんじゃない? そうすれば、spaghetti stack でもOk
だな。ただ、GC がないと使い物にならないだろうが。

Link にすれば、型整合のある変換も可能だよね。ただ、union
は意味ないか。record 型に直さないとね、

recursion と loop をdetect すれば、static にcompile
できる。あるいは、recursion の部分だけ配列にできる
んじゃないかな。

それぞれの利点と欠点を考察すればCWは通るんじゃない?
(本気?)

Mon Aug  4 12:48:40 JST 2003

converted call
480
8.070u 0.010s 0:08.22 98.2%     0+0k 0+2io 0pf+0w
call
480
6.590u 0.000s 0:06.67 98.8%     0+0k 0+0io 0pf+0w

だいたい10%ぐらい遅いなぁ。(なんで?) げ、-O6 だと十倍違う...

げ、powerpc の subroutine 内のstaticが通らんじゃん。

サブルーチンを三段に直しました。

% time ./a.out 0
720
9.590u 0.010s 0:09.64 99.5%     0+0k 0+0io 0pf+0w
% time ./a.out 1
719
12.610u 0.020s 0:12.71 99.3%    0+0k 0+0io 0pf+0w
% time ./a.out 2
720
6.310u 0.020s 0:06.41 98.7%     0+0k 0+0io 0pf+0w
% vi test/conv1.c
% gcc -O6 test/conv1.c
% ./a.out 0
720
% time ./a.out 0
720
1.990u 0.020s 0:02.03 99.0%     0+0k 0+2io 0pf+0w
% gcc  test/conv1.c
% time ./a.out 0
720
7.530u 0.000s 0:07.64 98.5%     0+0k 0+0io 0pf+0w
% gcc -O2 test/conv1.c
% time ./a.out 0
720
3.520u 0.010s 0:03.55 99.4%     0+0k 0+0io 0pf+0w
% 

ま、こんなものかな。-O2 に負けるなよって気もするが。

琉大は40Mbps

Intel PC (on PowerPC) の場合

[root@localhost ~/device]# time ./a.out 2                                       
470                                                                             
0.660u 0.010s 0:02.37 28.2%     0+0k 0+0io 92pf+0w                              
[root@localhost ~/device]# time ./a.out 3                                       
720                                                                             
0.920u 0.020s 0:01.74 54.0%     0+0k 0+0io 92pf+0w                              
[root@localhost ~/device]# gcc test/conv1.c                                     
[root@localhost ~/device]# ./a.out 0                                            
                                                                                
[root@localhost ~/device]# time ./a.out 0                                       
720                                                                             
1.310u 0.030s 0:01.39 96.4%     0+0k 0+0io 92pf+0w                              
[root@localhost ~/device]# gcc -O test/conv1.c                                  
[root@localhost ~/device]# time ./a.out 0                                       
720                                                                             
1.130u 0.030s 0:01.16 100.0%    0+0k 0+0io 92pf+0w                              
[root@localhost ~/device]# gcc -O4 test/conv1.c                                 
[root@localhost ~/device]# time ./a.out 0                                       
720                                                                             
0.870u 0.000s 0:00.87 100.0%    0+0k 0+0io 92pf+0w                              
[root@localhost ~/device]# gcc -O6 test/conv1.c                                 
[root@localhost ~/device]# time ./a.out 0                                       
720                                                                             
0.850u 0.020s 0:00.88 98.8%     0+0k 0+0io 92pf+0w                              
[root@localhost ~/device]#                                                      

PowerPC の場合は、PIC symbol がやっぱり遅いね。
こいつをなんとかするだけでだいぶ違うかも知れない。

Tue Aug  5 13:53:43 JST 2003

む、なんか、もう、そうなってるじゃん。

関数scope 内の staticの初期化が通らないんですけど。

直りました。対応してなかったみたいね。

Wed Aug  6 12:07:07 JST 2003

[kono@pw001 ~/device]% ./mc -s test/conv1.c
[kono@pw001 ~/device]% gcc test/conv1.s
[kono@pw001 ~/device]% time ./a.out 1
セグメントエラー (coreを出力しました)
0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 73pf+0w
[kono@pw001 ~/device]% time ./a.out 2
470
0.350u 0.000s 0:00.35 100.0%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 0
720
0.650u 0.010s 0:00.65 101.5%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 1
セグメントエラー (coreを出力しました)
0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 73pf+0w
[kono@pw001 ~/device]% time ./a.out 2
470
0.350u 0.000s 0:00.35 100.0%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 3
720
0.380u 0.000s 0:00.38 100.0%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 4
0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 77pf+0w
[kono@pw001 ~/device]% time ./a.out 0
720
0.660u 0.000s 0:00.65 101.5%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 1
セグメントエラー (coreを出力しました)
0.010u 0.000s 0:00.00 0.0%      0+0k 0+0io 73pf+0w
[kono@pw001 ~/device]% time ./a.out 2
470
0.350u 0.010s 0:00.35 102.8%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 3
720
0.390u 0.000s 0:00.38 102.6%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 4
0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 77pf+0w
[kono@pw001 ~/device]% gcc test/conv1.c
[kono@pw001 ~/device]% time ./a.out 1
0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 77pf+0w
[kono@pw001 ~/device]% time ./a.out 0
720
0.430u 0.000s 0:00.42 102.3%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% gcc -O test/conv1.c
[kono@pw001 ~/device]% time ./a.out 0
720
0.370u 0.000s 0:00.36 102.7%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% gcc -O2 test/conv1.c
[kono@pw001 ~/device]% time ./a.out 0
720
0.370u 0.000s 0:00.37 100.0%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% gcc -O6 test/conv1.c
[kono@pw001 ~/device]% time ./a.out 0
720
0.240u 0.010s 0:00.25 100.0%    0+0k 0+0io 88pf+0w

Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.95.3/specs
gcc version 2.95.3 20010315 (release)
Intel Architecture だと、結構、良い線いっているみたい。

Thu Aug 14 02:39:29 JST 2003

done
[kono@pw001 ~/device]% time ./a.out 0
720
0.640u 0.000s 0:00.63 101.5%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 1
719
0.720u 0.000s 0:00.71 101.4%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 2
470
0.330u 0.000s 0:00.33 100.0%    0+0k 0+0io 88pf+0w
[kono@pw001 ~/device]% time ./a.out 3
720
0.370u 0.010s 0:00.37 102.7%    0+0k 0+0io 88pf+0w


+jessica+kono time ./a.out 0
720
1.190u 0.010s 0:01.51 79.4%     0+0k 0+0io 0pf+0w
+jessica+kono time ./a.out 1
719
1.700u 0.000s 0:01.78 95.5%     0+0k 0+0io 0pf+0w
+jessica+kono time ./a.out 2
470
0.630u 0.000s 0:00.66 95.4%     0+0k 0+0io 0pf+0w
+jessica+kono time ./a.out 3
720
0.790u 0.000s 0:00.81 97.5%     0+0k 0+0io 0pf+0w
+jessica+kono time ./a.out 4
0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 0pf+0w

+jessica+kono gcc test/conv1.c
+jessica+kono time ./a.out 0
720
0.960u 0.000s 0:00.97 98.9%     0+0k 0+2io 0pf+0w
+jessica+kono gcc -O test/conv1.c
+jessica+kono time ./a.out 0
720
0.470u 0.000s 0:00.48 97.9%     0+0k 0+0io 0pf+0w
+jessica+kono gcc -O6 test/conv1.c
+jessica+kono time ./a.out 0
720
0.260u 0.000s 0:00.26 100.0%    0+0k 0+0io 0pf+0w

Mon Sep  1 13:49:43 JST 2003

short がやっぱり欲しいよね。long long はともかく...
そこまでいくと、ANSI-C 対応にできるんだが。long long
は難しい?

short は、そんなに難しくないはず。あとは、
    statement を含めたtreeの処理
    変換系の完成
この二つだな。GCC に組み込むのは無理だろう。

属性文法みたいな手法が使えればね。

あと、struct のtag。やっぱりword table を作り直さないと。

Wed Sep 10 21:53:16 JST 2003

short や unsigned short の前に、
なんか unsigned char もないんですけど。

Wed Oct  8 22:43:17 JST 2003

(また、一カ月、触ってないのか...)

無名 code はあった方がいいんじゃない?

   code *a(int i);
   a  = code(int j) { } 

みたいな感じ? C にはないけどね。もともと、名前を消費する
方だからあった方がいいかも。でも、実行時に作られるわけじゃない。
それに、こういうものを作ると closure だと思われるような
気もする。closure みたいなものは「自分で管理する」ってのが
CbC の思想だろ?

そういえば、static なcodeはあった方がいいんじゃない?

    static code func() { .... }

か。それはそうだな。

Fri Oct 10 13:08:01 JST 2003

link register をうまく使うにはcontinuationに
指定するだけではダメで、
     goto hoge(....,next);
code next..
みたいなのがあった方がいいんじゃない?

goto の後のステートメントは無名codeになればいいんだよね。

stack を使わないサブルーチンみたいなものか。単なるcall
になるわけね。それもいいかも。

Sat Nov 22 15:51:36 JST 2003

構造体のfieldの定義のnptrは、大域の名前テーブルから
取り除かないといけない。でも、取り除いていしまうと、
構造体からのポインタがずれちゃうので、まずい。

filed専用の領域を作るのだと、複数の構造体が同じ
field名を持つときにちょっと困る。構造体のタイプに
埋め込むのがいいんだけど...

そうすると、構造体のfiledかどうかをgetsymがチェック
するときにちょっと困る。

filed をlinear searchするのは嫌だけど、しかたないか。

なんか、struct の中に、
    void (*case_)(int cases,int def);
とかがあると、
    void (*case_)();
    int cases;
    int def;
という感じで余計なfieldが定義されてるみたい。

adecl で nptr が引数の最後を指してしまうのがまずかった。

Mon Nov 24 00:52:31 JST 2003

signed char は実装しましたが... test routine がない。

あと、short は、code_crxxxx の中でbyteの大きさに従って
処理するのがいいかな。

Mon Nov 24 10:53:31 JST 2003

short も実装したけど、まだ、コンパイルは通らない。

そろそろ stdio.h を通さないとダメだね。(いろいろあるだろうなぁ...)
とりあえず、#include <> をなんとかしないと。

long long の演算はともかく long long の代入はできた方がいい
か。でも、それなら、構造体の定義でいいんじゃない?
   typedef struct { char a[4]; } long long
みたいな感じ? それはできないが、コンパイラ内部ではそうするという
手もある。

Mon Nov 24 18:59:30 JST 2003

うーん、こんなエラー残っているのか。code_cpostint とか
はぜんぜん使われないわけ?

struct { char a[4],a; } は直しました。

short の引数の扱いも修正。

Mon Nov 24 22:20:29 JST 2003

同じレジスタをずーっと使わずにstatementごとに
ずらすと、ちょっと速くなるかもね。どうなんだろう?
rename されちゃえばあんまり関係ないのかも知れないけど。

二つのレジスタを交互に使うとかだと、まぁ、誤差ですね。

Wed Nov 26 13:27:00 JST 2003

include path は内蔵のものと、外部のものと二ついるわけね。

predefined が結構無いといけないみたい。

にゃ〜  inline は必須なの? macro で実装するのは難しいんじゃないかなぁ。
inline には、結構、いろんな変な部分があるんだよな。一旦はコンパイル
しないといけないはずだし。
    inline int f(int a,int b) {
	int c;
        c = a+b;
        return c;
    }
だよね。
    f(3,4)
があった時には、
    int _c,int _a,int _b; をlocal変数に付け加える
    _a = 3;
    _b = 4;
    _c = _a+_b;
をコンパイル。
    current register = _c
とする。かなぁ。

むしろ、
    c = { decl; statements* return value; }
を実装して、#define を拡張する
方が簡単じゃない? そのためには nest したdecl を扱わないと
だめだけど...

いや、やっぱり、中間木をなんとかするのかなぁ。

とりあえず、無視。普通の関数(static)としてcompileする。

やっぱり、long long はいるのね〜

やっぱり、enum もいるよね〜

なんか、知らないけど、やっぱり全部実装しないとだめなのね。

あと、const int かな。

Fri Nov 28 14:01:25 JST 2003

volatile ... (なにすればいいんだろう?)

なんか、*.c 以外だとソースを上書きしちゃうんじゃ...
  (これは直しました)

うーん、struct のtagとtype名を一緒にされちゃうのか...
こういうことをされると変数テーブルを直さないと動かせない...
TYPE_TAG みたいなアドホックなどだと直せない。
なんとかなんないかなぁ。

あと、struct のforward definition ってのがあるみたいね。

#if defined(A) && A で、後ろが評価されちゃうみたいだけど。そ
うすると後ろの名前がdefineされてしまう。ふーむ。こんなのどう
やって防げばいいんだ? 

やっぱりlong long を64bit にしないとファイルサイズが
合わない。

やっぱり include は、そのファイルのある場所から読み込む
性質があるのか。

Sat Nov 29 19:01:26 JST 2003

typedef enum {
  ...
        REGS_SAVED_ALL                  /* All registers */
} regs_saved_t;

やっぱり、あるのね。


void    (*signal ()) (int);

が動かなくなってます。

Sun Nov 30 05:30:56 JST 2003

ようやっと <stdlib.h> が通った。

nkf.c が while() { int hoge;... } を使っているのは、変。
なんで、こういうことするかなぁ。これをサポートするのは
不可能ではないけど、いろいろ手直しがいる。

なんか、少し早めに n->sc が定義されちゃって、変な
ことが起きているみたいだね。

stat の関数名とtag名が重なっているみたい。やっぱり
tag名の名前空間をわけないとだめかぁ...

Sun Nov 30 17:41:04 JST 2003

マクロを登録するときには、コメントをとらないとだめ。

while のslfree でマクロのchptrsave が破壊されてしまう。

やっぱり、nkf.c は、一発では動かないみたいね。compile は
できたけどさ。

   >> は符号依存 テストルーチンが入ってなかった

うーん、K&Rの引数の順序が関数の引数とずれているときは、
関数の順序の方を優先しないといけない... う、うーん。

{
   extern hoge...
}

int
h_conv(f, c2, c1)
    FILE  *f; int    c1, c2;

まぁ、いろいろあるねぇ。

#define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\
     ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
fprintf(stderr,"mime_getc h: %d c2 %d c3 %d\n",((hex(c2)<<4) + hex(c3)),c2,c3);
        return ((hex(c2)<<4) + hex(c3));

ふむ。(?::)+(?::) みたいな時には、code-set-fixed-register のregister
が二ついるわけね。push できないの?

    case COND:        /* a?0:1 should consider non-branch instruction */
    case DCOND:
    case FCOND:
        d = (car(e1)==COND?INT:car(e1)==DCOND?DOUBLE:FLOAT);
        e2=fwdlabel();
        if(d==INT) emit_push(); else emit_dpush(d);
        b_expr(cadr(e1),0,e2,0);
        g_expr_u(assign_expr0(stack_top(d),caddr(e1),d,d));
        jmp(e3=fwdlabel());
        fwddef(e2);
        g_expr_u(assign_expr0(stack_top(d),cadddr(e1),d,d));
        fwddef(e3);
        if (d==INT) emit_pop_free(emit_pop(0));
        else emit_dpop_free(emit_dpop(d),d);
        return t;

は、あんまり良くない。register machine ならいいんだけど。
結構、実装が変わるから、code-$(ARCH) に移した方がいいかな。


なんか、arg_reording() が、
    PowerPC
	   fnptr->dsp = arg_reorder(reverse0(sarg),reverse0(fnptr->dsp));
    IA32
	   fnptr->dsp = arg_reorder(sarg,fnptr->dsp);
ということになっているみたい。おんなじ順序じゃないのね。どうしようかな。
これは、わかりました。

    case COND:        /* a?0:1 should consider non-branch instruction */
    case DCOND:
    case FCOND:
        d = (car(e1)==COND?INT:car(e1)==DCOND?DOUBLE:FLOAT);
        e2=fwdlabel();
        b_expr(cadr(e1),0,e2,0);
        g_expr0(caddr(e1));
        t = creg;
        jmp(e3=fwdlabel());
        fwddef(e2);
        g_expr0(cadddr(e1));
        code_set_fixed_creg(t,1,d);
        fwddef(e3);
        return d;

なんだけど、t のcregが、ia32 ではvirtual register なので、変更される
ことがある。(こまったもんだね)

CONDには type をいれた方がいいみたいね。a?b:c type でlist5か。


 void    (*signal ()) (int);

これだと signal が二回 function だと思われる。

   recursive macro
#define stdout stdout

main()
{
   register double d;
   int i = stdout;
   d *= i;           register float への assop
   return (int)d;
}

というわけで、nkf は system の/usr/include/stdio.h で動きました。
なんか、うれしい。

ptr_cache のmr は確かに無駄だけど... 保留してまで取り除く
価値はないんじゃないかな。でも32bitとってるかならなぁ。
lvar cache みたいなものも面白いけど。まぁ、そこまで
やるなら、レジスタの寿命とか見ればいいんだよな。。。

Wed Dec  3 13:11:15 JST 2003

スレッドとの相性
っていうか、こいつをthread libraryとして使うにはどうすればいいの?
    env と return を生成する?

構文的に別にした方が安全だけど。

Sun Dec 14 16:26:19 JST 2003

long long やるの? 割算はサブルーチン呼び出しみたいね

float/double から long long, unsigned long long への変換もいるのか。
    F2LL
    D2LL
    F2ULL
    D2ULL
    LL2F
    LL2D
    ULL2F
    ULL2D
かぁ。(めんどくさいだけどさ)

(本気? どれくらいかかる? 2-3日かなぁ...)
     (実際には半年かかった...)

getsym の数字の扱いはunsignedでするべきだよね。
で、- があった時にoverflow を検出するのが良いよな。

あと、strol とかのoverflowの検出をさぼってるな。

Fri Jan  2 09:53:53 JST 2004

     goto hoge(...,next);
     fuagua....;

みたいな構文をいれる? Fortran みたい....
(簡単か?)

Sat Jan  3 17:12:46 JST 2004

FEATURE_LONGLONG 
FEATURE_FLOAT

みたいな感じで feature を落せる方が良い? 機能を増やす方向 
とは相性が良くない言語だから。

LEとかLTは、GE,GTで置き換えられるんだけど、片方が定数のときには
dual_op で入れ換えられちゃうので、やっぱり必要なみたい。

Mon Jan  5 15:55:37 JST 2004

byte code format というよりは、やっぱりbyte code encode
された構文木が欲しいんだよね。

ついでに interpreter も作るか。byte code interpreter ではなくて、
(ではなくて?) code 生成が速いんだから、code生成しながら実行する
方が良いね。やっぱり、incore compiler か。

inline なんだけど... #define に置き換えられる?
    inline int hoge(int hoga1) { hoge2 }
は、
    #define hoge(hoga1_0) { 
    #define hoga1 ((int) hoga1_0)
    int hoga1 = hoga1_0; hoge2 }
でいいわけだよね。で、問題は return だけど...

うーん、いま6ですな。

inline は、そのままstringバッファにしこんで、関数呼び出し時に
処理する方が正しいか。

    引数は、#define hoga1 ((int) hoga1_0) していく。
    展開終了時に元に戻す

あぁ、でも、大域変数がまずいか。

ということは、やっぱり、その場で構文解析してしまうのが良い。
    inlined LVAR (ARG)
の両方が必要。tree のコピーなしに展開することは可能? (できそうだけど...)

ということは、やっぱり、制御構造にもnodeを割り振るべきだよね。

order 1 compiler  + JIT + intensive optimizer

ですかね。

Wed Jan 14 10:21:49 CET 2004

function callを compiler の外に出せないかなぁ。
     code function_interface(args) {
          .....
          push(args); (in asm)
          push(next);
          goto function...
     }
     code function_continuation(args) {
     }
みたいな感じで... ま、遅くなるだろうけど...

でも、そうすれば、コンパイラの移植は比較的簡単になる。

Thu Jan 15 11:52:03 CET 2004

stack は、
    system wide に一つ ( classical environment)
    code に一つ ( Fortran type )
    object に一つ (like message buffer in ABCL)
っていう選択もあるね。

Sun Jan 18 11:08:13 JST 2004

(なんか、遅すぎなんだよね... CPS 変換か...)

shift/reset をCで実装するのは簡単だが...
     reset{
                 shift();
     }
みたいな感じ?

stack / data structure の保護の方法に、もっと何かがあるんじゃ
ないかな。

関数呼び出しなんだけど...

apply みたいなのがあればいい?
    goto apply(function_name,continuation(return_type),args....);
かな。で、この部分を、C/asm で書くというわけね。
ま、おんなじようなものか。(何と?) この部分だけ interpreter 的に
なっちゃうな。varargs でもいいんだけど...

コンパイラをCbCで書くと言う作業が残っているんだよな...

う、やっぱり、long long は、遠い... できんの?


Mon Apr  5 00:20:13 JST 2004

間違えて3日分消しちゃったい。

int でも RLVAR とかの unsigned/signed の区別がないとまずいよね。

包括的なテストルーチンがあった方が便利。long.c を消しちゃったし。

Fri Apr  9 02:11:42 JST 2004

やっぱり incore compiler と、non textural syntax が欲しい。
ま、そうだよね。

あと、#include の search path のセマンティクスを直さないと。

Mon Apr 12 12:19:35 JST 2004

3461        if (!integral(t=cadr(type))&&
3462                    !(t==FLOAT||t==DOUBLE) &&
3463                    !(t==LONGLONG||t==ULONGLONG) &&
3464                    (car(t)==STRUCT||car(t)==UNION)) {

じゃなくて、t>0 && (car(t)==STRUCT||car(t)==UNION)) {
じゃないか?


Wed Apr 14 14:26:04 JST 2004

creg なんだけど、直接レジスタを入れるのだと「複数レジスタを
使って double / long を扱う」ってのがやりずらい。だから、
register 変数を入れるのがいいんじゃない? でも、そうすると
変更が多くなるけど...

free_register の関係があるから、やっぱり、全部変えないと
だめだね。

creg/freg を止めたのは、MIPSが float/double を区別する
必要があるため。この時に、creg を構造体化するべきだった
みたいだね。
      creg = { ireg, freg, dreg }
みたいにしても良かったわけだ。

もしかして、regv って使ってないの? (そうかも...)

register は list で持つ? 配列にいれる?
      regs[0] = glist4(LREGISTER,use,r1,r2)
      regs[0] = glist3(REGISTER,use,r1)
みたいな感じ? うーん... それよりは、
      ireg_list
      dreg_list
      freg_list
      lreg_list
かな。でしょ? 意外にめんどくさい。ptr cache のコードもあるし。

まぁ、conservative にいこう。

lreg は、積極的に解放しないとまずいけど、どのタイミングで?
というか、creg もそのタイミングで解放して良いんじゃない?
ふーん。

gexpr_init() のタイミングで解放してもいいんだけど、それだと、
gexpr_0 で廻っているときに解放されないけど。
     g[long long hoge]
みたいな場合では、途中で解放して欲しいよね?

use_int とかで lreg は解放して良いんじゃない?

creg =0 で free_register(creg) が呼ばれているね。困ったな。

Sat Apr 17 17:01:02 JST 2004

long long register で、regsと regv をそろえる
必要はない。regs は普通に用意して、regv ではなくて、
lreg_hとlreg_lみたいな感じにする。

うーん、register full かぁ。何おかしくしちゃったかなぁ。

Wed Apr 21 17:32:40 JST 2004

unsigned のcosnt計算がおかしいんじゃない?

Thu Apr 22 12:33:04 JST 2004

ようやっと、int/float が元に戻りました。

lrexpr は、codegen で、long の計算に置き換えた方がいい?
でも、それだと、64bit 演算をサポートしているCPUがうれしく
ないか。

あと、もう少し! でも、2,3日かかりそう。
loprtc も、あった方がいいんじゃない?  (まね....)

Fri Apr 23 14:40:02 JST 2004

あとは、switch, inline, stdargs, alloca かな。 asm もあるか。
asm は、ちょっと趣旨から外れるからいいか。

PowerPC のalloca は、おかしい。おかしいよな。

join いれるの?

a?a,b:a,b って許されるの?

"" の中のマクロが展開されてしまうんですけど。(ま、そうなんだけど)

#hoge は無視するか、そのままにするか...

Sat Apr 24 14:39:14 JST 2004

long long op int, unsigned long long op int/unsigned

ってのがあるのか.... うーん...

Sun Apr 25 17:20:40 JST 2004

実装しないのにテストルーチン入れるなよ。。。 register lassop

compiler を書くには...
   (1) parser を書く
   (2) code 生成部を書く
   (3) compiler のcompile エラーを取る
   (4) compiler のコード生成をデバッグする
   (5) 生成したコードがアセンブラを通るかどうかを直す
   (6) 生成したコードが正しいかどうかを調べる 
で、(4) までできました。


やっぱり、use_int とかって、なんとなくだめ。だめな
理由があるんだろうなぁ。ほとんどバグはここから
来るんだものね。

use_int とかは、codegen でやったんじゃいけなくて、
もっとも下のcode生成部分でやらないといけないんじゃない?
それでいいのか?

あ、そうか、

creg に対する操作ばっかりじゃないので、code_xxxx(xxxx,creg)
というようになっている。そうすると、creg をその外で
creg = use_int(creg) する必要がある。だね。

    void
    code_lvar(int e2,int reg) {
	creg = use_int(creg);
	lvar_intro(e2);
	printf("\tla %s,",register_name(reg));
	lvar(e2);
    }

だと、reg が間に合わない。手遅れ。

reg にcreg 以外が入るのは、基本的には assign_opt 系ですね。
これを creg に直せば。。。。

    void
    code_lvar(int e2,int reg) {
	if (reg==-1) {
	    creg = use_int(creg);
	    reg = creg;
	}
	lvar_intro(e2);
	printf("\tla %s,",register_name(reg));
	lvar(e2);
    }

みたいな?

    #define use_int(reg) if (reg==-1) reg = use_int0(reg)
    void
    code_lvar(int e2,int reg) {
	use_int(reg);
	lvar_intro(e2);
	printf("\tla %s,",register_name(reg));
	lvar(e2);
    }
    use_int0(int reg) {
	creg = ireg;
	return creg;
    }

かな。 #define で? ま、どっちでもおんなじようなものか。

でも、これは変更多いなぁ。

Mon Apr 26 05:35:24 JST 2004

一応、no long long は通ったみたいだが。。

構造体の戻値を持つ場合に、引数がないとうまくいかない。

#include "" は、今読んでいるファイルのcurrent directory も探す。

まぁ、ia32 は、eax,edx にlong,long を積んで、あとは、
対メモリで計算するわけね。そうだろうな。むしろ、
やさしいかも。

あぁ、そうか、long の引数の渡し方は、
r10 はレジスタ、残りはメモリに入るわけね。

Wed Apr 28 13:01:13 JST 2004

だいぶ、通りました。ltosop は、終り。

drexpr, lrexpr で cond を処理してなかった。

浮動小数点の誤差はどうしようもないの? printf の問題?

あぁ、なんか、まだ、printf が局所変数を壊しているね。

そういえば、局所変数のアライメントは合わせてないけどいいの?

unsigned って、もしかして、もう少しルールが複雑?
              /   %   <<   >
    I op I    I   I   I    I 
    I op U    I   I   I    I
    U op I    I   I   U    I
    U op U    U   U   U    U
でもないか。

なんか、いろいろ直した割に、進んでないな。

code_bool がjmpを使うのはいかにもまずいよね。そうねぇ。

しかし、float/double printf("%d",f0>f1) の真偽値だけが反転する
バグが取れない。

code-gen.c の方は動いたが、float.c の方がだめ。
なんか、まるででたらめに動いているみたい....

function() の中で、lreg がinput registerと重なってしまう。

Thu Apr 29 19:40:08 JST 2004

良くわかんないけど通った。

Sun May  2 09:40:21 JST 2004

やっぱり LREGISTER なんて作るんじゃなかった。code_lconst
とかで edx,eda と dsi,edi pair の切替えをやらないと。

Thu May  6 08:33:23 JST 2004

ia32, powerpc とも long long まで、通りました。ia32 も一週間
かかったか。次は、MIPS, ARM ですな。

大域変数+オフセット ( heap[3] みたいなの) で、
heap+24  とか出ない。もともとは offset,y だったから
いらなかったんだけどね。

互換性を捨ててしまえば、大域変数ポインタを導入しても
いいんだけど。だだ、32bit 以上のオフセットだとRISC
命令だとまずい。
 
オブジェクト指向だとそのあたりは解決するんだけどね。

longlong/float のregressionはいいんだけど、もう少し
整合性があった方がいいかもね。

なんか、Linux のinclude directory って、どうにかなんないの?

assop で、
    calc left exp
    move creg,dreg
    move const,creg
    op  creg,(dreg)
って、やっているのなんか変じゃない?

a && b で、b のboolを計算しているのは変。use のフラグ
を見るのを追加したら。


Sat May  8 21:29:32 JST 2004

浮動小数点やlong longの代入で同じ値は一つにまとめるべきだよね。
連想 list を一つ持てば良いだけだし。

string をまとめるかどうかは、const かどうかによるわけだが...

RETURN register あたりの処理がダサイ。ま、しょうがないか。

MIPS のdebugにかかるんだけど、今は時期が悪いよな。なんで、
もっと早くできなかったのか。gcc modification はどうした?

だから register を 0 で入ってないとするのはまずいって
言っているのに...

float は normal register に積むのか。

        s.s     $f4,16($sp)
        mov.s   $f12,$f0
        mov.s   $f14,$f1
        mfc1    $6,$f2
        mfc1    $7,$f3
        jal     f

ま、いいんだけどさ。(でも、なんで$4,$5 を使わないんだ?)

long long も4,5,6,7 しかレジスタに積まない。ま、正解だけど。

げ、レジスタのセーブって自分でやるのか。(じゃ、mask ってなん
だよ...) ってことはentry はあとで出力しないとだめだね。

まぁ、いちいち驚かないけど... 細かいエラーが残っているな。

やっぱり codegen の拡張法を作っておかないとダメだね。

関数呼び出しパートをCbC自身で書けないのかなぁ。
あまりにめんどくさすぎ。

cpload は、gp レジスタの処理に関係するらしい。gp レジスタって何?
cploat $25 の $25 は、stack offset みたいね。$sp を変更するときに、
なんかのフラグを壊さないようにするための処理みたい。

だとすれば、code segment 側でstackを頻繁に移動するのはまずい?

float/double のフローは mc-parse では、少し、齟齬があるみたい。

は、良いとして....

    cprestore, mask の計算
    offset の合わせ

が終れば動くの? それだけ?

あぁ、 
    int endian;
    extern int endian;
も通す必要があるのね。まぁ、フラグの扱いだけだけど....

Thu May 13 12:58:58 JST 2004

 .frame の数字には input variable のsave分も入るんじゃないの?

   code_l1 の  ll0 がおかしくなるのは、strtoll がintに宣言されてるから。

function のargumentは複雑なものから計算して行くのがルールなのね。
ま、そうだよな。できないことはない....

そうなのか。最初にループを廻して複雑なものをレジスタなり変数なり
に代入して、引数リストを置き換えてしまえば良い。ついでに、
代入するべき変数はそこで計算しておいて... (って、これって、
parallel_assignment でやっていることと同じか)

その部分はcodegen でやってもいいんだけど... ia32 のような場合は
むしろ不要なのか。

でも、やっぱり、意外に複雑だよ。struct をどうするかとかさ。

struct は、call memmove するんだけど、そいつを先にやるわけには
いかない。先にやると、その間のfunction callが壊してしまう。
後に持って良くと、input register が壊れるので、やっぱり、
特別扱いする必要がある。ってことは...
    complex function argument
    struct copy
    simple arguments
っていう順番でやれば良いってことか.... うーん。

(うーん、でもなぁ。やるの?)

function argument の計算で、long long register が破壊されるのは、
なんか方法が悪いんじゃないの? 本来、lreg は値渡しできるべきだよね。
まぁねぇ。

複雑なものから計算する方が良いってことは、スタックに積む
引数から計算した方が良いってことか。

ま、それはできたとして...

Sat May 15 22:45:30 JST 2004

結局、.cprestore は、最初にないといけないので、include を
使うしかないらしい。

add.s の浮動小数点レジスタが印字されないけど。

Sun May 16 13:58:42 JST 2004

問題はレジスタのsaveだね。使ったレジスタはコード生成の後で
しかわからないので。後方にjmp すればいいんだけど。どんな
風に?

	subu    $sp,$sp,$L_r1_offset
        .cprestroe
        sw      $fp,$L_r1_offset-16($sp)
        sw      $31,$L_r1_offset-160($sp)
	addu    $fp,$sp,$L_r1_offset
	jal    $L_save-$L_save_label*4
	addu    $fp,$fp,$L_fregister_save
	jal    $L_fsave-$L_fsave_label*4
        move   $fp,$sp

 ...
        sw      $17,-12($fp)
        sw      $16,-8($fp)
$L_save:
        j       $31
...
        s.s      $f22,-16($fp)
        s.s      $f21,-12($fp)
        s.s      $f20,-8($fp)
$L_fsave:
        j       $31

みたいな感じにする? すると、必ず$31はsaveすることになるけど。
noreorder しないとだめかも。

この方がコンパクトだけど、
	subu    $sp,$sp,$L_r1_offset
        .cprestroe
        sw      $fp,$_Lr1_offset-16($sp)
        sw      $31,$_Lr1_offset-160($sp)
	j      $L_save
$L_fsave_0:
        move   $fp,$sp

 ...
$L_save:
       ...
        sw      $17,-12($sp)
        sw      $16,-8($sp)
        s.s      $f22,-16($sp)
        s.s      $f21,-12($sp)
        s.s      $f20,-8($sp)
        j       $L_save_0

の方がいいかな。save する必要がなければ、
	j      $L_save
$L_save_0:
        move   $fp,$sp

$L_save = $L_fsave_0

とできるし。

両方作って、時間計る?

まぁ、前者の方が凝っているし、命令数的にも変わらないから、
space factor 的に前者の方が速いんじゃないか?

でも後者の方が簡単だよな。

Mon May 17 01:09:02 JST 2004

さて、アセンブルは通るようになりましたが...

どうも、$0,$1が出てしまう場合があるみたい。これを検出する
手段を作った方が良いね。

あと、int の後のdouble/longlong は、$3 のあと、$5,$6 と
来るみたいですね。

さて、いよいよ、オフセット合わせか。

Tue May 18 13:05:24 JST 2004

なんかレジスタセーブがぼろぼろじゃん。max_reg_var とかが、
ちゃんとレジスタの個数を表すようにしろよ。

Wed May 19 13:49:40 JST 2004

endian に関するコードは、ちゃんとソースにそう書いた方が良いね。

やぁ、なんかEndianが合わないよ。ぜんぜん。

printf に $6,$7 と同じ値を渡しているのに、

    diff test/code-gen-all.gcc.out test/code-gen-all.mc-mips.out
    53,54c53,54
    < code_lrindirect ffffffffffffffc9 37 c8 80
    < code_lrindirect -55 55 200 128
    ---
    > code_lrindirect 37ffffffc9 37 c8 80
    > code_lrindirect 240518168521 55 200 128

となるのはなんでだろう? 37 が overwrite されているのか。
でも、37のポジションは正しいんだよな。37自体はレジスタには
乗ってないし。

Wed May 19 22:15:33 JST 2004

しかし、がんがんバグは取れていくわけだけど、なんか、
微妙にわけわからないバグが残っているな。

MIPSってconst のかけ算ないんだよね。だったら、*4ぐらい
はshiftした方が良いかも。

Thu May 20 21:46:17 JST 2004

register_dassop をテストしてなくて、コードも間違ってる。

chptrsave なんだけど、
     case hoge:
     macro_replace()
で、case hoge: が終了すると、getsymの先読みで、macro_replace
を展開して、そこが lfree ( chptrsave = list2(hoge,chptrsave) )に乗ってしまう。
docase で、lfree = slfree すると、そのlist2 は破壊されてしまう。
つまり、slfree=lfree;.... getsym  ...; lfree=slfree は、正しくない。
なので、list2 じゃなくて、glist2 して、free_glist2 してやるようにする。

でも、そもそも、macro_buffer は、どうなの? その領域は再利用されるのか?
そうでないと巨大なmacroを書かれたときに気まずい。cheap は、malloc
してもいいんじゃないかなぁ。

code-gen-all.c と simp1.c は通ったんだけど、basic.c が微妙に
通らない。なんでかな。diff もね。

Fri May 21 13:09:10 JST 2004

switch なんだけど、long long を通すと落ちるね。

なかなかself compileが通らないな。今度は、getsym か。やっぱり、$gp
関連?

代入文の型が右辺値の型になっていた。こんなバグが、まだ、
残っていたとは。

double register の順序を決めないとdead lock するな。

えーと、double register がconflict しまくるなぁ。
さすがに function では起きないらしいが...
ということは、set_[dl]operand の問題か。

やっぱり register parallel assign を書くのが簡単だよね。

slt/beq ってのが、うまく動いてないみたいね。


Sat May 22 12:49:55 JST 2004

なんか構造体の先頭はレジスタに置くみたいね... いいけど。
$5,$6,$7 か。

continuation frame は、$sp=$fp にするの? 関数引数は
$fpに積んでいるから、そうする必要があるわけだけど。
そうすると$fp を毎回動かさないといけないんだよね。
まぁ、PowerPCでも、そうしているわけだけど。

jal 後に $gp を書き戻すわけだけど、そのアドレスは
決まっているし、毎回セーブする必要もないけど。
$sp 相対だとまずいなぁ。

fmask,mask とかも要らないんじゃないの? そもそも
なんでいるんだろう?

(gdb) x/20i carg1
0x400a80 <carg1>:       lui     $gp,0xfc0
0x400a84 <carg1+4>:     addiu   $gp,$gp,30128
0x400a88 <carg1+8>:     addu    $gp,$gp,$t9
0x400a8c <carg1+12>:    addiu   $sp,$sp,-144
0x400a90 <carg1+16>:    sw      $gp,32($sp)
0x400a94 <carg1+20>:    move    $s8,$sp
0x400a98 <carg1+24>:    sw      $s2,16($s8)
0x400a9c <carg1+28>:    sw      $s1,20($s8)
0x400aa0 <carg1+32>:    lw      $t3,-32692($gp)
0x400aa4 <carg1+36>:    lw      $a0,0($t3)
0x400aa8 <carg1+40>:    lui     $t2,0xf000

というように .cp 関連は変換される。本当は自分でやった
方が良いんだけど。

ブランチは jal みたいには変換されないのか。まずい?

0x400b00 <carg1+128>:   move    $a1,$s5
0x400b04 <carg1+132>:   move    $a2,$s4
0x400b08 <carg1+136>:   move    $a3,$s3
0x400b0c <carg1+140>:   lw      $t9,-32664($gp)
0x400b10 <carg1+144>:   jalr    $t9
0x400b14 <carg1+148>:   nop
0x400b18 <carg1+152>:   lw      $gp,32($s8)

やっぱり sp 相対で $gp はセーブされるのか。jalr と
自分で明示する方が安心か。

  *.i が作られるのは良いが、 .include で
ファイル名がずれる。出力ファイルに相対して
 .i を作るべき。

a.c b.c のようにつなげると止まらなくなる。(-Dのループか?)

結構、比較のバグが残っているじゃん。定数比較でembugしたかもね。

long long の比較は int の比較から作る汎用ルーチンを作った方が
良くない?

つうか、まったく間違ってました。

Sun May 23 17:10:59 JST 2004

やっとMIPSが仕上ったよ。まだ、code jump は、できてないけど。

そもそも external jumpができるかどうか調べてないな。

slt $r1,$r2,12 みたいなコードも出したいが...

parallel_rassign って target=source で無限ループしない?

Sun May 23 21:21:22 JST 2004

やっぱり、boolean の扱いがなぁ。jmpでない方が良いよね。

Mon May 24 07:11:57 JST 2004

関数呼び出しの引数は、やっぱり$spオフセットで積むべきでしょう。
でないと、$fp!=$sp の時におかしくなる。($s8=$fp)

code から大域変数が読めない。

0x401170 <main1>:       lui     $gp,0xfc0
0x401174 <main1+4>:     addiu   $gp,$gp,28352
0x401178 <main1+8>:     addu    $gp,$gp,$t9
0x40117c <main1+12>:    addiu   $sp,$sp,-144
0x401180 <main1+16>:    sw      $gp,16($sp)
0x401184 <main1+20>:    sw      $ra,136($sp)
0x401188 <main1+24>:    b       0x401234 <main1+196>
0x40118c <main1+28>:    sw      $s8,132($sp)
0x401190 <main1+32>:    move    $s8,$sp

0x400aa0 <carg1>:       lui     $gp,0xfc0
0x400aa4 <carg1+4>:     addiu   $gp,$gp,30096
0x400aa8 <carg1+8>:     addu    $gp,$gp,$t9
0x400aac <carg1+12>:    addiu   $sp,$sp,-144
0x400ab0 <carg1+16>:    sw      $gp,32($sp)
0x400ab4 <carg1+20>:    move    $s8,$sp

ですか。$t9 ってなんだろう?

0x401290 <main+48>:     lw      $t9,-32744($gp)
0x401294 <main+52>:     addiu   $t9,$t9,4464
0x401298 <main+56>:     jalr    $t9
0x40129c <main+60>:     nop
0x4012a0 <main+64>:     lw      $gp,16($s8)

これか。ってことは、恐れていた通り、
    printf("\tj %s\n",s);
ではだめなのね。

$t8 は、$25 ってことは、$t9 は$26? jmp先みたいだね。 $jp?
cpload $25 の$25 じゃないの? じゃぁ、
        jrn = register_name(cadr(jmp));
        printf("\tmove $25,%s\n",jrn);
        printf("\tjal\t$31,$25\n");
すればいいのかな?

.ent しないっていう手もあるけど... 外から入って来た時に
どうする? (そもそも、code って、外から呼び出せるの?)

    printf("\tla $25,%s\n",s);
    printf("\tj\t$25\n");

でいいみたいだね。
    1,9d0
    < arg1: 0 1 2 3 4 : 1 1
    < arg1: 1 2 3 4 0 : 1 1
    < args: 1 2 3 4 0 : 1 1
    < 321=0
    < args3: 11 22 33 44 55 : 1 2 3 4
    < args4: 11 22 33 44 55 : 2 3 4 1
    < args5: 66 77 88 99 10 : 3 4 1 2
    < args6: 66 77 88 99 10 : 3 4 1 2
    < args3: 66 77 88 99 10 : 3 4 1 2
    make: [check-code] Error 1 (ignored)
    +pstwo1+kono ./a.out
    arg1: 0 1 2 3 4 : 0 0
    arg1: 1 2 3 4 0 : 0 0
    args: 0 263785888 4200109 2712942 0 : 0 0
    Segmentation fault
ま、いろいろあるね。


0x401180 <main1+16>:    sw      $gp,16($sp)

0x401298 <main+56>:     jalr    $t9
0x40129c <main+60>:     nop
0x4012a0 <main+64>:     lw      $gp,16($s8)

この一貫しないのやめてよ....  $sp!=$fp にすると、$gp がずれて
しまう。call の前に $fp=$sp にするという手もあるが....

結局、自分で、
     lw      $gp,16($sp)
するので解決。

Mon May 24 13:26:54 JST 2004

MIPS の jump は、できました。MIPSはR1SAVEしないのね。R1SAVE 
の方が若干安全な気もするが、毎回手間があるのはいただけないよ
ね。

leave で、control が必ず on になるのは何故?

次は、やっぱり、c2cbc でしょう。

(float) f == 1.0  で double に変換しているな。

register oprtc が、
        move $4,$20
        addu $4,$4,16
        move $20,$4
とかなるのは悲しくない?

Tue May 25 05:14:30 JST 2004

indirect jump で、$25 に代入するんだけど、
後ろに廻せば必ず simple になるから、そこでは
$25 に直接代入できるね。move 一つ減るだけだけど。

pcond は、pcond_const を持つべき。

cmp/jcond は、一つで処理した方が良い。switch 文も bne $6,1,$L_11 
とかできた方が良いよね。

struct proto tcp_prot = {
        .name           =       "TCP",
        .close          =       tcp_close,
        .connect        =       tcp_v4_connect,
        .disconnect     =       tcp_disconnect,
        .accept         =       tcp_accept,
        .ioctl          =       tcp_ioctl,
        .init           =       tcp_v4_init_sock,

は、便利だよね。あった方がいいよな。(そんなに難しくないし)
ただ、一旦全部リストにしないと格納できないか。混在した場合は
どうなるんだろう? 文句言えばいいの?

やっぱり、難しいんじゃないかなぁ。これって、その場でemit_data/
decl_data できないよね。local の場合はassign の列にコンパイ
ルすることはできるんだけど。global は、assign_data で、なん
かのキューに入れるか。mode を増やすわけね。

decl_data の先頭でgetsymするのはまずいわけね。
            while(t1) {
                offset = decl_data(car(t1),n,offset);  /* alignment? */
                ....
            }
の代わりに、

    getsym();
    if (SYM==DOT) {
      smode=mode;
      sstlist = stlist;
      stlist = 0;
      if (mode!=LOCAL)
	  mode = SNAMEMODE;
      while(sym!=RC) {
	  type = search_struct_type(..&offset1);
	  decl_data(car(t1),n,offset1);
      }
      if (mode== SNAMEMODE)
	  emit_sname_assign(stlist);  // global?
      offset += sizeof(struct);
      stlist = sstlist;
      mode=smode;
    } else {
      while(t1)
	offset = decl_data(car(t1),n,offset);  /* alignment? */
	....
    }
みたいな感じ? nest した場合は、emit_sname_assign でも decl_data
を呼んで、再度キューに入れるしかないか。

Mon May 31 19:08:57 JST 2004

register_assop は、いいんだけど、register_assop_const の
コードが良くないね。

Wed Jun  2 13:12:35 JST 2004

rexpr に value option を付けて、
   code_bool 
では、rexpr,drexp を呼んだ方がいいんだけど... && || とかどうする
かな。

あーあ、なんか恥ずかしいミスが残っているね。

Thu Jun  3 13:16:33 JST 2004

code_bool はできたんだけど、まぁ、自己満足だよね。

code_bool で !use の時に、null branchが残っちゃうけど...
ま、仕方がないか。

Fri Jun  4 12:57:28 JST 2004

switch 文をやるんだけど、

       main() {
           int i=3,j=1,k=0;
           switch(i)  
               for(;j<10;j++) {
                   case 3: k++; case 2: k++; case 1: k++; case 0: k++;
               }
           printf("%d\n",k);
       }

なんだけど、j<10 などを評価する前にjmpする必要があるので、最
初のcase文にjumpしないといけないが、jump する必要があるかど
うかは、switch の次の文を実際に評価してみないとわからない。

なので、 checkret() で、その処理を行う方が良い。
     if (first_case) {
         jmp(first_case); first_case =0;
     }
かな。もし、これが行われるなら、飛び先はtable jump routine であるべき。

switch をまとめるのはやったけど、現状のコードだとtable
は、ほとんどでないね。2分木は出るけど。IDが連続するように
工夫した方がいいのかな。

chunk の merge のalgorithm だけど.... O(N^2) だよね。

     c0,  c1,  c2, ... cn

で、(なんか見たことある...)

     c0,  c1,  c2, ... cn
     +------------------+ rate
     +---------------+    rate
     +----------+         rate
     +----+               rate
          +-------------+ rate
          +----------+    rate
          +-----+         rate
                   ...

というのを作る。((n-1)*(n-2)/2) か。で、一番、rate の高いものを
取るのが、正しいとは限らない.... rate じゃなくて、cover 率が
高いものの方が良い。消去法が良くて、まず、

     RATE 以下のものを消去する (生成しない)
     そして、cover 率の高いものをとって、すべてを取り尽くす

           +------------+ rate 75%
     +-------++------+    rate 80%

みたいなのをどうするかだけど... テーブルが少ない方を優先?
テーブルが一つが良いとは限らない。

count が多いのに delta が異なると一般的にはだめ。

     +-------++---------+ rate 80%
          <------>   みたいな形で取り合う場合もある。

この場合は cover rate が変わらないので、table rate で計算する?

えーと、生成した全ての区間の組合せが許されるわけではない。

     c0,  c1,  c2, ... cn
     +----+               rate   これが fix すると、
              +---------+ rate
          +-------------+ rate
          +-----+         rate
                   ...           などしか許されない。

後ろから計算しても前から計算してもおんなじはず。
ただ、飛び値が多い場合の計算量がなぁ。

まぁ、やっぱり、

  for i (0..n) {
    c_i を c_n に向かって可能な限り拡大する
    できなかったら、それを生成
  }

でしょ?

まぁ、だいたいできたんだけど、細かいバグが残っていそうだね。

    < # chunks 1 = sum  1/123 sum = 1
    ---
    > # chunks 1 = sum  1/2 sum = 1

なんてのもあるし。

merge が大きい方からやってくようにしちゃったけど、少し、
結果が良くないみたい。人間は、case 1: case 2: ... というように
書くからね。そんなに難しくないはずだが、直すのが面倒。

Sun Jun  6 02:41:27 JST 2004

次はバイナリサーチで、テーブルを生成するコードを書けば良いだ
けだが。2分法だときれいなブランチパターンにならない。8分法ぐ
らいで書くのがいいんじゃないかな。

 case_group_1:
      if (c==case_2) goto case_2 ( or nested case_group )
      if (c==case_3) goto case_3
        ....
      if (c==case_8) goto case_8
      goto default
 case_group_2:
      if (c==case_10) goto case_10
        ...
      goto default
 cslabel:
      if (c==case_1) goto case_1  (*)
      else (c<case_1) goto default
      if (c==case_9) goto case_9  (*)
      else (c<case_9) goto case_group_1 (or table lookup )
      if (c==case_17) goto case_17  (*)
      else (c<case_17) goto case_group_2
        ...
      else goto default;

かな... (*) は、オプション。ない方が良いCPUもあるだろう。MIPSとか。

フラットの方が良い場合もあるはず。(実測する?)

Sun Jun  6 09:39:13 JST 2004

で、nested branch は、どう実装すれば良いの? recursive に
書くんだよね? bottom up に書きたいところだけど。

   #define CASE_INDEX_COUNT 8
   switch_index(int chunk,int *cslist) {
       if (case count > CASE_INDEX_COUNT) {
	   chunk1 = gather_chunk()
       chunk1 = switch_index(chunk,&cslist);

   while(chunks) {
       chunk = switch_index(chunk,&cslist);

ぐらい? (chunk でやるの?!) ...  ん... だったら、merge_chunk
でできるんじゃないの? できるだろうけど、ちょっと複雑すぎるか。

table があるなら、必ず index は必要。

index がtableになることって... 偶然にはあるかも知れないし、
無理にすればできないことはないだろうけど...

Sun Jun  6 23:07:16 JST 2004

level 1 table がおかしい。そうだよなぁ。

今のアルゴリズムだと、10ずつ連続しているテーブルに
少数のanomalyがあるって時に困るね。テーブルが分解されちゃう。
ま、そんなコードないと思うけど。

cmpdimm を直すのを忘れてました。

あと、delta!=1 だと、割算したときの余りが0であることを確認しないと
いけない。gcc では、delta!=1 の表は出さないみたいだね。

あと、行き先が同じcaseは、range check にするとか...
(まぁねぇ。。)

ま、一応はできました。

kernel とか gcc とか compile できると良いけどねぇ。

Mon Jun  7 18:24:27 JST 2004

さて、次は、構造体の初期化か、c2cbc か。mc-tree の分離か。

局所変数の初期化がレジスタ変数であるに関わらずスタックを
初期化しているな。

  gcc -E -c -DCONFIG_TASK_SIZE=4096 -DCONFIG_KERNEL_START=1 -D__KERNEL__=1 tcp_ipv4.c -I../../include > ~/src/device/test/struct_init.c

kernel source は、まだ、早いんじゃない? asm とかあるし。
でも、asm も難しそうではないけどね。

stdarg は簡単なんだけど、初期化用の C source を持っていた方が
良いね。macro だけでなく typedef もしたいよね。

"test" "test" は、macro 中では使えない。っていうか使う必要ない?
どうせ、あとで解釈されるから。

hoge##name みたいなのの扱いだけど... hogefuga に変換されたあと、
また、展開する必要があるんだよね。

初期化ソースは、chptr に代入すると macro processing されない。
macro は、getline で行われるから。うーん。

うーん、line continuation と macro の関係は奥が深いな。
getch が null を返すのを認めれば良いんだけど、他のところの
影響が大きい。

##          l = va_arg(ap,long long);
## (*((longlong *)ap)++)

うーん。macro 関係か。space 除いているの誰だろう?

あ、そうか、register 上の引数は、varargs の場合は、
すべてメモリに入れないといけないわけね。じゃぁ、
浮動小数点か整数かはどうやって判断するの?

Wed Jun  9 10:14:35 JST 2004

切符買わないと。なんか、関数の引数の型のチェックをしてない
みたい。

stdarg できました。struct size のエラーはなに?

えーと、
	alloca 
	asm
	struct partial field init
        hoge##name
がないね。というか、これだけ? (頑張れ〜)

Thu Jun 10 17:57:35 JST 2004

struct partial field init は、できたんだけど、局所変数の場合
は、不定の部分を0にしているみたいね。つまり、static にとって、
コピーしているみたいね。これは標準的なセマンティクスなのかな?

やっぱり、重複した初期化は許されないのが普通なのか。

skipspc()=='.' だとコメントがスキップされない。ふーむ。
もういいよ。skip flag で。

なんで  macro_expansion が
    c = 1;
    macrop = list2((int)macropp,macrop);
    while(c && (*macropp++ = c = *body++)) {
なんて変なループなんだ?

Sat Jun 12 10:42:15 JST 2004

そうか、inline のために constant switch とかをやると、全体的
に statement をskip するってのを書かないといけないわけね。chk
を使えば良いんだろうけど。それほど、難しくはないけど....

alloca も r1 と $sp を動かしているだけじゃん。

残りは、
       alloca
       inline
       asm
と言うことになりましたが... MIPS のstdargも動いてないけど... 
問題は include file の方だものな。

typeof かぁ。
     typeof (hoge) i;
     sizeof(typeof(hoge));
     ((typeof (hoge)) fuga)
みたいな感じ。

なんか g() で、register_save が出ちゃってるね。

Sun Jun 13 12:20:39 JST 2004

ia32 の alloca は、関数の引数に呼び出されるのはまずい。あと、
stack の途中も、まずい。じゃぁ、どうするの?
      a = alloca(3)+3;
      f(i,alloca(3),j);
みたいなのでも破綻しちゃうのね。

powerpc でも結構奥が深いな。関数呼び出し時の引数は、
r1 相対でつまないとだめ。そうだよね。というか、
最初から r1 相対で積めよ。

        lwz r2,0(r1)
        neg r0,r0
        stwux r2,r1,r0
        addi r2,r1,208
        addi r0,r2,15
        srwi r0,r0,4
        slwi r0,r0,4
        stw r0,208(r30) <=== 最初のlocal 変数のアドレス。
        b L26
L25:
        li r0,0
        stw r0,208(r30)
L26:

ってわけか。

うーん、
      int i;
      goto f(alloca(100),&i);
なのってあるよね。だとすれば、local 変数はつぶさない方が
いいのか。その方が簡単か。そうすると絶対に local 変数と
goto の引数は重ならないから parallel assignment の必要
ないし。なんで、最初からそうしなかったんだろう?

しかし、そうするにはどこ直せば良いんだろう? max-func-arg?

まぁ、取り合えず、alloca と goto は両立しないってことで
いいんじゃない? 一段、subroutine はさめば良いだけだしね。

Mon Jun 14 20:48:13 JST 2004

PowerPC の alloca は動いたけど...

Tue Jun 15 10:47:53 JST 2004

やっぱ inline の方が asm macro より先? asm macro も constraints を
限定すればそんなに難しくないと思うけど。

inline は、本当は CSE とか flow 解析とかやらないといけないんだけどね。

ただ、inline するのが良いかは CbC との相性によるよな。

というわけで、asm が先の方がいいんじゃない?

ia32 のswitch 文がおかしくなってるぞ。

Wed Jun 16 13:05:40 JST 2004

asm は、({....; val;}) も一緒に実装しないとだめ。あと、
local_decls での redefined だけど、なんかいい方法あるの?
無視ってもいいんだけど...

association list を使って、unwind すれば良いんだけどね。
それは、全体的に手直しした方が良い。後回し。

cheap の扱いで boundary を見てないのがいつくあるね。

Thu Jun 17 17:10:21 JST 2004

えーと、
    "m" とかは、メモリの変更なので見なくてよろしい
    "r" はレジスタを割り当てる
    "=" は出力のマークなので無視して良い
    "+", "&" は出力のマークなので無視して良い
で、
    "0"   0番目のoperand
とかなんだけど... こいつは input (先にコンパイルする方)
に現れる。だから、output operand を先に処理する。out
put operand は単純な代入文だから、それでOk。

Fri Jun 18 13:33:19 JST 2004

なんか、%0,%1 とかって、同じレジスタに割り振られることも
あるみたいね。さらに、連続してでて来るとも限らないみたい。

ってことは?

なんか、間違えた。%0...%8 は、パラメターの順序を
さしているのね。そうだよな。

Sat Jun 19 00:17:33 JST 2004

asm は終りました。まぁ、ia32とかMIPSとかは、独自な問題が
あるんだろうけど。

Sat Jun 19 06:40:30 JST 2004

label がfunction localになってないみたい。

builtin_expect かぁ。

bit field が少しある見たい。

結局、全部、実装しないとだめか。
     q = (struct spin_lock) { };

とか。

    typedef struct __wait_queue wait_queue_t;

    struct __wait_queue {
	    unsigned int flags;
       ...
    };

って言う感じで typedef の struct が後だしジャンケンされてしまう。
後ろの struct def は、typedef された型名を知りようがない。うん。
0 なら、type に nptr が入っているので、それのfiled listを探せば良い。

やっぱbit filedしないとだめか。どうするのかな。type の拡張?

bit field 実装したくないよ〜

まぁ、構造体の代入と同じような形にすれば良いわけだけど。

bit field の初期化ってのもあるのか。(うげ〜)

うーん、やっぱ、果てないな。
    ASSOP, PREINC, POSTINC.... 
まぁ、
    BASSOP, BPREINC, BPOSTINC.... 
でもいいんだけど。

Sun Jun 20 20:21:38 JST 2004

どうも、mc-parse に、mc-codegen に相当する部分がかなり入り込んでいる
みたいだね。これを移すのはめんどくさいが... binop とか、もともと
mc-codegen にあるべきものなのか。

でも、これをしないと、構文に対応した構文木を取れないわけか。
inline で、構文木を再評価する場合もあるからなぁ。再評価した
場合に、構文木レベルで変更するべきなのか、コード生成レベルの
木でやるべきなのか、という問題もあるわけか。

macro も分割した方が良いね。

Mon Jun 21 00:29:12 JST 2004

mc-tree は、もう時代遅れ。切り離した方が良い。
conv も、だめなんじゃない?

なんか、随分、変えちゃったな。動かすのが大変そう。

できるだけ static にするんだけど...
     mc-codegen からだけ参照される mc-parse.c のextern
ってのが C では表現できない。一旦、extern すると使われてなくても
何にも言わなくなるから。

mc-codegen の使っている変数のうち、どれがstaticなんだが検出できない。

emit_data_closing の場所が変。

Tue Jun 22 01:05:09 JST 2004

ようやっとリカバリできたよ。

local scope { int hoge; ... { int hoge;... }} for(int i=0; hoge...)
は、やらざるを得ないだろうね。

Tue Jun 22 06:49:55 JST 2004

bit-field の alignment は、アーキテクチャによって任意って
感じだな。

MIPS

01:ffffffffffffffff
02:fffffff0 0000001f 00000000 00000000 00000000 00000000 00000000 00000000
02:00000000 00000000 ffffffff 00000001 00000000 00000000 00000000 00000000
02:00000000 00000000 00000000 00000000 ffffffff 00000001 00000000 00000000
01:ffffffffffffffff
02:fffffff0 000fffff 00000000 00000000 00000000 00000000 00000000 00000000
02:00000000 00000000 ffffffff 0000ffff 00000000 00000000 00000000 00000000
02:00000000 00000000 00000000 00000000 ffffffff 0000ffff 00000000 00000000
1:ffffffffffffffff
2:fffffff0 0fffffff 00000000 00000000 00000000 00000000 00000000 00000000
2:00000000 00000000 ffffffff 00ffffff 00000000 00000000 00000000 00000000
2:00000000 00000000 00000000 00000000 ffffffff 00ffffff 00000000 00000000

PowerPC

01:ffffffffffffffff
02:0fffffff f8000000 00000000 00000000 00000000 00000000 00000000 00000000
02:00000000 07ffffff fc000000 00000000 00000000 00000000 00000000 00000000
02:00000000 00000000 03ffffff fe000000 00000000 00000000 00000000 00000000
01:ffffffffffffffff
02:0fffffff fffff000 00000000 00000000 00000000 00000000 00000000 00000000
02:00000000 00000000 ffffffff ffff0000 00000000 00000000 00000000 00000000
02:00000000 00000000 00000000 0000ffff ffffffff 00000000 00000000 00000000
1:ffffffffffffffff
2:0fffffff fffffff0 00000000 00000000 00000000 00000000 00000000 00000000
2:00000000 00000000 ffffffff ffffff00 00000000 00000000 00000000 00000000
2:00000000 00000000 00000000 00000000 ffffffff ffffff00 00000000 00000000

実装は、mc-parse.c では決められないのか。

まず、
        boundary を含めて読み込み (必ず指定された型のサイズに収まる)
次に、
        読み込んだ部分の指定されたbitを置き換え
           まず 0 にして、置き換えと or を取る(?)
そして、
        書込
って感じですかね。64bit はめんどくさいな〜

ってことは、
       and mask をつくって、or mask をつくって、
       逐次実行
って感じですか。はぁ〜。
       
BIT_FIELD のsizeをやらないと、初期化ができない。

Wed Jun 23 14:06:10 JST 2004

(昨日は飲みすぎ...)

emit_data は、mc-codegen にあるべきだよね。

bit_field の大域変数の初期化ができない。いったん、どっかに
貯めないとだめ。assign_data level?

なんか、assign_expr の 引数 type が大域変数を上書きしてました。
それが恥ずかしいバグの原因だったのか。

Fri Jun 25 00:00:46 JST 2004

なんか、Union のテストコードを書いてない気がする。
Union は、間違ってました。

bit field はできました。

なんか MIPS のgccは、bit field にバグあるみたいだね。

Fri Jun 25 11:30:30 JST 2004

3249,3252c3249,3251
<     //  n = get_register_var(0);
<     g_expr_u(assign_expr0(n,list2(ADDRESS,cadr(e2)),INT,INT));
<     e4 = rvalue_t(list2(INDIRECT,rvalue_t(n,INT)),type);
<     g_expr(assign_expr0(list2(INDIRECT,rvalue_t(n,INT)),
---
>     g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT));
>     e4 = rvalue_t(list2(INDIRECT,n),type);
>     g_expr(assign_expr0(list2(INDIRECT,n),
3255,3256c3254
<     if (car(n)==LVAR) free_lvar(cadr(n));
<     else if (car(n)==REGISTER) free_register(cadr(n));
---
>     free_lvar(cadr(n));

なんだけど、lassop あたりでも問題ありそう。

bassop を呼び出す BPOSTINC で、post の処理をさぼってます。

っていうか、bassop は間違っているじゃん。

bassign だったら、読み出してbit replace で良いんだが、
op をかけるんだったら、bit_field として読み出して、
一旦、整数値にしてから計算しないとだめ。

post の処理は複雑なので専用のを書いた方が良い。

    if (simple) {
	tmp_var = bit_field
	tmp_var op= operand
	bit_field = new_var
    } else {
	address = lvalue;
	tmp_var = address->bit_field
	tmp_var op= operand
	address->bit_field = new_var
    }
    if (post) tmp_var;

ですかね。

Fri Jun 25 14:49:57 JST 2004

もう少し複雑だった。でも、終りました。codegen level で
終るのは良いよね。

まぁ、bit-field も、

     constant assign の時の最適化 (and/or mask の計算)
     1 bit の時の特別命令を使う?
     bit.r == 1 を、and 0x100 にコンパイルする

とかいろいろやることはあるけど、意味ないよな...

Sat Jun 26 16:32:57 JST 2004

で、local 変数の扱いだけど....

    大域変数、局所変数、タグ名、フィールド名、型名、ラベル

とあるわけだよね。で、スコープを任意にしたいわけだ。

     nptr を、局所->局所->大域 にlinkするようにすれば良い

malloc するようにする? それともlinkするようにするか。

うーん、hash 計算無しで lsearch しているところがあるな。
hash は別関数になってないし。


Sun Jun 27 10:58:04 JST 2004

大した変更してないけど、ia32 code がバグった。

Sun Jun 27 14:52:59 JST 2004

is_memory のバグでした。

そういえば、double register pair のparallel assignmentって
やってる?

うーん、やっぱり、codegen が register pair を知ることが出来
るように、list2(LREGISTER,high,low) みたいな形にしたいよね。
なんで、だめなんだったっけ? 
	list2(DREGISTER,list2(REGISTER2,high,low))
	list2(LREGISTER,list2(REGISTER2,high,low))
	list2(FREGISTER,list2(REGISTER,high))
とか?
	list3(REGISTER,1,reg);
	list3(DREGISTER,2,reg,reg);
	list3(FREGISTER,1,reg);
かな。

いいんだけど、変更多くない? でも、use_reg とかの複雑さを考えると、
そうした方がいいんじゃないかなぁ。

でも、変更多いよね。利点としては、regs[] を lregster 分取らなくて
すむことかな。でも、本当に簡単になるのかな?

code_*() でレジスタを使っている部分を修正する必要があるから、
かなり大きな変更になるのか。でも、code_*() に引き渡す変数と
構文木中の要素が同じになるのは重要だよね。

構文木でのレジスタ変数のユニークさを維持しないと、
    if(r!=reg)
        printf("\tmr %s,%s\n",register_name(reg),register_name(r));
    return;
みたいなのが困るね。ということは reverse poiner がいるってこ
とか。

overlap を見るときに、自分自身が overlap していても問題ない。
ただし、重ならないようにコピーしないとだめ。そうしないと、
巨大な構造体を二回コピーするはめになる。

      |---||--------------|

           |--------------||---|

      |--------------|     |---|

      |--------------||---|

みたいな感じだね。これは、まだ実装してないんだよね。

Sun Jun 27 21:06:28 JST 2004

やっぱり、name/namebuf 関連は書き換えるんでしょ?

まず、get_name/get_string  は、cheap 上にコピーする。
で、new_def でなかった時には cheap を元に戻す。
name, namebuf は、なくす。

  string hash (oblist) ->  hash table ->
    nptr -> macro/reserve/local/global/typedef etc

となる。local nptr は、local_scope list に登録し、
scope を抜けるときに消す。

get_name/string でt既に登録してしまう。gserach/lsearch/msearch
は、登録されたhash からのlinked list で良い。gsearch も linked
list にする必要がある。nptr には、next をつける?

あぁ、ARM には fpp はないのね。いや、GBAにはないけど、
Zaurus にはあるっていうパターン?!

ってことは... MIPS と PowerPC を足して二で割ったような実装
をしないといけないのか。うーむ。

macrobuf は、cheap で共有できるはず。そうすれば、linebuf 以外は
一つになる。linebuf も一緒にできるかな? それは、無理なんだけど...
cheap なんだけど、extendable にするためには...

     struct cheap {
         char *cheap;
         char *last;
	 struct cheap *next;
     }

として、これへのポインタをcheapとして用いれば良い。cheapp とかが
あるので、やっかいだが..

Mon Jun 28 20:18:03 JST 2004

あのさ、それをやっちゃうと、chptr も cheap を参照するんだから、
そっちも、直さないとだめじゃん。

いや、それはない。mappend で、必ず cheap chunk に収まるはず
だから。結構、無駄が出る可能性もあるけど、別にいいんじゃない?
巨大に展開した macro の最後の方だけ cheap からはみでるとか。
だからどうなの? 2M とかに展開されるわけでもないだろ?

mappend で chunk boundary にかかると copy で append を
壊してしまう。どうせ、cheap rest してから、chptr を
切替えるんだからいいんだけどさ。

Tue Jun 29 17:36:36 JST 2004

  #define car(a) heap[a]
だけど...
       typedef struct tree {
          int id;
          int next;
       } TREE;
として、
   #define as_tree(a) (TREE)(heap[a])
	  TREE t = tree(a);
	  if (t.id == HOGE) {....
っていうようにアクセスする手はあるよね。
   #define tree(a) ((TREE)(heap[a]))
	  if (tree(a).id == HOGE) {....
でもいいか。

conservative に変えたいのか、drastic に変えたいのか
どっちだよ。


name space は、tag, macro, その他? typename は重なっていてはいけない。
field も別だけど。sc で区別するわけだけど...

hash_search が返すのは name spcae assoc だよね。

巨大なname があると、 macro 展開された chptr を上書きする可能性がある。
             cheap->ptr         chptr
    |--------|-name1-| |-name2-|pppppppp|
             cheap->ptr         chptr
    |--------|xxxxxxx| |-name1-name2-|--|
先までコピーしてやればいいんだけど...
                                     chptr
    |--------|xxxxxxx| |-name1-name2-|pp| |pppppp|

でも、chptr は、boundary にかかることはないんだから、こういうことは
起きないんじゃないの? chptr はかからなくても、cheap->ptr は、かかる
可能性があるか。

これのコピーを実装して、mappend ではpage 転送しないようにすれば、
mappend で reset_cheap しても良い。

Thu Jul  1 20:28:49 JST 2004

    { int hoge;
        { int hoge; ....} }
だけど。。。

異なるレベルだってのをどうやって見つけるの?  define case は、
わかるから大丈夫か。なんかオプションいるの?

   hash -> name_space -> nptr
           global (typename, global, function)
           tag
           field
           local -> name_space
		    label
                    tag
                    field

であるべきだよね?

Fri Jul  2 06:46:27 JST 2004

こんなに変更しちゃって、動くわけないよね。

単体テスト書く?
    cheap
    hash
ぐらい?

やっぱり、大変だわ。あと、もう少しだとは思うけど。

Fri Jul  2 23:38:14 JST 2004

あと、もう少し..

セルフコンパイルのバグがとれないよ。

もしかすると、void fuga(b,d,e,f) { return hoge(a,b,c,e) ;  }
っていうプログラムで完全に、tail recursion するなら、
CbC と、おんなじなんじゃない? (条件は?)

その方が簡単か? いや、関数呼び出しと互換性を維持しないといけない
ので、やっぱり、こっちの方が難しい。レジスタのセーブとかあるし。

そうか、I2C, I2S, U2UC, U2US が必要なみたいだね。それに応じて、
    code_i2c
    code_i2s
    code_u2uc
    code_u2us
がいるのか。

endian 特有の問題なのか。じゃぁ、hash のバグとは関係ないのね。

K&R argument が redefined 扱いで、新しい変数になって
しまう。

Sat Jul  3 15:16:50 JST 2004

ようやっと recovery できました。

global heap の拡張は難しいよね。特に、heap の使い方が
割りと雑な今は難しい。nptr,heap,local ともinteger で
アクセスするならともかく。

また、くだらん、gcc の拡張か... 使うなよ... __label__

やっぱり、型名は大域変数とは別な名前空間だよな。

まぁねぇ。 code が、結構、コンフリクトしているな。ま、そうだけど。

三項演算子の一部を省略できるのか。

いくつか問題はあるが、kernel source は、通りました。

Sun Jul  4 19:17:02 JST 2004

arg の中に関数があって、それがさらに関数引数を持っていると、
それがdefineされてしまう。それが使われるとEXTRN1になって、
未定義関数になってしまう。

とりあえず、こんなものかな。

あとは、
         inline
         c2cbc converter
ですね。

inline は高く付きそうだけど。

inline をマクロで実装するのは比較的簡単なんだよね。だけど、
c2cbc を考えると、やっぱり、構文木で実装するべきでしょ?

global heap は拡張可能じゃない? local heap がない時に、
やばそうだったら拡張してしまう。realloc でいいし。
pointer とっているのは scope だけじゃないか?

うーん、やっぱり、global heap の拡張は、それほど単純じゃない
みたいね。


41c41,43
< int args,init_vars,heap[HEAPSIZE];
---
> int args,init_vars;
> int *heap;
> static int HEAPSIZE = HEAPSIZE0;
236a234,245
> void
> clear_lfree()
> {
>     if (gfree>HEAPSIZE-LHEAPMARGIN) {
> 	HEAPSIZE *= 2;
> 	heap = realloc(heap,HEAPSIZE*sizeof(int));
> 	if (!heap) error(MMERR);
> 	fprintf(stderr,"heap extended to %d\n",HEAPSIZE);
>     }
>     lfree= HEAPSIZE;
> }
> static void
331a353,354
>     if (!heap) heap = (int *)malloc(HEAPSIZE*sizeof(int));
>     if (!heap) error(MMERR);

ぐらいではぜんぜんだめ。

別に問題なくできるじゃん。なにやってんだ?

LDECL の中間 nlist って本当にいるの? こんなのがあるから、中
間の nptr を一つ無駄にしているんだよね。make_local_scope だ
けで良いんじゃないかな。macro は、それで動いているわけだし。

なんか、struct が、ちょっとだめなみたいだな。type名がlocal
になってしまうから?

なんか、type と tag をglobalにするので通ったけど... scope
に関しては、もう少しテストを書かないとだめだな。

Mon Jul  5 14:11:07 JST 2004

local label ね。まぁ、簡単なんだけど...

lazy flag で、
     do if 
       make l = listN(IF,cond,then,else)
       if(lazy)
            return l;
       else
            eval_if l;
     eval_if
みたいな感じ?

Tue Jul  6 17:46:50 JST 2004

type と tag を大域にするんじゃなくて、tag だったら大域、
type は、LTDECL のみで局所っていうようにするべきだよね。

static が global になっちゃってるな。

あ、いけない、なんか壊しちゃったよ。。。

bit field って

	e4 = rvalue_t(e2,type);
	g_expr(assign_expr0(e2, list4(BFD_REPL,e4,e3,t), type,type));

なんだけど、これだと、
        e2 を出力して、push して、
        e2 をもう一回読み込んで load
        そして replace
        pop して assign
って感じなんだよな。別にいいんだけどさ。
        e2
        load
        replace
        store
っていうようにしたいんだけど。

でも、この部分って long long も通っているから変更するとなると
量が多いんだよな。

GVAR + offset が、list2(INDIRECT,list2(ADD..)) に展開されるので、
simple の方にもっていかれない。ということは、GVAR を GVAR + offset
という構成にした方が良いってことだよね。

list2(GVAR,nptr) なんだけど、これを、list2(GVAR,nptr,0)
にすれば良い? まぁねぇ。あんまり使われないとは思うけどね。
実際、出るコードは変わらないし。

結構、複雑。複雑すぎるんじゃないの?

Wed Jul  7 23:19:35 JST 2004

できたけど、mips の register usage がおかしい。もっと
レジスタを使えるはず。

save_stack で、regisiter を解放するのを忘れてました。

parallel_rassign では、一つ解放したら、そこを他の依存ループ
を解決するのに使うのが良い。けど...

どうも、余計に extsb しているみたいだな。

本来は必要な時に変換するべきだよね。でないと、
       lbz
       extsb
       stb
しちゃうから。

Thu Jul  8 02:31:03 JST 2004

ARMは、どうもadd, sub は、8bit 幅で定数を持てるみたいね。

table がmax-min を16bit だと仮定しているみたい。倍数を
含んでいるときは、その限りでない。

Fri Jul  9 14:45:56 JST 2004

LDECL は、disp < 0

const も実装しないといけないんだよな〜

arm は、大域変数を、
        ldr     r3, .L28+88
    ....
.L29:
        .align  2
.L28:
        .word   i1
        .word   i2
        .word   s1
        .word   s2
        .word   us1

みたいな形で間接参照するわけだけど、参照した順にリストに格納しないと
だめ? 変数表に格納したい所だが... make scope で出来ないかな?
linear list で持ってもいいんだけど。

ptr_cache の方でリストを持てば?

なんか、add # の意味が良くわからないよ。別に常にメモリ
参照で問題はないんでしょ?

良くわからないけど、
      8bit 幅の定数で、シフトが2ずつ
みたいな感じ?

でいいけど、どんなアルゴリズムで生成するんだよ。

    8bit mask を2ずつシフトして、
      残りが取れるかどうかをみる

えーと、16x8x8 ぐらいのオーダ?
    for(sign=-1;sign<=1;sign+=2) {
	if (sign==1) d = c; else d = -c;
	for(i=0;i<32;i+=2) {
	    if (!(im=mask8(d,i)))  continue;
	    id = d - im;
	    if (id==0) goto found;
	    for(j=i+8;j<32;i+=2) {
		if (!(jm=mask8(id,j)))  continue;
		jd = id - jm;
		if (jm==0) goto found;
		for(k=i+8;k<32;k+=2) {
		    if (!(km=mask8(jd,j)))  continue;
		    kd = jd - km;
		    if (km==0) goto found;
		}
	    }
	}
    }
	emit_const(c);
    found:
	if (sign==1) emit_add(im,jm,km);
	else emit_sub(im,jm,km)
ですかね。1024 ループか。。。 const 毎に?

しかも、その中で、もっとも短い命令を探さないとだめなのか。

pointer offset も、そうなのかな? (その可能性はあると思う)

12*8*4 = 384 ぐらいか(最悪で)

    sub mask8 {
	my ($d,$bit) = @_;
	$d & (255 << $bit);
    }

    sub make_const {
	my ($c) = @_;
	my ($sign,$im,$jm,$km);
	my ($min_stage) = 4;
	my ($msign,$mim,$mjm,$mkm);
	for($sign=1;$sign>=-1;$sign-=2) {
	    my $d;
	    if ($sign==1) { $d = $c; } else { $d = -$c; }
	    last if ($min_stage==1);
	    for(my $i=24;$i>=0;$i-=2) {
		$jm = $km = 0;
		next if (!($im=mask8($d,$i)));
		my $id = $d - $im;
		if ($id==0) { 
		    $min_stage=1; $msign = $sign;
		    $mim = $im;$mjm = $jm;$mkm = $km;
		    last;
		}
		next if ($min_stage<=2);
		for(my $j=$i-8;$j>=0;$j-=2) {
		    $km = 0;
		    next if (!($jm=mask8($id,$j)));
		    $jd = $id - $jm;
		    if ($jd==0) {
			$min_stage=2; $msign = $sign;
			$mim = $im;$mjm = $jm;$mkm = $km;
			last;
		    }
		    next if ($min_stage<=3);
		    for(my $k=$j-8;$k>=0;$k-=2) {
			next if (!($km=mask8($jd,$k)));
			$kd = $jd - $km;
			if ($kd==0) { 
			    $min_stage=3; $msign = $sign;
			    $mim = $im;$mjm = $jm;$mkm = $km;
			    last;
			}
		    }
		}
	    }
	}
	if ($min_stage<=3) { emit($sign,$im,$jm,$km); }
	else { print "emit const $c\n"; }
    }

ぐらいでした。

Sun Jul 11 12:54:26 JST 2004

やっぱりlarge offset はうまく動いてないみたいね。

local global table は、12bit offset(+sign 1bit) だから4096/4
で1000命令毎には出力する必要がある。しかも、既に出力されてい
るものは、前のを使う必要がある。なるほどね。っていうことは、
テーブルにそういうフラグをつけないとだめか。(それぐらい
アセンブラでやってよ〜) 

すべてのprintfにcounter をつければ良いわけだけど、いくつかは
問題があるだろうな。ちょっと量多いしね。

ARMには short ってないのか。short を多用しているプログラムは
だめなのね。

(でも、どっちかって言うとテスト環境を作る方が難しそう)

slとかipとか思い入れがありそうなレジスタの名前も大した意味がある
わけではないらしい。

ARMって、なんかsigned char とunsinged char の区別がないな。

lvar offset が、ちょっとめんどくさいかな。
constant が決まってないから、せっかく作ったcode_add
が使えない。いや、決まるのかな?

Sun Jul 11 20:37:20 JST 2004

やっぱり、local variable のオフセットがその場で定数でないのは
まずい。

                     負の値
         fp          <-------|
   +------+------------------+
          <----lvar_offset--->

なのがまずいんだよね。

          負の値
         fp------->          |
   +------+------------------+
          <----lvar_offset--->

にすれば良いだけだよね。なんけど、def で pre decrement しているが
まずい。が、<0 でないとまずいので、単純な post decrement でもだめ。

でも、これ修正量が多いよね。

          負の値               
         fp------->          sp----->
   +------+------------------+
 callee   <----lvar_offset--->  caller
   arg                            arg
   <------> pre known offset
   ---->

と、直せば良い。

ん、だが....

                       <------r1_offset------------------------------>
                                                 <-lvar_offset------->
 r+  +------------+---+-------+------------------+--------------+----+    -
      callee arg   xx   local   register save       caller arg     xx
                        disp      reg_save          max_func_args*SIZE_OF_INT
        lvar>0          lvar<0                      lvar>0x1000 0000
                      r30                                            r1
                                       
とするのは、PowerPC では変更が大きすぎる。レジスタセーブする場所
が良くわからないし。

もしかして、register save 領域は固定?! 


Mon Jul 12 05:35:33 JST 2004

うーん、やっぱり、難しいよな... 何故か、printf が local variable
を壊してしまう。

register save 領域は固定なわけきゃないだろ。最初からやり直して、

 function call stack frame
                      <-------r1_offset------------------------------>
                                      <------------lvar_offset0------>
                      <--lvar_offset-->
 r+  +------------+---+---------------+----------+--------------+----+    -
      callee arg   xx   register save   local      caller arg     xx
                          reg_save      disp       max_func_args*SIZE_OF_INT
        lvar>0                         lvar<0       lvar>0x1000 0000

ということになりました。frame の設定のところだけ無条件に32bit add
になったが仕方ないな。これだと、callee arg は不定オフセットにならざる
を得ない。reg_save が最後まで決まらないから。

はぁ。大変なのはPowerPCだけで、MIPSとia32 は、そのまま動くというのが
わかりました。

Mon Jul 12 12:54:14 JST 2004

が、結局、MIPSを $fp からの裸オフセットにするのは苦労したね。
  .frame $fp じゃなくて、 .frame $sp にすると動くのか。
あと、goto 関連は、
    code_environment
    code_fix_frame_pointer
    leave
の三つを直さないとだめなのね。

この変更は、ARMのオフセット計算を固定オフセットで行うために
やっているんだけど、ARMのレジスタセーブを固定領域にすれば、
あるいは、どこかに追いやれば、callee arg も含めて固定に出来
るはず。


なんか浮動小数点レジスタは f4 だけみたいね。

	    mov	ip, sp
	    stmfd	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
	    sub     fp, ip, #4
	    sub     sp, sp, #12
    .L3:
	    ldmea	fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc}
    .Lfe1:

まるで、6809 の PSHS X,Y,D だね。PULS X,PC とか。

なんだけど、これだと、

                      <-------r1_offset------------------------------>
                                      <------------lvar_offset0------>
                      <--lvar_offset-->
 r+  +------------+---+---------------+----------+--------------+----+    -
      callee arg   xx   register save   local      caller arg     xx
                          reg_save      disp       max_func_args*SIZE_OF_INT
        lvar>0                         lvar<0       lvar>0x1000 0000

にならざるを得ない。となると、どっちかは、不定オフセットだな。
ま、callee 側でしょう。ま、これに習うか。あるいは、ポインタ
で指してもいいんだよね。ていうか、reg_save に関わらず決まった領域
をとっちゃえばいいんじゃない? 大した量じゃないし。浮動小数点
レジスタも一つだしね。

もう少しかかりそうだね。

Wed Jul 14 12:45:01 JST 2004

やっぱり浮動小数点ありとなしを一緒に実装するのはめんどい。

あれ、? mc-code-mips.c の
    rexpr_bool(int e1, int reg)
    {       
	int e2,reg0;
	int op = car(e1);
    return 0;

ってなんだ? せっかく作ったのに?

ちょっとバグってました。でも、なんでだろう? logic miss がある?

drexpr_bool for MIPS は作ってないみたいね。long long はさすがに
大変そうだし。

double/long long の定数だけどさ、
    local const table  に連続して入れる
    大域領域に初期化して、そこへのポインタをlocal const table に入れる
でいいんだけど... 前者だと、searchがめんどい。後者だと、double load
になるので、なんか嫌。たまたま一致した0を使えないのもなんかね。

adr なんて言うのがあるのか。adr して ldmia ってなんか変。mvfs #0 
なんてのがあるのか。0,1,10 があるのがわかるけど...

float の switch ってあるの?

(はぁ、めんどくさい... 一週間かかってるし...)

Sun Jul 18 20:45:48 JST 2004

なかなか終らないね。GBAとLinux Zaurus と両方だからな。
(やっぱ ARM に手をつけたのは失敗でした)

alloca の引数が定数の場合をやってないね。

まだ、先長そう。でも、やりたかったんだから、仕方ない。

浮動小数点レジスタ一つっての嘘だな。レジスタは使うたびに、
毎回セーブするみたいね。

Wed Jul 21 13:51:56 JST 2004

さて、inc_inst を、どうやっていれるか....

copmpile error は取ったけどさ。

Fri Jul 23 13:28:24 JST 2004

なんか頭が回らないな。

Sat Jul 24 19:27:55 JST 2004

うん。mc-arm で構文エラーがでるのは、なんかを壊しているから
なんだけど、それを直接にデバッグするのは、あんまり良い方法
じゃないんだろう。この程度のエラーを自動的に見つけてくれるのが
欲しいよ。


Tue Jul 27 13:45:21 JST 2004

.L183:
        mov     sl, r9
.L178:
        mov     r9, sl
.L175:
        mov     sl, r9
.L172:
        mov     r9, sl
.L169:
        mov     sl, r9
.L166:
        mov     r8, sl
.L163:

これねぇ。

まぁ、でも、なんとなく戻って来たか。

ぼろぼろだなぁ。論文も書かなきゃいけないのに。

Thu Aug 12 14:15:40 JST 2004

ちょっと間あいたね。ARMも、もう少しだけど、c2cbc の方を先に
しないと。C++ からの変換はどうする? cfront って動くのかな?

(あんな論文書いちゃって...)

Mon Aug 16 17:27:17 JST 2004

COND は、できるだけ CREG_REGISTER を使うようにしたけど、
アドホックだね。(まぁねぇ)

CONDのテストが入ってないなぁ。

Tue Aug 24 15:39:27 JST 2004

register 割当てが変。ほとんどをregister var に割り当てるように
なっているけど、もっとtmpがないと計算できないよね。

Thu Sep  2 20:46:56 JST 2004

そういえば Input register をtmpに使わないのはなんで?

順調にバグ取りは進んではいるんだけど...

Sat Sep  4 18:04:40 JST 2004

INPUT/REGISTER が double int register と float register 
で一貫してない。

Wed Sep  8 01:08:35 JST 2004

lvar_offset_label, r1_offset_label っているの? fp を
使ってるんだから、いらない説もあるが..

局所変数を負のオフセットでアクセスし、関数呼び出しをsp オフセット
で積むなら、いらないはず。

Sat Sep 11 15:13:33 JST 2004

やっぱり、CSE ぐらいやるべきじゃない? マクロで生成されるとねぇ。
   if (o==H1||o==H2|o==H3)
みたいなものね。まぁねぇ。

でも、そうすると、asm がなぁ。でも、そうすると elimination 
もやりたいよね。

それよりは、inline が先か。

Tue Sep 14 14:36:15 JST 2004

arm lvar のlarge offset をなんとかしないと。lvar intro
でなくてもできるはずだよね。

だけど、ptr cache と const list
を一般的に一緒にできない? 両方ともconstだしねぇ。

そうか、ptr cache は外にでちゃっていて、nptr を前提にしている
ので、ちょっと難しい。uniq nptr を当てはめてやればよいみたい
だけど...

        str     r1, [fp, #0+.L3]
        str     r2, [fp, #4+.L3]
なんだけど、L3 が巨大なのでだめになってしまう。(まぁ、そうだよね)
まぁ、でも、L3 は巨大にはならないんじゃない?

Wed Sep 15 16:50:46 JST 2004

basic のレジスタに載った引数をスタックに戻すところがおかしい。


そうか、C++ のmaglegationをいれれば、C++ とは接続可能。
だけど。


Wed Oct 13 21:06:31 JST 2004

mvn は1's complement で、sub は2's complement なみたいね。
なので、8bit const の時におかしくなる。

32bit word のalignmentは4でなくてはならないらしい。

0x20005cc <code_lvar_address+216>:      str     r0, [r11, -#22]
(gdb) p $r0
$13 = -1073742791
0x20005d0 <code_lvar_address+220>:      ldr     r0, [r11, -#22]
(gdb) si
(gdb) p $r0
$15 = -63324161
(gdb) p (char*) -1073742791
$16 = 0xbffffc39 " \004@L
(gdb) p (char*)-63324161
$17 = 0xfc39bfff <Address 0xfc39bfff out of bounds>
(gdb) quit

うーむ。

Fri Oct 15 08:46:59 JST 2004

        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #16
        str     r0, [fp, #-16]    引数1
        str     r1, [fp, #-20]    引数2
        str     r2, [fp, #-24]    引数3
        str     r3, [fp, #-28]    引数4
           ...
        ldr     r2, [fp, #4]      引数5
        add     r3, r3, r2
        ldr     r2, [fp, #8]      引数6

そうか。レジスタの引数分はメモリには取られないで、局所変数側
におかれるらしい。spは、stmfd で自動的に調製されるから、sub sp
は局所変数分だけ。fp の#4は戻り番地だけ?

でも、それだと va_next が困るんだけど。

Fri Oct 15 20:51:19 JST 2004

        mov     r3, #0
        str     r3, [sp, #0]
        mov     r3, #1069547520
        add     r3, r3, #3145728
        ldr     r0, .L28+388
        adr     r1, .L28+392
        ldmia   r1, {r1-r2}     @ double
        bl      printf

ってわけで、またがったdouble/longは、半分だけレジスタに置かれる
みたいね。

Sat Oct 16 19:12:31 JST 2004

ま、それは直ったんだけど、register は、input register 以外は
全部 save しているみたいだな。frame あわせがめんどくさい。

cmf f4,#0が、f4 が初期化されてないと落ちるみたい。illigal instruction
っていうけど、 f4 の値によるのか?

fdecl_struct(int fntype)
{
   ...
        mode=ADECL;
            args = 0;
            def(&str_ret);
            struct_return = list3(list2(LVAR,str_ret.dsp),sz,type);
            caddr(fnptr->ty) = glist2(POINTER,caddr(fnptr->ty));

なんだけど、これって save_input_register されてLVARになるわけ
だよね。def した時にはレジスタに割り当てられる可能性もあるよね。
そういうことはないのか。

で、mc-parse.c で、
    if (struct_return) {
       ...
                gexpr(list4(STASS,rvalue(car(struct_return)),e,e1),0);

ってなるわけだよね。

で、mc-code-arm.c では、引数のdspが変更されるからだめなわけね。(スタック
に割り当てられてないから)

だから、struct_return を save_input_register で修正する必要がある。

ARMでは、register割り当て分がstackに取られてないので、struct_push
で、その分をregister にcopyしないとだめ。でも、そうすると、受け側
はどうするの?
        mov     ip, sp
        sub     sp, sp, #8
        stmfd   sp!, {r4, r5, fp, ip, lr, pc}
        sub     fp, ip, #12
        sub     sp, sp, #96
あ、こんなことやってるし〜

Sun Oct 17 13:13:00 JST 2004

なんか long long に関しては、gcc の方が結構、間違っているなぁ。

signed char に関しては、ldrsb ってのがあるみたいね。なんで、
arm-linux-gcc ではでないんだろう?

Mon Oct 18 00:15:05 JST 2004

self compile が通らない。他のテストを優先するべきか。

Mon Oct 18 20:25:16 JST 2004

emit_copy の offset の扱いが一貫してないらしい。
あと、 powerpc でr3,r4,r5 を使った状態でmemmoveが呼ばれるみたい。

うーん、やっぱり構造体をレジスタに割り振るのってかなりめんどう
なのね。特にネストする関数では...

構造体はstack上で必ず align されるらしい。

ARM の bitield なんだけど  |---====|=====|====----| と三つにまたがるのが
許されるみたいだね。char でも |--===|===--| があるし。ってことは、かなり
変えないとだめだてことだなぁ。あなあきでなければ、割りと正しく動くんだけど。

残りは、stdarg と bitfield だけか。まぁ、いいんじゃない? stdarg は、
stdarg.h を自分で作れば良いみたい。

Tue Oct 19 11:12:16 JST 2004

また、? のエラーか。
##      mode=(s==STRUCT?GSDECL:GUDECL);
# 1287: : creg=r4 freg=f0
        ldr     r4, [fp, #4]
        mvn     r7, #6
        cmp     r4, r7
        bne     .L713
        mov     r7, #2
        b       .L714
.L713:
        mov     r7, #3
        mov     r0, r7
.L714:
        ldr     r7, .L709+4
        str     r0, [r7, #0]
テストルーチンが必要だね。

(MIPSとかPowerPCとか、だいぶ壊しちゃったみたい...)

C との呼出しがずれている(やっぱりレジスタ?) mc と gcc のオブジェクトを
混在させるとだめだね。

浮動小数点関係の Endian がおかしい

Tue Oct 19 19:07:57 JST 2004

        stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}

ってわけで、r0-r3 がinput registerで、r4-sl がregister_var とtmp
を兼ねるわけだね。r4から全部をregister_var に割り振ると破綻するだろう。

ってことは、一時変数ではなく積極的にレジスタ変数を使った方が
良いわけだけど...

save_stack で register var はsave する必要はない。けど...

longlong_lib で creg は RET_LREG になっていたけど、その外で、
emit_pop_free する時に、その一部がRET_LREGと重なっていて、
一緒にfreeされてしまう。そうすると、次のemit_popで、上書きされてしまう。
なので、RET_LREGにしないで、lmove してしまうのが良い。

align がおかしい

Sat Oct 23 23:33:11 JST 2004

struct を使った interface をregister にmapするかどうか。まぁ、
難しいけどね。

やっぱりarmのbitfieldを合わせるのは止めた方がいいんじゃない?
long long 以外は、型を大きくして対応できる。long long のはみ出し
は、ちょっと対処できない。
      a:8 =>  a0:4<<4+a1:4
      a:8 = hoge =>    a0:4 = hoge<<4, a1:4 = hoge;
というように分解する?

Sun Oct 24 14:19:13 JST 2004

code_frame_pointer と code_environment は同じなんですけど...

巨大な構造体を並列代入すると、

自分自身が重なっている
   |----------|
       |----------|

では、
   |----------|
            --copy-> |----------|
     他のものを代入
            <-copy--
       |----------|
ってことになる。

これは、ちょっと手間が大きい。
   |--|---|---|
       |--|---|---|
と分割する(分割が細かくならない?)
   |---|--|---|
       |---|--|---|

分割はだめだね。自分自身しか重なってないのだったらoverappable copy
する。
   |----------|----------|----------|
       |----------|----------|----------|

circular dependency はrecursive callする必要はないね。

なんか、構造体が一度、スタックにあげられてから戻されているみたい

RSTRUCT って、本当にいるの?

なんか、「まだ、emit_copy が間違っている!」

PowerPC は、code のレジスタに割り当てられた分のスタック上の引数
を割り当てているな。なので、
## code carg6(int i, int j,int k,int l,struct arg args0)
##     goto carg3(args0,args0,i,j,k,l);
で、args0 のcopyが余計に出るね。 しかもずれ方が変。(*)

無害ではあるんだが...

でも、それでバグを見つけたわけか。

だいぶ、enbug しちゃったよ...

emit_copy でmemmove する時には、offset は無視する。address + offset
から、reverse に address までコピーするという意味だから。

memmove は、一時レジスタを壊してしまうので、parallel assignment
の一時には普通のレジスタは使えない。

PowerPC の code segment で、引数が、CALLER_ARG つまり、関数呼び出し
のスタックと重なっている。code_disp_offset では調整できないらしい。
今までは、(*) のせいで余計に一時変数を取っていたので顕現しなかった
らしい。

うーん... 一応、直ったけど...

他のがどんどん動かなくなる...

Mon Oct 25 03:13:48 JST 2004

codegen で、jump しているのだけど、そこでは、offset -1 で、
局所変数となる。局所変数をそのままcode_segment の引数に
しているらしい。

code_segment側でも、同じoffsetで処理するが、ARMの場合は、
offset 0- -xx までは、register save が入る。それを書き潰し
してしまうらしい。goto 時に。で、戻ったときにerrorとなる。
register は全部、save するので、差はわかっているので、それを
足せば良いだけだけどね。(これ、前もやったな...)

Mon Oct 25 19:36:16 JST 2004

なんか、できた。

まだ、レジスタ分のオフセットがcode_segmentで取られるのは直してない。
ARM の bit field の穴塞ぎもね。

あとは、
       inline
       CbC2C
       C2CbC
だけだね。

Wed Oct 27 08:48:37 JST 2004

MIPSのallocaは、$spを移動するので、j の後の、code segement の
        lw      $gp,$L_41($sp)
はまずい。が、通常は、
        lw      $gp,$L_41($fp)
が出る。だから、alloca で$gpを移動する必要はない。しかし、code_segment
で alloca は使えない。$gp をswしなおせば?

input interface 構造体の alignment を64にすれば、マッチする可能性が
ちょっと高くなる。

const がレジスタに既にあるかどうかをチェックする? ま、いらないか。

ARM の bitield 
    |---====|=====|====----|
    |--===|===--| 
は、mc-codegen 側で対処しない? char/short/int は -> short/int/long
にすれば良いわけだよね。

問題は、long だけ。はみだすのはintだってわかっている。

bit_filed
	bit_field(upper) << offset + bit_filed(lower)

bassign
	bit_filed(upper) = value >> offset;
	bit_filed(lower) = value << (32-offset-size);

bassop ....

やっぱだめだめ。

bit_filed の前に、読み込みの段階で
     upper2 << offset + (lower&mask >> 32-offset-size)
するか。

bit_field_repl,bit_filed_repl_const はそのままで、
代入するときに、二回 replace する。

おんなじことか。

** そうではなくて、

long でintが余ったときの確保する場所(int)(bitfield_opt)をstack上に用意する。
(new_lvarでしょうね) get_register_var でもいいけど... ARM では意味ない
だろうな。

     mc-codegen:bit_field では、load する時に、bitfield_opt にもload
     code_bit_field では、必要ならば、bitfield_opt から値を読む

     mc-codegen:bassign では、load する時に、bitfield_opt にもload
     mc-codegen:bit_field_repl では、必要ならば、bitfield_opt も置換する
     代入時には、忘れずにbit_field_opt も書き込む

     mc-codegen:bassop では、tmp1 を読むときにbitfield_opt にもいれる

でいいんじゃない? 虚しいが...

Thu Oct 28 17:40:35 JST 2004

それだと変更点が多すぎる。long long でバウンダリがまたがる時
には、格納type を struct { int [3]; } として、一時領域に格納
する。実際には、アドレスが帰って来ることになる。で、code_bit_
replace_const などでは、アドレスに対して処理すれば良い。そう
すれば、codegen 側の変更は(ほとんど)なくなる。

でも、そうすると格納型と値型を区別しないとまずいね。

Fri Oct 29 04:19:58 JST 2004

code-* 側にはtypeの内部構造とかを渡すのは良くない。

あとは、格納型>値型の時のbitの値の修正だな。

この手のbit-field って、本来なら、inline で *C* で記述されるべき
ものだよね。

Fri Oct 29 20:30:41 JST 2004

できたけど.... bassign の中のsassignでアドレスが狂うバグが
あるらしい。本来は、余計なコピーがあっても、害はないはず
なんだが、
diff test/bitfield.gcc.out test/bitfield.mc-arm.out
1058c1058
< 2:00000000 00000000 00000000 def00000 56789abc 00000234 00000000 00000000
---
> 2:00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
と言う形で、上書きしてしまう。

dum()をはさむと直ったしするのでレジスタのメンテナンスの
問題らしいが...

大域変数のptr cacheが、jump のinput argument regsiter を
壊してしまう。ARM以外はどうして壊さない? 単にレジスタ
使用の順序の問題で、でる可能性はあるってことか。
jump の中でusig_reg すれば良いんだけど。

get_input_register* でcodeの場合だけ using_reg しちゃったけど、
いいのかな?

あっと、goto の浮動小数点レジスタ渡しをあまりテストしてないね。

bitfield は、アドレス渡しで、代入しない方が良いね。

Sat Oct 30 17:48:18 JST 2004

いいんだけど変更がきつい...

  a = b = c = 0

で、a は定数代入にはならないのね? 通常はいいんだけど、bitfield
とかでは余り良くないね。

Sat Oct 30 20:39:34 JST 2004

MIPS の$4,$5,$6,$7 は引数渡しに使われるわけだけど、
6,7にlong long が入るときには、$5 には、$6 と同じ値が入る?
いや、bitfield1.c の printf の %lld が %d になっていただけでした。

ARM の lreg でregsiter が lost するのを止められない...
use_input_reg(int reg,int mode) ってやっぱり、おかしいよね。

なんか、直すのに5時間もかかったよ。

ARM では、use_int/use_longlong の繰り返しで lreg がlost する
らしいのだが、他のmips/powerpc では、そういうことは起きない。
なんでだろう?

Wed Nov  3 18:31:28 JST 2004

やっぱり構造体をint単位に分解すると並列代入は良くなるね。し
かし、それだと、巨大な構造体ではコンパイル時間がかかりすぎる
のと、コードがでかくなってしまう。

並列代入も、もう少し考えるべきだな。
   code f(int a,struct b) {
       goto g(b,a);
   }
みたいな場合だね。

分解してから、もう一度、memcpy にまとめるという手もあるけど...
代入ベースではなくて、swap base の置換にする?
   for(i) swap(a[i],b[i]);
みたいな感じ?
   code f(struct a,struct b) {
       goto g(b,a);
   }
みたいな場合は、そんなのが望ましいが...

分解して巡回依存を解消して、address でsort すれば... memcpy
は検出できるはずだけど...

あ、そうか、巡回依存は、基本的にswapで解決できるはず。
    copy(a,b)
    swap(a,b)
の組合せで、最適な結果が得られるはず。そうすれば、saveとか
をしなくてすむ。
     (a,b,c) <= (b,c,a)
は、
     swap(a,b); swap(c,a);
となる? あれ?

case triple
       a     b       c
     |---||-----||---------| 
        b       c        a
     |-----||---------||---|

うーん、

     circular_dependency =>   smallest dependent element
                              singleton or not

     swith(circula_depent(&small)) {
     case CIRCULAR_DEPEND:  save(small); remove(small); break;
     case DEPEND_SINGLETON:  memcpy(small); break;
     default: continue; // try another
     }

これだと、a がsave, b がsaveで、c がsignleton ということになる。
いや、b もsingleton になるかな? b&c を一つのmemcpyにまとめる
のは、それほど意味はないが...

これでも、
case eq
         a          b
     |---------|---------| 
         b          a
     |---------|---------| 
は、save code が出てしまう。また、上の場合でも、a がでかい場合
があるよね。本来、
     one integeter save
で全部できるはず。(お手玉swap) で、分解すればお手玉swap codeは出る。

memcpy するためには、その先を全部saveしないとだめ。だから、memcpy
とは両立しない。うん。だから、swap operation にするのが良い。が、
case triple をswap operation で解決する方法が良くわからない。
       a     b       c
     |123||45678||9abcdefgh| 
     |-23||45678||9abcdefgh| {1}
     |423||-5678||9abcdefgh| {1}
ってな感じかぁ。これは、space/operation trade off なの?
       a     b       c
     |123||45678||9abcdefgh| 
     |-23||45678||9abcdefgh| {1}
     |4-3||15678||9abcdefgh| {2}
     |45-||12678||9abcdefgh| {3}
     |456||-2378||9abcdefgh| {1}
     |456||7-318||9abcdefgh| {2}
     |45678||-12||9abcdefgh| {3}
     |45678||9-2||3abcdefgh| {1}
     |45678||9a-||31bcdefgh| {2}
     |45678||9ab-||12cdefgh| {3}
     |45678||9abc-||23defgh| {1}
     |45678||9abcd-||31efgh| {2}
     |45678||9abcde-||12fgh| {3}
     |45678||9abcdef-||23gh| {1}
     |45678||9abcdefg-||31h| {2}
     |45678||9abcdefgh||-12| {3}
     |45678||9abcdefgh||1-2| {3}
     |45678||9abcdefgh||12-| {3}
     |45678||9abcdefgh||123| {-}
       b        c        a
で、できるにはできるんだが....

これと、memcpyとどっちが速いかはアーキテクチャとmemcpyによる。

だから、
    ある程度、小さい構造体は分解
    大きなものは、singleton/smallest detection をまずやる
    save が大きすぎるときには、circular dependent 内部でお手玉を出す
ってな感じですかね。

お手玉なんだけど、
       a   b       c
      |-||---||-------|
      123456789abcdefgh 
       a b1    c     b2    c_t + c_s をswap
      |-||||-------||-|
      123459abcdefgh678 
      b2 b1    c     a     a_t + b2  をswap
      |-||||-------||-|
      678459abcdefgh123 
        b     c      a     b2,b1 をswap
      |---||-------||-|
      456789abcdefgh123 
ってな感じで大きなものからswapかな。こうすれば自動的に分割される
ので、分解は必要なくなる?

     circular_dependency =>   smallest dependent element
                              singleton or not

     swith(circula_depent(&small,&large_conflict)) {
     case CIRCULAR_DEPEND:  
	if (size(small) < SAVE_MAX) {
	    save(small); remove(small); break;
	} else {
	    swap_divide(large_conflict);
	    reposition(conflict);
	    remove(large);
	    break;
	}
     case DEPEND_SINGLETON:  memmove(small); break;
     default: continue; // try another
     }

     swap:     ld  r0,(to);
               ld  r1,(from);
               st  r0,(from++);
	       st  r1,(to++);
               if (cnt-->0) goto swap

って感じ? swap された最後が、どういうパターンになるかは、ちょっと
面白い問題だけどね。

Thu Nov  4 10:15:29 JST 2004

あ、なんか long long の定数シフトで > 32 の場合を忘れているね。

Fri Nov 12 15:37:42 JST 2004

やっぱり、record (taged union) は欲しいよね。

    struct {
       enum {hoge0,hoge1,hoge2} i;
       switch(i) {
       case hoge0: struct {...} b;
       case hoge1: struct {...} c;
       case hoge2: struct {...} d;
       }
    } a;

    assert(a.i==hoge0);
    a.b.j = 3;
    assert(a.i==hoge0);
    printf("%d\n",a.b.j);

うーん、あんまり良くないなぁ。これだったら、いらないよね。

Fri Nov 12 15:59:32 JST 2004

Template あるいは型変数は入れたくないよね。入れるとしても、
上位言語だろうなぁ。

Sat Nov 13 11:05:06 JST 2004

main() { printf("%d,%d\n", -555>>3,-555/8); }
-70,-69

なるほどね。

なんか arm-linux-gcc がバグっているな...

    ltosop_register()
    {
    register long long i1,i2,i; 
    register unsigned long long u1,u2,u; 
    u1 = 632423423; u2= 32394234;
    u = 0;
        ....
    u = u1 & u2;
    printf("#2052:ltosop r u 6 %llu\n",u);

        sub     r6, fp, #48
        ldmia   r6, {r2-r3}
        sub     r7, fp, #48   <---?!
        ldmdb   r7, {r6-r7}
        and     r2, r2, r6
        and     r3, r3, r7
        sub     r7, fp, #64
        stmia   r7, {r2-r3}
        ldr     r0, .L640+92

なんでかね。

Sun Nov 14 15:59:33 JST 2004

よし、inline やるか。

   inline function (or parsed tree)
       // list4(INLINE,name,type)
       sc = INLINE
       attr = parse
   declaration (argument, local, static)
       list4(ST_DECL,next,NMTBL *nptr,stmode)        done by def (?)
   statement
       list3(ST_IF,next,list3(cond,then,else))
       list4(ST_DO,next,cond,while)
       list4(ST_WHILE,next,cond,while)
       list3(ST_FOR,next,list4(A,B,C,body))
       list4(ST_SWITCH,next,expr,body)
       list3(ST_COMP,next,body)
       list2(ST_BREAK,next)
       list2(ST_CONTINUE,next)
       list3(ST_CASE,next,label)
       list3(ST_DEFAULT,next)
       list3(ST_RETURN,next,expr)
       list3(ST_GOTO,next,expr,env)
       list3(ST_ASM,next,list4(A,B,C,D),e1)
       list3(ST_LABEL,next,label)
       list3(ST_COMMENT,next,comment)  (?)

  いくつかはexprと重なるけど... (まずい?) RETURN, ASM

 (1) make inline tree
 (2) evaluate inline function (copy and partial evaluation)
        peval(inline_func,args)
    similar to the function call (with type check)

    const いるのかなあ。
    builtin_constant_p かぁ。

 partial evaluation しながら code 生成する? (難しい...)
 partial evaluation してから code 生成する。まぁ、こっちでしょうねぇ。
    g_expr を変更しなくてもすむ

Mon Nov 15 17:37:57 JST 2004

code hoge() {  a; }
code hoge1() { b; }
 
では、a-> b に、そのまま落ちるべきだろうね。ファイルが分離される
場合は少し困るが.... 型が合わない場合にエラーを出さないと。

if (0) hoge; でhogeが生成されてしまう。control で切っても出るね。
いや、消えてました。ただ、jmp は生成されてしまうね。checkret
で、チェックするべきでしょう。

checkret は、control が生成されるところで呼ばれるわけだから、本来は
control=1 にするのは、checkret だけであるべき。
    jmp(hoge) は、pending_jmp
を設定して、checkret で、pending_jmp を生成するわけだが。
で、pending jmp が設定したlabelに等しければ、pending_jmp は0に
設定される(しかしreferenceされたかも知れないからlabelは生成する?)
label にreferenceしたかどうかのflagを付けた方が良い?

if (1) hoge else fuga ; で fuga が生成されてしまう。bexpr で
always jump かどうかを返したいところだが...

Mon Nov 15 21:25:15 JST 2004

構造的にはさ、inline は、CbC の外で行われるべきものだよね。
内部で処理してもいいんだけど、本来は外でやるべきものです。

gcov は面白い!

Sat Nov 20 16:44:38 JST 2004

古いswitchの実装が壊れている。lazy jump の影響らしい。

PowerPC が cmp immideate value を出力してない。このあたりは、
積極的に落した気がするけどね。直すとめんどくさいかも。
MIPS と ARM は、ちょっとしくじってるな。

あれ、複数のファイルをコンパイルするときの問題があったような
気がするんだが... あるね。
    ./mc-hoge mc-*.c


Sat Nov 20 22:00:36 JST 2004

あぁ、なんかいろいろ破壊しているし〜

なんか、いろいろ残ってたね。ia32 の long eq/ne 。 int + unsigned が
unsigned になったり。

size < int のstruct の値の渡し方がおかしい

Sun Nov 21 13:02:09 JST 2004

gexpr に parse = list2(expr,parse); するオプションを付ければ、
inline の手間は少なくてすむかも。

static でないと実体も出力する必要があるわけね。

const, volatile がないと大した最適化ができない。まぁ、あんまり
やらないつもりなんだけど。

const, volatile は型にするとめんどー。だけど、C にそうなら型だろう。
storage class でいいなら簡単なんだけど。sc を bitmask にするか。
       extern (or static)
       extern used
       const

attr には、INLINE, CONST, VOLATILE がとりあえずはいる。

定数の大域変数と局所変数の初期化された値をどこかにとっておく必要がある。
どこ? dsp? attr?

address の引き算が間違ってる。

定数は .literal4 っていうのに割り振られるみたいね。

l.c がlocal typeの爆撃で壊れている。list3 にしたからだろうな。

macro.c に signed char の依存性がある?

size_t に関しては少し調べた方がいいんじゃないの?

## struct temp temp3 = {
##    .c = (int)&b,
##    .d = -10,
##    .a = (int)b
## };
.globl  _temp3
_temp3:
        .long 0       はぁ?
        .space  4
        .long 59997
        .long -10
   space は?
## 
## 

いろいろあるな。

Mon Nov 22 22:34:03 JST 2004
  typespec
        if(mode==LDECL) return 0;   // not a type
        t= INT;                     // empty typespec 
だから、
        smode = mode; mode = STAT;
        checksym(LPAR);
        mode = LDECL;  // typespec required this
        if((t=typespec(ctmode))==0) {
            mode = STAT;   // too late for expression 
            expr(0); 
かぁ。

hash があんまり良くない。っていうか、compiler で20%、l.c で98%...
rehash は、ちょっと難しすぎる。せめて、オプションで設定できる
ようにするか。

#define hash_value(hash,ch) (hash = (37*hash)^(11*(unsigned char)(ch)))
// #define hash_value(hash,ch) (hash = (37*hash)^((unsigned char)(ch)))

なのかぁ。open hash だからか。

Wed Nov 24 13:21:03 JST 2004

レジスタの
        mov creg, regv
        add creg,$3
        mov regv, creg
はなんとかしたいよね。

goto 文で、parallel assignment が、
        i+1
みたいな場合に、
        mov creg,regv
        add creg,$1
        store creg,lvar
        load creg,lvar
みたいなのを出してしまう。それは、i+1 がis_memory でないから。
単純に、これを残すと、source list にi が入らないので、iをoverwrite
されてしまう。

で、is_contains_p1 で、source を列挙すると、parallel_assign が
止まらなくなる。(何故?)

remove0(soruce) で含まれているsourceを全部落し切れないからだね。
save したあと、source を書き換えるわけだけど、その部分が考慮されてない。
うーん、ちょっと諦めた方が良いみたいだなぁ。

やっぱ、まじめに parallel assign かかないとだめなんじゃないの?

えーと、
     i = i+1
ってのがあると、i=i でないから消えないで残る。これを処理する方法が
ないわけね。でも、circular dependency にならないのは何故?

Thu Nov 25 09:05:24 JST 2004

progress で捕まえられているんだから、そこでなんとかする?

dependency singleton を見つければ良いわけだよね。複数見つかっていれば
save しているはずなわけだから。

circlular dependency に渡されているのはsourceの「一つのメモリ」であって、
式でない。だから、circular dependency ではoverlap を見つけられないわけ
だね。

うーん、やっぱり、adhoc なわりに複雑になってしまう。これだったら、CSE
を真面目にやった方がいいんじゃないかなぁ。

tmp1 は、違うエラーだな。code4 の中のprintf が j を壊しているね。
なんで、r30 から負のoffset をcaller が爆撃するんだ?

r1 を延ばして片付けたけど... そういえば、register の分を code
segement ではメモリに割り振らないって話はどうしたの? 

    list5(target,next, ty, source, source-dependency)

だよね。そうすると、source list から単純にremoveできない。他の
dependencyを削除しちゃうかも知れないから。なので、source は、
やめて、list5 を直接使った方が良い? そうすれば、target を
remove すれば自動的にremoveされるので...

progress でなんとかすると、やっぱり、全部 save されちゃうね。
toplogical sort しないとだめか。

singleton が良い。multi ならば、どうせsaveするんだから。
list5 はやらないとだめ。


#define CHECK_HEAP(b) ({int _k=(int)(b);if(_k>heapsize)error(-1);_k;})
#define car(e) (heap[(int)(CHECK_HEAP(e))])

は、いいんだけどさ、これのコンパイルが間違っているみたいね。

っていうか、expr() 中で docomp が実行されてコード生成されちゃうから
まずよな。何とか、する方法としては... (うーん、思い付かないな。
だめなんじゃないの?)

単独のサブルーチンを生成して、そこへの関数呼び出しにすれば?
code 生成系を足さないとできないか。
	b hoge
    haga:
	fuga
	st value
	ret
    hoge:
	bl haga
	value 
まあ、いいんだけど、大半の場合は、必要ないんだよね。

あぁ、これだと、({   goto exit0;  }) みたいなのがだめだ。
	b L1
    L2:
	fuga
	st value
	j L3
    L1:
	.........
	b L2
    L3:
	value 
ですかぁ? はぁ。

Sat Nov 27 08:51:01 JST 2004

({}) で、init_vars がnestする可能性があるのを忘れてました。

register stack が異なるので破綻しているみたい。

    ## 	if (car(ns)==sc) {
    ## (heap[(int)(({int _k=(int)(ns);if(_k>heapsize)error(-1);_k;}))])
	    b	L_2215
    L_2216:
    # 3764: gexpr_init: creg=r11 freg=f14
	    lwz r11,lo16(-16)(r30)
	   ....
    L_2215:
	    lwz r11,lo16(28+L_2206)(r30)
	    b	L_2216

どうしようかなぁ。

Sun Nov 28 02:41:11 JST 2004

> L_code_postinc$non_lazy_ptr:
>       .indirect_symbol _code_postinc
>       .long   0

なんだけど、PowerPC で、
     関数として使われている is_function && sc==EXTRN1
           binding helper 必要
           non_lazy は不要
と、
     大域変数としてい使われている
           binding helper 不要
           non_lazy のみ必要
を区別する必要があるみたいね。これは parse.c で追加する必要がある。

もっとも、.long 0 が余計に出力されるだけだが。

Sun Nov 28 03:42:04 JST 2004

float/double/longlong のcode segement argument のテストをしてない。

ia32 の ({}) がおかしい。

Sun Nov 28 15:49:54 JST 2004

listn を object に変える?

   struct nodes {
      union {
	  int tag:12;
	  int type:4;          LONGLONG,INT,SHORT,CHAR
	  int unsigned:1;
	  int arity:4;
	  int size4:4;
      } tag;
      int next;
      union:tag {
	  int arg0,...argn;
      }
   }

Mon Nov 29 11:55:14 JST 2004

attr は、連想リストにするべきか。

partial evaluation を、どの段階で行うかっていう問題があるのか。

expr15 (function call)

inline 木作成の最中に展開すると繰り返し展開することになる。
しなくても良いが... しかも、ST_* が expr の中に残ってしまう
ので、g_expr で、ST_* を扱うことが必須。ってことは変更が結構
大きい。ここで展開すると binop の最適化にひっかかるので簡単。
docomp と同じ扱いが必要?

function (codegen)

ここで展開すると、代入とかが変数扱いしかしなくなる。手遅れ。

ってことは、expr15 で、partial evalucation はやる。inline
中は展開しないとして、残った ST_* は、g_expr で処理する
ってことですね。

static でもポインタを取られたりすると関数を生成する必要がある。
extern なら、なおさら。それは、自分でやらないとダメ。まぁ、
inline の関数リストを作るのが良いんだろうけど。

Wed Dec  1 18:40:37 JST 2004

chk は、mc-code-*.c に現れるべきではない。

static  で used っていう属性がないとちょっとまずい。compiler warning
だすべきだし。

switch(5) みたいな場合をone pathで取り扱うのは、ちょっと面倒。
     switch(5) 
        for() {
	default: ...
        case 3: ...
        case 5: ...
        case 7: ...
        }
みたいな場合があるわけだよね。しかも、default があるかどうか
は、switch の場合ではわからないし。cslist をチェックすればわ
かるか。でも、default code を取り除けるかどうかは、default 
を見つけた時点ではわかりえない。

pexpr では、もっと詳しい情報が得られるので、より簡単になる。

Thu Dec  2 12:06:22 JST 2004

attribute ねぇ。見たくないねぇ。

inline は、あとは partial evaluator だけだね。

gexpr とおんなじ感じで、すべてをcopyする必要がある。lvar は、
表引で入れ換え。disp は、その分、増加させる。register 宣言は、
その時で探すことになる。pfdecl でもレジスタは再配分しないと
いけないんだけどね。

partial evaluator って思ったより量が多いなぁ。

Fri Dec  3 12:47:50 JST 2004

inline の引数を計算して、vartable に割り振る。pexpr で定数な
ら、そのまま定数に。変数だったら alias を避けないといけない
ので、new_lvar & copy 。変数でも、const (read only)なら、そ
のまま使って良い。このあたりは、const って宣言しなくてもコン
パイラの方で検出できるけどね。このコンパイラはさぼる方針なの
で。

複雑な式なら変数を確保(new_lvar)して代入する(式をparseに付け
加える)必要がある。なんだけど、一回しか使われてないなら、そ
のまま使っても良い。後で使われない可能性も高いので。この「一
回」の意味は結構複雑。attr で評価されたどうかを覚えておく方
が良い? ただし、副作用がある場合は、使われてなくても、一回は
評価する必要がある。f(k,i++) {ret k;} みたいな場合。しかも、
f の前に評価する必要があるのか。i がその後使われないなら実行
する必要ないし.... 副作用のあるなしや、evalられない場合を判
定するのは難しいから、無条件生成でしょうね。でも、すぐにasm
に食わせる場合とかあるけど。

     vartable     argument (-4)
        -> ptr    local    (0)
                  local    (4)

ってな感じ? argment size は、どうやって計算するんだっけ?

あと、return value の返し方だけど... ない場合は簡単だけど、
ある場合は、
    if()に使われる場合
    代入される場合
    使われない場合
とあるよね。ST_COMPにすることは簡単なんだけど、余計な
変数が必要になる。COMMA でいいのか。
     if() { retrun ...} else { return ... }
のような場合はどうする? COND に変換する?
     while() { return hoge; }
は?
     ({ while() { ret = hoge }; } ret;)
かな。全体的に、
    ({hoge....  ret=hoge.... ; ret;})
にする? hoge が構造体の場合は....

goto するっていう技もありか。
         { return exp; ... } =>   {  exp; goto exit; ... exit: }
にする。こうすれば変数は不要。nest した時にだめか。いや、goto
しないとだめなのか。pexit_label ってのがあるわけね。

単純な場合を単純にするには? 単一で最後の時だけ特別扱いする?

local 変数も使うものだけ生成した方が良いんだが... それには
2 pass 必要。rechability は2passでないとだめか。あ、めんどう。
一旦展開した後、不要なコードを取り除くっていう感じですかね。
そうでないと switch の不要コードを取り除けない?

pcontrol みたいなので除去できない? pcontain みたいな感じで、
直前のSTが実行される(かもしれない)コードを含んでいるかどうか
を判断する。pcontain = pcontrol のorみたいな感じ?

Sat Dec  4 12:24:26 JST 2004

問題は、is_readonly() だろ? (とりあえず)諦めちゃうっていう手
もあるけど。is_readonly で、vartable に外のtreeをいれると、parse
tree に外のlvarが入り込む。それを識別する方法が必要になる。
それは、まぁ、debug のためにも必要だから良いんだけど、type tree
の中に、list2(KONST,e) をいれると、他の型チェックが == では
すまなくなってしまう。has_type(INT,t) みたいな形? それは、う
っとうしすぎる。そもそもconst嫌いだし。でなければ、すべての
タイプに*Cみたいなのを作る? いきなり倍ですか。いやだめだね。
compund type にもconstは付くはずだから。const struct hoge
みたいな?

list2(LVAR,hoge,fuga) でhogeに足し算するようなコードはまずい。
そういえば、大域変数の引き算とかはあんまりやってないな。

Sat Dec  4 13:18:05 JST 2004

そうか、inline function のcontinuation っていう問題があるの
か。もちろん、外の関数に戻れば良いわけなんだけど、戻る場所が
異ってしまう。inline が生成されるかどうかによって異る。inline
の外に必ず戻るってのは、どちらかといえば容易に実現できる。こ
っそり、return/env を渡してやれば良いから。

goto で関数の任意の位置に戻れるってのは誘惑的だし、その方が
整合的ではあるんだけど... 構文が良くわからないな。setjump に
突っ込めるってのは一つの解決方法か。

    if (setjmp(hoge)==0) {
       goto f(&hoge);
    }

code f(jmp_buf *hoge) {
    goto hoge(1);
}

ですか? そういえば、code の中でlongjmp するとどうなるんだろう?
局所変数は壊してしまっているので、呼び出した関数には戻れないね。
まぁ、やっぱり、それを戻れるようにするんじゃないの? setjmp 構文
は、あんまり良くない。それをいうなら return/environmentも良くない
けどね。shift/reset みたいな構文が良いか?


Sun Dec  5 18:14:05 JST 2004

関数の引数のconstの情報をどこにとっておくかが良くわからない。
やっぱり CINT とか作る? 結局、const って、すべての型に直交している
から、そういう風にしなければ、tree で持たないといけないよね。
そうすると、あらゆるところで、pointer判断が入ってしまう。それは
うれしくない。それよりは、
   #define TYPE(a) (a & 0xfffffffe) 
   #define IS_CONST(a) (a & 1) 
のがまし? じゃぁ、
   #define IS_UNSIGNED(a) (a & 2) 
とかもいれる?

それは、変更が大きいので、とりあえず、mc-inline.c のエラーを
とってからにするか。

Tue Dec  7 12:19:08 JST 2004

lvar を二度置換するのはまずい。オフセットのタグを増やす方が良い。
本来は不要だけどね。

Wed Dec  8 13:04:18 JST 2004

うーん....
       type tag
ねぇ。

     type tag                            10bit
の属性か
     signed/unsigned                      1bit
     size                                 4bit   (double/float)
     const                                1bit
     volatile                             1bit
     restrict                             1bit
     assop                                1bit                           
     arity  (number of recursive tree)    4bit
属性で16bit とるべきでしょうね。
     ATTR(tag,size,sign,assop,arity)
        (tag<<16)+sign+(size<<1)+(assop<<9)+(arity<<12)

CONV も ICONV,FCONV + source type (INT) とかがいいみたいだね。

んー、なんかいまいちだな。

Thu Feb 17 13:07:36 JST 2005

また、あいだが空いているよ。string と const の再利用がいまいちだね。

Tue Mar  1 14:55:55 JST 2005

arm なんだけど、post increment とかあるよね。さぼらずにやろう。
        ldrb    ip, [r0, #1]!
あと、arm は、predication をちゃんとやらないとgccには勝てないね。
まぁ、できないことはないんだろうけど、めんどくさそう。peep hole
的に? まぁ、inline mode でやるしかないでしょうね。

        sub     ip, fp, #68
        ldmia   ip!, {r0, r1, r2, r3}
        stmia   lr!, {r0, r1, r2, r3}
        ldmia   ip!, {r0, r1, r2, r3}
        stmia   lr!, {r0, r1, r2, r3}

これは.... memcpy なのか。

Sat Jul 30 14:41:54 JST 2005

あぁ、function の型のlist node にVOIDというprimitive型が入ってしまって
いるね。これは、なんか、やっちまった記憶があるが... どうも、もともと
あまりちゃんとしてなくて、type<0でも car(type)とかやってたみたいだね。

inline code ってのはありえるの?

何か知らないが gcc が .s の#マクロの展開をするようになってるね。

    #include_next <stdarg.h>

ですかぁ?!

    ./mc1 -s -ob10.s mc-parse.c
    /usr/include/sys/cdefs.h:335:Macro syntax
    #  error Unknown architecture

このエラーはなんかあったが... __ppc__ が定義されてないのがいけないのだよ。
ifdef を見るときには EMPTY になってるな。

##     nptr_pool->ptr += sizeof(NMTBL);
## 4074: gexpr_init: creg=r3 freg=f14
        lwz r3,0(r11)                     nptr_pool を読み込んで来る
        stw  r3,lo16(-20)(r30)
        la r3,lo16(-20)(r30)   
        la r10,lo16(-20)(r30)
        addi r10,r10,lo16(24)
        stw r10,0(r3)

これだな。

iassop の hoge += const の処理が間違っていたみたい。他のは?!
そもそも、この定数演算の処理ってだめだめだよね?

いつどこで、こうなったのか... って、そもそも、ここに落ちるのが
変だよね。

lassop も同じ問題があったね。
        /*  new = &e2 */
        /*  *new = *new op e3 */
        n = list3(LVAR,new_lvar(size_of_int),0);
        g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT));
        g_expr(assign_expr0(rvalue_t(n,INT),
            list3(op,rvalue_t(list2(INDIRECT,rvalue_t(n,INT)),t),e3),t,t));
        free_lvar(cadr(n));
そもそも、なんでこうなんだ? e2 が極めて複雑な場合なんだよね?
get_register_var しないの?

なんで、この悪事が露見しなかったのかは謎だが...



Mon Nov  7 20:30:26 JST 2005

MIPS で、
        jal fptodp
で、呼出側の局所変数を壊すってのがまだあるらしい。

じゃないみたい。

> f50 では、引数は
>        $f12,$f14,$6,$7
> というように4つ乗るらしい。(こまったもんだ...)

なんだけど、int との混在状況ではそうならないらしい。

$4 が使われていると $f12 は使わずに $5 を使うという方針のようですね。

Tue Nov  8 20:20:29 JST 2005

構造体の局所変数の初期化に式を書けない。全部、定数かどうかをチェックする必要あり。

goto で struct 一つだけを引数にとったときにうまく動作しない.. (っていうか、
int 以外の引数じゃうまく動作しない   )ってバグを直しました。

ia32 の emit_copy が無限ループ。

Thu Nov 10 18:46:39 JST 2005

ia32 のfloat drindirect のoffset

構造体のalignmentをやってませんでした。

Unioon のdisp の計算、変じゃないか?

    } else if (mode==GUDECL||mode==LUDECL) {
        // disp = ((disp+(size_of_int-1))&~(size_of_int-1));
        if (type>0 && car(type)==BIT_FIELD) {
            cadr(caddr(type)) = 0; sz = size(cadr(type));
        }  else {
            sz = size(type);
        }
        fields = list4(type,fields,(int)(n->nm),0);
                                                ^^^ disp じゃないの?
    ....

    case GUDECL: case LUDECL:
        if (disp < sz) disp = sz;
        return n;

と union だけdispが特別扱いのようですが... あんまりテストされてないなぁ。

Sat Nov 26 09:53:48 JST 2005

MIPS で、
code segment 中の float/double conversion の後で大域変数にアクセスすると
code dump する件ですが...

      l.s $f12,16($11)
      jal fptodp
      sw $2,16($sp)
      sw $3,20($sp)

0x400ab0 in print_foo ()
pc =00400ab0 fp =7ffff900 r2 =00000012 r3 =00000003 r4= 7ffff670 r5= 00000000
r6 =00000012 r7 =00000000 r8 =00000c00 r9 =00000010 r10=00000000 r11=10000130
0x400ab0 <print_foo+32>:        jalr    $t9
(gdb) ni
0x400ab8 in print_foo ()
pc =00400ab8 fp =7ffff900 r2 =00000000 r3 =40100000 r4= 00000000 r5= 800fffff
r6 =7fffffff r7 =00000000 r8 =00000000 r9 =00100000 r10=00000000 r11=00000401
0x400ab8 <print_foo+40>:        lw      $gp,64($s8)
(gdb) p (void*)((int)$gp)
$3 = (void *) 0x10008030
(gdb) si
0x400abc in print_foo ()
pc =00400abc fp =7ffff900 r2 =00000000 r3 =40100000 r4= 00000000 r5= 800fffff
r6 =7fffffff r7 =00000000 r8 =00000000 r9 =00100000 r10=00000000 r11=00000401
0x400abc <print_foo+44>:        sw      $v0,16($sp)
(gdb) p (void*)((int)$gp)
$4 = (void *) 0x0


わかりました。code segment の中では jal じゃなくて 

        la      $25,fptodp
        jalr    $25
        lw      $gp,$L_7($sp)

しなきゃいけなかったんだ。なんでそうかは忘れた。($fp を使われちゃうからなのね)

Sun Nov 27 15:04:31 JST 2005

code じゃなくて _code にすれば?

function call を code segment 自体で書ければ、mc-code-xxx.c の負担が減る
んだけど。asm と併用で? でも、その部分自体が system 依存だからなぁ。

S式構文を導入する? mc-parse.c のコード生成部分を分離しないと。

recursive type の拡張がいるよね。でないと code segement の型の正確な
定義が出来ない。

    typedef hoge(arg) { ...; }  hage;

で、hage をhogeの中で使えるようにすると C と意味が変わってしまうし、
one path compile しにくい。

Sun Dec  4 14:16:24 JST 2005

構造体の初期化で、構造体のネストとか配列を無視して、ずらずら、
並べるってのがるらしい。

   sturct hoge { int a; double b[3]; } = {1,2,3,4};

みたいな。今は、エラーになるけどね。その方がいいと思うけど。

Sat Dec 10 19:24:59 JST 2005

partial evaluator だと、やっぱりフロー解析しないとだめだよな〜
途中で malloc したり中間変数で取った構造体を消さない限り、
本当は inline は意味ない。static の扱いで別に害はないんだけどさ。

難しい割りに使えない機能の一つだね。

const は無視するって技もあるな。変数についた変数の値に
対するconst は ctmode で判るはずだよね。

enter_scope は連想配列ベースだから、上のレベルの変数は
見えるはず。だから、partial evaluation 中の値の書き換え
は、enterscope してやればいいんじゃないの?

Sun Dec 11 18:18:04 JST 2005

もしかして、inline 用なら attribute でいいんじゃないの? type check
しないんでしょ?

attribute は変数にしかつかない。関数の型にconstを入れるとすれば、
ANSI-Cとの互換性を考えても type system に入れるべきでしょう。

emit_data で、型だけ見て処理してました。値の型を見ないとね。
address 以外は型検査で落していたらしい。

int a0();
int a5();

#define TYPE double

TYPE addrs[]={
     (TYPE)&a0,
     (TYPE)&a5,
     (TYPE)a0,
     (TYPE)a5,
     0,
};

なるほど、long long ではエラーを出して良いらしい。

unsgined i = -5;

で、昔は 0xff...ffa が入ったけど、今は、0が入るみたい。うーん。
これを区別するためには、CONSTと UCONST を区別する必要があるね。
まぁ、やるべきなんだろうけど...

Mon Dec 12 21:53:38 JST 2005

type system にいれると primitive type (intなど)もリストにしない
とだめなのか。それも、ちょっとなぁ。まぁ、qualifier があった
時点で、list3(ATTR,type,attribute) とするという手もあるけど。
それが合理的かな〜


局所変数のalignmentを def と new_lvar の二箇所でやってました。
しかも、間違ってました。

Fri Dec 16 12:57:46 JST 2005

まぁ、type に attribute を入れるのが良いとは思う。でも、たぶん、
    if (type<0) {
	switch (type) {
	case INT: ....
みたいなコードがたくさんあるはずなので、その前に attribute を
取り除くコードを入れないといけないらしい。ちょっと影響が大きい
ので、気が重い。

attribute の情報は構文木には入らない。変数には attr field 
があるので入る。関数の引数の情報はtypeに入るはずなので、そ
れでだいじょうぶ? 引数のリストは構文解析中しかないので、型
に入れるしかない。structのfieldに入る場合もあるしね。それを
実際にチェックするかどうかはコンパイラの方針だけど。代入時
にチェックすることは面倒だが可能。

    list(ATTRIBUTE,type,value)

ですか? value はint = (ctmode)?

    type = set_type_attr(type,ctmode);
    get_type_attr(type)

かな。type_value みたいなのもいるかも。

Fri Dec 16 20:57:40 JST 2005

うーん、やっぱり、結構変更が大きいなぁ。しかも、テストルーチンが
あんまり用意されてないし。

correct_type のエラーかぁ。

Sat Dec 17 13:45:17 JST 2005

function() が複雑すぎ。codegen の方に共通部分を収納した方が良くない?
可能だとは思うが、難しいね。IA32 の方が古すぎる。

さすがに4つも書いたので共通化できるはずだが。

そういえば、mc-tree も動かなくなってるんだよな。

gen_inline で vartable を使っているけど、enter_scope でいい
んじゃないの? 新しい変数を使うときは、new_lvar すれば良いし。
同じ変数名で置き換えをするときがちょっと気まずいか。いや、macro_
function と同じで、既に値は計算してあるんだろ? っていうか計
算してからdef & assignするわけだよね。def しないといけない
ところがあれだが... def する方が整合性は高いが、その必要は
ないはず。ということは、enter_scope でいいのかな。getsym
しないから、だめか。

Wed Dec 21 16:52:40 JST 2005

PowerPC のprintf でfloatが混在する場合が「まだ」おかしい。

来年は64bit version だな。

今の実装でできるの?

あぁあぁ、PowerPCのprintfがぼろぼろじゃん。っていうか、
dots & freg  の扱いが間違ってるな。

ia32 の cond の float も間違ってる。

Thu Dec 22 11:48:39 JST 2005

cond のテストルーチンを入れたので、まぁ、いろいろバグが取れました。

ia32 の方では dreg が不必要にuseされている場合があるらしい。

printf もなんとか。assign_expr でのtype checkが変だった。

Fri Dec 23 00:24:38 JST 2005

inline の引数のpoinetrとったらどうするの? エラー?

inline function のLVARのオフセットはあまり意味がない。
index にするか? それともオフセットの連想配列にするか。

IVAR とか IRVAR とか作るのかな。type は入らない? LVAR とかと混在すると思うので
いるんだろうなぁ。

parital evaluator では、pexpr を再帰呼出ししないといけないわけね。

recursive inline の検出はやらないといけないわけね。

(あぁ、なんかやっちゃったみたい.... また、風邪拾っちゃったよ〜)

Fri Dec 23 19:37:42 JST 2005

ST_* 系列は、先に、cadr(e) を評価しちゃうのでif とかswitchとかの
スコープが狂ってしまう。

st_* のcadr(e)の評価は g_expr0 でやっているのでst_*側でやる
必要はないらしい。pexpr のネストが深いのは気になるが、直し方が
わからず。大域変数を使うのが良いらしいが。
   pwhile(int in) {
    out = list2(out,pexpr(in));
    return cadr(in);
  }
みたいな感じ?

    Wed Dec 28 00:31:30 JST 2005

違うね。

    pexpr() {
	e1=cadr(e);
	switch(car(e)) {
	case CASE:
	... parse=list(CASE,parse,hoge,hoge); break;
	}
    }
    parse = reverse0(parse);

みたいな感じか。

Sat Dec 24 21:00:17 JST 2005

pfdecl で、inline を生成するんだけど、そこで引数のn->dspが arg_register
などで破壊されてしまう。すると、inline がinlineを含んでいた時に破綻します。
なのでコピーを作ることで対処。

inline return は、まだ、ちゃんとつくってないね。代入になる
場合があるから、ret_var みたいなので取っておけば良いか。
(これは、いまだにさぼり)

gen_inline なんだけど、最初は、partial evaluation だけやるつもり
だったみたいだね。g_expr_u したのは間違いなのか。(そもそも、_u
じゃないし) 部分的なpartial evaluation は、やってもやらなくても、
どっちでもいいはず。

Sun Dec 25 16:26:03 JST 2005

あぁ、確かに goto のラベルは、inline の中ではlocal なscope
にしないといけないのであった。で、どうすれば良いわけ? 

うまく直せない。scope 関係を見直せば良いんだけど.... enter_top_scope とか。
マルチレベルscopeになるわけね。

ではなくて、parse してしまえば、single level scpe になるので、
enter_scope して、st_label では、make_local_scope すれば良いらしい。

## 65:     } while ( k < j);
        la r11,lo16(-20)(r30)
        la r10,lo16(-24)(r30)
        cmpw cr2,r10,r11

なので、rvalue が取れてないみたいね。そう言われてみると、
IVAR のravalue とかは無視してましたが、RVALUEみたいなのが
いるってこと? 

RINDIRECT で逃げようと思ったが、

## 40:    if (i>j) return j;
        li r11,-3
        lwz r11,lo16(0)(r11)
        li r10,5
        lwz r10,lo16(0)(r10)
        cmpw cr1,r10,r11
        ble cr1,L_37
        li r10,-3
        lwz r10,lo16(0)(r10)
## 41:    else return i;

const でreplaceする時がまずいな。RIVARみたいなのを作ると、
ちょっとcaseが増えすぎるが... pindirect でいんちきするか。

(で、あとで、やっぱりだめで、const replace を諦めてるし)

const で置換したIVARのアドレスを取られると気まずいなぁ。

このあたりはマルチパスでないとできない。まぁ、parse tree を
持っているので可能ではあるけど。

Sun Dec 25 20:24:02 JST 2005

さて、return を作らないとだめか。

なに、結局、

    return value がないときは jump 
    return value がある時には、g_expr でjump

にする? とりあえず。

pfdecl で struct_return は、なんとかしてるの?

やっぱ、ret() で、 code_set_return_register(1);
は、だめじゃん。if 文の分岐で値を同じレジスタ
に置くためには.... ?: と同じ方法か。

code_get_fixed_creg ねぇ。
        t = code_get_fixed_creg(USE_CREG,d);
        gen_jmp(e3=fwdlabel());
        fwddef(e2);
        t1=g_expr0(cadddr(e1));
        code_set_fixed_creg(t,1,d);
ですか。

Mon Dec 26 10:54:29 JST 2005

  .cstring とかのデータモードとglobalラベルが変。

これねぇ。string をconstに置くかどうかは arch によるわけだから、
mc-code-*.c で解決するのが正しいわけだけど、emit_data に分散して
しまっているね。

Mon Dec 26 22:57:49 JST 2005

引数中の関数型の定義があまり正確でないらしい。型宣言のない
code segment の呼び出しで、間違った値を送ってしまう。

大きな構造体二種類を含む parallel assignment が 無限ループ
する。分割を小さくすると通る。

register のtargetがoverrapしている場合に、registerを free
してからsave_targetしているので同じregisterが再利用されて
しまって無限ループしているらしい。save_target で register
overlap を見るようにしたけど、ad-hoc じゃない? (ま、
もともと今の実装が ad-hoc だし)

ASSIGN_STRUCT_DIVDE ってDIVDEする大きさのlimitなのか。
大きいのは逆にdivdeしないのか。

Mon Dec 26 23:18:06 JST 2005

そもそも、仮引数のユーザに名前と大きさを決めさせているんだ
から、順序はこっちで決めれば良い。その代わり、異なる名前で
仮引数を受けるのは許さないってのがいいかもね。とすると、code
segment の引数のdefault とかを考えるとかなり、不思議な感じ。
なんか整合性の良い interface ってあるんだろうか? stack を含
めて? 

   goto hoge(i=1,j=3,...)

みたいな?

Tue Dec 27 18:17:55 JST 2005

inline をstaticとして扱うoptionがあった方がいいかもね。

あ、そうか。inline で new_lvar したら、あとでfreeしないと。
ということは、keep track しないとまずいのね。

## 94:  i += k;
        la r3,lo16(-32)(r30)
        lwz r3,lo16(0)(r3)
        li r11,3

当然、const arg でないとconstantに置き換えてはいけないわけね。
address を取られた場合も同様。ということは、has_address みたいな
attribute も必要なわけだ。

ま、それはあとで。

Wed Dec 28 17:29:59 JST 2005

skipspc() で、inmode の時に、cheap に書かれてしまうので、
cheap 上の string  をterminate しないうちに、skipspc()
してはいけないわけね。

なんだが、"hoge" "ahoge" のcaseに、inmode の ST_COMMENT
が干渉してしまうわけね。それは、まずいか。

やっぱり、STRING は、"" で一つにして、複数つながる
っていう構文にした方が良いね。

    list(STRING,value,continue)

みたいな感じ。でも、それだと変更が多い(何故か nptr にいれてた...)
ので、やっぱり、append しました。

Thu Dec 29 09:59:38 JST 2005

PowerPC の get_lregister が失敗するのが、まだ、微妙に残ってる。
足りないはずないんだけどね。input register も探させちゃうか。
そういえば、最初は input register は使わない方針だったけど、
今は使ってもいいんじゃないの?

Fri Dec 30 16:31:33 JST 2005

IVAR の置換だけど、

453         int lvar;
454         if (car(lvar=cadr(e))==IVAR) {
455             lvar=p_lvar(cadr(e)); // can be anything....
456             switch(car(lvar)) {
(gdb) l
457             case LVAR:
458                 return rvalue_t(lvar,cadddr(e));

だと、やっぱり、LVAR のindirect と干渉してしまう?

indirect の型は、その場のtypeでは型変換が終ってしまっている
ので、その前のでないとだめ。そもそも型を渡さずに、
UCINDIRECT とかを見るべきだよね。逆か? RINDIRECTを
一つにして型を持ち歩いた方がいいのか?

配列のADDは、inline でどこに消えちゃったの?
  (indirect で消しているみたいね)
って、あと一つまでいったか。

やっぱり offset がうまく動いてませんでした。

お疲れ様。

あぁ、-D が動いてないね。

ia32 は  inline のregister_varをfreeしたことがなかったみたいだね。

Sat Dec 31 10:34:44 JST 2005

code_return_struct で、一時構造体がinlineの場合にうまく
とられない。

.data
.globl foo
        .comm foo,4
        .comm ebp,4
.text
        .set ebx_offset,16
.globl check
check:
        pushl %eax
        pushl %ebx
        movl ebp,%ebx
        movl ebx_offset(%ebx),%eax
        cmpl %eax,foo
        jne bad
        popl %ebx
        popl %eax
        ret
bad:
        popl %ebx
        popl %eax
        ret

とかで stack のぶっこわしを検出できます。

Sat Dec 31 17:08:08 JST 2005

decl_data で ADECL をチェックしてないから、引数の初期化が
あるな。C++ では、確かあったような気もするが...

arg offset のネストを「まだ」処理してなかったのか.... 引数の
中の引数宣言は「名前をつけない」ってのが普通だったからなぁ。

## の廻りのスペースを取る方法がわからない。なのと、; を一つ余計に食ってしまう。この手のバグは取りにくいよ。

## の次の置き換えの繰り返しに対してもspaceを取らないといけないので、
depth first には解決できないね。## で mconcat のflag を立てて、
mappend した後、## を取り除くのが良いのではないか? (もっさいが...)

Sun Jan  1 10:59:19 JST 2006

inlucde_next で、重複したinclude_pathにひかかってしまって、
同じのを開けてしまう。

#include の時にchptrsave stackは? top_init でclearするのは
変だとしても。#define \n hoge \n #include とか? 冗談だろ。

decl_data のINTの場合にcorret_typeするとsigned/byteの情報が
失われてしまう。

local struct init の場合に式を使うことができない。やっぱり、まずいか。
local struct static を切ればいいんだけど。式があったら、
代入するようにすれば良いんだが。(ま、いいか?)

inline でも、

adpt_ps2/adpt_libps.c(.text+0xb0c): undefined reference to `ot_Init_node'
adpt_ps2/adpt_libps.o: In function `GsClearOt':

ちゃんと extern 付けてくれれば、動くのになぁ。

adpt_ps2/adpt_libps.c:    ot_Init_node(); 
adpt_ps2/ot.c:ot_Init_node( void ) 
adpt_ps2/ot.c:    ot_Init_node();
adpt_ps2/ot.h:inline char ot_Init_node( void );

あぁ、ひどい。inline っていう嘘をつくことが可能なのか。しかも、
Warning さえ出ないのか。でも、動いてはいるのか。

n->sc にFUNCTIONが入るのは間違い?

linux が通らなくなってるね。struct field のネストね。通したはずなんだが。

getsym で構造体のデータがlocal defineされてしまう。SFDINIT modeか。
LDECL だけで定義するんじゃないのか? 大域変数の場合もあるけどね。

decl_data で、構造体の中身の代入には assign_data で代入文が
出てしまうらしい。でも、それでもemit_dataに飛ぶ理由は不明だな。

Tue Jan  3 15:39:54 JST 2006

あぁ、なんか、union のdispの問題が今ごろ明らかになっているらしい。

いや、そうではありませんでした。decl_data が LVAR のdspを
いじっているせいでした。

statement expression ({int x; x+1})  だけど、inline でも、
call してregister save した方が良いのだが....

    parse = list3(ST_COMP,parse,expr(0));

とすると、expr(0)で生成されたparseは失われてしまう。(何故かわかる?)

Wed Jan  4 09:41:39 JST 2006

そろそろ mc-tree を作り直す時か...

ST_COMPがネストしすぎ。ST_COMPじゃんなくてlistをデフォルトに
すればいいんだよな。append, reverse0 がたくさんでるけど。

やっぱり、statement expression が後ろに廻されてるね。
        if ({hoge,i}) ....
を、
        hoge;
	if (i) ...
とcompileしていいのか? LCALL の代わりに「SAVE_REGISTER」みたいな
ことはできないの?

素直に list3(STATEMENT,statement,value)とすれば? one path では出来ないか。

                    goto exit0;
                printf("#0051:2nd inner %d %d %0x\n",i,k,&&exit1==exit);
            exit0:
            i;
        ....
        printf("#0061:inner %d %d %0x\n",i,k,&&exit1==exit);
    }
    k++;
exit0:

やっぱり、label のネストはあるのか... enter_scope しないで
なんとかする方法ないの? pvartable にkeepすればいいんじゃない?
だから、new_lvar すればいいんじゃないか? (いいんだけど、
変更が大きい...)

p_goto が、なんか二重に呼ばれている。まぁ、害はないんだが...

硬いなぁ。scope.c が全然通らない。このコンパイラも複雑すぎる。
また、simple に戻すのをやらないといじれなくなってしまう。

mode,stmode の関係が炸裂してるね。mode,stmode,ctmode と
必要なのか。一つにできないの?

あぁ、なるほど。local_table でstaticを出力するんだけど、こ
のstatic は、inline で共有しないといけないわけね。別々にコ
ードが生成されても単一のコードを呼ぶのと同じでないといけな
いから。だから、毎回local_tableを出すのはまずい。
使わないstaticのreferenceを出すわけにもいかない。
local_table をinline code にいれるか?

LLDECL は変。LDECL でtypeを見てやれば十分なはず。

801             if (inmode && mode==LDECL) { 
802                 parse = list4(ST_DECL,parse,(int)n,list2(stmode,ctmode));
803             }

こんな間違いしているし。

inmode でも lastexp があるので、checkret は必要じゃん。

Thu Jan  5 14:10:10 JST 2006

ようやっと scope は通りました。

doif, p_if, st_if と三段階に同じ処理をするのか。それがずれると、
特に、pxxx で IVAR の置換が残ってしまうらしい。

local variable のKONST attribute に式が入る場合があり、
それが pexpr されてないらしい。でも、ここに式が入ると、
毎回計算されるので、結局、うれしくない。なので、
本当の定数の場合だけセットする方が良い。

微妙に embug してるな。

Thu Jan  5 18:14:45 JST 2006

構造体の初期化なんだけど、
    {1,2,3,4,{5,6},7}
    {1,2,3,4,(struct hoge){},7}
    {1,2,3,4,struct_hoge,7}
    {1,2,3,4,5,6,7}
を区別できないんだけど。

もしかして、expr(0) してから判断するのかな。

つうか、{} を一旦、リストに格納してからコード生成するのか。
その方がいいか。

でも、adhoc にtypeid があったら構造体のコピーということに
しました。

bit field をinline するなら、bit field value を計算するのを
やらないとだめだね。code_bit_replace とかに interpreter mode
をつければいいんだよな。

Thu Jan  5 22:18:50 JST 2006

linux kernelは一応、通りました。IA32 でinlineで関数の引数の
呼ばれる順序が変わる。あと、scope.c のinlineがだめだな。
なにか、まずいことをやっているのか? signed?
    return list3(COMMA,pexpr(e1),pexpr(e2));
みたいなことをやると、IA32では引数の呼び出し順序が異なるので、
p_decl とかがずれるみたいだね。この手のを全部取らないとダメだ。

IA32のis_writableに RLVAR が入るのは何故?

xreg と creg を変更するコード生成があると、
emit_pop_free で creg が regs[creg]=0 されちゃうときがある。
emit_copy の後とかね。すると code_set_fixed_creg で、creg が切替えられてしまう。
そして、値が伝わらない。

ia32 では emit_pop_free で creg かどうか見てるみたいね。それでも
いいんだけど...

Fri Jan  6 13:31:32 JST 2006

gen_inline で、peval してstatementがない時には、生成しないんだよね。
ということは、argument のgexpr もなんとかしないといけないわけね。

argument のreplaceは、lvalue でやらないと話がわやになってしまう。
ってことは、de_ravlue っていうか lvalue() あるいは、paddress
を通さないとダメなのね。


##       spview[counttag]=spview[enemyfaste];^M
## 904: : creg=$2 freg=$f12
        la $11,spview
        move $2,$11
        li $10,24
        la $8,enemyfaste
        lw $9,0($8)
        mult $9,$9,$10
        addu $9,$9,$2
        move $10,$11
        li $7,24
        lw $6,-92($fp)
        mult $6,$6,$7
        addu $6,$6,$10
        li $6,24
        move $5,$9
        move $4,$6
        jal memmove

あーぁ、やってるよ。$6 にものの見事に上書きか。parallel assign している
はずなんだけどね。

emit_copy がparallel assign してませんでした。ARM を作ったときに
いれたと思ったんだけどね。

Fri Jan  6 19:19:16 JST 2006

MIPS のfloat register の save_stackが間違ってました。

PowerPC の math.h のinlcude がうまくいきません。

Sat Jan  7 01:33:01 JST 2006

switch(c) で c が定数の場合は、別に作らないとだめか。
式を持ち歩けば良いんだよね。今はレジスタを持ち歩いている
わけだけど。

pexpr で処理するのは、statementにcontrolがあるかどうかを
判断しなければならないので難しい。

inline は const をいれない状態だと、ほとんど部分計算は
ないね。flow 解析しないと。


えーと、volatile const ってのは、
    自分では書かないが、
    誰かが変更する可能性があるので、
    常に読みにいかないとだめ
ってことだよね。is_readony==1 だけど、is_const はfalse なのか。
inline local の場合でもそうなの?

    const int i = 3;
    switch(i) {
    case 1: printf("#0035:1\n"); break;
    default:
    case 2: printf("#0036:2\n"); break;
    case 3: printf("#0037:3\n"); break;

これで、case 2(=default) が選択されるのか。ってことは、
default が来たら、残りは全部無視して良いわけ?


インタフェースの順序を大きい順にすると、コピーの
被害が少ないが....

string の共有はやらないの? hash table にまで、いれたのに。
set_attr が出来たので楽勝でした。

まぁ、でも、そろそろ封印だな。

あぁ、そうか。ST_COMMENT がgetcでinrement_cheapと干渉するのは、ST_COMMENT
の方がまずいよ。でも、直せないな。負けた、string のところだけ?
わかった。ST_COMMENT が別な「cheap pointer」を使えばいいのか。

UTF-8 使えるようにする? ascii を拡張すれば良いだけだよね。


なんか、macro の history のcheckをしてないな。


Sat Jan  7 20:34:12 JST 2006


しかし、ここまで作っておいてなんだけど...

    function(arg)
    {
	interface *arg;
	calling_function(arg)
    }

でもいいんじゃない? だめ? レジスタ渡しのargがないけどね。


extern printf(const char *,...);

struct interface
{
    int a;
    int b;
};

code f(struct interface a);
extern code h(struct interface a);

code g(struct interface a)
{
    goto h(a);
}


code f(struct interface a)
{
    if (a.b) {
	printf("%d\n",a.a);
	goto f(a);
    } else {
	goto g(a);
    }
}

これを以下のように変換するわけだ。

    struct interface
    {
	int a;
	int b;
    };

    void f(struct interface *a);
    extern void h(struct interface *a);

    void g(struct interface *a)
    {
	h(a);
    }


    void f(struct interface *a)
    {
	if (a->b) {
	    f(a);
	} else {
	    g(a);
	}
    }


	.globl _g
_g:
	b L_h$stub
	.align 2
	.globl _f
_f:
	lwz r0,4(r3)
	cmpwi cr7,r0,0
	beq+ cr7,L5
L8:
	b L8
L5:
	b _g

結構、ちゃんとでるじゃん。でも、printf を混ぜたりすると、結
構、わけわからんコードが出るね。戻って来るっていう前提があ
るから、やっぱりレジスタのsaveがきついんだよな。

レジスタの引数渡しは絶対にでないけどね。(とは限らないか?)

引数をすべて同じにするというのが肝なのか。

でも、これだったら比較的簡単にCに変換できるんじゃないか?
    CbC to C
ってわけだね。

そういう意味では一種の「プログラミングスタイル」なんだよな。

さすがに、構造体を引数にすると、こんなに簡単なコードは
出ないみたいだね。ということはポインタにせざるを得ない
のか。

スタック関係のコードを抑圧出来れば、mc でも悪くないか。

つまり、gcc で、
    tail recursion しか「無理に」しない制約 (__code)
を導入して、それを実現するcallを
    __goto f(hoge);
にしてやれば良いわけだ。

あと、構造体をコピーしないモードだね。call semantics が違うから
これは必要なのか。pointer でもいいんだけどさ。違うのはここか。

4.0なら、比較的簡単に実現できるのではないか?

pointer の方がinterfaceの切替えも楽だし。

Mon Jan  9 19:29:06 JST 2006

なんか、-E も -Cc も「ぜんぜん」動きません。mc-tree.c が
ぼろぼろだからだな。 まぁ、そうだよな。

ここら辺がconverterにするつもりだったんだけど、簡単には出来ない
かも。まぁ、今は、inline mode があるから、tree を作ってから
印刷するっていう技もあるけどね。

bitfield で、丁度、範囲がbyte/word boundary に一致した
時には普通の代入ですむんだけど、それを考慮してない。
make_mask の時にチェック可能。(まぁ、やる必要ないけどさ)

あと、if (hoge.bb) とか if (!hoge.bb) ぐらいは処理したい
よね。if (hoge.bb==0x1) とか if (hoge.bb!=0x1) も。
この場合はshift しないで and または or ですむから。

ltosop で、オペランドの一つがint の時もやった方が良いかな。

それよりは、64bit対応かな。

fdecl, code_decl で、一旦、tree を生成してから、コード生成
するオプションがあった方が良い。その方が最適化が可能。
それをdefaultにするべきか?

inline のst_switch は、もっと賢くあるべき。

Tue Jan 10 11:30:33 JST 2006

parse tree base で変換するなら、binop を通すのはまずい。

binop では、式と型の組みで持たないとだめ? その方が
良いはず。

う、あっさり、converter も動いたか。

あとは、parse tree mode と source generator from parse tree を
作れば良いわけね。

まぁ、converter は one path なんで限界はあるんだよね。もっと
簡単に出来るかと思ったけど、実際に動かしてみると、結構、
だめだめ。-E は、簡単に作れるから作ってみたけど、やっぱり
変だよね。本体を2 pass にすることも可能だが、いろいろ
面倒か。と考えると、parse tree が結局楽か。

Wed Jan 11 13:58:03 JST 2006

ARM の定数テーブルの溢れを修正、freg_arg のバグ。

a0+a1+a2+.... で、局所変数から局所変数へのコピーが出るのは
ダサイ。が、そのためには、
    gexpr(e1);
    emit_push();
ではなくて、
    emit_push(e1);
にしないとだめだね。直しても対した量ではないが...

emit_push() では、register_full かどうかを見てないから、
get_register() のところで、stack のclearが出るわけか。
あぁ、そんなコードが出てるね。

machineop のところで、なんとか出来ないの? emit_pop
では free_lvar しているしな。

    void
    machinop(e1)
    int e1;
    {
	int e2,e3,op;

	e2 = cadr(e1);
	op = car(e1);
	switch (car(e3 = caddr(e1))) {
	case RGVAR: case RLVAR: case CONST:
	    g_expr(e2);
	    if (simpop(op)) 
		oprt(op,e3);
	    else 
		oprt_div(op,e3);
	    return;

昔は、やってたみたいだね。

あぁ、そうじゃないよ。tosop の前のgexpr では RGVAR とかが
くれば良いんだが、それはbinop でやっていて、mc-inline.c
では、binop は呼ばれないから、最適化がかからないわけね。
IVAR level で binop を呼んでも意味がない。
ということは、mc-inline.c でbinopを呼べば良いから、やっぱり、
list(op,e1,t1,e2,t2) という形でないとだめなわけね。

でも binop は type を変えてしまうので、それを保存するように
直さないとだめ。

これだと、parse tree を正確に保存することはできない。
type を含めた変換をしないと構文解析できないし。

long long のEQ/NEQ が、long long を返しているようですが。

 -O99 だと、mc1 が落ちて、mc2 は落ちない。ってことは、
なんか余計なレジスタが干渉しているらしい。

  PowerPC で -O99 だと、cmpflag 4 が保存されることを gcc4  
が要求するらしい。

+leo+kono time ./mc  mc*.c 
./mc mc*.c  0.93s user 0.11s system 93% cpu 1.105 total
+leo+kono time ./mc1  mc*.c
./mc1 mc*.c  1.21s user 0.11s system 93% cpu 1.406 total
+leo+kono time ./mc2  mc*.c
./mc2 mc*.c  1.19s user 0.12s system 84% cpu 1.542 total
   gcc 最適化なし
+leo+kono time ./mc  mc*.c
./mc mc*.c  1.34s user 0.12s system 93% cpu 1.556 total

コンパイラぐらいだとgcc4 の -O99 の20%ぐらいの速度差らしい。gcc の最適化なし
よりは速いのか。

 -O99 の初期化してないっていうエラーメッセージに対処するために
いろいろ初期化を入れちゃったけど、本当は必要ない。

Thu Jan 12 13:03:12 JST 2006

あぁ、そうか。
    binop(...) {
	int e = binop0(...);
	if (inmode) return list3(op...);
	else return e;
    }
とすれば良かったわけね。まぁ、pexpr でひっかかりまくる
可能性はあるが....

Thu Jan 12 22:28:32 JST 2006

code hoge()
{
    goto hoge();
}

int
f()
{
}

code hoga()
{
    f();

    goto f();   // bad
}

main()
{
    hoge();     // bad
}

最初の方のエラーを出せないな。

なんか、エラーにすると正しいものもエラーになってしまう。

function として使われたかどうか、code として
使われたかどうかのフラグが必要か。attribute?

一回、goto f(); では function として処理しちゃっている
から、構文解析レベルではチェックできないな。
mode を変えないと。stmode?

codegen level では構文エラーを出さない方針が良いらしい。

Fri Jan 13 09:34:10 JST 2006

inmode を fdecl の最後でクリアすると、fargtype が
変になるらしい。local heap 上に取られてしまうから
なんだろうけど。でも、fdecl でinmode をクリアしないのは
おかしい。

local struct の型情報は local heap に取られるけど、
global_table で参照される可能性がある。global に
置いてもいいんじゃないの?

もともと global に置いていたが、decl_data の関係で
mode を入れ換えているうちに、間違えてしまった
みたいだね。あとは、inmode が甘かったので、
global heap に残すものをあまり気にしてなかった
みたい。

Sat Jan 14 22:58:45 JST 2006

goto with environment だけど、code segment の中からの切替えは可能らしい。
しかし、通常の関数からのgoto with environment はうまく動かない。
これは何故だろう?

そうか、env を設定したときは、構造体はコピーしないといけない
わけね。それは、code segment からでも同じ。

逆にメモリのoverrap は気にしなくて良いのか。通常の関数に戻
る場合は、引数一つと決まっているからな。

Sun Jan 15 09:24:58 JST 2006

return がない時には、retlabelを生成しないほうがいい。

env を設定したら、jump のtargetをenv へのindirect + offset に
変えないとダメ。

goto with env は r1 しか変更してない。それは、code segment では、
stack top に過ぎない。r30 の方を変更しないと。
(いや、これは PowerPC 版だけの問題なのか...)

code_set_frame_pointer が実はstack top しか設定してない。

env が設定されている場合は、メモリ上のinterfaceは、
そのままコピーを実行すれば良く、並列代入する必要はない。

stack tpo はcode segment では frame pointer から計算される。(無駄?)
から、設定する必要は実はない。function に戻るときは必要。

new_environ のメモリ構成は...

                 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
   #             *                           r30 <---r1_offset---------> r1
r+ +----------+--+----------+----------------+-----------+----------+----+
    cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                   r20-r29     lvar>0         lvar<0      lvar>0x1000 000
                   f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
                              *SIZE_OF_INT                  *SIZE_OF_INT

と書いてあるが、
        disp = -args;
とか、
    /* reverse all argument offset (with size) */
    arglist = fnptr->dsp;
    for(t=arglist;t;t=cadr(t)) {
        n=(NMTBL *)caddr(t);
        if(n->sc==LVAR)
            n->dsp = -n->dsp-cadddr(t);
    }
とかやっているので、lvar>0 ってのは存在しないらしい。つまり、
全部、local variable 扱いになります。inline code ってのも
面白いけど、この辺を考慮しないとだめだね。

ってことは、fp はenvironment の一番下(つまり environment の
指しているところそのまま、で良いってことか? やっぱり
関数呼び出しに比べてなんて簡単なんだ。

R1SAVEして、frame pointer = environment でないのは、
PowerPC 版だけか。ということは、PowerPC 版の R1SAVE
を解消することから始めないとだめなみたい。

基本的に、stack pointer は、save しておくか、frame
pointer から計算すれば良いらしい。どうして、R1SAVE
することにしたのかは不明。

function has return value but reached to the end
なんだけど、reachability のcheckが while(1) の
時とかやってないので、結構、うるさい。

Sun Jan 15 16:06:29 JST 2006

code_fix_frame_pointer って何をやっているのだろう?
arm/mips では、何もしてない。powerpc,ia32 でも、
消去できるのでは?

でさ、env をさっさと計算して get_register_var に入れてしまう
のが良いと思う。で、INDIRECT+offset にして代入すれば良い。

PowerPC, IA32 では、disp_offset ==0 には、原理的に出来ない。
互換性の問題だから。code_segment の code_disp_offset を disp_offset
に合わせることは出来るはず。そうすれば、mc-codegen の方で 
disp_offset を見ることはないんじゃないの? 

そもそも、そうでないと parallel assignment がうまく動かない
はずだよね。

というわけで、disp_offset==code_disp_offset は必須ということに
なりました。これで、code_fix_frame_pointer はなくなりました。

non destructive creg ってのは、あっても良いかも。

Sun Jan 15 23:16:10 JST 2006

あーぁ、ia32 のレジスタ変数がloopでは、virtualがずれるので
うまく動かない。jmp では、標準に直すべきなのか。ってことは、
ia32 ではレジスタはやっぱり禁止か。か、あるいは、virtual
を止めるかだね。esi/edi はvirtualしないっていう風にすれば
いいか。lreg は?

いや、だめですね。check_virtual みたいな方法だと、もっと、
いろいろ変更しないと動かない。use_data_reg() とかは、
根本的にだめってことじゃないか? (いまさら?)

use_register(reg,REG_EAX) などが、 reg = use_register(reg,REG_EAX);
という形式ならば、rename し切れなかった時に、別なレジスタを返せる。

通常は register はcopy して使うわけだから、rename はされな
い。setup_edx とか、get_register で esi/edi が返されて rename
されてしまった時がまずいわけだけよね。 その時だけ check_virtual
すれば?

esi/edi をget_regsiter しないと、assop などで、致命的に足り
ないことになる。

rname しないとすると、use_data_reg したら、必ず後で戻す
みたいな実装か?

get_register では data_registerが取れて、get_pointer では、
esi が取れて、それは、use_data_reg/setup_edx では、使われない
みたいな感じかなぁ。

Mon Jan 16 08:42:16 JST 2006

やっぱり ia32 は、設計が悪い。

    rname, dreg は廃止
    use_data_reg は、use_int などと同じ形式に
    setup_edx などは止め、parallel_rassign を使用する

とすれば、register を復活できるのではないだろうか?
mc-code-mips とかから再構成する?

Mon Jan 16 09:03:27 JST 2006

というわけで、

cbc - 環境/インタフェースの切替え

やっぱり、そのままでは動きませんでしたが、付けてみました。
うまく使うと、POSIX Thread 的に使うことも可能。

例題は CbC_project/device/test/throw.c にあります。

code
throw(interface1 arg,int i,int j)
{
    char *space = (char *)malloc(ENVSIZE)+ENVSIZE;
    printf("%d %d %d %d %d\n",arg.last,arg.a,arg.c[99],i,j);
    arg.last=97;
    goto throw1(arg,i,75),space;
}

こんな感じで使います。space (切替えるべき環境)は、stack な
のでメモリ領域の一番下を指しているようにしてください。context
とか呼ぶ人もいるだろうな。大きさ的にどれくらいいるかは、
状況による。64Kbyteはとるべきでしょう。

でも、常に interface がコピーされるのでは、あまり意味がない
のか。interface をコピーしないで保存するモードがあれば良い
のかな。

    goto throw1(),space;

みたいな感じ? env が最後を指しているのが不便だが。

    code hoge(interface &hoge) {};

みたいな? もともと参照だしね。引数のずれを防ぐのも考えないと。
struct に64byteのalignment を入れるか。

やっぱり、特定の型を作って、
    __env env = new_env(size);
    goto throw(env);
みたいな感じの方がいいのかな。

int
main1()
{
    interface1 arg;
    char *space = (char *)malloc(ENVSIZE)+ENVSIZE;
    ret = return;
    env = environment;
    goto throw1(arg,-6,77),space;
}

ってな感じで、Cの環境から呼ぶことも可能。

space が一番下ってのも変だが、stack だから仕方がない? こういう風に
実装するなら、下向きに延ばすことも可能だが.... C のスタックと干渉
するから、だめか。

Tue Jan 17 10:56:08 JST 2006

一応、ia32 から rname と dreg は落しましたが....

    get_register が必ず成功するようにする
	register_var をセーブするような手法が必要かも?
	free_register で戻す
	でも、save されたって言う保証がない?
    dreg を使っていたところを get_register に直す
    use_data_reg0 を書き直し

というわけで、結構あるなぁ。(こんなのより論文書いたら?)

なんか creg=0 をemptyだと思っているみたいだけど、-1 だろ?

酒飲んでないけど、頭が廻らん。

Wed Jan 18 11:42:18 JST 2006

あと、もう少し。code-stringの後の .text のalignはいらんだろ。

なんか、creg に reg_var を割り振るように直してしまったが、
だいたい動いているんだけど、かなり怪しい。その方がコード
は良いんだが.... これは read only creg なんだよね。

終りました。tosop は、いい加減だが、あんなもので動くのか。
要は「tosop に入る前に確保するレジスタは emit_push で確保する」
「use_register では、code_save_register で使うレジスタを確保する」
ってことだね。

register は0からでなく1から始める。code_gexpr では、creg に
レジスタが入っている場合は、creg を clear。free_register する
場合には、register variable かどうかをチェック。

他のも、これにする方が正しそう。

Wed Jan 18 14:47:39 JST 2006

register の順序を変えると動かなくなるってのは、コードの信頼性が
低いってことなんだよな....

Thu Jan 19 16:49:23 JST 2006

hoge()
#if 0
{

とかで、type が、おかしくなるらしい。ありそうな話だ。

これといい、原因といい、くだらんバグだった。初期化してない
変数を使ってたのにwariningでないのは最適化をかけないからか。

register stack overflow ってなかなかでないのね。ローカル
変数をレジスタにマップしない限りレジスタって意味ないのか。

Fri Jan 20 16:48:01 JST 2006

なんか ARM の code segment の方のoffset がぼろぼろだ。
つじつまはあっているんだろうけど。

disp_offset==0 のシステムはいいんだよね。ARM だと、
fp を設定してからregisterをsaveするので、不定の
オフセットが存在する。jump with environment した
時には、その分がずれてしまう。

通常のfunction からの goto でも、このずれは存在する
ので、fp の修正はいずれにせよ必要。

だけど、jump はcodegenにあるので、汎用に修正しない
といけない。

fp を jump/leave 時に offset_label の分だけずらすことに
しました。code_fix_frame_pointer で処理します。
env を設定したときには、environment は、修正されたfp
を持っているので、fix しないようにします。

いずれにせよ、environment は、設定した環境の中で不定の
場所に陣どるので注意が必要。

Sat Jan 21 18:06:10 JST 2006

tosop のつまらないoptimizeのおかげでかなりはまりました。
これよりは、assignment の方の
    creg = hoge op hoge;
    *lvalue = creg;
を、
    *lvalue = hoge op hoge;
とする方をやりたいが....

converter が、うまくないのは、1 pass だからだよね。multi-path
通るようにできないかな?

goto hoge(),env; で、env が 0 だったら、fp の切替えをしない
って方が良くない? 出力コードは複雑になるが...

Mon Jan 23 13:52:32 JST 2006

あ、なんか、converter すごいかも。やっぱり、このままで、
c2cbc,cbc2c が楽勝で書けるみたい。なんで 1 pass じゃだめだ
と思ったんだろう?

Wed Jan 25 12:42:57 JST 2006

c2cbc は、式の途中の関数呼び出しを分解しないといけないので、
先読み抜きで変換するのは出来ない。だから、expr tree のprint
が必要。逆に言えば、それを作りさえすれば良い。

で、expr16 で、strop, binop とかやっているので、それを
parse tree  に変更しないとダメ。ってことは、これようの、
tree id が必要だってことか。逆に言えば、それだけか?

cbc2c は、code 宣言、goto 文だけを変換すれば良いので、
可能じゃないか?

Wed Jan 25 19:58:40 JST 2006

cbc2c で、env 切替えはどうやってコンパイルするの?

Thu Jan 26 23:42:18 JST 2006

やっぱり、strop/array をいじると動かなくなるね。

本来、parse tree にtypeは入るべきではないんだよね。
syntax tree だったら tree にそってparseすればtypeは決まる。
parse tree だったら、node でtypeは決まっているはず。

binop にtypeが二つついているあたりが中途半端な矛盾に
なっているんだよな。

そうか、rvalue では、ARRAY/PERIOD/ARROWに RINDIRECT を付けないとダメ。
ということは、RARRAY/RPERIOD/RARROW/RIVAR があった方が、
構文木が保存されるから、そっちがいいわけね。

確かに、RINDIRECTで、IVAR の先読みをするのはおかしいものな。

bitfield と RSTUCT は、なんか変だよ。rvalue の扱いがあまり
consistent でないらしい。

問題は、RIVAR の導入でどれくらいバグが出るかだな。
    RIVAR   = INDIRECT + IVAR
    RARRAY  = INDIRECT + ARRAY
    RPERIOD = INDIRECT + PERIOD
    RARROW  = INDIRECT + ARROW
で、良いわけなんですが...

これで、expr のtreeから、構文木を生成できるはずだが。

Fri Jan 27 20:47:00 JST 2006

PowerPC で、r1 の下の方を呼び出した関数がいじってしまうのは、
なんでなんだろう? register save 分かとも思うが、生成された
コードにはそういうのはないんだよな....

RIVAR   = INDIRECT + IVAR にすると、CRIVAR とかを作らない
といけないらしい。type を持ち歩けば、そのあたりは不要な
わけなんだけど。むしろ逆にRINDIRECT only でもいいわけね。

typecheck だけど、goto 文の中で local 変数へのpointer を
持ってたら warning を出すのが望ましい。

で、expr のconvert ですが、どうするの? inmode 入れちゃって、
一気にプリントが簡単ですが.... statement level? なんか、
構造がまったく変わっちゃうな。時間かかるかも。

Mon Feb  6 20:31:48 JST 2006

statement expression とかがあるので、結局は、全部
印刷しないとだめ。ってことは、tree_parse を書き直さない
とだめだね。

cast とかが落ちる可能性もあるので、正確には元に戻せない。

あと、type_print mode との切替えをするかどうかだな。
切替えはするんだと思うんだけど.... うまく出来るかどうか
が問題。しない方が簡単だが、そうすると、conv/*.c の
整合性が良くないか。それもいいけどさ。

gen_inline なんかで、


Fri Feb 10 21:18:41 JST 2006

gcc のinclude path を Makefile (じゃなくて、mc-code-*.c か)
に取り込む仕組みが必要だね。

Sat Feb 18 20:45:46 JST 2006

そうか local_struct_init だけど、式での初期化があるから、
memcpy で実装するのは良くないわけね。もちろん、式があった
どうかを判断することは出来るんだけど...


Sun Mar  5 20:05:41 JST 2006

やっぱり、print_expression とか、print_statement とか
作るじゃない?

Fri Mar 17 18:33:16 JST 2006

 gcc -print-search-dirs

ってのがあるのか。

Mon Mar 27 12:08:08 JST 2006

64bit support と、SSE3 とかの対応を入れた方がいいかな。
本当に、浮動小数点処理にSSE3を使うのが普通なのかどうかは
知らんけど。

Intel のコンパイラを見るべきなのか?

Tue Mar 28 23:59:57 JST 2006

C_FUNCTION の get_name  を見た後、nptr->dsp を設定するべきか?

    *cheap->ptr = 0;
    cheap = increment_cheap(cheap,&name);
    i++;
    nptr = name_space_search(hash_search(name,&scheap,i,hash,DEF),STRING);
    // if we already have this, hash_search will reset cheap
    nptr->dsp = i;

再利用を考えると、これじゃないか? (また、時間があったら、直そう...)

Sun Apr 16 17:41:36 JST 2006

やっぱり、list の実装が見えるのは良くない。GC を入れても良いし。
そういう意味では、そろそろ捨ててもいいし、作り直しても良いんだよな。

list のタグで要素の型がわかる方がいいけどね。ということは、
Object で構成するってこと? Java で書き直してもいいけど。
まぁ、いいろいろイキヅマリガあるよな。

Wed Apr 19 14:37:36 JST 2006

list を必ずtag付きにして、型を決め打ちすれば良い。gettree を
任意のベクタにすると良いね。
    型        expression
    int
    double
    long double
    long long
    NMTBL
    xx        extension
3bit x n ぐらいか?
    9  bit tag              
    4  bit type tag         (singed, long long, float, double, char, short)
    3  bit length
    15 bit (3*5) 型リスト
ぐらい?

    #define GSYMS           (8192*32)
    #define HEAPSIZE        120000
    #define CHEAPSIZE       (sizeof(NMTBL)*8192)
    #define LBUFSIZE        4096
    #define STRSIZE         4096

ここら辺も初期値をオプションで指定できた方が良い。

Mon May 29 02:52:40 JST 2006

そうか... sse2 をサポートしないと、やっぱりだめなのね。
Pen 4 以上では。

Wed Jun 21 14:58:17 JST 2006

64bit 対応とかいろいろあるよな。
SPU は比較的容易にサポート出来そう。

でも、それより先に、
    statement を含むparse tree のprint
    statement を含むparse tree のS式表現のprint
    S式表現のparser
を書かないと。

Wed Sep  6 16:42:43 JST 2006

gcc の C99 だと、

 __builtin_fabsf(__x)   // float
 __builtin_fabs(__x)    // double
 __builtin_fabsl(__x)   // long double
 __builtin_inf()
 __builtin_inff()

とかいうのがあるみたいだね。

cheat するより、実装するのが簡単か?

    __DBL_MIN__  1.17549435e-38F
    __DBL_MIN__ 2.2250738585072014e-308
    __LDBL_MIN__ 2.00416836000897277799610805135016e-292L

も内蔵なのか。まぁ、これは書けば良いだけだが。

long double ねぇ。こんなのやるのやだ ...

     int foo asm ("myfoo") = 2;

This specifies that the name to be used for the variable `foo' in the
assembler code should be `myfoo' rather than the usual `_foo'.

 You cannot use `asm' in this way in a function _definition_; but you
can get the same effect by writing a declaration for the function
before its definition and putting `asm' there, like this:

     extern func () asm ("FUNC");

こんな brain dead があるのか。困ったものだ。

これ、どうやって実現するのかな。attribute でしょうね。ASM_NAME か、なんか?
とりあえず無視?

__asm になっているからだめなので、__asm も 処理すると「無視する」モードに
なっていることがわかりました。


Thu Sep  7 10:41:54 JST 2006

attribute だと、毎回チェックがうざい。nptr->nm を直接変える方が望ましいが...
key と表示のポインタを分ければ簡単に実現できるんだけど。

Intel Mac は、relocatable code なので、ptr_cache を実装する必要が
あるらしい。register 変数を破棄すれば可能かも。

offset pointer は、使う直前で取得するのでもOk。ループの中だと嫌だが...
そうすれば大域変数を使用しないルーチンでは、取得ルーチンを省ける。
SSE2 を含めて、PowerPC スタイルに変更した方が合理的なんだろうな。

でも、時間的にはけっこうかかってしまうみたい。

もう一つの、goto hoge(a,...); だけど、結局、stack を実装することに
なるんじゃないの? 大域的なsyntax sugar だと考えることも可能では
あるが、コードが共有されるところが異なる。.... の部分がメモリ
に乗るというのを保証して、それ以外を別なところにあるというのが
確定しないとまずい?

もう少し考えてみないと実現できるかどうかわからない。

Sun Sep 10 11:46:30 JST 2006

return がないとかのwaringを出した方が良いね。
それほど難しくないはず。


Sun Sep 10 22:05:38 JST 2006

test/i3.c がひどい...

Wed Sep 27 13:47:47 JST 2006

PowerPC の 構造体の引渡しが int とかと混在すると、gcc と整合しないらしい。

        .globl _main01
_main01:
        mflr r0
        stmw r30,-8(r1)
        stw r0,8(r1)
        stwu r1,-80(r1)
        mr r30,r1
        bcl 20,31,"L00000000001$pb"
"L00000000001$pb":
        mflr r31
        stw r3,104(r30)
        stw r4,108(r30)
        stw r5,112(r30)
        stw r6,116(r30)
        stw r7,120(r30)
        stw r8,124(r30)
        stw r9,128(r30)
        stw r10,132(r30)
        lwz r0,108(r30)

あぁ、integer の要素の場合は、先頭のいくつかは、レジスタに
マッピングされるみたいだね。

これは、なんかあったな。ARM は、そういう仕組みになっていて
対処しているみたいだね。なんでだろう?

あ、そうか。Intel Mac の対応があるんだった... しくしく。

filep の overflow をチェックしてない。(こういうの多そう...)

Sat Oct  7 13:41:13 JST 2006

inline のswitchの展開ぐらいいれた方がいいが...

0x19d9c <__i686.get_pc_thunk.bx>:       mov    (%esp),%ebx
0x19d9f <__i686.get_pc_thunk.bx+3>:     ret    

ですか。

string は、ebx でPC相対で取って来るわけね。(ださ〜) ということは、
やっぱり、一つレジスタを潰さないとだめか。

しかも、EBX なわけ?!

大域変数は、
        leal    L_uc1$non_lazy_ptr-"L00000000006$pb"(%ebx), %eax
        movl    (%eax), %eax
        movb    $-56, (%eax)
だから、やっぱり、レジスタ一つ EBX とは別に潰すことになる。

ということは、デフォルトでレジスタが二つ潰れるわけね。

で、ptr_cache は使うの? ううーん... 使っても害はないはず。
ptr_cache は get_register() が絶対失敗しないことに依存している
んだよね。

そして、浮動小数点の計算は、すべて mmx(sse2) らしい。ぶぅ。
mmx は 8 個レジスタがあるわけね。

もしかすると、修正は以外に少ないかも。

Tue Oct 10 02:15:24 JST 2006

む。先ながそ。

Intel Mac の global_table() がめんどくさい....

Tue Oct 10 22:13:24 JST 2006

define されたfucntion  へのcallはstub を経由する必要はない。
ってことは、defined  されたかどうかの attribute があった
方がいいね。

あぁ、なんか「関数呼び出す引数の分だけ、スタックを取っておいて、
関数呼び出し時にスタックを調整するようなことはしない」
なのか。

おっと、stack は 16byte alignment でなければならないわけね。

あ、そうか。ebp が-12 offset だと、16byte alignment に一致しない。

use_data_register() と  ptr_cache() の相性が良くないらしい。

偶然動いたりするのか... しくしく。


use_data_reg() で初期化してない変数を使ってました。

"hoge" "hage" を #ifdef で挟むと動かない... (ふーん...)

escape() 内部で処理したのが間違いだったみたいだね。
このコードは呼ばれないはずなので取り去るべき。

Thu Oct 12 00:05:15 JST 2006

switch 文で、行き先がおなじ分を「まとめる」ってのを
してない。range にまとめられるなら、それが有利か。

Thu Oct 12 12:08:36 JST 2006

    code hoge(i,j,cont,...);

    code hoga(int a,int b,int k, int l, int m);
    {
        int i,j,k,l,m;
	code (*cont)(int,int,...);
	goto hoge(i,j,hoga,k,l,m);
    }

    code hoge(int i,int j,code (*cont)(int,int,...), ...) {
	goto cont(i,j,...);
    }

の実装なんだけど.... fix typed stack あるいは、bounded stack かな?

                 * gotoを呼び出した関数のr1 ! r1(goto前のr1)
   #             *                           r30 <---r1_offset---------> r1
r+ +----------+--+----------+----------------+-----------+----------+----+
    cousin arg xx  reg save !callee arg      !code local  caller arg  xx
                   r20-r29     lvar>0         lvar<0      lvar>0x1000 000
                   f20-f31  <-my_func_args--><--disp-----><-max_func_arg->
                              *SIZE_OF_INT                  *SIZE_OF_INT

長さが知り得ないので、code local variable をどこに取っていいか
わからないという問題がある。ふん。 

呼び出されたときのstack (っていうのかな?) top を見れば良いのかな?
local variable 分も入っているようですが.. まぁ、r30 使っても
いいんだけど。

ということは、「隠れて、code segment argument の長さを持ち歩く」
ってことだね。その方が良い。

あぁ、でも、PowerPC とかだと、local variable は、r30 からの
固定オフセットで取っているのか。いや、そんなことないな。
r1 からアクセスしているようですね。

いや、関数呼び出しの時の引数をr1から積んでいるらしい。
これは変更しないとだめだね。

i386 でも、%ebp からアクセスしているな。

      | frame pointer                     | stack pointer
      v----> argument      local <--------v

という形にしないとだめか。stdarg を使うためには、順序を関数呼び出しに
合わせないとだめだが...

つまり、local variable を CALLER ARG 上にとってやれば
良いらしい。問題は、stack をずらしたとき(alloca)に、
pointer がずれるってことだが... (それはcopyするか...)

逆に言えば、これをやれば、動きます。ということだね。メモリの
アクセス範囲は | frame pointer --> <--- stack pointer |
に閉じるわけか。

意味的には、全体を展開してしまえば、全部固定長になるので、
問題はない。

ちょっと、修正が多いかな...

Wed Oct 18 21:35:36 JST 2006

GVAR の dsp は(initialization のフラグ以外) 空いているので、
ここに、asm("alias") の属性を入れるのは構わない。まぁ、毎回、
attribute チェックしてもいいんだけど。そんなけちる意味もな
いので、alias field をNMTBL に足してもいいんだけどね。

function の場合は、属性に入れるんでしょ?

Tue Oct 31 20:16:16 JST 2006

関数の引数に固定長の配列を渡すと破綻するらしい。 (test/ps2.c)
gcc には可変長配列ってのもあるにはあるんだよな。

構造体と同じ扱いにしたが。

いや、違うな... ARRAY は integral なんじゃないのか?
単なるpointerだろ? 違うの?

大域変数の倍
   array            +            array
引数の場合
   pointer -> array + pointer -> array

引数の配列は、ポインタとして扱うわけだが、typedef されている
場合もある。

typedef されてなくても、多次元配列の倍数がずれるというバグが
あるらしい。

わかった。引数の配列型は、ポインタ型に変換されるのだが、そ
れは、typedef される場合もあるので、def() で行う必要がある。
また、adecl や decl で処理すると、多次元配列の場合に二回処
理されてしまう場合があるらしい。

これに関連して、a[1][1]だと、(e+1)+1 みたいなコードがでて、
これは、binop で最適化出来ないね。

Wed Nov  1 23:23:41 JST 2006

そうか、push_struct で、ARMのcodeを入れてやれば、PowerPC 版
も簡単に出来そう。

callee 側は、どうせスタックに書き戻しているんだから別に
良いわけね。

ARM のpush_struct を全部持って来た方がいいらしい。

Sat Nov  4 19:40:49 JST 2006

なんか、i3 のエラーを直してないね。見送りにしたわけ?

Sat Nov  4 22:47:13 JST 2006

      | frame pointer                     | stack pointer
      v----> argument      local <--------v

なんだけど、これだと、local variable のoffsetが、その場で
定数にならないという問題があるんじゃないの?

いや逆か。sp からなら、必ず定数になるわけね。

subroutineから、code を呼び出す時に、parallel assignment
が使えないが、この場合は、sp の値は決まっているはず。
というか後で合わせれば良い。caller_arg を sp からの
オフセットで書き込む必要がある。

      | frame pointer                     | stack pointer
      v----> argument      local <--|-----v
                                    caller_arg

というわけかな。

caller_arg は、関数の最後でないと決まらないので、large offset
では、やっぱり、困る。(だから、local var を fp からにしたの
だったが...)

      | frame pointer               | stack pointer
      v----> argument      local <--|-----v
                                    caller_arg

にすればいいんだろうけど... 許されるのか? いくつかのアーキテクチャ
では、そうなっているらしいが。

まぁ、MAX caller arg を決めるっていう手もあるけどね。その方が
楽か....

Sun Nov  5 14:21:19 JST 2006

expr16 で statement expression をparseしようと思うと、
IVARが生成されてしまうので気まずい。pexpr するのは、
少しおかしい。

やっぱり parse してからcompileするモード作る?   そうすると、
いろいろ出来るようになる。inmode=PARSE とかいうのを作るか。

細かい問題があるみたいだね。

Mon Nov  6 21:00:47 JST 2006

asm("name")  の属性の処理をしないと。急ぐのか?

asm/attribute の区別が必要。

n->nm は、そここで使っているので、やっぱり、search 用の名前と
表示用の名前と分けた方が良い。一旦、hash を引いてしまえば、
表示用の名前の方でいいんじゃないか? orignal へのポインタは
用意するとして。n->nm, n->name と二重にする手もあるけどね。
そっちのが方が断然やさしいが。

Fri Nov 17 19:04:49 JST 2006

local variable のalignment を、mc-codegen.c の def() で
制御する必要がある。stack のalignment 以上には制御できない
わけだけどね。

attribute に出て来るidentifierって予約語じゃないんだよな。
どう処理しようかな。最初の1文字とか... (本気か?!)

まぁ、name space を専用に作るのが普通だろうとは思うが...

順調に進んでいるけど。

typedef されたsymbol に付いているattribute を引き継ぐ必要が
ある。それは、どこで...

Sun Nov 19 14:10:54 JST 2006

なんか、ia32/gcc 2.9 の時のvarargs が壊れているらしい。

ARMのスタックalignmentは、ずれているようだ... stack top
自体がalignされているべきだと思うので、直すんだろうな。

Tue Nov 21 05:06:37 JST 2006

struct のaligned(16) (引数無しもあるらしい...) だけど、
nptr に set_attribute してしまってはだめらしい。関数の
arugment もそう。

typedef された attribute は、どうする? もともと、タイプ
の方に attribute してやれば、こんな問題は出ないのだが...
hoge *p; では、hoge のattribute を引き継いではだめ。

ってことは、set_attr は要らないってこと? (かもね...)

Sun Nov 26 13:15:39 JST 2006

code segment のvariable interface を許すためには、Intel の
stack code を直した方が良い。

alloca のgexpr は、binopされてないので、最適化されない...

あぁ、ia32 は、lvar_intro とかも使ってないわけね。
offset は、結構複雑になるので、直す方が良いらしい。

時間かける価値あるの? 少しかかりそうだな...

Fri Dec  1 22:45:28 JST 2006

long double の実装ねぇ。

Mon Dec 25 22:02:12 JST 2006

     f((struct arg){.fuga = 3});

が、うまくうごかない。init_vars は、いつどこで評価されるべきなの?
    decl_str_init
あたりなみたい。

うーん、結構、壊して来ちゃった。

     f((struct arg){.fuga = g()});

みたいな場合もあるよね?
    flush_local_static_struct()
あたりをちゃんと直さないと。

Sat Jan 13 18:52:37 JST 2007

emit_init_vars() は ad-hoc にしちゃだめ。どこで出て来るかわからない
んだから。

あと、式のcarに0を入れるのは反則なはず。

tmp7.c が通らないぞ。

Sun Jan 14 20:01:03 JST 2007

やっぱり、ちょっと変更が大きいけど、タグに木の大きさを入れるべきだな。

あぁ、そうか。

##      f((struct arg){.fuga = 3,.aho=5});

とかだと、構造体はstackに積めば良い。だが、exprの中で、emit_init_vars
してしまうと、それは出来ない。deleyed みたいな扱いをすればいい?
実際に使われるところでemit_init_vars() するみたいな?


Wed Jan 24 14:12:20 JST 2007

get_register_var を使った後、free してない例が多いみたい。


Sat Apr 28 21:00:15 JST 2007

どうも、code_dassop のテストをしてないらしい。

i387 の演算で、use flag を間違えると、387 のstack overflow
が出るらしい。g_expr は use flag を1にするので注意。


Sun Apr 29 23:59:16 JST 2007

mc-ia32 では、function callをpush を使わないように直さないとだめ
らしい。浮動小数点もSSE2に直すべきでしょう。結構、めんどくさい。

long double もいるのかなぁ。

mc-powerpc for PS3 は、なにがこけるのかよくわからん。

mc-spu も、まだまだ、やることはあるらしい。この三つをいつ片付けるの?
一緒にか?

まぁ、のりの問題だがな。

64bit 対応をどうするんだろう?

Fri May  4 20:07:59 JST 2007

なるほど。PS3 だと、register に乗った引数の分は、スタックが
取られてない。だから、bl regsiter_save する前に、stack を
移動する必要がある。

Breakpoint 3, 0x1000068c in i50 ()
(gdb) x/20x $r1
0xff9e00f0:     0xff9e0320      0x10001280      0x00000008      0x00000009
0xff9e0100:     0x0000000a      0x0000000b      0x0000000c      0x0000000d
0xff9e0110:     0x0000000e      0x0000000f      0x00000010      0x00000011
0xff9e0120:     0x00000012      0x00000013      0x00000014      0x00000015
0xff9e0130:     0x00000016      0x00000017      0x00000018      0x00000019
(gdb) q

そうすると、浮動小数点の場合は...

Sat May  5 03:32:27 JST 2007


dofor で、docomp で、RC を読んだときに、{...} k++; で、k を
既に読んでしまっている。その後に、leave_scope しても、current nptr
は、update されない。なので、leave_scope 中で、nptr を書き換える必要がある。


PS3 ppc の make diff が通らない...
code-gen-all の inline も

PPCで、inc_flag をしないと、long long の比較でしくじる

PS3 ppc は、レジスタ2が予約らしい (library で使うとアウト)

bitfield がずれている。



Sat May  5 13:10:05 JST 2007

ia32 のidiv/imull の符号の扱いがおかしいらいが....

いや、これは引数の呼び出し順序の問題ですね。これを
変えるのは不可能ではないのだが...

ia32 のmake diff が通らないのは、「まだ」stack frame がずれ
ているからだ。%edi を壊しているね。

(gdb) x/20x $r1
0xff909150:     0xff909180      0x00000000      0x00000000      0x00000001
0xff909160:     0x00000002      0x00000003      0x00000004      0x00000005
0xff909170:     0x00000006      0x00000007      0x0ff8dff4      0xff909180
0xff909180:     0xff909350      0x10001344      0x00000008      0x00000009
0xff909190:     0x0000000a      0x0000000b      0x0000000c      0x0000000d
(gdb) 
0xff9091a0:     0x0000000e      0x0000000f      0x00000010      0x00000011
0xff9091b0:     0x00000012      0x00000013      0x00000014      0x00000015
0xff9091c0:     0x00000016      0x00000017      0x00000018      0x00000019
0xff9091d0:     0x0000001a      0x0000001b      0x0000001c      0x0000001d
0xff9091e0:     0x0000001e      0x0000001f      0x00000020      0x00000021

PS3 のPPC は、やっぱり引数の上に、なんか乗っているんだな。それが普通なのか。
だったら、そうするか。(stdarg を内蔵関数以外で実現することが出来なくなるが)

Sun May  6 09:31:46 JST 2007

Ps3のPPCはできたけど、開いている穴の大きさが8と16の差がある。r1_offset の制御が
出来てないみたいだね。


Sun May  6 17:47:59 JST 2007

statement expression が関数の引数の中で呼ばれると、

	b L1
    L2:
	fuga
                     use REGSTER  %esi AS temp  (a)
	st value
                     free %esi
   
	j L3
    L1:
	.........
                     saved input in register var %esi
	b L2             (a) が起きて、%esi を壊す
    L3:
	value 

となって、esi を壊してしまう。complex argument のsaveと衝突するわけ
だ。

これは、他のarchitecure でも起きる問題なのか。ちょっと、
根が深いな...

statement expression の中で、temp として使ったregister var
のlistを覚えておいて、それを LCALL でsave restore してやれ
ば良い。

あるいは、LCALL の時点で使っているレジスタ変数をすべて
save/restore すれば良い。こちらの方が簡単だが量が多い。

そうすると、statement expression の中で変更された
レジスタ変数をoverwriteしてしまうので、だめ。

	b L1
    L2:
	fuga
                     use REGSTER  %esi AS temp  (a)
	st value
                     free %esi
	j L3
    L1:
	.........
                     saved input in register var %esi
        save_register %esi
	b L2             (a) が起きる
    L3:
        restore register %esi
	value 

というタイミングか。それよりは、その時点でparse treeを展開した方が
まだ、ましか...

あるいは、docomp する時に、全てのレジスタ変数を使ったことに
しておくか... それでも、ia32 ではだめだけど。

inmode==INLINE+1 の時に、若干展開が異なる。gen_inline()
する方がいいのか?

うーん、それも、いろいろ面倒なようだね。どうせ、やらなきゃ
いけないんだが。

とりあえず、ad-hoc に直したが、あとで、ちゃんと直さないと。
(get_input_arg AS_SAVE で、register variable  を使わなければ良い...)

展開するしかないんだろうなぁ。

実は    Sun Jan  1 10:59:19 JST 2006 の時点で気づいていたのだが、
忘れてしまったらしい....

resgister save すると、({  goto hoge; .... }) で、かなり困る。

Fri May 25 19:12:04 JST 2007


関数をparse する時に、inmode == INLINE でcompileして pfdecl して
やれば、parse tree base になる。

fdecl/doif などで !inmode のコードは通らなくなるので、全部、
取り除いてしまって構わない。mc-inline.c の st_if などは、
むしろ、codegen.c にあるべきだったのか。こうなると、mc-parse は、
parser のみになるので、その意味でも正しいね。

こうすると、大抵のものはglobal heap に置かれてしまうので、GCが
必須になる。もともと、getfree は複雑すぎるので... local heap
stack を縮めるのは止めて、

(1)
    全部local heapにとり、関数をcompileして、pfdecl したあと、
    型宣言とかinline funcitonのみを global heap にコピーする。
(2)
    汎用のGCを書いて、statement のtop levelで、それを読んでやる。
    あるいは、スタック上のlocal heapを含めて任意の時点で GC する
       (こちらの方が正統的だが、遅そうだ...)

という手があるね。まぁ、そのままでも kernel compile とかしない
限りは、だいじょうぶだとは思うが...

parse tree を取った後の、最適化に関しては、まぁ、いろいろ可能だが、
そんなに無理してもしょうがない。

arg_register は、もっと頭が良い方がいいが...

UDPCL 側に影響が出る可能性を否定できないが... コード生成は、
st_if 側に限るんだろうな。

GC やるんだろうなぁ。変更的には、結構大きくなるが...

code_decl 用の  pcode_decl を書く必要があるようだね。

Fri Jun  8 13:53:53 JST 2007

まぁ、それは置いておいて、mc-spu の方をやるか。is_int_reg とかが
あるので、
    REGS_MAX = 128*3
ぐらいにする?

Tue Jul 31 13:33:59 JST 2007

delc_data は inline tree にならない。これは、良くないので、
一旦、parse tree に落す必要がある。

    list(ST_DECL,next,nptr,type,(mode,smode,stmode),initialize)
    initialize
           list(CONST,value);                     =1
           list(ARRAY,next,e);                    ={1,2,3}
           list(CAST,next,type,e);                ={(struct hoge){..})

かな?

decl_data_*は、offset を返すのではなくて、式を返す。

その式を解釈する assign_data シリーズを新しく作る。

(いろいろ書いているけど、進まないね〜)

Fri Aug  3 18:06:49 JST 2007

CAST/DECL_DATA は、あとは、コード生成を書くだけか。

結局、inmode only にして書き直すのかな〜

Wed Sep 12 19:53:33 JST 2007

DECL_DATA のコード生成が全然書いてないじゃん〜

つうか、でたらめかも... もう少し考えないとだめだ。

Mon Sep 17 16:56:54 JST 2007

print_operator も書いてないのか。

Fri Sep 28 07:04:00 JST 2007

やっぱり、pexpr 内部で、type 大域変数にアクセスするのは、
まずいだろ?

Sat Sep 29 12:48:30 JST 2007

デバッグが果てしない...

Sat Sep 29 14:25:41 JST 2007

なんか、むちゃくちゃ難しいよ...

Mon Oct  1 18:10:30 JST 2007

decl_data は、いちおうできた。

あとは、code segement も pexpr から生成するようにして、
default で inmode になるようにすれば良い。

今の逐次生成モードは残すのか? 出来ることと出来ないことが
かなり違うからなぁ。

これで、parse tree から、元のソースを復活できるようになった
ので、c2cbc が書けます。

でも、まぁ、spu やるか?

Tue Oct  2 17:49:09 JST 2007

いろいろ微妙に動かない。

scope のinline が動かない。

fact-a の print のnptr の扱いが変。

code segment の宣言の扱いは不便すぎる。(2 path を書くか?)

Fri Oct  5 16:47:49 JST 2007

Intelのnested function call order は直しました。

CAST を pexpr で展開しないと、contains_p でCONVがひっかからない。

あとは、
    fact-a の print のnptr の扱いが変。
ここだけ。

    void print(  void (*print)() ) {
    }

とした時にまずい?

これは、local_scope の中で enter_scope するかどうかの問題
だったようです。

関数定義の時のnptr は、def していないようだ...

Sat Oct  6 15:47:41 JST 2007

ようやっと出来たよ...

COMPの構文を保存してない。

fdecl を pfdecl を呼び出すようにする。(直接生成はoptionで残す?)

Sun Oct  7 17:43:42 JST 2007

parse tree を導入するのだったら、one path mode は、切ってしまった
方が、mc-parse.c が小さくなる。どうせ、debug しなくなるだろうし。
case 文の逐次比較モードと同じか。

   goto(fuga(ab,c))

みたいな構文にすれば、#define で reflection 可能。まぁねぇ。
でも、通常、引数の拡大が必要 (meta state)。やっぱり、汎用の
reflection 構文が必要なんじゃないかな〜

__code goto(fname,args,...)
{
     goto();
}

を定義すると、goto そのものの意味が変わるというのが良い?

anchor も考えてないしな〜

そうか、ia32 を sse2化するっていうのも残っているのか。
どこで mmx register を save する? caller 側?

Mon Oct  8 00:24:58 JST 2007

main のinline化で、まだ、通ってないものがたくさん。float が
若干おかしいらしい。varargs/alloca がだめらしい。

あぁ、そうか。エラーメッセージの表示場所がわからなくなってしまう。
これは、あれをやるしかないのか?

Mon Oct  8 14:13:57 JST 2007

inline されたlocal 変数のscope は? top level だけ変?

Wed Oct 10 13:46:49 JST 2007

cast は、(float)1 みたいなのだと、correct_type は、rvalue する。

(hoge *)p みたいな場合でも、ravlue  するべき? 左辺のcastの
場合は、rvalue してはまずい。右辺では? RSTRUCT では?

うーん、やっぱり RCAST が必要なみたいだな。correct_type では、
int/long などの時には、rvalue している。これは正しい。
CAST は、rvalue されない。ravlue では、CASTは no touch。

わかりました。

1422                type = cadddr(e1);
1423                return correct_type(pexpr(e2),caddr(e1));

で、pepxr(e2) が type を書き換えている。prindirec で、間違った
type を返しているのがまずい。両方直すんだろうな。


Wed Oct 17 18:36:23 JST 2007

だいぶ破壊しちゃったよ... RSTRUCT が一貫してない。mc-code-*.c
を直すのは本末転倒。-r scope-fix までだと、変更が多すぎる。

はぁ〜 ちょっと頭痛い。酒か、血圧か? 血圧計が欲しい...

まぁ、順調に進んではいるんだけどねぇ。

Wed Oct 24 01:15:25 JST 2007

PowerPC の方が diff が通る。微妙になんか残っているようだが...

IA32 は、diff が通らない。何故だ?

あぁ、switch のparse mode がぜんぜん通ってないよ...
non parse mode の inline は、通っているのに。

Wed Oct 24 08:33:49 JST 2007

switch をparse mode で二回 inline 展開すると破綻するらしい。

Wed Oct 24 11:06:55 JST 2007

parse mode は出来ました。長かった...

macro / inmode の干渉が macro_if で起きるとは意外でした。

pexpr で、stack がどんどん深くなるのは良くない...

pexpr は、parse にappend するべきなんでしょう。reverse がうるさいが。

adhoc に code_save_register_stack  とか使ったけど、本当は、
削除出来るんだろ。

Thu Oct 25 08:19:20 JST 2007

Mac OS X も、LP64 なので、

http://www.unix.org/version2/whatsnew/lp64_wp.html

このcompilerも、int->long に書き換える必要がある。
ということは...
  #define int long
でも、いいんだけど...
  int i;
  printf("%d\n",i);
で、こける。
  int i;
  printf("%ld\n",i);
でないとだめ。

やっぱり、pointer が入る部分だけ、long に書き直すのが良いのかな。

ふーん.... PPCの書き換えは、それほど大変ではなさそうだが...

むしろ、long double の実装の方がなぁ...

switch で、long long ってのもありみたいだね。まぁ、64bit のみで
実装と言うのが良いんでしょうけど。

long を64にするのは、難しくないが、int がshort と同じ扱いになるの?
extend するのもあれだが...

Fri Oct 26 12:41:38 JST 2007

pointer の書き換えはいいんだけど、bug を取りにくい。
mc-macro で、car にstring pointer を入れているのは、
どうする?

Sat Oct 27 13:30:55 JST 2007

けっこう、スムースだな... macro のと、ST_DECL あたりに、
なんか残っているらしい。

Thu Nov  8 21:16:12 JST 2007

switch 文が const で inline された時の処理が間違っているようだ....

Sun Nov 11 22:24:59 JST 2007

cslist がなんだか思い出せないが、直りました。

Wed Nov 14 13:03:42 JST 2007

で、SPU だけど.... cross compiler と binutil いれるか...

128 のレジスタを三つ持つのもなんなので、そのまま。ということは、
use_int とかは必要ない?  is_int_reg とかは、必要ないわけね。
じゃぁ、このままいくか...

SPU のほとんどの演算は vector 演算なのか。このコンパイラって、
そういう新しいデータを構造を増やすのに向いてないんだよね。

    8bit, 16bit, 32bit, 32bit x 4

かぁ。vector type を足すんだろうなぁ。vector_add とかはださいが...

あぁ、そうか。関数呼び出しでも16byte単位でスタックに積むわけね。
printf は、どうしようもなく stack に積むらしい。

byte を書き込むってことは出来ないらしい。ふーむ。

これは、local/global memoryを使うこと自体、禁止という感じのようですね。

まぁ、とりあえず動かすことを考えて、vector 型とかは、あとで導入しよう。

Wed Nov 14 18:42:42 JST 2007

PS3 powerpc が動かなくなってるよ。

argment/local variable の alignment は、当然、system 依存か...

size_of_int と size_of_pointer を区別しないと...

parallel assign でレジスタをsaveしているけど、size_of_int だと
足りない。なので、get_register_var に変えるべきでしょう。
(もったいないけどね)
memmove との干渉があるので、get_register は使えない。

target のsize_of_int と compiler の size_of_int も別にしないと。
なるほど。

new_lvar 自体を直した方がよさそうだな〜 たくさん使われているし。

get resiter var すると、save code が出ちゃうので、微妙に
痛しかゆしなんだよな。まぁ、それに文句言うなら、もっと、
ちゃんと、register assignment しないといけないわけだけど。

データ型を拡張しやすくするのは重要だよね。C++ じゃないけどさ。

#define FASS    (FOP+ASS)
#define FCMPGE  (FOP+CMPGE)
#define FCMPEQ  (FOP+CMPEQ)
#define FCMPNEQ (FOP+CMPNEQ)
#define FASSOP  (FOP+ASSOP)
#define FCMP    (FOP+CMP)
#define FMINUS  (FOP+MINUS)

とか、かっこわるいし。type 自体に、処理メソッドへのポインタを
設けるんだろうなぁ。 ちょっと修正が多いけど。少し考えてみないと。

Tue Nov 20 15:22:43 CET 2007

SPUはかならず16byte でアクセスして、その後で、shuffle byte
で処理する形らしい。なので、char でも、16byte load して、
変更して書き込みという形になる。

local 変数に関しては、16byte alignment で処理して、shuffle
byte  を避けるので良いと思う。ただ、pack されたstruct とか
はだめ。でも、lvar だったら、offset を見れば良い。

でも、配列とかのアクセスだと、
        lqd     $2,176($sp)
        cbd     $3,0($sp)
        shufb   $2,$4,$2,$3
        stqd    $2,176($sp)
が必須となる。まぁ、そうでしょうね。

大域変数の場合も同様? 16byte alignment を仮定して良いらしい。

pointer の場合はだめで、shuffle byte が必須。

ptr_cache は、SPU の場合は、使わない方が良いらしい。256k
しかメモリがないので、オフセットで足りてしまうらしい。
16bit(64k) + 2bit alignment というわけですか。

code もそれに含まれる?

Sat Nov 24 11:19:15 CET 2007

mc-code-spu.c をどんどん破壊しているなぁ。

Sun Nov 25 12:21:26 JST 2007

メモリ上に取られる局所変数は、spu ではほとんどないと思って良い。
アドレスを取られているか、構造体か、どちらか。

構造体もできるだけレジスタ上に置いた方が良い。それは、st_* で
処理する? どういう条件で、構造体をレジスタにマップ出来るかは、
結構、複雑らしい。

かなり限定した場合だけにしてもいいんじゃないか?

だとすれば、メモリ上の局所変数へのアクセスは、あまり効率
良くなくても良いということ。だから、常にpackされていると
仮定して良い。

Sun Nov 25 21:07:43 JST 2007

REGISTER.field の形式のみの時に、register にmapする?
別にそうでなくても良いんだけど。

address を取られてなければ、register にmapして良い。

register 上にpackして、構造体を置く。でも、SPUの
場合は、pack した方が良い場合と、そうでない場合を
識別する必要がある。それは難しいだろ? (不可能じゃ
ないだろうが...)

Sun Nov 25 22:07:53 JST 2007

char で16byte取るのも良いんだけど、char a[10] とかで、
 *(a+1) = 3 とかやられると、だめ。こいつは、連続している
必要がある。(逆に言えば、SPUでは、そんなことをしては
いけない...)

でも、毎回、shuffle byte するのは(32bit int でも、
おこなう必要がある)ちょっと...

いずれにせよ、一般的なbyte(8-32bit)アクセスを書く必要は
ある。で、それが曖昧だからだめだめなんだよね。subroutine
call してもいいんじゃないか?

sp が16byte alignment だってのは仮定していいの? (おそらくは...)
じゃぁ、cbd 8(sp)ってのが意味不明。

Wed Nov 28 12:32:13 JST 2007

おっと、ptr_cache を取るのは早すぎたが... lqa は aligned address
しか扱わないので、汎用のshuffle byte code を使えない....

Tue Dec 25 22:22:11 JST 2007

あぁ、Recursive Macro は、やっぱり扱ってないじゃないか〜

Mon Jan 21 11:46:52 JST 2008

PS3 PPC が動かなくなっているんだよな。

Wed Jun 11 17:49:30 JST 2008

Recursive macro は、一旦、macro_epansion/getsymを出てしまうと、history
を使った recursive check にはひっかからない。

check_recursive にひっかかっても、もう一度、retry されてしまうので、
意味がない。

chptr の切替えでmacro_history をclearすると、get_name_from_chhptr()
で clear されてしまうので、そのあと check_recurse しても無意味。

難しいな....

clear するタイミングを prev_macro_end でおくらせる。

mutual recursive macro の semantics が gcc とは異なるらしい。

Sat Nov  8 15:06:22 JST 2008

しばらくいじってないね。

Thu Aug 20 13:56:12 JST 2009


    どうも、goto hoge(0),env; で、env  を渡すのがよろしくない。
	goto hoge(0,env);
    と言う形にして、hoge 側で env を設定するのはどうか?

	__code main_return2_1(int i,stack sp) {
	    goto (( (struct main_continuation *)sp)->main_ret)(0),
		   ((struct main_continuation *)sp)->env;
	}

    を、
  
	__code main_return2_1(int i,stack sp) {
	    goto (( (struct main_continuation *)sp)->main_ret)(0,
		   ((struct main_continuation *)sp)->env);
	}
    という形にする。

    そうすれば、goto 文は、かなり簡単になる。


Thu Nov  4 22:47:08 JST 2010

LP64 だと、scalar の扱いをなんとかしないと。

INT/UNSIGNED の区別がない...

Sat Nov 13 20:41:12 JST 2010

eh は生成しなくても動くみたいだ。

CONST に INT/UNSIGNED の区別がない... どうしようかな。

Thu Nov 18 21:32:42 JST 2010

だいぶ動いた。ia32, ppc もテストできるのはうれしい。 

long double と vector 型を増やしたい...

Thu Nov 18 23:41:39 JST 2010

save_input_register をできるだけ送らせれば、code の mmx input register を
使っても良い結果になるはず。code の先頭で、memory に store してしまうのでは、
register にとる意味がない。

Intel64 が mmx を save しないのは、そういう噂があったからだろうけど、
ばかげた話だ。

string の長さを無制限にするのは難しそう。でも、i64.c でははみ出てる。

Fri Nov 19 23:56:10 JST 2010

code_ofset_diapl0 を 0 にしないと、code segment 側の呼び出しがずれる。

function からの goto と、code からの goto の offset は、異なる。

Sat Nov 20 09:45:56 JST 2010

そうか。code_decl/pcode_decl で、argument offset を逆転させているので、
       caller argument  と callee argument
の code_arg_alignment が合わなくなるのね。code_code_arg_alignment ってのを
作るべき?


Sun Nov 21 09:51:14 JST 2010

部分的に初期化されない構造体はゼロが入るべきで、それは、local_struct_static
で行われるのだが、inline 側で正しく対処されてない。

local_struct_static は、inline ではできないみたいに書いてあるけど、
なんでだろう?

parse_mode でなければ正しく動く。

穴があったら、そこにゼロをいれる見たいなコードにする?

Tue Nov 23 17:45:50 JST 2010

stdarg は、コード生成と va_arg を statment expression で乗り切りました。疲れた。

Tue Nov 23 23:02:38 JST 2010

register をsave するのに、push を使っているけど、その分、余計にstackを確保する
必要がある。でも、そうすると、function_disp_offset にラベルを使う必要がある。
それは、ちょっとうれしくない。pushではなくて、local 変数にsaveすると言う
技もあるが... その方がいいか?

Tue Nov 23 23:29:12 JST 2010

i64 は、diff2 まで終了。

PS3 PPU は、ほとんど動く。ただし、

     gcc 4.2 と gcc 4.1 では、  singed char/unsigned char を int に代入した時の振舞が違う。

らしい。そのせいで、いろいろ一致しない。

Wed Nov 24 02:34:43 JST 2010

variadic の最初の引数のアドレスを固定した名前(その関数に局所的な)で覚えておけば、
stdarg の実装に便利なんじゃないか?

bitfield に cast すると、良くないらしい。rvalue が二重にかかる。

Thu Nov 25 13:21:05 JST 2010

asm の引数のチェックが甘いみたいだな。

non parse mode が動かなくなっている。

Fri Nov 26 12:23:47 JST 2010

rvalue が RLVAR とかに idemopoent なので、pindirect がおかしい。

indirect に rvalue を使うのはまずいの?

   ASS と CONST (FUNCTION)、REGISTER が特別な場合らしい

+rvalue では、0.1+1 とかも来てしまうので、無条件に INDIRECT にするのはダメ。
+INDIRECT にしている時とそうでない時がある。

prindirect でも、同じ混乱があるらしい。それで、lvar の最適化ができなくなっている。

あぁ、やっぱり、rvalue が mc-inline に現れるのは変なのね。たとえ、LVAR/RLVAR 
最適化のためであっても。

ravlue が、indirect を付加してしまうので、動作がが変。 non parse mode の整合性が
取れない。

Fri Dec  3 14:27:04 JST 2010

assign_expr0 の rvalue は、取ってしまっても意外に動く。float がおかしくなるらしい。

Fri Dec  3 22:22:14 JST 2010

non parse mode の CAST で、rvalue を取れば良いのかどうかがわからない。
ad-hoc な直し方ではダメらしい。

Mon Nov 21 20:37:22 JST 2011

## #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
## #define __DARWIN_ALIAS_STARTING(_mac, _iphone, x)   __DARWIN_ALIAS_STARTING_MAC_##_mac(x)

FILE  *fopen(const char * __restrict, const char * __restrict) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_2_0, __DARWIN_ALIAS(fopen))

なので、_mac を一度置き換えて、

    __DARWIN_ALIAS_STARTING_MAC___MAC_10_6

にしないとだめで、#define __MAC_10_6  1060 の方の

    __DARWIN_ALIAS_STARTING_MAC_1060

に置き換えてはダメらしい。

#sym が、"sym" に置き換わっている。sym をmacro変換してから置き換える必要がある。

Mon Sep 16 18:05:18 JST 2013

strinit が、まだおかしい。

recursive macro の結果が逆。

Wed Apr  2 12:12:34 JST 2014

LOCAL_STRUCT_INIT_STATIC は、定数の初期化をした構造体を static で用意して、それをlocalにコピーして、
実行時に変更部分だけ代入するという実装。

構造体の初期化は、
     parse_mode = 1 ( inmode ) & local_struct_static
でないと動かなくなっている。

expr14 の中で LOCAL_STRUCT_INIT_STATIC すると、再帰的に行われるので、local struct を再利用する必要があるが、
その時の offset を知りえないという問題がある。

decl_data 側で再帰構造定義を処理してやると、それは避けられるらしい。

local_struct_static 以外だといろいろ動かなくなっているようだ。

でも、局所構造体はゼロ初期化しなければならないので、local_struct_static が正しいだろう。
ということは、decl_data 側で再帰定義を扱うのが正しいのだろうな。

local_struct_offset を大域変数にしてやれば良い。(いや、それは難しすぎる)