Lua2.4バイトコードprintを印刷する.c

3964 ワード

コンパイラに関する部分はluacだけ残っています.cのdo_dump関数の解析を行いました.この関数には主に2つの呼び出しがあり、バイトコードと印刷バイトコードが格納されます.まず、印刷バイトを見てみましょう.バイトコードを印刷するには、コンパイラのコマンドラインオプションに「-l」オプションが必要です.
static void do_dump(TFunc* tf)     /* only for tf==main */
{
 if (dumping) DumpHeader(D);
 while (tf!=NULL)
 {
  TFunc* nf;
  if (listing) PrintFunction(tf);
  if (dumping) DumpFunction(tf,D);
  nf=tf->next;     /* list only built after first main */
  luaI_freefunc(tf);
  tf=nf;
 }
}

バイトコードを印刷して呼び出すのは上のPrintFunctionで、listing条件で制御されていることがわかります.一方、listingはコマンドラインに「-l」オプションがある場合にのみ1となります.実際に使用すると、ここで小さなエラーが発生していることがわかります.-p-lオプションが同時に使用されている場合(構文解析のみでdumpバイトコードは使用されません)、PrintFunctionは一度だけ呼び出されます.つまり、メイン関数のバイトコードのみが印刷され、他のカスタム関数のバイトコードは印刷されません.-pオプションを削除すると(すなわち、デフォルト出力luac.outファイルにバイトコードを同時に格納する)は正常です.例として、以下のLuaスクリプトについて説明します.
function add(x, y)
    return x + y
end
print (add(3, 4))

-p-lで実行すると、印刷結果は以下の通りである:main of"test.lua"(25 bytes at 00602090)0 PUSHFUNCTION 00602120;"test.lua":1     5    STOREGLOBAL    13    ; add     8    PUSHGLOBAL    7    ; print    11    PUSHGLOBAL    13    ; add 14 PUSHBYTE 3 16 PUSHBYTE 4 18 CALLFUNNC 2 1 21 CALLFUNNC 1 0 24 RETCODE 0おかしい、関数addはどこへ行ったの?-lで実行すると、印刷結果は、main of「test.lua」(25 bytes at 00120 D 8)0 PUSHFUNCTION 0012168、"test.lua":1     5    STOREGLOBAL    13    ; add     8    PUSHGLOBAL    7    ; print    11    PUSHGLOBAL    13    ; add    14    PUSHBYTE    3    16    PUSHBYTE    4    18    CALLFUNC    2 1    21    CALLFUNC    1 0    24    RETCODE0function "test.lua":1 (9 bytes at 00112168); used at main+1     0    ADJUST    2     2    PUSHLOCAL0    0    ;     3    PUSHLOCAL1    1    ;4 ADDEP 5 RETCODE 2 7 RETCODE 2見たでしょう、ここには次のadd関数のバイトコードが増えています.これはなぜですか.プログラムにエラーが発生したはずです.分析してみると、-pオプションがある場合、do_dumpコードのtf->nextはNULLで、-pオプションがない場合は良いです.デバッグしてみると、DumpFunctionを実行した後、tf->nextが割り当てられ、DumpFunctionのThreadCodeについて次の文が見つかりました.
 case PUSHFUNCTION:
 {
  CodeCode c;
  p++;
  get_code(c,p);
  c.tf->marked=at;
  c.tf->next=NULL;    /* TODO: remove? */
  lastF=lastF->next=c.tf;
  break;
 }

-pオプションがある場合、上記の文は実行されないので、tf->nextには値が割り当てられておらず、上記の印刷バイトコードは関数addのバイトコードを印刷できません.通常、主関数とすべてのLuaスクリプトで定義された関数がコンパイルされた後、Tsuncチェーンが形成され、関数のバイトコードはTsuncのcodeフィールドに存在します.print.hには、バイトコードを印刷する際に使用されるバイトコード命令の名前配列が定義されている.PrintFunctionのコードを見て
void PrintFunction(TFunc* tf)
{
 if (IsMain(tf))
  printf("
main of \"%s\" (%d bytes at %p)
",tf->fileName,tf->size,tf);  else   printf("
function \"%s\":%d (%d bytes at %p); used at main+%d
",  tf->fileName,tf->lineDefined,tf->size,tf,tf->marked);  V=tf->locvars;  PrintCode(tf->code,tf->code+tf->size); }

メイン関数とユーザがカスタマイズした関数の印刷された記述情報が異なり、IsMainマクロによりメイン関数か否かが判定される.define IsMain(f)(f->lineDefined==0)ユーザー定義関数の定義行は必ず0より大きい値で、メイン関数は0に設定されます.次に、PrintCode印刷バイトコード命令を呼び出す.
static void PrintCode(Byte* code, Byte* end)
{
 Byte* p;
 for (p=code; p!=end;)
 {
 OpCode op=(OpCode)*p;
 if (op>SETLINE) op=SETLINE+1;
 printf("%6d\t%s",p-code,OpCodeName[op]);
 switch (op)
 {
/*cases and other codes*/
}
}
}

印刷命令の位置と命令の名前はprintfの一言です.不正な命令であればop>SETLINEで、空の文字列が印刷されます.なぜなら、OpCodeName配列の「SETLINE」の次の文字列が空白列であるからです.次に、switch caseが他の命令のいくつかの他のデータに関する情報を印刷する.命令のデータ部分と使用する文字列に関連する部分が含まれます.印刷されたバイトコードを比較すると、コードの意図がわかりやすくなります.この部分は、バイトコードを簡単に解析することに相当します(仮想マシンで本当にバイトコードを実行したときの比較と簡単です).だから、一行の分析はしない.これまでの質問:>do_dumpメソッドで調整するdumpに関するメソッドは何ですか?---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------