comparison Changes @ 59:eeca07d1b1c2

*** empty log message ***
author kono
date Wed, 19 Feb 2003 21:22:19 +0900
parents
children 262c8059e5df
comparison
equal deleted inserted replaced
58:727c280bdd25 59:eeca07d1b1c2
1
2 Thu Nov 25 17:27:12 JST 1999
3
4 subroutine call がない
5 局所変数もない
6 その代わり、大域変数を多用する
7 大域変数のスコープは局所的
8 Fortran の用に局所変数は静的に取る
9 recursion する時には、自分で保存する
10 subroutine call時のレジスタのセーブも局所的に行う
11 それは、ちょっと変じゃない?
12 やっぱりデフォルトのフレームは持ち歩くか?
13
14 recursive call とそうでないのを区別するか?
15
16 fp は用意する方が良い
17
18 関数定義と同時に、それ専用のfpの構造体を用意する
19
20 C をcompileする時には、stackを持ち歩く
21 fp = (struct func_state *)stack
22 えっと、どこに代入するの? そういう問題もあるわけね。
23 じゃあ、fpは特別? それは気に入らないな。static
24 なfpにすれば良いわけね。
25
26 func(void *stack) {
27 static struct func_state {
28 static struct func_state *fp;
29 int local1;
30 brahbrah...
31 } func_state; // ここまで hidden
32 func_state.fp = (stack -= sizeof(struct func_state));
33 }
34
35 func_state をとってくる演算子があった方が良い? そうね。
36 func.state
37 ぐらい?
38
39 fp->local1 みたいなことだけするなら、C と同じになる。
40
41 call する時のarguemnt も、
42 static な func_state に置く
43 stack 上の func_state に置く
44 という二通りの選択肢がある。Cと互換なら、当然、後者。
45
46 Recursive なら後者だが、この言語は状態遷移を記述するから、static
47 なものでも良いはず。
48
49 Internal function は? あってもいいんだけど...
50
51 Recursive call する時には、 fp をsaveする必要があるね。
52 (--(struct func_state *)stack) = fp;
53 call callee(&fp->arg,continuation,stack);
54 call しても、戻って来ないから... continuation は一般的にはcode
55 だから... それは Internal function にするか。
56
57 continuation に一般的にcompileする方法を考えないといけないか。
58 self は必要なわけね?
59
60 言語の名前も考えないといかんなぁ。
61
62 C からのコンパイラも書かないといけないのか...
63
64 Mon Dec 13 18:53:04 JST 1999
65
66 compiler based で、内部で partial evaluation できる?
67
68 func をdatabaseとして扱えないなら、それはできない。
69
70 しかし、状態遷移としては取り扱える。
71
72 func.state
73 func.code
74
75 みたいな形にしてpartial evaluationすれば良い
76
77 でも止まるのか?
78
79 textual でない、中間的なコード表現があった方が良い? <-> interpreter?
80
81 Prolog ではなんでいけないの? --> Unification が重いから
82
83 Sat Nov 27 13:50:41 JST 1999
84
85 func.state とか作るのだったら、
86 struct {
87 struct {
88 int i;
89 } state;
90 state *code = {
91 i = i+1;
92 };
93 } name;
94 みたいな形で、それ自体を構造化すれば? で、代入すると部分評価される。
95 代入も可能。なるほど。
96 *name.code;
97 値はあるわけ? 値は &state でしょうね。
98 self があれば、
99 struct {
100 struct {
101 int i;
102 } state,
103 *code = {
104 self->i = self->i+1;
105 };
106 } name;
107 かな。self = state だよね。
108
109 union の拡張もあわせて議論すると...
110
111 Partial evalutator をセマンティクスや実行系にいれておくことは可能か?
112
113 byte code とか仮想マシンだったら可能。そうでない場合は?
114
115 いずれにせよ、構造体のタグのunique性を修正しないとだめだな。
116
117 ヘッダファイルはどうするの?
118
119 Mon Dec 13 18:53:18 JST 1999
120
121 library との整合性は?
122
123 exec sequence では、
124 (--(struct func_state *)stack) = fp;
125 call callee(&fp->arg);
126 という形でpointerだけ渡すの? それは変だよね。
127
128 値渡しにするとすれば、複数の値を渡せたほうが良い。
129
130 func(void *stack) {
131 static struct func_state {
132 static struct func_state *fp;
133 int local1;
134 brahbrah...
135 } func_state; // ここまで hidden
136 func_state.fp = (stack -= sizeof(struct func_state));
137 }
138
139 の引数自体が、構造体であるべき。
140
141 func(
142 struct void *stack
143 ) {
144 static struct func_state {
145 static struct func_state *fp;
146 int local1;
147 brahbrah...
148 } func_state; // ここまで hidden
149 func_state.fp = (stack -= sizeof(struct func_state));
150 }
151
152 で、構造体に register storage を許す。
153
154 func(
155 static struct argment {
156 register void *stack;
157 register void *continuation;
158 }
159 ) {
160 static struct func_state {
161 static struct func_state *fp;
162 int local1;
163 brahbrah...
164 } func_state; // ここまで hidden
165 func_state.fp = (stack -= sizeof(struct func_state));
166 }
167
168 すると、caller の方も、構造体を引数とするのが自然。
169
170 call caller(
171 static struct argment {
172 register void *stack;
173 register void *continuation;
174 } arg = {a,b};
175 )
176
177 みたいな。もちろん、この構造体はインタフェースと呼ばれる。
178
179 argument は、callee にあった方が良いけど、caller 側にあっても
180 良い。register なんかは、そう。
181
182 caller(interface caller_arg = {a,b,c})
183 みたいなsyntax かな。
184 caller->interface = {a,b,c};
185 *caller->code;
186 を、
187 caller(a,b,c);
188 と称する。
189
190 function には、interface と code と state があることになる。
191
192 state にアクセスする時のlockは? protected state? synchonized state かな?
193 もちろん、sequential implementatoinでは、そんなものはいらない。
194
195 function {
196 interface:
197 register int a;
198 register struct self self;
199 state:
200 int b;
201 serialized int c;
202 code:
203 b = a;
204 }
205
206 int にvoid value を定義する。実装は重くなるけど...
207
208 serialzed の semantics は?
209
210 もう少しmicro-Cに近く!
211
212 carring state と static state。
213
214 Mon Dec 13 19:42:41 JST 1999
215
216 interface に regsiter keyword を使うのは、あまりに
217 実装よりすぎる。でも、でないと状態にできない?
218 そんなことはないか。やっぱりcaller側のstatic 領域に
219 直接書き込む?
220
221 だとCより遅そう。でも、引数に40個とかかかれたら...
222
223 Wed Dec 15 14:09:49 JST 1999
224
225 C と互換にする?
226 goto function(argments);
227 goto *continuation(argments);
228 みたいな感じで。
229
230 stackの管理は? どうせ、library との互換はとらないと
231 いけないんだから...
232
233 local 変数がある場合は stack を動かす。でも、戻す奴がいない。
234 closure 化するか?
235
236 return した時の挙動が複雑になる。大域returnするわけだら。
237
238 argments をstatic 領域にかきこむ方式だと互換性がとれない。
239 stack 上の frmae pointer 上にないとダメだから。
240
241 両立させるのは無理か? つまり、これだと、呼び出された方の
242 frame semantics は、C と互換になる。だから、stackの直後に
243 frame pointer があると思っている (そうか? ) frame pointer
244 stack pointer に沿って移動した直後に、そこからのoffset
245 で引数を操作することになる。
246
247 つまり、それはだめだったことじゃない? つまり、goto だと、
248 frame pointer は、stack の直後とは限らないから。前の
249 frmae pointer 相対に引数にアクセスしてくれれば別だけどね。
250
251 stack に引数を積むのは容認して、goto の場合は、向こう側で
252 stack を畳むってのは? ということは、普通の関数と定義の
253 方法を変えるってことか。ま、悪くはないか。
254
255 すると、goto のsemantics は、C と互換になる。それを受ける
256 方が異なることをする。それは、なんかおかしいな。それに、
257 それだと関数呼び出しが軽くならない...
258
259 ということは、やはり、C のcall は、call funciton で
260 実現して、その他の呼び出しは、すべて、goto 扱いに
261 する方が正しいだろう。
262
263 問題は、この言語の関数をcallされた時だな。dual entry にして、
264 call の時と、goto の時を区別するか。
265 func: stack processing
266 func_goto: normal processing
267 ...
268 みたいな感じ。でも、return はないから...
269
270 このあたりも自分で記述できる言語であるべきだよね。その通り。
271 つまり、C とのstub も自分で記述すると言うことか。
272
273 protocol function {
274 interface c {
275 register "%esp" struct {
276 entry code ret(int);
277 void *fp;
278 } *sp;
279 register "%ebp" void *fp;
280 };
281 code function_code {
282 fp = sp;
283 sp += sizeof(struct local);
284 struct local *local = sp;
285
286 local->i = 1;
287 goto *fp->ret(local->i),sp=fp; // return(local->i);
288 };
289 }
290
291 みたいな感じでさ。さっすが、アセンブラ。いまいちreturnが汚いけど。
292 まぁ、return はそのままreturnでもいいけどさ。
293
294 あ、これは良いかも知れない。code が複数かけるから。
295
296 state 以外は、consitent state であることを保証しない。ってのは?
297 local 変数は使っても良いけど、call/goto の前後で、値を保証しないか...
298
299 うーん、だんだん炸裂してるなぁ。
300
301 だから、レジスタに対するマッピングの記述と、そうでない部分の
302 記述は分離するべきでしょうね。
303
304
305 全部一辺に実装するわけにはいかないからぁ...
306
307 Thu Dec 16 13:44:21 JST 1999
308
309 lock は状態遷移レベルで実現するのだから、self などを
310 使ってlockする必要はないはず。
311
312 全体の直列化は、状態遷移レベルで、
313 lock(storage) -> transition
314 みたいな形で記述すれば良い。この当たりを、どのように記述するかは
315 もう少し先送りしよう。
316
317
318 引数はレジスタ渡しにしよう。長い引数は、呼び出し側の領域への
319 ポインタとする。実装を規定しても良い。そうすれば、varargs
320 みたいなものはなくなる。だいたい、なんで、そんなものがいるんだろう?
321 配列を渡せばいいじゃん。
322
323 なので、引数は一つ(or 二つ)に限るという方法もある。
324
325 とすると、やはり、前もって静的領域や動的領域を確保することは
326 できない。
327
328 この言語では動的領域は自分で確保するわけだから、その点は問題ない。
329
330 Thu Dec 16 20:24:55 JST 1999
331
332 とすると関数呼び出しは、
333 # register save
334 # set 1st argument in register %eax
335 # set 2nd argument in register %ecx
336 # set extra aguments in save area
337 # set extra argument pointer in %edx
338 jmp function
339 という形式になるわけね。second を処理するのはめんどくさいから一つ
340 にしよう。
341
342 えーと、frame pointer はないけど、コンパイルの手順からすると
343 あった方が良い。しかし、frame pointer そのものをstatic
344 にとるのはまずい。だから、frame pointer がfirst argment
345 ということにする方が正しい。とすると引数は、さらに、その
346 後と言うわけか。
347 f(fp,argment)
348 fp を渡すのにさらにargment をレジスタで渡すのはおかしい。おかしいけど、
349 ま、良いか。
350
351 return しないなら、return type の定義をとるのは変だな。
352
353 f(fp,arg1,arg2,arg3) とすると、それぞれが決まったレジスタに入って、
354 多い分は配列にあると思われる。ふむふむ...
355 fp->xx
356 でアクセスすれば、そのまま局所変数になる。全部、配列で
357 送っても良い。
358
359 .set label,value
360
361 で as は値をセットするようですね。
362
363 関数コールの後は戻って来ないから後始末の心配はしなくてよい。
364 frame pointer を使ったら自分で面倒を見ること。
365
366 だと
367 a = atoi(s);
368 みたいなことはできない...
369
370 普通のCの定義と交じると間違いやすい。
371
372 とすると、struct と同様に、
373 protocol
374 code
375 interface
376 state
377 を用意するわけね。時間あるのかぁ?
378
379 とりあえず、register 渡しのfunction 定義とgoto文を実装する。
380
381 code name(register "%ebp" void *arg) {
382 goto name(arg);
383 }
384
385 ぐらいかな? で、first argment が必ずregisterにのるようにしないと
386 いけない。register storage class を入れて、
387 register "%ebp" void *arg
388 とかするわけね。
389
390 ってことは、まず、レジスタを実装しないといけないわけね。
391
392 で、stack を使った演算は、一応、そのままにする? それでも動くはず。
393 式の途中でgotoは使えないんだから、それでいいはず。
394
395 で、それから、これを拡張していく。
396
397 interface c {
398 register "%ebp" void *arg;
399 }
400 code name(interface c) {
401 goto name(c.arg); // c. は省略可能
402 }
403
404 とかね。さらに、
405
406 protocol name {
407 interface c {
408 register "%ebp" void *arg;
409 }
410 code name(interface c) {
411 goto name(arg);
412 }
413 code name1(interface c) {
414 goto name(arg);
415 }
416 }
417
418 などとするわけか。なんと、これが C と共存するわけね。うーん。
419
420 Fri Dec 31 11:44:03 JST 1999
421
422 code でなくて、別な名前のほうが良くない? segment? action?
423
424 レジスタ名が入るのは、やっぱりいや。optionalには許す。
425
426 interface は構造体のようなものだから... 構造体でいいんじゃない?
427 構造体の場合は... malloc する? う、うーん。malloc するとして、
428 いつfree するの?
429
430 再入するときには、壊れてていいんじゃない? multi-thread でなければね。
431 multi thread では、状態は、レジスタ経由または、thread local に持つ
432 必要がある。static は、だから thread local に持たなくてはならない。
433 大域変数に割り振っちゃだめ。でも、いまは、やめて
434
435 interface は、とりあえず、二つまでの値渡しにしよう。
436 self と arg
437 ですね。
438
439 もう少し拡張しやすいコンパイラがいいなぁ。
440
441 code name (c,a)
442 struct state *c; struct arg *a;
443 {
444 goto name(arg);
445 }
446
447 local 変数は? この互換性の問題かぁ。
448
449 KL/1 を意識して、interface は heap に置くことにしても良い。
450 GC は言語に入れておくべきだが、interfaceは machine independent
451 であるべき。だとすれば use/forget みたいものはいるだろう。
452 でも今のところは考える必要はない。
453
454 えーと、
455 code name (c,a)
456 struct state *c; struct arg *a;
457 {
458 int i;
459 goto name(arg);
460 }
461 の時の一時変数iはどうするの? 基本的にはレジスタ割り当てだけど...
462 使用させない? んー、大胆な御意見。まぁ、やっぱりheapに割り当てちゃう
463 のが簡単か。でも、どうせ抜ける時にはいらなくなるわけだから...
464
465 ほんらい、この変数は、次のcallでは必要無くなるのが普通。
466
467 とにかく、レジスタ変数は必要なんでしょう?
468
469 だから、GC と合わせて言語を設計すべきだよね。API を規定して、
470 異なるGCを選択できるようにする。
471
472 Sat Jan 1 22:40:22 JST 2000
473
474 とーにかく、 storage class regisgter を実装しよう。
475
476 stmode=REGISTER
477
478 で、local storage とおなじ扱いとする
479 static register? は、ない。
480
481 symbol table に storage class をたせば? dsp==EXTRN で判定しているから、
482 local 変数が36以上あるとおかしくなるぞ?
483
484 sc は GVAR/LVAR だけど、regsiter は LVAR の特殊な奴だから、
485 sc に入れるほうが正しいか...
486
487 Sun Jan 2 01:47:17 JST 2000
488
489 register 変数はできました。けど、regsiter を二つ使うと、
490 一杯になってしまうので、REGISTER6 でコンパイルしないと
491 結構ひどい。が、register 変数を%esi,%edi に割り当てれば
492 いいか。
493
494 Sun Jan 2 04:43:04 JST 2000
495
496 で、
497 code name (c,a)
498 struct state *c; struct arg *a;
499 {
500 goto name(c);
501 }
502 の一時変数無しは実装できます。引数は二つまでね。
503
504 .file "tmp.c"
505 .version "01.01"
506 gcc2_compiled.:
507 .text
508 #
509 # code name(c,a)
510 .align 2
511 .globl code
512 code:
513 .type code,@function
514 # struct state *c; struct arg *a;
515 # {
516 # goto name(c);
517 movl %esi,%esi
518 jmp name
519 _5:
520 .size code,_5-code
521 .ident "Micro-C compiled"
522
523 う、すごい。
524
525 goto 文がめんどくさい。stack をたたんで、jmp すれば
526 よいだけだが..
527
528 Sun Jan 2 11:17:50 JST 2000
529
530 普通のcallをcontinuation baseにすることができる?
531
532 Sun Jan 2 20:28:45 JST 2000
533
534 goto 文だけど、やはり、一度、expr で生成してから、top level
535 で jump code を生成しよう。
536
537 Tue Jan 4 03:32:55 JST 2000
538
539 code をtypeにしないと、
540 code *p;
541 とか書けないね。
542 int *p();
543 と同じだけどさ。
544
545
546 main(ac,av)
547 int ac;
548 char *av[];
549 {
550 goto code1(ac,av);
551 }
552
553 code code1(ac,av)
554 int ac;
555 char *av[];
556 {
557 if (ac)
558 goto code1(ac,av);
559 else
560 goto ac(ac,av);
561 }
562
563 Tue Jan 4 04:56:56 JST 2000
564
565 うーん、なんかレジスタにつむ順序が違う
566 これは、adecl がreverseにつむから。
567
568 code のretrun
569
570 やはりcodeはtypeにしないとだめ。
571
572 main()
573 {
574 goto code1();
575 }
576
577 とかだと、main に戻って来れない。もちろん、code1() 以降で、
578 return するわけにはいかない。(main の disp をcode1 は知り得ない)
579 goto label をcode1の引数に送れば?
580
581 main()
582 {
583 goto code1(ret);
584 ret:
585 }
586
587 これだと、ret がforward labelかどうか分からないけど?
588
589 code1 中で使う中間変数を stack 上にとるのは悪くない。しかし、それを
590 %ebp 経由でアクセスするということは、main の中間変数を壊すということ。
591 それを防ぐには、main 中のgoto codeで、%ebp を修正してやれば良い。
592 (今は戻って来ないので問題ない)
593
594 code1 のgoto では、戻って来ないから、その必要はない。しかし、
595 label をcode1 中で渡されると、ちょっと気まずい。
596
597 とすると、それは禁止して、main() 中でstackをたたんでからgotoするか?
598 そうすると、無限後退して、結局、帰れないことになる... うーん。
599
600 main() 中のlocal code を許せば、それは解決するが..
601
602 main()
603 {
604 goto code1(code2);
605 code code2() {
606 return;
607 }
608 }
609
610 みたいな感じ。でも、そうするとscope rule を変える必要があるので厳しい。
611 ま、悪くはないけどね。
612
613 continuation を明示する方法もある。
614
615 main()
616 {
617 goto code1(continuation);
618 }
619 code code1(ret)
620 code (*ret)();
621 {
622 goto *ret;
623 }
624
625 かな? call/cc ?
626
627 label へのgotoを許すのもいいけど、
628 でも、label を許すと、すごくspagettyにならない?
629
630
631 Tue Jan 4 11:47:24 JST 2000
632
633 contiunation じゃなくて、return keyword を使おう。
634 (実際、continuation と少し違うし)
635 type が少し変になるけど、まあ良い。
636
637 int
638 main()
639 {
640 goto code1(return);
641 }
642 code code1(ret)
643 code (*ret)(int);
644 {
645 goto *ret(3);
646 }
647
648 だな。prototype も付けないといけないか。
649
650 Tue Jan 4 12:21:44 JST 2000
651
652 これだとmethodがすべてstatic になってしまう。dynamic なmethod
653 呼び出しにするには? dipatcher を自分で作ることになる。かなり
654 めんどくさいが...
655
656 code method(obj,arg)
657 {
658 }
659
660 か、あるいは、inline にするか... #define のかわりに inline ねぇ。
661 これはあとで考えて良い。
662
663 Tue Jan 4 14:22:19 JST 2000
664
665 main の変数を書き潰すのと、gotgo (*reg)(123) での値は、
666 register 渡しで、current register にのらないので、
667 結局、return label は専用に作る必要がある。
668
669 Tue Jan 4 18:14:07 JST 2000
670
671 stack を継ぎ足して、呼び出す方式を取れば、call by value
672 のregister 渡しを制限する必要は無くなる。
673
674 複数の値を返すことも容易だ。
675
676 .file "tmp.c"
677 .version "01.01"
678 gcc2_compiled.:
679 .text
680 #
681 # code name(a,b,c,d,e,f)
682 .align 2
683 .globl code
684 code:
685 .type code,@function
686 # struct arg *a,*b,*c,*d,*e,*f;
687 # {
688 # int g;
689 # goto name(a,b,d,e,f);
690 jmp name
691 _5:
692 .size code,_5-code
693 .ident "Micro-C compiled"
694
695 おお?!
696 %esp new %esp = old %esp - 12 -4
697 %ebp-4 = g
698 %esi = a
699 %edi = b
700 %ebp = old %esp 0
701 %ebp+4 = c code_arg_offset=0
702 %ebp+8 = d
703 %ebp+12 = e
704 %ebp+16 = f
705
706 interface は付けよう! というか、
707 goto name(struct {xxxx})
708 みたいな感じで良いわけね。どれをregisterにいれるかと言う問題はあるが。
709
710 で、どうやってcallすればいいわけ? emit_pushするかわりにpush
711 する?
712
713 うう、これでは、だめか。code argument の数が変わると、
714 ebp をいちいち動かすことになる。そこにはold sp があるから
715 そいつもコピーする必要がある。
716
717 %esp new %esp = old %esp - 20
718 %ebp-20 = g
719 %esi = a
720 %edi = b
721 %ebp-16 = c code_arg_offset= -16 ((nargs-max_reg)*int_size)
722 %ebp-12 = d
723 %ebp-8 = e
724 %ebp-4 = f
725 %ebp = old %esp 0
726
727 そうか、function からcallする時には、local 変数を書き潰して良い。
728
729 # goto name(a,b,d,e,f);
730
731 %esp new %esp = old %esp - 20
732 %ebp-20 = g
733 %esi = a
734 %edi = b
735 %ebp-16 = c code_arg_offset= -16 ((nargs-max_reg)*int_size)
736 %ebp-12 = d
737 %ebp-8 = e
738 %ebp-4 = f
739 %ebp = old %esp 0 disp=0 (*)
740 local1 <----16 local variable
741 %edx -12 <- disp_offset
742 %ecx -8
743 %ebx -4
744 %ebp = %esp 0
745 %eip 4 <- arg_offset
746
747 となる。ということは、pushl %ebp は、間違い。
748
749 だけど、%ebp をそのまま使うのは良くない。disp_offset がかかっているから。
750 だから、もう一度 pushl %ebp したほうがよい。しかし、push する先は、
751 上の、(*)。
752 leave movl %ebp,%esp
753 popl %ebp
754 じゃなかったか?
755
756 Thu Jan 6 13:00:33 JST 2000
757
758 できたね。これでとりあえず動くはず。速度は問題だが...
759 あとは、
760 ANSI-C prototype
761 ANSI-C prototype check
762 Interface Definietion
763 GC support
764 Direct handling of Frame
765 だね。簡単に出来そう? たぶん...
766
767 Fri Jan 7 09:42:53 JST 2000
768
769 goto 文が動いてなかった。あと peep hole optimization version も
770 作るか?
771
772 continuation として label を送れるようにするべきか?
773 そうすると便利なんだけど、ちょっと、汚いプログラムが
774 出来るようになる。あと、送り側の環境(frame)を維持する
775 必要がある。ま、できなくはないか...
776
777 そうすると、label が値を持つようになる。
778 a = label:;
779 とか。うーん。label:(a,b,c) {}; みたいな形で、parallel 代入を許すと言う
780 手もあるね。
781
782 こちらの方がCとの相性は良いが... main() { label:(){ ... } }
783 みたいなnestを許すかどうかと言う問題がある。
784 変数の参照を許さなければ、特に問題はない。
785
786 a = label: は、二重の意味があるなぁ。
787
788 言語の名前。DinnerBell II とか? join も入れる?
789 code entry_a().entry_b() {}
790 ですか? parallel call も?
791
792 Fri Jan 7 19:53:53 JST 2000
793
794 いまのままだと return が環境を持ってないから、大域脱出できない。
795 まぁ、環境を入れてもいいんだけど、どこに置くかと言う問題が
796 あるね。
797
798 そうじゃなくて、return 側で判断するか?
799 retrun(ID)
800 みたいな形でIDで判断する。そうすれば、return 側でID
801 を見て判断できる。けど...
802
803 まぁ、はやり、環境を持って歩く方がいいかなぁ。でも、
804 引き渡しているから、二つ引き渡して、片方を使われたときに、
805 反対側が消えてしまうのはいたいよね。今のままならば、
806 そういうことは起こらない。
807
808 continuation 特有の問題を避けるなら、このままでもいいんだが...
809 contrinuation や環境は、このシステムでは自分で作ることが
810 できるからね。
811
812 そうなんだけど.... retlabel や retcont は実はオブジェクト
813 全体に一つあれば良い。
814
815 引数を渡すときに、そこに環境へのポインタをいれてやれば良いので、
816 解決は割と簡単だが、そうすると、例の構造体を引数で渡すと言う
817 問題を解決する必要がある。
818
819 でも、今の実装ならば、まったく同じ変数の構成ならばコピーは
820 実際には起こらないわけだから問題ないはず。特に、それを保証するために、
821 interface を実装する必要がある。
822
823 return ->
824 (void *)old bp
825 return address
826
827 bp を直接操作できるようにするといいんだけど....
828
829 Sat Jan 8 08:49:59 JST 2000
830
831 今は、code 内ではreturnできないわけだけど。実は、return って、
832 code return0(i) int i; { return(i); }
833 か? 今は禁止してないから書けちゃうよね。どういうcodeが出るんだろう?
834
835 doreturn() では retpending をセットしているだけだから、control=1
836 のまま。で、code の終りにくるのでエラーになる。checkret は、
837 statement の引数で判断するようにしたほうが合理的だろう。
838
839 大域脱出は結構根が深いよね。途中をスキップされてうれしいか?
840 destructor と同じで、途中のcodeは全部呼びたいのが普通だろう。
841
842 bp が同じになるまで return すれば良いわけだよね。
843 return と同じで、明示的に環境を引き渡すようにするか。
844 type は void * で良い?
845
846 return する時にstackの上限を越えているかどうかを自分でチェックする
847 必要があるね。誰にreturnするかをcodeで明示すれば良いわけだけど。
848
849 code return0(i) int i; { return(i); }
850
851 を許して、そこで、frame pointer を大域あるいは渡した引数と
852 比較して処理する?
853 code return0(i,env) int i; env *env; {
854 if (env==self) return(i);
855 }
856 あれ? これはおかしいよね。
857 code return0(i,env) int i; env *env; {
858 if (env!=self) {
859 env->return();
860 return(i);
861 }
862 }
863 も、なんか変だよなぁ。呼び出しと逆順に帰りたいわけだが...
864 実際、逆順には帰っているわけだよね。
865
866 return の中でこそこそ比較するという技もあるけど。
867
868 問題は、destructor に渡す情報だよね。もちろん、self で良いわけだが、
869 このあたりは、言語外の問題で、それを明示的にしたいから、この言語を
870 作っているわけなのだから、これを内部で処理するのはおかしい。
871
872 code return0(i) int i; { return(i); }
873
874 これだと、return の型が合わないと言う問題が生じるな。簡単には
875 チェックできない。
876 int
877 main() {
878 code a() {
879 }
880 code b() {
881 return(i);
882 }
883 }
884 にすれば、check はできるようになる。でも、これだと、
885 int
886 main() {
887 a: {
888 }
889 b: {
890 return(i);
891 }
892 }
893 と差がない。module 化を言語外でやるというのが主旨なのだから、これでは
894 まずい。これは高級アセンブラなのだから。
895
896 あそうか、return と、大域脱出時のabortとは、状況が違う。だから、
897 別なcode を呼び出さないとだめ。あるいは、値で区別するか。これは、
898 logic programming のfail/success と似ている。
899 main() { } abort { ... }
900 でもいいけど?
901 main() { code abort { ... }; code return { ... }}
902 かな?
903
904 本来、subroutine call自体が、かなりの省略形なわけだから、これは
905 仕方がない。今のままで通常のsubroutine callをシミュレートできるのか?
906 code (struct arg {...},void *sp) {
907 struct env;
908 push(sp,arg);
909 push(env,arg);
910 }
911 できるけど、ちょっと重い。やはり、frame pointer を直接操作しないと
912 だめ。
913
914 goto 文のほうに、env を一緒に送るものを作ったほうがいいのかも。
915 goto (*ret)(),environment;
916 かな。type は? (void *)?
917 goto ret(),environment;
918 にはならないの? そうすれば、自分でthreadを制御できる。environment
919 の正当性を評価しなくて良いの? まぁ、ねぇ。
920
921 これは実装は容易だが... goto といちいち書くのが本当にいいのか?
922 env に対するoperationがあった方がいいなぁ。push とか?
923
924 code return0(i) int i; { return(i); }
925
926 を認めれば、return 擬変数はいらなくなる。
927
928 でも、実は、return は、caller の引数の数と一致してないといけない
929 わけだから、 code return0(i) int i; { return(i); } はだめ。env
930 と一致してないといけない。ということは分離するとまずいんじゃない?
931 あれ? そんなはずないな。
932
933 Sun Jan 9 01:15:56 JST 2000
934
935 やはり、分離してはまずい。もともと、
936 goto func(arg);
937 自体が、
938 goto func(arg) with current.env
939 みたいなものだ。つまり、これは、DinnerBell の、
940 self message: arg
941 と同じ。self->func(arg); でも良い。が、function callと区別が付かないのは
942 良くない。
943
944 そうすると、type code はsize int でなくなる。
945 code *p = func;
946 ではいけなくて、
947 code p = {func,env};
948 でないといけない。実際、
949 goto func(arg)
950 では、current environment を pushl %ebp でstack = current env
951 に積んでいるわけだから。
952
953 いずれにせよ、
954 struct p = q;
955 は実装する必要がある。localな、
956 code p = {func,env};
957 も動くはずだが...
958
959 code (*p)();
960 goto (*p)(arg);
961
962 はだから少しおかしい。これは、goto がenv を補っていると考えるべき。
963
964 このようにすると、常に、
965 func,env
966 の組をcodeとみなすことになる。これは、object と呼ぶべきだ。
967 ただ、既存のobjectとは別だよな。actor の方が良い?
968
969 うーん、これでjoinを入れれば、完璧なDinnerBellだな。並列送信はないけど。
970
971 Sun Jan 9 01:40:05 JST 2000
972
973 local 変数の初期化はallocation の後に遅らせる必要がある。
974 nptr に入れられるはずだよね? nptr に初期化フラグを足すか?
975
976 文途中で出現するlocal変数の初期化。ちゃんと動いているの?
977
978 構造体のcopyは、lcheck を修正すべきでない。
979
980 Sun Jan 9 08:49:43 JST 2000
981
982 うーん、なんか修正が多いなぁ。あと、関数呼び出し、goto 文の
983 構造体への対応か。
984
985 goto (*code)();
986
987 が、self env を使うのか、code の先の値を使うのかを区別する
988 必要がある。もし*を使わないとするとlabel(FNAME)との区別が
989 つかないぞ。あ、でも、環境を持ち歩くことにしたから、label
990 へもjumpしようと思えばできるね。
991
992 並列送信はなくても、この構成ならばstatement単位の並列性を検出するのは
993 容易だろう。
994
995 やればできるけど、この修正の量だと1日じゃ終らないかなぁ。
996 不動小数点も入れるのでしょう?
997
998 Mon Jan 10 09:00:12 JST 2000
999
1000 引数に構造体を許すには、必ずANSI-Cにする必要がある。難しくは
1001 ないが...
1002
1003 goto 文には label, code, continuation の3つが来る。
1004 continuation = code + env
1005 | label +env
1006 なのだが、code/label では、env の内容が異なる。できれば面白いが、
1007 その価値はあるのか?
1008
1009 しかし、code , env を分離するとあまりに危険すぎる。どうせgoto
1010 が危険なんだからいいか? その方が簡単。簡単なら、そっちの方法を
1011 とるべきじゃない? うーん。
1012
1013 return の関数依存性はなくした方が良い。
1014 一つにするのは、pop の問題があるので良くないが...
1015
1016 そうか、ret をenvを指定して戻るようにしたから、leave する必要は
1017 なくなった。そして、push %ebp に相当する部分は、lea -disp(%ebp),%sp
1018 で消去されている。ということは、jump のfunction依存部分はいらない
1019 ということだね。
1020
1021 でも、汚いなぁ。read only属性をhardware supportできればなあ。
1022
1023 sched_yeilds() 相当を書けるかな? lock は?
1024
1025 一応、できたけど、やっぱり汚い。
1026
1027 Wed Jan 12 16:12:27 JST 2000
1028
1029 あは。ANSI prototype はめんどい。
1030 bexpr()
1031 で、関数での引数の順序と、そのあとの宣言の順序が変わることがある。
1032 そうすると、うしろの方が優先されてしまう。これは、こまる。
1033
1034 そうか、code_arg_offset のような方法だと、ANSI style では、
1035 困ってしまう。
1036
1037 Thu Jan 13 04:46:12 JST 2000
1038
1039 # goto name(a,b,d,e,f);
1040 code name { int g; ...
1041
1042 %esp new %esp = old %esp - 20
1043 %ebp-20 = g code's local variable
1044 %ebp-12 = f <- new_disp
1045 %ebp-8 = d
1046 %ebp-4 = d
1047 %ebp-0 = c
1048 %edi = b
1049 %esi = a
1050 %ebp = old %esp 0 disp=0 new env
1051 local1 <----16 old local variable ( to be erased )
1052 %edx -12 <- disp_offset
1053 %ecx -8
1054 %ebx -4
1055 %ebp = %esp 0 <- old env
1056 %eip 4 <- arg_offset
1057
1058
1059 Thu Jan 13 13:38:24 JST 2000
1060
1061 だいたいできたけど、test/tmp7.c のprintf のtype mismatch は
1062 なんなんだろう? ASNI の副作用だろうなぁ。
1063
1064 これだと、プロセスの切替えのときには、結構な量のデータを
1065 コピーすることになる。それでもいいんだけど...
1066
1067 それごと、どっかにとって置く。continuationへの参照みたいなもの
1068 ができないかな。
1069
1070 コピーができれば、environment/return の組は動くわけだから、
1071 それへの参照と切替えがあっても良いよね。
1072
1073 Fri Jan 14 12:03:35 JST 2000
1074
1075 Libretto のkeyboardが壊れた... control key が効かない...
1076
1077 printf の参照の問題は解決しました。list2 がlocalなheap
1078 に割り当てているのがいけなかったね。
1079
1080 return の処理は、goto 文で処理するより、environment に
1081 returnto する方が良くはないか?
1082
1083 environment は実は送り先でそれなりの準備が必要。
1084 new-environment() みたいなlibrary があれば、thread にできる。
1085
1086 join は?
1087
1088 funcall を用意すると良いね。
1089
1090 Mon Jan 17 15:23:34 JST 2000
1091
1092 struct aa f1() {
1093 return bb;
1094 }
1095
1096 みたいなのは? 関数の型か代入の型を見て、crn にpointerを渡して、
1097 あとでcopyしてから stack を畳む。
1098
1099 # bb=f1(aaa);
1100 movl $bb,%eax
1101 pushl %eax
1102 movl $aaa,%eax
1103 pushl %eax
1104 call main2
1105 popl %edx
1106 copy %eax,%edx,$400
1107 addl $400,%esp
1108 # return a1;
1109
1110 あ、でも、それだと、local変数を返したときに困るね。leave; ret;
1111 してはいけなくて...
1112
1113 あ、やっぱり、こういう場合はコピー先をmain2に引き渡しているみたいね。
1114 void f1(struct aa *ret) {
1115 *ret = bb ;
1116 return;
1117 }
1118 と同じか。これは簡単。
1119 f1().a[55]
1120 みたいな場合は、局所変数に強制的に取ってしまうみたいね。それはそうだ...
1121 が、うちの実装だとちょっと厳しいか。
1122 leal $-sizeof(struct),%esp
1123 pushl %esp
1124 なんだけど、関数呼び出しの途中ではできないから....
1125
1126 # main(ac,av)
1127 # int ac;
1128 .align 2
1129 .globl main
1130 main:
1131 .type main,@function
1132 pushl %ebp
1133 movl %esp,%ebp
1134 pushl %ebx
1135 pushl %ecx
1136 pushl %edx
1137 # char *av[];
1138 # {
1139 # register int i;
1140 # register char *p;
1141 # int j = 3;
1142 # struct { int b; void (*c)(struct aa); } q = {3,main1},r;
1143 #
1144 # j = 3;
1145 subl $20,%esp
1146
1147 このsublを後から指定してやればOk。
1148
1149 でも、それだと jump の時にずれない? ずれるか? ずれるね。うーん。
1150 実行時にチェックしてやるのも変だし。
1151
1152 まぁ、それほど必要な機能ではないんだけど。
1153
1154 これもcontinuationを渡してやると言う手法が使えないことはないんだが...
1155
1156 関数呼び出しの最初にやってやればいいか。それでできるかな?
1157
1158
1159 Sun Feb 20 23:59:16 JST 2000
1160
1161 MIPS のcall frame
1162
1163 $sp = $fp
1164 local variables
1165 saved register (including $31 = return address)
1166
1167 mask は使用したレジスタのbit pattern
1168 -4 は何?
1169
1170 18 .mask 0xc0000000,-4
1171 19 .fmask 0x00000000,0
1172 20 0000 D0FFBD27 subu $sp,$sp,48
1173 21 0004 2C00BFAF sw $31,44($sp)
1174 22 0008 2800BEAF sw $fp,40($sp)
1175 23 000c 0000000C move $fp,$sp
1176 24 0010 21F0A003 jal __main
1177 25 0014 03000224 li $2,0x00000003 # 3
1178 26 0018 000082AF sw $2,a
1179 27 001c 04000224 li $2,0x00000004 # 4
1180 28 0020 00C082AF sw $2,b
1181 29 0024 05000224 li $2,0x00000005 # 5
1182 30 0028 000082A3 sb $2,c
1183 31 002c 06000224 li $2,0x00000006 # 6
1184 32 0030 08C082A3 sb $2,d
1185 33 $L1:
1186 34 0034 21E8C003 move $sp,$fp # sp not trusted
1187 here
1188 35 0038 2C00BF8F lw $31,44($sp)
1189 36 003c 2800BE8F lw $fp,40($sp)
1190 37 0040 0800E003 addu $sp,$sp,48
1191 38 0044 3000BD27 j $31
1192 39 .end main
1193
1194 これと同じようにするならば、regiterの使用数を最初に調べる必要が
1195 あるのだけど、one path compiler である micro-C では、それは
1196 できない。したがって、enter は後ろでする方が良い。
1197 Mon Jan 20 18:25:27 JST 2003
1198
1199 3年間さわってないのかよ。何やってんだ?
1200
1201 goto 文のバグをとらないといけない。
1202
1203 まず、関数引数の構造体の展開。これは、どうってことないはず。
1204
1205 goto (*code)(i+1,j,...)
1206
1207 まず、いじらなくてすむ変数を摘出する。
1208
1209 foreach arg
1210 compare
1211
1212 単純演算 ( op+const , pointer , const assign ) などは、ここで検出する。
1213 大半は、そのようになるはず。
1214 レジスタに乗せる分があるから... それには触らないとして...
1215
1216 複雑なものは、前もって計算しておく。(get_register する)
1217 スタック上かレジスタ上に作る。
1218
1219 残りは並列代入となる。再帰的に計算する。
1220
1221 えーと、大きな順にやるんだっけ? 小さな順にやるんだっけ?
1222 code f( int a, int b, int c ) {
1223 goto g(b,c,a);
1224 }
1225 みたいなやつだよね。
1226
1227 移動するものを一つ検出する。
1228 そのために移動が必要なものを移動しておく(再帰)
1229 代入する
1230
1231 こんなんでいいのか? ループしない? するよね。ループしたら
1232 get_register する。
1233
1234 前の例だと、
1235
1236 g(b,c,a) のbに着目する。
1237 bに代入するコードを出すと、a が壊れる。
1238 a が必要かどうかを調べる。それは、引数のリストを見ればわかる。
1239 その前に、a を移動する。a の移動先を見て、
1240 空いていれば、移動してOk。しかし、c
1241 なので、 c を見る。と b になるので、ループするのがわかるので、
1242 b を get_register する。
1243 で、c が移動できる。で、aを移動して、とっておいたbを代入。
1244
1245 Tue Jan 21 22:45:09 JST 2003
1246
1247 とりあえず、jump は複雑すぎる。もっと簡単にすることを考える。
1248 parser 側である程度処理できない?
1249
1250 goto f(a+3,b(),c);
1251
1252 などを、
1253
1254 a = a+3;
1255 b = b();
1256 goto f(a,b,c);
1257
1258 程度に簡略化する。この時、f(a,b,c) は(できるだけ)、元の
1259 関数の引数リストに近付ける。のは無理なので、単純変数
1260 まで落す。
1261
1262 あまり関係ないか。一時変数はどうせいるわけだし。ってこと
1263 みたいね。
1264
1265 だとすると、元のコードと、そう変わらんね。前のも、そんなに
1266 悪くないってことか。
1267
1268 Wed Jan 22 14:33:12 JST 2003
1269
1270 やっぱり、途中で局所変数を増やしたいよね。
1271
1272 Fri Jan 31 20:30:36 JST 2003
1273
1274 なんか #ifdef / #if がないとだめだな。実装する?
1275 しました。
1276
1277 Tue Feb 4 01:04:12 JST 2003
1278
1279 ## while ((*chptr++ = c = getc(filep->fcb)) != '\n') {
1280 _1120:
1281 movl $10,%eax
1282 movl $8,%ecx
1283 movl filep,%edx
1284 addl %ecx,%edx
1285 movl (%edx),%edx
1286 pushl %edx
1287 xchg %edx,%eax .... edx に$10が入る (なんでxchg?)
1288 call getc
1289 addl $4,%esp
1290 movl %eax,-20(%ebp) c に代入
1291 movl $chptr,%ecx
1292 pushl %ecx
1293 popl %ebx
1294 movl (%ebx),%ecx ecx にchptrの中身
1295 addl $1,(%ebx)
1296 movb %al,(%ecx)
1297 subl %edx,%eax eax-edx ($10)
1298 je _1119
1299
1300 が壊れる理由なんだけど...
1301
1302 edx,ecx が破壊されちゃうみたいね。
1303
1304 Tue Feb 4 12:17:07 JST 2003
1305
1306 ようやっと直したよ...
1307
1308 use_pointer って、なにもしなくていいんだよね? eax,ebx を避ける
1309 ってことらしいけど。
1310
1311 inline/引数付き #define 欲しくない? 置き換えは、local name stack に積んじゃう。
1312 展開は function で行う。
1313
1314 getch を工夫する必要はあるが。置き換えスタックが必要。
1315
1316
1317 Wed Feb 5 01:16:00 JST 2003
1318
1319 大域で定義された struct field が大域変数と重なっていると落ちる。
1320 そりゃそうだけど。どうするの? (直した記憶があるんだけどなぁ...)
1321 struct 毎に field 名とoffset/type の組を持てばい良いんだよね。
1322
1323 なんだけど、タグ無しの構造体もあるから、型名の方に付ける必要
1324 もある。というのは、型名のない構造体もあるから。タグ名には、
1325 一応、リストがついている。なんかに使う必要があったんでしょう
1326 ね。あ、めんどう。無条件にやっても大域変数名を汚すのを直すの
1327 が難しい。
1328
1329 ちょっと、あれだけど、「型名.フィールド名」で登録してしまうのはどう?
1330 型名が後で出て来るところが気まずいが...
1331
1332 def で登録するときに、nptrにdispを代入せずに、struct field list
1333 (大域変数) に入れて、type の方に、field list (list3(nptr,offset,
1334 type)) を入れれば良い。
1335
1336 あとは、strop の方でtypeのlistを見るようにすれば良いわけだ。
1337
1338 これなら、簡単に直せるはず。LUSTR/GUSTRなどの区別もなくなるし。
1339
1340 Wed Feb 5 02:10:14 JST 2003
1341
1342 浮動小数点ねぇ。完全なANSI Cにするのは大変。でも、
1343 浮動小数点ぐらいないと。
1344
1345 code generation part を、さらに分割して、
1346 複数のコード対応にしやすいようにする。
1347 おそらく、それほど共有する部分はないけどね。
1348
1349 Sample C code をコンパイルして、その結果から(半分手動で)
1350 Micro CbC code generation part を生成する方法を用意する。
1351
1352
1353
1354 Thu Feb 6 11:47:03 JST 2003
1355
1356 Code Segement を単位として使うときに、大域変数はどういう
1357 ように分けるの? static なんかは意味ないよね。
1358
1359 もちろん、自然にグループ分けされるわけだけど。
1360
1361 あとデータフローだよね。データフローに関しては、
1362 あんまりやってないなぁ
1363
1364 Fri Feb 7 14:36:15 JST 2003
1365
1366 inline では、必らず、局所変数の増加がある。また、inline
1367 は普通の関数として展開しておく必要もあるらしい。(何故?)
1368
1369 #define ねぇ。
1370
1371 #define c(a,b) g(a+1,b+1)
1372 #define g(a,b) printf("%d %d\n",a+1,b+1);
1373
1374 main() {
1375 int a,b;
1376 a =1; b = 3;
1377 c(a,b);
1378 }
1379
1380 local #define がいるんだよね。g の中で a が出て来た時には、
1381 c のa の置き換えは起こってはいけない。ということは、c
1382 の置き換えはg が始まる前に終っている必要がある。dynamic
1383 scope なんだから、assoc の上乗せで良いはず。
1384 macro のlevelを定義して、あるレベルでは、それ以前の展開
1385 を行わないという手法が良いかな。
1386
1387 c(a,b) => a=>"a+1", b=>"b+1"
1388 g(a,b) => (a=>"a+1+1",a=>"a+1"), (b=>"b+1+1",a=>"a+1")
1389
1390 みたいな感じ?
1391
1392 やっぱり関数解析でマクロ処理をやらせるのは無理かな? 先読みされちゃうし。
1393
1394 Sat Feb 8 00:53:52 JST 2003
1395
1396 macro は途中まで書きました。置き換えをマクロが呼び出された
1397 時点で cheap に置くと、それを解消するタイミングがない。
1398 ここだけmallocしても良いが..
1399
1400 chptrsave はlistにする必要がある。list で良い。
1401
1402 やっぱりmacro levelを見て、自分と一致したassoc valueまで
1403 手繰って置換するんでしょう。そうすれば、置き換える必要は無い。
1404 ということは、local_define にmflagsを格納する必要がある。
1405
1406 c(a,b) => a=>"a", b=>"b"
1407 a=>"a" .. mflag == 1
1408 g(a,b) => (a=>"a+1+1",a=>"a+1"), (b=>"b+1+1",a=>"a+1")
1409 a=>"a+1" .. mflag == 2
1410
1411 macro のもとのnptr が残ってないと、オリジナルを返せない。オ
1412 リジナルは、sc などが破壊されてしまう。ってことは、local macro
1413 は、local table を汚してはいけないってことだよね。ってことは、
1414 macro table は、もとのとは別に用意する必要がある。
1415
1416 #define c(a,b) g(a+1,b+1)
1417 #define g(a,b) printf("%d %d\n",a+2,b+2);
1418
1419 main() {
1420 int a,b; a ... local
1421 a =1; b = 3;
1422 #ifndef a
1423 c(a, a = "a".. macro mflag==1
1424 g(a,
1425 a="a+1" mflag==2
1426 ^ a = "a" mflag==1
1427 While replacing a in g's body, a should not
1428 be replaced to (original) "a", should be c's a.
1429 b);
1430 /* 3,5 expected */
1431 #endif
1432 }
1433
1434 うーむ。ややこしい。
1435
1436 main()
1437 c(a,b) mflag++
1438 a=>"a" mflag ==1
1439 g(a,b) mflag++;
1440 a=>"a+1" mflag ==2
1441 ^ is replaced by c's "a" not g's a;
1442 いったん mflag level n で展開したら、それは mflag level n-1 となる。
1443
1444 Sat Feb 8 18:13:43 JST 2003
1445
1446 いちおう、mflag まではデバッグしたが.... mflag を戻してないんじゃないの?
1447
1448 ---c(a,b)----------------------- mflag ==1
1449 a=>hoge, b=>hoga (mflag==1)
1450 ----g(ac,bc)----------------- mflag ==2
1451 ac=>goge, bc=>goga(mflag==2)
1452 ----printf(a,b)---------- mflag ==3
1453 a=>poge, b=>poga(mflag==3)
1454
1455 g が呼び出されると、ac,bc は mflag==1 でのみ置換される。
1456
1457 あるテキストを置き換えると、それは置き換えたマクロのmflag level
1458 (つまり一つ少ないレベル)になる。
1459 置き換え終ったら、元のlevelに戻す。
1460
1461 mflag==2のlevel では、mflag==2のlocal macroの展開しかしない。
1462
1463 置き換えると、mflag level 1 になるので、そこで mflag==1 のlocal
1464 macro を展開する。mflag==0 は常に展開を行う。
1465
1466 Sun Feb 9 11:35:23 JST 2003
1467
1468 うーん、なんかtypeが、list とCHARなどと入混じっているじゃん。
1469 int save = chptrsave;
1470 で、chptrsave が、$chptrsave になってしまう。
1471
1472 Sun Feb 9 22:33:36 JST 2003
1473
1474
1475 #define car(e) (heap[(int)(e)])
1476 #define cadr(e) (heap[((int)(e))+1])
1477 car(cadr(e))
1478
1479 だろ。
1480 car ->
1481 #define e cadr(e) (mleve=1)
1482 cadr ->
1483 #define e e (mleve=2)
1484
1485 むぅ。これ、うまくいかないんじゃん。こまったなぁ。
1486
1487 #define c(a,b) g(a+1,b+1)
1488 #define g(a,b) printf("%d %d\n",a+1,b+1);
1489 c(a, b);
1490
1491 こっちもだめじゃん。ふーむ。lisp interpreter のように
1492 作ればいいはずなんだけど。
1493
1494 Mon Feb 10 08:10:25 JST 2003
1495
1496 結局、list base のinterpreter を実装しました。きちゃないが。
1497 前の方法でも、頑張ればできるんでしょうけどね。
1498
1499 Tue Feb 11 13:50:03 JST 2003
1500
1501 struct copy だけど... 関数がstructを返すときに、引数に前もって
1502 積んでおくのでは、そこに値がコピーされてしまうし、あとで、
1503 スタックをたたんで置くときにきまずい。
1504
1505 function call の時に、引数の型のチェックをしてない
1506
1507 type に -1 とheapの引数が混在しているやつだけど..
1508 やっぱまずいんじゃないか?
1509
1510 temproal struct は再利用できるんだけど、dispの変更ができないので
1511 新しく作るしかない。大きいときだけ新しく作るなんていうセコイ
1512 技はあるけど。(そうすると、帰って来た値へのポインタを使えなく
1513 なるが.... 別にいいよね。戻り値それ自身を直接 return する
1514 時もだいじょうぶなはず)
1515
1516 結局、呼出側で、領域を確保して引き渡すことにしました。この方法だと、
1517 代入のときに二度コピーする必要もない。
1518
1519 register を使用しているかだけじゃなくて、実際にcreg/dregに
1520 値があるかどうかを記憶する必要がある。
1521
1522 Wed Feb 12 11:09:22 JST 2003
1523
1524 それだけどさ... やっぱりアドホックに実現するのは難しいんじゃないの?
1525
1526 まぁねぇ。register の場所の確保と、寿命は別だから、それで
1527 いいんだけど、regs flag だけでなんとかならないのかな。
1528 こういう変更ははまるが虚しい。
1529
1530 Thu Feb 13 18:37:36 JST 2003
1531
1532 さて、そろそろ jump にとりかかりますか。
1533
1534 構造体の引き渡しのシークエンスに使う局所変数の位置がgccと違う...
1535
1536 そろそろ register は構造体にすべきだね。
1537 struct register {
1538 int used;
1539 int valued;
1540 char *name;
1541 char *wname;
1542 char *bname;
1543 int type; /* register variable or not */
1544 int number;
1545 }
1546 virtual/real は、どうする。
1547
1548 Sat Feb 15 14:00:03 JST 2003
1549
1550 fdecl_struct を構文的に引数が出現するときに行うと、int *f(int
1551 a) などで、* の評価が終る前に、int aが評価されしまう。*obj
1552 のobj を評価し終らないとfのタイプが確定しない。int*f()[] み
1553 たいな場合があるから。(?) なので、gcc と、そろえるためには、
1554 arg の先頭で fdecl_struct を行う方法ではだめで、fdecl 中であ
1555 とから修正する方が良い。
1556
1557 fix しようにも引数リストなんて、存在しないじゃん!
1558
1559 varargs を実装するのはめんどくさかろう...
1560
1561 rvalue(expr(),type) では、expr() のtypeをrvalueに引き渡せな
1562 い。でも、type を大域変数にすると、rvalueを異なるタイプで呼
1563 び出すときにtypeを変更する必要がある。このrvalueのtype の扱
1564 いは、かなりはまったことがあるので、rvalue(int e,int type)の
1565 方が良いことは確かなんだが...
1566
1567 struct_push のregisterの扱いが複雑すぎ。なんか、もっと
1568 簡単にならないの?
1569
1570 Sun Feb 16 07:58:23 JST 2003
1571
1572 代入しなくて良いからと言って、ソース
1573 のリストから除いては、上書きを防げない。
1574
1575 Sun Feb 16 22:55:58 JST 2003
1576
1577 vdisp ってなんだったんだ?
1578
1579 Mon Feb 17 12:35:39 JST 2003
1580
1581 並列代入は出来たみたい。代入は小さいものを先にすべきなのか?
1582 まぁ、できりゃいいんだけど、横に避けるものが大きいのはいや
1583 だよね。
1584
1585 Tue Feb 18 11:56:10 JST 2003
1586
1587 overraped 用の emit_copy
1588 float/double
1589 long long
1590
1591 Tue Feb 18 19:34:31 JST 2003
1592
1593 code argument の符号を反転させると、list2(LVAR,offset)
1594 のoffsetがアドレスの方向と一致しているという前提が
1595 崩れる。それで、構造体の格納順序がずれてしまう...
1596
1597 ということは... def(n) でcodeの時はargumentは、局所変数と同じ
1598 扱いでマイナス符号で処理した方が良い。
1599
1600 できたみたい。でもさ、
1601
1602 int main( int ac, char *av[])
1603 {
1604 int n;
1605 goto arg1(0,1,2,3,4,return,environment);
1606 }
1607
1608 って、きっと return 文がないと、文句を
1609 言われるよね。むむむ。
1610
1611 post processing する時にoverrapしてないという保証がない。
1612
1613 Wed Feb 19 15:38:55 JST 2003
1614
1615 自分自身とのoverrrapを見てないので、
1616 struct a a,int i
1617 int i,struct a a
1618 みたいな時に自分自身を壊してしまう。なので、emit_copy
1619 が、ちゃんと方向を見て壊さないように処理する必要がある。
1620
1621 call bcop でいいじゃん。まね。