Lua2.4バイトコードprintを印刷する.c
コンパイラに関する部分はluacだけ残っています.cのdo_dump関数の解析を行いました.この関数には主に2つの呼び出しがあり、バイトコードと印刷バイトコードが格納されます.まず、印刷バイトを見てみましょう.バイトコードを印刷するには、コンパイラのコマンドラインオプションに「-l」オプションが必要です.
バイトコードを印刷して呼び出すのは上のPrintFunctionで、listing条件で制御されていることがわかります.一方、listingはコマンドラインに「-l」オプションがある場合にのみ1となります.実際に使用すると、ここで小さなエラーが発生していることがわかります.-p-lオプションが同時に使用されている場合(構文解析のみでdumpバイトコードは使用されません)、PrintFunctionは一度だけ呼び出されます.つまり、メイン関数のバイトコードのみが印刷され、他のカスタム関数のバイトコードは印刷されません.-pオプションを削除すると(すなわち、デフォルト出力luac.outファイルにバイトコードを同時に格納する)は正常です.例として、以下のLuaスクリプトについて説明します.
-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について次の文が見つかりました.
-pオプションがある場合、上記の文は実行されないので、tf->nextには値が割り当てられておらず、上記の印刷バイトコードは関数addのバイトコードを印刷できません.通常、主関数とすべてのLuaスクリプトで定義された関数がコンパイルされた後、Tsuncチェーンが形成され、関数のバイトコードはTsuncのcodeフィールドに存在します.print.hには、バイトコードを印刷する際に使用されるバイトコード命令の名前配列が定義されている.PrintFunctionのコードを見て
メイン関数とユーザがカスタマイズした関数の印刷された記述情報が異なり、IsMainマクロによりメイン関数か否かが判定される.define IsMain(f)(f->lineDefined==0)ユーザー定義関数の定義行は必ず0より大きい値で、メイン関数は0に設定されます.次に、PrintCode印刷バイトコード命令を呼び出す.
印刷命令の位置と命令の名前はprintfの一言です.不正な命令であればop>SETLINEで、空の文字列が印刷されます.なぜなら、OpCodeName配列の「SETLINE」の次の文字列が空白列であるからです.次に、switch caseが他の命令のいくつかの他のデータに関する情報を印刷する.命令のデータ部分と使用する文字列に関連する部分が含まれます.印刷されたバイトコードを比較すると、コードの意図がわかりやすくなります.この部分は、バイトコードを簡単に解析することに相当します(仮想マシンで本当にバイトコードを実行したときの比較と簡単です).だから、一行の分析はしない.これまでの質問:>do_dumpメソッドで調整するdumpに関するメソッドは何ですか?---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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に関するメソッドは何ですか?---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------