(57)【要約】【課題】アセンブリ言語の部分を跨いで生存するレジスタとアセンブリ言語の部分において指定されるレジスタとが実際にバッティングする場合のみ検出することができるプログラム開発装置を提供する。【解決手段】プログラム開発装置１は、ターゲットプロセッサ上で実行される目的プログラムのための原始プログラム中に、ターゲットプロセッサのレジスタを直接指定している１以上の代入文を含むか否かを解析する構文解析部１１と、原始プログラムがコンパイルされ割り付けられるレジスタの生存区間情報を検出し、検出した生存区間情報に基づき割り付けられるレジスタが１以上の代入文を跨いで生存しているか否かを検出する検出部とを有する。【選択図】図２
2009258796.tif 000002
【特許請求の範囲】
【請求項１】
ターゲットプロセッサ上で実行される目的プログラムのための原始プログラム中に、前記ターゲットプロセッサのレジスタを直接指定している１以上の代入文を含むか否かを解析する解析部と、
前記原始プログラムがコンパイルされ割り付けられるレジスタの生存区間情報を検出し、検出した前記生存区間情報に基づき前記割り付けられるレジスタが前記１以上の代入文を跨いで生存しているか否かを検出する第１の検出部と、
を有することを特徴とするプログラム開発装置。
【請求項２】
前記第１の検出部の検出結果に基づき前記割り付けられるレジスタの退避及び復帰コードを生成することを特徴とする請求項１に記載のプログラム開発装置。
【請求項３】
前記１以上の代入文中に前記レジスタ以外の記憶部を使用するコードを検出する第２の検出部と、不使用のレジスタの情報を出力する出力部とを有することを特徴とする請求項１又は請求項２に記載のプログラム開発装置。
【請求項４】
前記出力部から出力される前記不使用のレジスタの情報に基づき、前記第２の検出部において検出される前記コード中の前記記憶部を前記不使用のレジスタに転用することを特徴とする請求項３に記載のプログラム開発装置。
【請求項５】
ターゲットプロセッサ上で実行される目的プログラムのための原始プログラム中に、前記ターゲットプロセッサのレジスタを直接指定している１以上の代入文を含むか否かを解析し、
前記原始プログラムがコンパイルされ割り付けられるレジスタの生存区間情報を検出し、検出した前記生存区間情報に基づき前記割り付けられるレジスタが前記１以上の代入文を跨いで生存しているか否かを検出すること
を特徴とするプログラム開発方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラム開発装置及びプログラム開発方法に関し、特に、レジスタの破壊の発生を検出することができるプログラム開発装置及びプログラム開発方法に関する。
【背景技術】
【０００２】
従来、プログラミング言語により記述されたプログラムを機械語に変換するために、プログラム開発装置が用いられている。プログラマが、高級プログラミング言語によりプログラムを作成する場合、プログラム中で使用する変数を、マイクロプロセッサの資源であるどのレジスタ及びメモリ領域に割り付けるかは、プログラム開発装置の最適化及び資源割付け手段により決定される。そのため、プログラマは、マイクロプロセッサの資源に関して意識することなく、純粋にアルゴリズムに集中してプログラムを開発することができる。
【０００３】
しかしながら、組み込み機器向けのプログラム開発等では、すべての処理を高級プログラミング言語により作成するとは限らず、プログラマが機械語命令に対応するアセンブリ言語を記述しなければならない場合がある。この理由は、コンパイラ自体の高級プログラミング言語から機械語命令への翻訳において、プロセッサ特有の命令を実行するような翻訳ができないためである。更に、マイクロプロセッサに１命令で複数の機能を果たす機械語命令が記述できない。例えば、近年多く見られるマルチメディア対応命令などの高機能な処理を使用したくとも、高級プログラミング言語の文法では命令を使うように記述できない。或いは、たとえ記述できたとしても、コンパイラによっては、効率のいい形での機械語命令に翻訳することが難しい場合があるためである。
【０００４】
従って、このような場合、プログラマは、高級プログラミング言語と機械語と１対１に対応し、細かくレジスタの指定ができるアセンブリ言語とを組み合わせてプログラムを記述する。
【０００５】
このような場合、高級プログラミング言語により記述された原始プログラムは、コンパイラから読み込まれ、アセンブリ言語により記述されたアセンブラソースファイルは、リロケータブルオブジェクト生成手段から読み込まれて、それぞれのリロケータブルオブジェクトファイルを得る。これらのリロケータブルオブジェクトファイルに対し、アブソリュートオブジェクト生成手段を起動することで、１つのアブソリュートオブジェクトファイルを得ることになる。
【０００６】
また、１つのファイルに高級プログラミング言語とアセンブリ言語との記述を混在させたい場合、プログラマは、コンパイラの拡張機能を利用して原始プログラムを作成し、コンパイラから読み込むことによりリロケータブルオブジェクトファイルを得る。コンパイラの拡張機能とは、インラインアセンブリ文、機械命令関数、或いはアセンブリ言語によりC言語の関数と同様の振る舞いをするように記述するアセンブリ言語関数などを利用することができる機能である。
【０００７】
しかし、コンパイラの拡張機能を利用する場合は、プログラマが明示的にレジスタ名を指定して、値の受け渡しを直接記述するようになっている。そのため、プログラマは、プログラムに使用したレジスタの種類及び役割をすべて把握していなければならず、複雑な処理を記述しようとした場合、プログラマにレジスタの種類等を把握させることは、大きな負担となる。また、レジスタ名を指定して値を直接設定するため、ハードウエア仕様又はコンパイラの動作に不慣れなプログラマが使用すると、プログラムの動作不良の原因ともなる。
【０００８】
Cコンパイラは、C言語の中に記述されたインラインアセンブリ文中で使用されるレジスタ、或いは、レジスタ擬似変数への代入式など、プログラマが直接レジスタを指定している記述については関知しない。即ち、C言語のプログラム中で使用されるある変数が、インラインアセンブリ文を跨って生存している場合、インラインアセンブリ文中で指定されているレジスタと同一のレジスタがその変数に割り当てられることがあるという問題がある。そのため、プログラマは、コンパイラを実行して生成されるアセンブリコードを目視して、問題となる箇所を発見しなければならず、不正なレジスタの指定の発見はたいへん困難である。
【０００９】
そこで、インラインアセンブリ文の使用時におけるチェックをプログラマに課すことのないよう、プログラムの翻訳を行うコンパイル装置が提案されている（例えば、特許文献１参照）。
【００１０】
この提案によると、中間プログラムの仮引数の使用部分を全て変数に置き換え、この変数がアセンブリルーチンを跨いで生存しているかを調べる。この変数がアセンブリルーチンを跨いで生存している場合、アセンブリルーチンで指定されているレジスタを全て検出し、アセンブリルーチンで指定されているレジスタ以外のレジスタを変数に割り当てる。
【００１１】
しかし、インラインアセンブリを跨いでいる変数に割り当てられるレジスタが、インラインアセンブリ中で指定されているレジスタとバッティングしていないこともある。そのため、この提案による処理は、無駄な処理となる場合もある。
【特許文献１】特開２００１−２２５９１号公報
【発明の開示】
【発明が解決しようとする課題】
【００１２】
そこで、本発明は、高級プログラミング言語とアセンブリ言語とが混在するプログラムにおいて、アセンブリ言語の部分を跨いで生存するレジスタとアセンブリ言語の部分において指定されるレジスタとが実際にバッティングする場合のみ検出することができるプログラム開発装置及びプログラム開発方法を提供することを目的とする。
【課題を解決するための手段】
【００１３】
本発明の一態様によれば、ターゲットプロセッサ上で実行される目的プログラムのための原始プログラム中に、前記ターゲットプロセッサのレジスタを直接指定している１以上の代入文を含むか否かを解析する解析部と、前記原始プログラムがコンパイルされ割り付けられるレジスタの生存区間情報を検出し、検出した前記生存区間情報に基づき前記割り付けられるレジスタが前記１以上の代入文を跨いで生存しているか否かを検出する第１の検出部と、を有することを特徴とするプログラム開発装置を提供することができる。
【００１４】
本発明の一態様によれば、ターゲットプロセッサ上で実行される目的プログラムのための原始プログラム中に、前記ターゲットプロセッサのレジスタを直接指定している１以上の代入文を含むか否かを解析し、前記原始プログラムがコンパイルされ割り付けられるレジスタの生存区間情報を検出し、検出した前記生存区間情報に基づき前記割り付けられるレジスタが前記１以上の代入文を跨いで生存しているか否かを検出することを特徴とするプログラム開発方法を提供することができる。
【発明の効果】
【００１５】
本発明によれば、高級プログラミング言語とアセンブリ言語とが混在するプログラムにおいて、アセンブリ言語の部分を跨いで生存するレジスタとアセンブリ言語の部分において指定されるレジスタとが実際にバッティングする場合のみ検出することができるプログラム開発装置及びプログラム開発方法を実現することができる。
【発明を実施するための最良の形態】
【００１６】
以下、図面を参照して本発明の実施の形態を詳細に説明する。  
（第１の実施の形態）  
まず図１に基づき、本発明の第１の実施の形態に係るプログラム開発装置の構成を説明する。図１は、本発明の第１の実施の形態に係るプログラム開発装置のハードウエアの構成を示す構成図である。
【００１７】
本実施の形態のプログラム開発装置１は、コンピュータ装置であり、本体装置１０１と、各種処理の実行結果を表示する表示部１０２と、キーボード１０３と、マウス１０４とを含んで構成されている。本体装置１０１は、中央処理装置（以下、CPUという）１０５と、記憶装置１０６とを含んで構成されている。記憶装置１０６には、C言語及びアセンブリ言語により記述された原始プログラムが記憶されている。ユーザは、各種指示をCPU１０５に与えるためのキーボード１０３及びマウス１０４等の入力部を操作することにより、上述した原始プログラムを入力データとして指定することができる。このようなプログラム開発装置１を用いてプログラムを実行することにより、原始プログラムから後述するオブジェクトファイルを生成することができる。
【００１８】
図２は、本実施の形態に係るプログラム開発装置の機能構成を説明するためのブロック図である。プログラム開発装置１は、構文解析部１１と、中間コード生成部１２と、最適化／資源割付部１３と、デバッグ情報生成部１４と、アセンブリ命令生成部１５と、リロケータブルオブジェクト生成部１６と、アブソリュートオブジェクト生成部１７とを含んで構成されている。
【００１９】
構文解析部１１は、入力される原始プログラム２１に対し、字句解析、構文解析及び意味解析を行い、所定のフォーマットにより解析したデータを記憶装置１０６の一部に格納する。中間コード生成部１２は、構文解析部１１の解析したデータの結果に基づいて中間コード２２を生成する。
【００２０】
最適化／資源割付部１３は、生成された中間コード２２に対し、不要コードの削除、定数の畳み込み、誘導変数最適化等、プログラムのコードサイズ削減及び実行速度向上を目的とした最適化処理を行い、且つ、プログラム実行時に割り付けられるCPU資源を決定する。ユーザは、オプション指定により、コードサイズ削減及び実行速度向上等の最適化項目をプログラム開発装置１に対して指示することができる。
【００２１】
デバッグ情報生成部１４は、最適化／資源割付部１３により処理された中間コードからデバッグ情報を生成し、生成したデバッグ情報を保持する。デバッグ情報生成部１４に保持されるデバック情報には、配置情報、各アセンブリ命令に対し原始プログラム２１の行番号を対応付ける行番号情報、原始プログラム２１に記述されている関数及び変数の名前及び型などについての情報及び原始プログラム２１に記述されている変数が、CPU資源に割り付けられ、最後に参照されるまでの区間を示す生存区間情報等がある。後述するデバッグシステムでは、デバッグ情報生成部１４により生成されたデバッグ情報が利用される。
【００２２】
アセンブリ命令生成部１５は、最適化／資源割付部１３により処理された中間コードをターゲットプロセッサが実行可能なアセンブリ命令列に変換し、アセンブラソースファイル２３を生成する。また、アセンブリ命令生成部１５は、デバッグ情報生成部１４により生成されたデバッグ情報をアセンブラソースファイル２３の対応する箇所にデータ列として出力する。なお、アセンブリ命令生成部１５においてアセンブラレベルでの最適化が行われることもあり、最適化が行われた場合には、デバッグ情報の修正も行われる。
【００２３】
リロケータブルオブジェクト生成部１６は、アセンブリ命令生成部１５により生成されたアセンブラソースファイル２３からリロケータブルオブジェクトファイル２４を生成する。
【００２４】
アブソリュートオブジェクト生成部１７は、上述した処理により生成された複数のリロケータブルオブジェクトファイル２４ａを適切にリンクして、シンボル及び変数の配置アドレスの最終決定を行い、アブソリュートオブジェクトファイル２５を生成する。アブソリュートオブジェクトファイル２５は、ターゲットプロセッサ上において実行が可能な最終的な形式のオブジェクトファイルである。オブジェクトファイルには、ユーザがオプション指定によりデバッグ情報を含ませることが可能であり、デバッグを行う場合には、デバッグ情報を含んだアブソリュートオブジェクトファイル２５をデバッグシステムに読み込ませる。以下、構文解析部１１からアセンブリ命令生成部１５までをコンパイラと呼ぶ。
【００２５】
図３は、C言語により記述された原始プログラムの例を示す図である。図４は、図３の原始プログラムをコンパイルして得られるアセンブラソースファイルの例を示す図である。
【００２６】
図３に示すように、C言語により記述された原始プログラム２１には、main関数の中において関数func()が呼び出されている。この原始プログラム２１を上述したコンパイラによりコンパイルすることにより、図４に示すアセンブラソースファイル２３が得られる。アセンブラソースファイル２３では、原始プログラム２１に記述されている変数毎にレジスタが割り付けられている。
【００２７】
図４に示す$12は、演算結果を一時的に保持する用途で使用されるレジスタである。$1,$2,$3は、引数に設定された値を引き渡す用途で使用されるレジスタである。$8は、関数func()が呼び出される前後において、値が保証されるレジスタである。以下、値が保証されるレジスタを値保証レジスタと呼ぶ。$0は、関数の値の返却に使用されるレジスタである。
【００２８】
このように、コンパイラが変数に割り付けるレジスタは、コンパイルする時点おいて使用可能なレジスタから順番に選択されるわけではなく、目的により予め規定されているレジスタ使用規約に従ってレジスタの割り付けが行われる。図５は、コンパイラのレジスタ使用規約の例を示す図である。
【００２９】
図５に示すレジスタ群３１、具体的には$9,$10,$11,$12は、演算の途中結果が一時的に置かれる用途で用いられる。これらのレジスタは、生存区間内に関数が呼び出されるとレジスタの内容は保証されず、値が書き換わる可能性がある。
【００３０】
一方、図５に示すレジスタ群３２、具体的には$5,$6,$7,$8は、生存区間内に関数が呼び出されてもレジスタの内容が保証される用途で用いられる。これらのレジスタを関数内で使用する場合、その関数の先頭においてこれらのレジスタの値がスタックに退避され、関数の最後においてスタックに退避された値がレジスタに戻されるという動作が決められている。コンパイルを実行する場合、コンパイラは、上述したレジスタ使用規約に従い、自動的に適切なレジスタを選択する。更に、コンパイラは、値保証レジスタがある場合、その値を保護するための退避及び復帰コードを生成する。
【００３１】
しかし、インラインアセンブリ文及びアセンブリ言語関数等を使用する場合、コンパイラは、ユーザが直接レジスタを指定している記述については関知しない。そのため、ユーザは、コンパイラのレジスタ使用規約を記憶し、レジスタ使用規約に従いプログラムを記述しなければならない。
【００３２】
図６は、アセンブリ言語関数を用いて記述されたプログラムの例を示す図である。図６に示すように、アセンブリ言語関数では、データの受け渡しにレジスタ擬似変数を利用する。レジスタ擬似変数とは、矢印Ｃ１１で示す行のＲ１０である。ユーザは、このレジスタ擬似変数を利用して、ターゲットプロセッサのレジスタを直接指定し、指定したレジスタに値を設定することができる。
【００３３】
図７は、図６のアセンブリ言語関数を呼び出すC言語により記述された原始プログラムの例を示す図である。図７に示すように、C言語により記述された関数func1内において、上述したアセンブリ言語関数により定義された関数user_func()が矢印Ｃ１２で示す行において呼び出されている。
【００３４】
図８は、図７の原始プログラムをコンパイルして得られるアセンブラソースファイルの例を示す図である。このアセンブラソースファイルは、ユーザが図７の原始プログラムにコンパイルを実行することによって得られるファイルである。このとき、コンパイラは、レジスタ使用規約に従い、原始プログラム中の変数に対し自動的に適切なレジスタを割り付ける。
【００３５】
図６に示す関数user_func()では、コンパイラのレジスタ使用規約によると、一時用のレジスタである$9,$10,$11,$12と、関数呼び出しの前後において値保証レジスタである$5,$6とがユーザにより指定されている。そのため、この関数user_func()を呼び出す他の関数が$5及び$6のレジスタを使用する場合、この関数user_func()を呼び出した時点において、$5及び$6のレジスタの内容が破壊されてしまうことになる。即ち、関数user_func()を呼び出すプログラムに対しコンパイルを実行したときに、コンパイラがある変数に$5又は$6のレジスタを割り付けた場合、呼び出された関数user_func()内では、$5及び$6のスタックへの退避が行われていないため、ユーザが指定したレジスタの使用により、$5及び$6のレジスタの内容が破壊されてしまうことになる。$5及び$6は、関数呼び出し前後において値保証レジスタのため、$5又は$6が、関数user_func()を跨いで生存している場合、プログラムの動作不良が発生する。
【００３６】
そこで、ユーザがコンパイルを実行すると、プログラム開発装置１は、構文解析部１１において原始プログラムを解析し、ユーザが指定したレジスタ擬似変数があるか否かを検出する。レジスタ擬似変数が存在する場合、関数呼び出し解析部により求めた関数呼び出し情報が参照され、呼び出し元の関数が検出される。その後、レジスタ擬似変数が使用されている関数とこの関数の呼び出し元の関数とのそれぞれにおいて使用されている全てのレジスタが検出される。
【００３７】
このように検出される関数とレジスタの関係を図９に示す。図９は、関数呼び出し情報とレジスタ使用情報の例を示す図である。この図９は、図８に示すプログラムの関数呼び出し構造と使用レジスタとを概念的に示している。図９に示すように、関数main()から関数func1()が呼び出され、関数func1()から関数func2()と関数user_func()とが呼び出されている。関数func1()内では、$1,$2,$3,$5,$6,$8,$9,$12,$15のレジスタが使用され、関数func2()内では、$1,$2,$8,$15のレジスタが使用されている。関数user_func()内では、ユーザが指定したレジスタとコンパイラが割り付けたレジスタとが使用されている。コンパイラが割り付けたレジスタとは、スタックフレームの形成、戻り値の処理等に使用されるレジスタであり、コンパイラが自動的にコードを生成する。関数user_func()においてユーザが指定したレジスタは、$5,$6,$9,$10,$11,$12であり、コンパイラが割り付けたレジスタは、$0,$1,$8,$15である。
【００３８】
次に、呼び出し元の関数func1()において使用されている全てのレジスタの生存区間情報を検出する。なお、検出する生存区間情報は、値保証レジスタだけでもよい。このレジスタの生存区間情報は、上述したように、デバッグ情報生成部１４により求められる。図１０は、呼び出し元の関数のレジスタ生存区間情報の例を示す図である。この例では、$5及び$6のレジスタの生存区間情報のみ示している。図１０に示すように、$5のレジスタが関数user_func()を跨いで生存している。そのため、関数user_func()内においてユーザが$5のレジスタを指定している場合、レジスタの内容が破壊されることになる。
【００３９】
このような場合、プログラム開発装置１は、レジスタ擬似変数が使用されている関数user_func()を跨いで生存しているレジスタが存在することを表示部１０２を用いてユーザに通知する処理を行う。
【００４０】
ここで、レジスタ破壊を通知する処理の流れについて説明する。図１１は、レジスタ破壊を通知する処理の流れの例を示すフローチャートである。
【００４１】
まず、ユーザが、マウス１０４等を用いてソースプログラムを指定し、コンパイルを実行すると、関数の先頭から構文解析が行われ（ステップＳ１）、ソースプログラム中にユーザがレジスタを直接指定している代入文があるか否かが検出される（ステップＳ２）。具体的には、図６の矢印Ｃ１１のように、ユーザがレジスタを直接指定し、指定したレジスタに値を設定している記述を検出する。
【００４２】
ユーザがレジスタを直接指定している代入文がない場合、NOとなり、処理を終了する。ユーザがレジスタを直接指定している代入文がある場合、YESとなり、関数呼び出し解析部により求めた関数呼び出し情報が参照され、呼び出し元の関数が検出される（ステップＳ３）。
【００４３】
次に、中間コードから呼び出し元の関数のレジスタの生存区間が検出され（ステップＳ４）、検出された生存区間にユーザがレジスタを直接指定しているか否かが検出される（ステップＳ５）。呼び出し元の関数のレジスタの生存区間内にユーザがレジスタを直接指定していない場合、NOとなり、処理を終了する。呼び出し元の関数のレジスタの生存区間内にユーザがレジスタを直接指定している場合、YESとなり、レジスタの破壊をユーザに通知する（ステップＳ６）。
【００４４】
以上の処理の結果、ユーザが直接レジスタを指定している関数を跨いで生存するレジスタが存在する場合、プログラム開発装置１は、その関数を呼び出すことによるレジスタの破壊の発生をユーザに通知するようにした。その結果、ユーザは、ユーザが直接指定したレジスタとそのレジスタを跨いで生存するレジスタとがバッティングしていることを認識することができる。
【００４５】
よって、本実施の形態のプログラム開発装置によれば、高級プログラミング言語とアセンブリ言語とが混在するプログラムにおいて、アセンブリ言語の部分を跨いで生存するレジスタとアセンブリ言語の部分において指定されるレジスタとが実際にバッティングする場合のみ検出することができる。
【００４６】
（第２の実施の形態）  
次に、第２の実施の形態について説明する。第１の実施の形態は、ユーザによるレジスタ指定の存在する関数が、ある１つの関数から呼ばれる場合であり、第２の実施の形態は、ユーザによるレジスタ指定の存在する関数が、複数の関数から呼ばれる場合である。
【００４７】
本実施の形態のプログラム開発装置の構成は、第１の実施の形態のプログラム開発装置の構成と同様なため説明を省略する。
【００４８】
図１２は、C言語により記述された原始プログラムとコンパイルして得られるアセンブラソースファイルの例を示す図である。図１２に示すように、func1(),func3(),func4()の３つの関数が、レジスタ擬似変数を含む関数user_func()を呼び出している。
【００４９】
ユーザがコンパイルを実行すると、関数呼び出し解析部により求めた関数呼び出し情報が参照され、レジスタ擬似変数を含む関数とこの関数を呼び出しているすべての関数とが検出される。その後、レジスタ擬似変数を含む関数とこの関数を呼び出しているすべての関数とのそれぞれにおいて使用されているレジスタが検出される。
【００５０】
このように検出される関数とレジスタの関係を図１３に示す。図１３は、関数呼び出し情報とレジスタ使用情報の例を示す図である。この例では、関数main()から関数func1(),func3,func4が呼び出されている。また、関数func1()から関数func2()が呼び出されるとともに、関数func1(),func3(),func4()のそれぞれから、レジスタ擬似変数を含む関数user_func()が呼び出されている。図１３に示すように、関数user_func()においてユーザが指定したレジスタは、$5,$6,$9,$10,$11,$12である。また、関数user_func()を呼び出している関数func1()において使用されるレジスタは、$1,$2,$3,$5,$6,$8,$9,$12,$15である。同様に、関数func3()において使用されるレジスタは、$1,$2,$3,$6,$8,$12,$13,$15であり、関数func4()において使用されるレジスタは、$1,$2,$3,$11,$12である。
【００５１】
このように検出された関数func1(),func3(),func4()のそれぞれについて、第１の実施の形態にて説明したレジスタの破壊の発生を通知する処理を実行することにより、プログラム開発装置１は、ユーザにレジスタ破壊の発生の通知をすることができる。
【００５２】
次に、レジスタの破壊が発生する場合、破壊されるレジスタの退避及び復帰が必要であることをユーザに通知する処理について説明する。ここで、関数func1()では$5のレジスタの生存区間内に関数user_func()が呼び出され、関数func3()では$6のレジスタの生存区間内に関数user_func()が呼び出され、関数func4()では関数user_func()が呼び出される前後において、値保証レジスタが使用されていなかったと仮定する。
【００５３】
この場合、関数user_func()を呼び出しているすべての関数内において、関数user_func()を跨いで生存する値保証レジスタは、$5及び$6のみとなる。関数user_func()では、ユーザが、$5及び$6のレジスタを指定しているため、関数user_func()が呼び出されると、レジスタ破壊による動作不良が発生することになる。
【００５４】
そこで、$5及び$6について退避及び復帰コードを挿入することになる。この退避及び復帰コードの挿入には、２つの方法が存在する。１つ目は、呼び出される関数の先頭に退避コードを挿入し、最後に復帰コードを挿入する方法である。この場合、関数user_func()の先頭に$5及び$6の退避コードを挿入し、関数user_func()の最後に$5及び$6の復帰コードを挿入する。
【００５５】
例えば、関数user_func()内において$7及び$8のレジスタが使用されていても、関数func1(),func3(),func4()において$7及び$8のレジスタが使用されていないため、関数user_func()に$7及び$8の退避及び復帰コードは不要となる。そのため、上述した第１の方法によれば、不要な退避及び復帰処理を抑えることができる。
【００５６】
２つ目は、関数の呼び出し元の関数内において、関数を呼び出す直前に退避コードを挿入し、関数の呼び出しが終了した直後に復帰コードを挿入する方法である。この場合、関数func1()において、関数user_func()を呼び出す直前に$5の退避コードを挿入し、関数user_func()の呼び出しが終了した直後に$5の復帰コードを挿入する。同様に、関数func3()において、関数user_func()を呼び出す直前に$6の退避コードを挿入し、関数user_func()の呼び出しが終了した直後に$6の復帰コードを挿入する。関数func4()においては、値保証レジスタが使用されていないため、退避及び復帰コードは不要となる。
【００５７】
第１の方法によれば、関数func4()が、関数user_func()を呼び出す場合、関数user_func()内に挿入された$5及び$6の退避及び復帰コードは、不要なコードとなる。しかし、第２の方法によれば、呼び出し元の関数内において必要な退避及び復帰コードのみが挿入されるため、第１の方法に比べ、不要な退避及び復帰処理を抑えることができる。
【００５８】
ここで、値保証レジスタの退避及び復帰が必要か不要かを通知する処理について説明する。図１４は、値保証レジスタの退避及び復帰が必要か不要かを通知する処理の流れの例を示すフローチャートである。ステップＳ１からＳ５は、上述した第１の実施の形態と同様であるため説明を省略する。
【００５９】
ステップＳ５において、検出された生存区間にユーザがレジスタを直接指定しているか否かが検出され、呼び出し元の関数のレジスタの生存区間内にユーザがレジスタを直接指定している場合、退避及び復帰が必要であることをユーザに通知する（ステップＳ１１）。ユーザは、レジスタの退避及び復帰処理が必要であることを認識すると、上述した２つの退避及び復帰コードの挿入方法から適当な方法を選択し、退避及び復帰コードの挿入を実行することができる。
【００６０】
最後に、全ての呼び出し元の関数をチェックしたか検出される（ステップＳ１２）。全ての呼び出し元の関数をチェックしていない場合、NOとなり、ステップＳ４に戻り、同様の処理が繰り返される。全ての呼び出し元の関数をチェックした場合、YESとなり、処理を終了する。
【００６１】
以上の処理の結果、ユーザが直接レジスタを指定している関数を跨いで生存するレジスタが呼び出し元の関数内に存在する場合、プログラム開発装置１は、その関数を呼び出すことによるレジスタの破壊の発生を防ぐための退避及び復帰のための処理が必要なことをユーザに通知するようにした。その結果、ユーザは、ユーザが直接指定しているレジスタとそのレジスタを跨いで生存するレジスタとがバッティングしていることを認識し、レジスタの破壊を防ぐための退避及び復帰コードを挿入することができる。
【００６２】
よって、本実施の形態のプログラム開発装置によれば、高級プログラミング言語とアセンブリ言語とが混在するプログラムにおいて、アセンブリ言語の部分を跨いで生存するレジスタとアセンブリ言語の部分において指定されるレジスタとが実際にバッティングする場合のみ検出することができる。
【００６３】
なお、ユーザが直接レジスタを指定している関数を跨いで生存するレジスタが存在する場合、プログラム開発装置１が、レジスタの破壊を防ぐための退避及び復帰コードを自動的に挿入するようにしてもよい。
【００６４】
（変形例）
なお、第２の実施の形態の変形例として、関数user_func()内において一時用のレジスタに不足があり、止むを得ずスタックメモリに退避させる場合、関数呼び出し前後において使用されていないレジスタを一時用のレジスタとして転用するようにしてもよい。ここでは、関数呼び出し前後において使用されていないレジスタとして、上述した値保証レジスタを一時用のレジスタとして使用する。本変形例のプログラム開発装置の構成は、第２の実施の形態のプログラム開発装置と同様のため説明を省略する。
【００６５】
一時用のレジスタである$9,$10,$11,$12は、その内容が破棄されても構わないレジスタである。しかしながら、一時用として定められているレジスタは、この４本のため、一時用のレジスタを４本以上使用したい場合は、レジスタの内容を退避及び復帰させるコードの記述、即ち、図６の矢印Ｃ１３で示す行を追加し、４本のレジスタを使い回さなければならない。
【００６６】
しかし、関数user_func()を呼び出す呼び出し元の関数内において、使用されていない値保証レジスタがある場合、その値保証レジスタを関数user_func()内において一時用のレジスタとして転用することができる。また、呼び出し元の関数内において、値保証レジスタが使用されている場合でも、そのレジスタが関数user_func()を跨いで生存していなければ、同様に、呼び出し元の関数内において使用されている値保証レジスタを呼び出されている関数user_func()内において一時用のレジスタとして転用することができる。
【００６７】
図１５は、値保証レジスタを一時用のレジスタとして転用する処理の流れの例を示すフローチャートである。ステップＳ１からＳ１２は、上述した第２の実施の形態と同様であるため説明を省略する。
【００６８】
ステップＳ１２において、全ての呼び出し元の関数がチェックされると、ユーザ関数内、即ち、関数user_func()内において不足している一時用のレジスタがないかチェックされる（ステップＳ２１）。不足している一時用のレジスタがない場合、NOとなり、処理を終了する。不足している一時用のレジスタがあり、且つ、呼び出し元の関数で使用されていない値保証レジスタがある場合、YESとなり、その値保証レジスタを一時用のレジスタとして転用することができるという情報をユーザに通知する（ステップＳ２２）。
【００６９】
上述した第２の実施の形態の例では、呼び出し元の関数func1(),func2(),func3()内において、値保証レジスタである$7,$8が使用されていないため、関数user_func()内において、$7,$8を一時用のレジスタとして転用することができる。よって、ユーザは、値保証レジスタを一時用のレジスタとして転用することができることを認識する。その結果、ユーザは、この通知された情報に基づいて、関数user_func()を最適なコードに修正することができる。
【００７０】
このような処理を図６のアセンブリ言語関数のプログラムに適用し、最適なコードに修正したアセンブリ言語関数のプログラムの例を図１６に示す。図１６は、図６を最適化したアセンブリ言語関数のプログラムの例を示す図である。
【００７１】
図１６では図６に対し、関数user_func()の先頭において、値保証レジスタである$5及び$6の退避コードが追加され、関数user_func()の最後において、値保証レジスタである$5及び$6の復帰コードが追加されている。更に、矢印Ｃ１４に示す行では、呼び出し元の関数において使用されていない値保証レジスタを一時用のレジスタとして使用している。そのため、図６の矢印Ｃ１３の行に示す一時用のレジスタの退避及び復帰コードが削減でき、最適なコードの生成を実現できる。
【００７２】
よって、本変形例のプログラム開発装置によれば、不必要な退避及び復帰コードを削減することができる。
【００７３】
なお、値保証レジスタを一時用のレジスタに転用することができる場合、プログラム開発装置１が、値保証レジスタを一時用のレジスタに転用し、自動的に最適なコードに修正するようにしてもよい。
【００７４】
さらになお、本変形例を第１の実施の形態に適用してもよい。即ち、図１１に示すステップＳ６の処理を実行後、図１５に示すステップＳ２１及びＳ２２の処理を実行する。その結果、本変形例と同様に、不必要な退避及び復帰コードを削減することができる。
【００７５】
本発明は、上述した実施の形態に限定されるものではなく、本発明の要旨を変えない範囲において、種々の変更、改変等が可能である。
【図面の簡単な説明】
【００７６】
【図１】第１の実施の形態に係るプログラム開発装置のハードウエアの構成を示す構成図である。
【図２】第１の実施の形態に係るプログラム開発装置の機能構成を説明するためのブロック図である。
【図３】C言語により記述された原始プログラムの例を示す図である。
【図４】図３の原始プログラムをコンパイルして得られるアセンブラソースファイルの例を示す図である。
【図５】コンパイラのレジスタ使用規約の例を示す図である。
【図６】アセンブリ言語関数を用いて記述されたプログラムの例を示す図である。
【図７】図６のアセンブリ言語関数を呼び出すC言語により記述された原始プログラムの例を示す図である。
【図８】図７の原始プログラムをコンパイルして得られるアセンブラソースファイルの例を示す図である。
【図９】関数呼び出し情報とレジスタ使用情報の例を示す図である。
【図１０】呼び出し元の関数のレジスタ生存区間情報の例を示す図である。
【図１１】レジスタの破壊を通知する処理の流れの例を示すフローチャートである。
【図１２】C言語により記述された原始プログラムとコンパイルして得られるアセンブラソースファイルの例を示す図である。
【図１３】関数呼び出し情報とレジスタ使用情報の例を示す図である。
【図１４】値保証レジスタの退避及び復帰が必要か不要かを通知する処理の流れの例を示すフローチャートである。
【図１５】値保証レジスタを一時用のレジスタとして転用する処理の流れの例を示すフローチャートである。
【図１６】図６を最適化したアセンブリ言語関数のプログラムの例を示す図である。
【符号の説明】
【００７７】
１  プログラム開発装置、１１  構文解析部、１２  中間コード生成部、１３  最適化／資源割付部、１４  デバッグ情報生成部、１５  アセンブリ命令生成部、１６  リロケータブルオブジェクト生成部、１７  アブソリュートオブジェクト生成部、１０１  本体装置、１０２  表示部、１０３  キーボード、１０４  マウス、１０５  CPU、１０６  記憶装置
【図１】
2009258796.tif 000003
【図２】
2009258796.tif 000004
【図３】
2009258796.tif 000005
【図４】
2009258796.tif 000006
【図５】
2009258796.tif 000007
【図６】
2009258796.tif 000008
【図７】
2009258796.tif 000009
【図８】
2009258796.tif 000010
【図９】
2009258796.tif 000011
【図１０】
2009258796.tif 000012
【図１１】
2009258796.tif 000013
【図１２】
2009258796.tif 000014
【図１３】
2009258796.tif 000015
【図１４】
2009258796.tif 000016
【図１５】
2009258796.tif 000017
【図１６】
2009258796.tif 000018