(57)【特許請求の範囲】
【請求項１】
入力された第１のプログラムをコンパイルして第２のプログラムを出力するコンパイラ装置であって、
上記第１のプログラムの一部を手続呼出に変換して上記第２のプログラムを作成する変換手段と、
予め決められた変換すべき対象を展開するためのひな形であるテンプレートと、
上記手続呼出により呼び出されるべき手続のための引数から得られる情報を利用して上記テンプレートを書き換えることによってその手続の定義を記述したコードを生成する生成手段と、
上記第２のプログラムおよび上記生成手段により生成されたコードを出力する出力手段と、を有し、
上記コードは、上記第２のプログラムの中に含まれている上記手続呼出を上記第２のプログラムの外で展開することにより作成される
ことを特徴とするコンパイラ装置。
【請求項２】
上記第１のプログラムから予め決められた特定のパターンを検出する検出手段をさらに有し、
上記変換手段は、その検出手段により検出されたパターンをそのパターンに対応する手続呼出に変換する請求項１に記載のコンパイラ装置。
【請求項３】
上記検出手段は、上記第１のプログラムから組込み手続を呼び出すための呼出を検出する請求項２に記載のコンパイラ装置。
【請求項４】
上記検出手段が上記第１のプログラムから複数の互いに同じパターンを検出した際には、上記変換手段は、それら複数のパターンを同一の手続呼出に変換する請求項２に記載のコンパイラ装置。
【請求項５】
１以上のプログラムを含む第１のファイルが入力され、その１以上のプログラムをコンパイルし、そのコンパイルされた１以上のプログラムを含む第２のファイルを出力するコンパイラ装置であって、
上記第１のファイルに含まれている１以上のプログラムから予め決められた特定のパターンを検出する検出手段と、
上記検出手段により検出されたパターンをそのパターンに対応する手続呼出に変換することにより上記第１のファイルに含まれている１以上のプログラムをコンパイルする変換手段と、
予め決められた変換すべき対象を展開するためのひな形であるテンプレートと、
上記手続呼出により呼び出されるべき手続のための引数から得られる情報を利用して上記テンプレートを書き換えることによってその手続の定義を記述したコードを生成する生成手段と、
上記変換手段によりコンパイルされたプログラムおよび上記生成手段により生成されたコードを出力する出力手段とを有し、
上記コードは、上記変換手段により得られるプログラムの中に含まれている上記手続呼出をその変換手段により得られるプログラムの外で展開することにより作成されるものであり、
上記変換手段が上記第１のファイルから複数の互いに同じパターンを検出した際には、上記変換手段は、それら複数のパターンを同一の手続呼出に変換するコンパイラ装置。
【請求項６】
上記出力手段は、上記生成手段により生成されたコードを上記第２のファイルに出力する請求項５に記載のコンパイラ装置。
【請求項７】
各ファイルがそれぞれ１以上のプログラムを含む複数のファイルが入力され、それら入力ファイルに含まれているプログラムをコンパイルするコンパイラ装置であって、
上記入力ファイルに含まれているプログラムから予め決められた特定のパターンを検出する検出手段と、
上記検出手段により検出されたパターンをそのパターンに対応する手続呼出に変換することにより上記入力ファイルに含まれているプログラムをコンパイルする変換手段と、
予め決められた変換すべき対象を展開するためのひな形であるテンプレートと、
上記手続呼出により呼び出されるべき手続のための引数から得られる情報を利用して上記テンプレートを書き換えることによってその手続の定義を記述したコードを生成する生成手段と、
上記変換手段によりコンパイルされたプログラムおよび上記生成手段により生成されたコードを出力する出力手段とを有し、
上記コードは、上記変換手段により得られるプログラムの中に含まれている上記手続呼出をその変換手段により得られるプログラムの外で展開することにより作成されるものであり、
上記変換手段が上記入力された複数のファイルから複数の互いに同じパターンを検出した際には、上記変換手段は、それら複数のパターンを同一の手続呼出に変換するコンパイラ装置。
【請求項８】
コンピュータを用いて、入力された第１のプログラムをコンパイルして第２のプログラムを出力するコンパイル方法であって、
上記コンピュータにより実現される変換手段が上記第１のプログラムの一部を手続呼出に変換して上記第２のプログラムを作成するステップと、
上記コンピュータにより実現される生成手段が、上記手続呼出により呼び出されるべき手続のための引数から得られる情報を利用して、予め決められた変換すべき対象を展開するためのひな形であるテンプレートを書き換えることによってその手続の定義を記述したコードを生成するステップと、
上記コンピュータにより実現される出力手段が上記第２のプログラムおよび上記生成手段により生成されたコードを出力するステップと、を有し、
上記コードは、上記第２のプログラムの中に含まれている上記手続呼出を上記第２のプログラムの外で展開することにより作成される
ことを特徴とするコンパイル方法。
【請求項９】
コンピュータに、入力された第１のプログラムをコンパイルして第２のプログラムを出力させる、ためのコンパイラプログラムを格納する記憶媒体であって、
上記コンパイラプログラムは、
上記第１のプログラムの一部を手続呼出に変換して上記第２のプログラムを作成させ、
上記手続呼出により呼び出されるべき手続のための引数から得られる情報を利用して、予め決められた変換すべき対象を展開するためのひな形であるテンプレートを書き換えることによってその手続の定義を記述したコードを生成させ、
上記第２のプログラムおよび上記生成手段により生成されたコードを出力させるものであり、
上記コードは、上記第２のプログラムの中に含まれている上記手続呼出を上記第２のプログラムの外で展開することにより作成される
ことを特徴とするコンパイラプログラムを格納する記憶媒体。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ある言語で記述された入力プログラムの少なくとも一部をコンパイルしてその言語と同一の言語またはその言語と異なる他の言語で記述されたプログラムを出力するコンパイラに係わる。特に、出力プログラムがFortran またはＣ言語などであるプリプロセッサ方式のコンパイラに係わる。
【背景技術】
【０００２】
コンピュータの動作を記述するためのプログラミング言語は、使用目的や適用分野などに応じて様々な拡張言語または改良言語が開発されている。たとえば、Fortran をベースとする拡張言語としては、ＨＰＦが広く知られている。また、Ｃ言語をベースとする拡張言語としては、Ｃ++、Ｃ9x、ＤＰＣＥなどが知られている。
【０００３】
ところが、これらの拡張言語で記述されたプログラム等をアセンブラまたは機械語に翻訳する際には、いったんベース言語に変換することが有利なことが多い。このため、これらの拡張言語を扱うコンパイラは、一般に、出力の言語がその拡張言語のベース言語であるプリプロセッサ方式で実現されることが多い。たとえば、ＨＰＦで記述されたプログラムをFortran で記述されたプログラムに変換して出力するコンパイラが開発されている。
【０００４】
関数SUM  SCATTER は、下記の形式で呼び出される。
SUM  SCATTER(ARRAY, BASE, INDX1, INDX2, ... , INDXn, MASK)
ここで、「ARRAY 」は、任意の数値型であり、且つ任意の次元数を持つ配列である。数値型は、処理系が許す任意のバイト数の整数型、実数型、複素数型などである。「BASE」は、「ARRAY 」と同じ型であり、任意の次元数を持つ配列である。「INDX1, INDX2, ... , INDXn 」は、スカラであるか「BASE」と同じ次元数を持つ配列であり、「ｎ」は「ARRAY 」と同じ次元数である。「MASK」は、スカラであるか、「ARRAY 」と同じ次元数を持つ配列であるか、あるいは省略される。
【０００５】
したがって、たとえば、もし、処理系が１０種類の数値型を持ち、１次元〜７次元までの配列をサポートすると仮定すると、この関数の自由度は以下のように計算できる。
「ARRAY 」が１次元のときは、「ARRAY 」の自由度が１０、「BASE」の自由度が７、「ｎ＝１」なので「INDX1, INDX2, ... ,INDXn」の自由度が２、さらに「MASK」の自由度が３である。従って、この場合、組合せの数は、１０×７×２×３＝４２０となる。同様に、「ARRAY 」が２次元〜７次元のときの組合せの数は以下の通りである。
【０００６】
２次元：１０×７×２2     ×３＝８４０
３次元：１０×７×２3     ×３＝１６８０
・
・
・
７次元：１０×７×２7     ×３＝２６８８０
よって、合計の組合せ数は、５３３４０通りになる。さらに、ＨＰＦでは、一般に、配列は複数のプロセッサに分割して配置されるので、分割配置の種類（block,cyclicなど）や分割次元の違い、および多次元分割などを考慮すると、その組合せは膨大なものとなる。
【０００７】
したがって、抽象度の高い組込み手続の変換を、通常のライブラリを用いて実現しようとすると、以下の問題が生じる。
(1) すべての組合せに対応しようとすると、ライブラリが巨大になり、結果としてそのライブラリを記憶するための記憶媒体（メモリ容量）も大きくなってしまう。
【０００８】
(2) 複数のケースに対応できるような入口名（総称的な名前、あるいは抽象的な名前）を使ったとしても、結局はライブラリの中でケース分けをする必要があるので、上記(1) の問題は解決されない。
【０００９】
(3) 複数のケースに対応できるような入口名（総称的な名前、あるいは抽象的な名前）を使い、且つ様々な型や次元数でライブラリを作る方法も考えられるが、実際には以下の問題を伴う。
【００１０】
(a) 次元数の違いに対応するためには、ループのネスト数を可変にできればよいが、Fortran やＣ言語ではそのような記述はできない。また、再帰呼出しで記述すると、実行速度が低下する。
【００１１】
(b) 型（たとえば、４バイトの整数型や８バイトの実数型）を共通化することは困難である。たとえば、プログラム中の式の中に整数型の数値と実数型の数値が混在していた場合、これらの型は実行コードが互いに異なるので、型ごとに処理を分ける必要がある。このため、命令列中に判断分岐が多数登場することになり、実行速度が低下する。
【００１２】
(c) 複数のプロセッサに分割された配列を引数としてサポートする言語においては、単純な分割（例えば、最終次元での均等なblock 分割）に対しても一般的な分割（すべての次元において任意の分割方法で分割できる方法を想定する）と同じ扱いになるので、実行速度が低下してしまう。
【００１３】
このように、抽象度の高い組込み手続をプリプロセッサ方式で変換しようとすると、ライブラリを記憶するための記憶媒体が巨大になってしまった。あるいは、記憶媒体の巨大化を回避しようとすると、コンパイル能力が低下していた。
【００１４】
この問題を回避する方法の１つとして、組込み手続のすべての部分についてライブラリを用意しておくのではなく、組込み手続の呼出しパラメータに係わる部分のみをコンパイル時に生成（具体化）する方法が考えられる。例えば、インライン展開技術を用いてソースプログラム中の手続き呼出を変換する手法が考えられる。
【００１５】
ところが、プリプロセッサ方式のコンパイラにおいては、手続き呼出の登場場所によっては、インライン展開が出来なかったり、困難であったりすることがある。以下、問題点を説明する。
【００１６】
(1) 通常、宣言部において実行文を展開することは出来ない。このため、宣言部に関数呼出等が存在する場合は、それをインライン展開することはできない。もし、宣言部に登場する関数呼出等をそのままインライン展開すると、得られたプログラムをベース言語のコンパイラで翻訳したときにエラーが発生することになる。たとえば、図１Ａに示す入力プログラムの宣言部をFortran プログラムにコンパイルすると、図１Ｂに示すコードが得られる。また、図２Ａに示す入力プログラムの宣言部をＣプログラムにコンパイルすると、図２Ｂに示すコードが得られる。これらの例では、宣言部において実行文（図１の例では、関数ABS 、図２の例では、関数strlen(s) ）が展開されているので、コンパイル結果として得られるプログラムをそれぞれFortran コンパイラまたはＣコンパイラで翻訳すると、エラーが発生してしまう。
【００１７】
(2) 実行部においても、文法上の制約により、インライン展開が出来ない場合がある。たとえば、Fortran 90では、「where 文の中では代入文以外の実行文を記述してはいなない」という制約があるので、where 文の中に登場する関数をインライン展開できない場合が生じる。
【００１８】
(3) 名前の衝突の回避が困難な場合がある。たとえば、展開すべき手続内で組込み関数SUM が使用されている場合、もし、呼び出される側で変数名SUM が使われており、この変数が呼出の実引数として現れるとすると、同一の名前が重複するという問題を回避することは困難である。
【００１９】
(4) 実行文等を展開する場合、それを単にその場所に展開するだけでなく、文脈に応じて周辺のコードも変換しなければならないことがある。たとえば、図３Ａに示すように、入力プログラムの中のELSEIF文の条件節に関数呼出（図３の例では、関数ABS ）が現れる場合には、IF文の入れ子構造を変換する必要が生じる。このため、図３Ｂに示すように、インライン展開が複雑になる。また、入力プログラムの中のDO WHILE文の条件節に呼出し関数が現れる場合は、その関数をループの直前およびループ内の双方で展開しなければならず、この場合もインライン展開が複雑になる。一方、Ｃ言語では、たとえば、for 文の括弧内の２番目または３番目の式を展開する場合には、同様にインライン展開が複雑になる。
【００２０】
このように、プログラム等をコンパイルする際、インライン展開が可能であれば、そのコンパイルに必要な情報を格納するための記憶領域を小さくすることができるなどのメリットが得られるが、オブジェクト言語が処理手続を記述できる場所について制約がある言語であった場合には、インライン展開が出来なかったり、あるいは困難だったりする。すなわち、オブジェクト言語が機械語やアセンブラのように実行コードの出現場所についての制約が少ないコンパイラにおいては、インライン展開をするにあたっての問題も少ないが、オブジェクト言語がFortran やＣ言語などのように実行コードの出現場所についての制約が多いプリプロセッサ方式のコンパイラにおいては、インライン展開をするにあたって上述のような問題が発生しやすい。
【００２１】
本発明の課題は、実行速度が高速で、且つコンパイルに必要な情報を格納するための記憶領域が小さくなるプリプロセッサ方式のコンパイラを提供することである。
【発明の開示】
【００２２】
本発明のコンパイラ装置は、入力された第１のプログラムをコンパイルして第２のプログラムを出力する構成を前提とし、第１のプログラムの一部を手続呼出に変換して上記第２のプログラムを作成する変換ユニットと、上記手続呼出により呼び出されるべき手続の定義を記述したコードを生成する生成ユニットと、上記第２のプログラムおよび上記生成手段により生成されたコードを出力する出力ユニットとを有する。
【００２３】
第１のプログラムをコンパイルすることにより第２のプログラムを作成する際、手続の定義を記述したコードは第２のプログラムの外に生成され、第２のプログラム中にはそのコードを呼び出すための手続呼出が記述される。すなわち、第２のプログラム中には実行コードは展開されない。したがって、オブジェクト言語が処理手続を記述できる場所について制約がある言語であった場合においても、実行されたときにエラーの発生を伴わない第２のプログラムが得られる。また、第２のプログラムの記述が複雑になることはなく、インライン展開を用いる場合と比べ、第２のプログラムをベース言語コンパイラで翻訳する速度の向上が期待される。さらに、上記装置においては、入力プログラム中の変換すべき対象のすべての組合せに対してコンパイルに必要な情報を用意しておく必要がないので、そのためのメモリ容量が小さくなる。
【発明を実施するための最良の形態】
【００２４】
本発明は、入力されたプログラムの少なくとも一部をコンパイルするプリプロセッサ方式のコンパイラに係わる。プリプロセッサ方式のコンパイラ（「プリコンパイラ」とも呼ばれている）は、ソースプログラムを読み込み、そのソースプログラムの少なくとも一部を変更してそのソースプログラムのコンパイルのための準備を行うプログラムである。以下の実施例では、Fortran およびＣ言語を採り上げ、ソースプログラムの中の呼出（関数、サブルーチン、ライブラリ等の組込み手続を呼び出すための呼出）などをオブジェクトコードに変換する機能を中心に説明する。なお、本実施例のコンパイラは、ソース言語とオブジェクト言語とが互いに異なっている場合、およびソース言語とオブジェクト言語とが互いに同じ場合の双方に適用可能である。
【００２５】
本実施例のコンパイラの概略動作の一例を図４を参照しながら説明する。ここでは、ソースプログラム１が、たとえば、Fortran の拡張言語の１つであるＨＰＦで記述されており、その中に「Ａ＊＊Ｎ」が含まれているものとする。「Ａ＊＊Ｎ」は、「ＡのＮ乗」を表す。また、オブジェクト言語は、例えば、Fortran であるものとする。この場合、コンパイラ２は、たとえば、ソースプログラム１の中の「Ａ＊＊Ｎ」を「ＰＯＷ（Ａ，Ｎ）」に変換することによりオブジェクトプログラム３を生成すると共に、「ＰＯＷ（Ａ，Ｎ）」により呼び出されるべき手続を記述するコード（オンラインコード）４を出力する。この手続の定義は、たとえば、「Ｎが所定値よりも小さいときには掛け算を実行し、Ｎが所定値以上のときには巾乗演算を実行する。」である。また、コード４は、この手続をオンライン展開することにより得られる。なお、「オンライン展開」とは、あるプログラム中に登場する手続等をそのプログラムの外でサブプログラムとして展開することを意味する。また、オンライン展開により得られるコードを「オンラインコード」と呼ぶことにする。
【００２６】
なお、コンパイラ２は、必要に応じて、オブジェクトプログラム３の手続呼出を用いてオンラインコード４を呼び出すための記述（たとえば、インタフェース宣言）をオブジェクトプログラム３に加える。
【００２７】
このように、コンパイラ２は、ソースプログラム１の一部を手続呼出に変換することによりオブジェクトプログラム３を生成する際、その手続呼出により呼び出されるべきコードをオンラインコード４としてオブジェクトプログラム３の外に作成する。すなわち、手続呼出により呼び出されるべきコードは、オブジェクトプログラム３の中では展開されない。従って、オブジェクト言語が手続を記述できる場所について制約がある言語であったとしても、オブジェクトプログラム３が実行されたときに文法エラー等が発生することはない。
【００２８】
図５は、本実施例のコンパイラの機能ブロック図である。ここでは、プログラム毎にソースコードが与えられることを前提とする。
ソースプログラムは、構文解析部２１により分解・解析された後にコンパイラ１０に入力される。構文解析部２１は、入力コードを中間コードに変換する機能を備え、既存のプログラムをそのまま流用できる。
【００２９】
コンパイラ１０は、検出部１１、変換部１２、および展開部１３を備える。検出部１１は、変換すべき対象を検出する。具体的には、検出部１１は、ソースプログラムから予め決められた特定のパターン（たとえば、手続呼出など）を検出する。変換部１２は、検出部１１により検出された変換すべき対象に対応する手続名を決定し、その変換すべき対象をその手続名に置き換える。そして、コンパイラ１０は、変換部１２によりその一部が変換されたソースプログラムをオブジェクトプログラムとして出力する。展開部１３は、検出部１１により検出された変換すべき対象に対応するオンラインコード（手続コードまたは実行コード）を生成する。なお、このオンラインコードは、オブジェクトプログラムが実行されたときに、変換部１２により決定された手続名に対応付けられて呼び出される。そして、コンパイラ１０は、その展開部１３により生成されたオンラインコードを出力する。
【００３０】
コード生成部２２は、コンパイラ１０から出力されたオブジェクトプログラムおよびオンラインコードをアセンブラまたは機械語に翻訳し、それらをそれぞれ出力する。コード生成部２２は、既存のプログラムをそのまま流用でき、最適化処理を行うこともできる。
【００３１】
図６は、図５に示したコンパイラ１０の動作を説明するためのフローチャートである。ここでは、コンパイラ１０に入力されるソースプログラムをプラグラムＰ、コンパイラ１０によりコンパイルされたオブジェクトプログラムをプログラムＰ' と呼ぶことにする。なお、この処理は、１つのソースプログラムが入力される毎に実行される。
【００３２】
ステップＳ１では、プログラムＰ内で変換すべき対象Ｃ1 ,....,Ｃn を検出する。変換すべき対象Ｃ1 ,....,Ｃn は、たとえば、関数、サブルーチン、ライブラリの呼出である。
【００３３】
ステップＳ２〜Ｓ５の処理は、ステップＳ１において検出された各変換すべき対象Ｃ1 ,....,Ｃn について実行される。ステップＳ２では、変換すべき対象Ｃi の特徴Ａi を抽出する。「特徴」とは、例えば、関数名などの呼び出すべき手続の名前、引数の次元、数値型などである。ステップＳ３では、変換すべき対象Ｃi に対して、プログラムＰ内でユニークな手続名ｆi を生成する。すなわち、各変換すべき対象Ｃ1 ,....,Ｃn に対して、互いに異なる手続名を割り当てる。
【００３４】
ステップＳ４では、変換すべき対象Ｃi を手続ｆi の呼出に置換する。ここで、「手続ｆi の呼出」とは、当該プログラムが実行されたときに、手続ｆi を呼び出すための呼出である。ステップＳ５では、特徴Ａi に対応する手続コードＳi を生成する。そして、この手続コードＳi の手続名としてｆi を指定する。これにより、手続コードＳi は、当該プログラムが実行されたときに、手続ｆi の呼出により呼び出されることになる。
【００３５】
上記ステップＳ２〜Ｓ５の処理をすべての変換すべき対象Ｃ1 ,....,Ｃn について実行すると、プログラムＰにおいて各変換すべき対象Ｃ1 ,....,Ｃn がそれぞれ手続ｆ1 ,....,ｆn の呼出に置換され、また、各手続ｆ1 ,....,ｆn の呼出にそれぞれ対応して手続コードＳ1 ,....,Ｓn が生成される。そして、ステップＳ６において、変換すべき対象Ｃi を手続ｆi の呼出に置き換えることにより得られるプログラムＰ' 、及び生成された手続コードＳ1 ,....,Ｓn が出力される。なお、プログラムＰ' および手続コードＳ1 ,....,Ｓn は、互いに同じファイルに出力されてもよいし、互いに異なるファイルに出力されてもよい。また、ソースコードが複数のプログラム単位を含む場合には、各プログラム単位に対して上記処理が繰り返し実行される。
【００３６】
次に、具体的な実施例を説明する。以下では、コンパイラ１０に対して図７Ａに示すソースプログラムが入力された場合を想定し、関数SUM の呼出を変換すべき対象として説明する。なお、関数SUM は、引数により指定された配列の要素の総和を返す関数であるものとする。また、ソースプログラムは、中間コードに変換されていてもよい。
【００３７】
ソースプログラムが入力されると、コンパイラ１０は、そのソースプログラムをスキャンすることにより関数SUM の呼出を検出する。図７Ａに示す例においては、関数SUM は、４行目の「SUM(A)」および５行目の「SUM(N(51:100))」により呼ばれていることが検出される。
【００３８】
続いて、コンパイラ１０は、「SUM(A)」をユニークな名前が割り当てられた手続の呼出に変換する。この実施例では、新たに生成される名前は、変換すべき対象の手続名と、ソースプログラムの名前と、そのソースプログラムの中で登場した順番との組合せにより決定される。この場合、図７Ａに示す例では、「SUM(A)」はプログラムSAMPLEの中で最初に登場した変換対象なので、新たな手続名として「SUM  SAMPLE １」が割り当てられる。なお、コンパイラ１０が新たに生成する名前とユーザにより定義される変数名などとの重複を回避するためには、コンパイラ１０は、ユーザが使用できない名前を選択するようにすればよい。たとえば、「xxx  」で始まる名前を予め予約しておくことによりユーザの使用を制限する方法や、「＃」や「＄」などのユーザが滅多に使用しない文字を含む名前を生成するようにする方法が考えられる。
【００３９】
この後、コンパイラ１０は、ソースプログラムの４行目を以下のように変換する。このとき、「SUM  SAMPLE １」の引数は、「SUM(A)」の引数をそのまま使用する。
B=SUM(A)  →  B=SUM  SAMPLE 1(A)
続いて、コンパイラ１０は、引数Ａを解析することにより、「SUM(A)」の特徴を抽出する。これにより、以下の情報が得られる。
【００４０】
arg-type  ＝  ＲＥＡＬ
ｍ＝３
lb(1) ＝１
ub(1) ＝１０
lb(2) ＝１
ub(2) ＝２０
lb(3) ＝１
ub(3) ＝３０
ここで、「arg-type」は引数の型、「ｍ」は引数の次元数、「lb(i) 」および「ub(i) 」はそれぞれ引数の第ｉ次元の下限値および上限値である。
【００４１】
コンパイラ１０は、「SUM  SAMPLE １」の手続コードを生成する際、テンプレートを利用する。テンプレートは、予め決められた変換すべき対象を展開するためのひな形であり、データベース等に格納されている。関数SUM を展開するためのテンプレートの例を図８に示す。
【００４２】
テンプレートは、抽象的な表現を用いて作成されており、変換すべき対象の特徴に応じてそのテンプレートをカスタマイズすることにより対応する手続コードが生成される。また、１つの呼出に対して複数のテンプレートを設けてもよい。例えば、重要な呼出に対しては複数種類のテンプレートを設けておき、その呼出の特徴に応じてそれら複数のテンプレートの中から適切な１つを選択して利用するようにしてもよい。さらに、手続の引数などをパラメータとして具体的なソースコードまたはオブジェクトコードを生成するような処理プログラムとしてテンプレートを作成することも可能である。
【００４３】
コンパイラ１０は、図８に示すテンプレートを利用し、引数Ａを解析することにより得られている情報に従って「SUM  SAMPLE １(A) 」についての手続コードを生成する。このようにして生成された手続コードの例を図９Ａに示す。
【００４４】
手続コードは、具体的には、以下のようにして作成される。すなわち、引数Ａの「型」が「REAL」であるので、図８に示すテンプレートにおいて、「arg-type」として「REAL」が書き込まれる。また、引数の各次元の下限値および上限値として「１」「１０」「１」「２０」「１」「３０」が書き込まれる。さらに、このコードが「SUM  SAMPLE １(A) 」により呼び出されるようにするために、手続名として「SUM  SAMPLE １」が書き込まれる。
【００４５】
「SUM(N(51:100))」についての処理は、基本的に、「SUM(A)」についての処理と同じである。すなわち、コンパイラ１０は、まず「SUM(N(51:100))」をユニークな名前が割り当てられた手続の呼出に変換する。図７Ａに示す例では、「SUM(N(51:100))」はプログラムSAMPLEの中で２番目に登場した関数SUM なので、新たな手続名として「SUM ＿SAMPLE＿2 」が割り当てられる。この後、コンパイラ１０は、ソースプログラムの５行目を以下のように変換する。
【００４６】
WRITE(*,*) SUM(N(51:100)) →  WRITE(*,*) SUM SAMPLE 2(N(51:100))
続いて、コンパイラ１０は、引数を解析して「SUM(N(51:100))」の特徴を抽出する。これにより、以下の情報が得られる。
【００４７】
arg-type  ＝  ＩＮＴＥＧＥＲ
ｍ＝１
lb(1) ＝５１
ub(1) ＝１００
この後、コンパイラ１０は、図８に示したテンプレートを利用して「SUM  SAMPLE 2(N(51:100))」についての手続コードを生成する。生成された手続コードの例を図９Ｂに示す。
【００４８】
図７Ｂは、コンパイラ１０を用いて図７Ａに示したソースプログラムをコンパイルした結果を示す図であり、図６に示したフローチャートにおけるプログラムＰ' に相当する。図７Ａおよび図７Ｂに示すように、ソースプログラム中に複数の変換すべき対象（関数SUM を呼び出すための呼出）が存在する場合、コンパイラ１０は、それらに対して互いに異なる手続名を割り当てることにより、それらの変換対象を互いに識別可能な手続呼出に置き換える。この変換処理により得られたコード（オブジェクトプログラム）は、図７Ｂに示すようなプログラムコードイメージか、対応するオブジェクトコードとしてファイルに出力される。また、コンパイラ１０は、各手続呼出に対して、手続コードを生成して出力する。ここで、コンパイラ１０は、複数の手続コードを一括して出力してもよいし、生成するごとに、順次、出力するようにうしてもよい。
【００４９】
このように、コンパイラ１０は、図７Ａに示すソースプログラムが入力されると、図７Ｂに示すオブジェクトコード、および図９Ａおよび図９Ｂに示す手続コードを出力する。ここで、手続コードは、オブジェクトコード内では展開されない。したがって、コンパイラ１０のオブジェクト言語が手続コードを記述できる場所について制約を持っていたとしても、コンパイル結果がその制約に違反することはない。
【００５０】
従来、たとえば、FORTRAN やＣ言語などでは、プログラムの宣言部において実行文を展開することができないので、宣言部に組込み手続等の呼出が記述されていた場合には、従来のコンパイラではその宣言部を正しくコンパイルすることはできなかった。ところが、本実施例のコンパイラによれば、組込み手続等の呼出はオブジェクト言語における手続呼出に置き換えられるだけなので、そのような問題は生じない。
【００５１】
上記図５〜図９を参照しながら説明した実施例では、ソースプログラム中の変換すべき対象が互いに同一ではない場合を採り上げた。すなわち、図７Ａに示した例では、２つの変換すべき対象は、呼び出すべき関数は互いに同じであったが、その引数は互いに異なっていた。
【００５２】
ところが、ソースプログラム中に複数の互いに同一の変換すべき対象が存在することがある。この場合、もし、図５に示したコンパイラ１０を用いてそのソースプログラムをコンパイルすると、複数の互いに同一の手続コード（オンラインコード）を生成することになり、コンパイラの総出力コード量が必要以上に多くなってしまう。以下、この問題を解決したコンパイラについて説明する。
【００５３】
図１０は、本発明の他の形態のコンパイラの機能ブロック図である。図１０において使用する符号のうち、図５において先に使用しているものは同じ機能を持つユニットを表す。すなわち、コンパイラ３０において、検出部１１、変換部１２、展開部１３は、基本的に図５に示したコンパイラ１０のものと同じユニットである。
【００５４】
コンパイラ３０は、重複判定部３１を備えることを特徴とする。重複判定部３１は、検出部１１によりソースプログラムにおいて検出された複数の変換すべき対象のうち、互いに同じものが存在するか否かを調べ、その結果を変換部１２および展開部１３に通知する。互いに同じ変換すべき対象が存在しなければ、変換部１２および展開部１３は、図５〜図９を参照しながら説明した動作を実行する。一方、互いに同じ変換すべき対象が存在する場合は、変換部１２は、それらをそれぞれ互いに同じ呼出に変換し、展開部１３はそれらの呼出により共有的に呼び出される手続コード（オンラインコード）を１つだけ生成する。
【００５５】
図１１は、図１０に示したコンパイラの動作を説明するためのフローチャートである。
ステップＳ１１では、まず、重複判定部３１が使用するメモリ領域Ｒ（管理テーブル）をクリアする。なお、メモリ領域Ｒには、ソースプログラム中に存在する変換すべき対象の特徴が登録され、さらに、各特徴に対してユニークに割り当てられる手続名が登録される。ステップＳ１２は、図６のステップＳ１と同様に、プログラムＰ内で変換すべき対象Ｃ1 ,....,Ｃn を検出する。
【００５６】
ステップＳ１３〜Ｓ１９の処理は、ステップＳ１２において検出された各変換すべき対象Ｃ1 ,....,Ｃn について実行される。ステップＳ１３では、図６のステップＳ２と同様に、変換すべき対象Ｃi の特徴Ａi を抽出する。ステップＳ１４では、特徴Ａi が、先にステップＳ１４〜Ｓ１９の処理が終了している変換すべき対象Ｃ1 ,....,Ｃi-1 の特徴の中のいずれかと同じであるか否かを調べる。特徴Ａi が、先の処理がなされた変換すべき対象Ｃ1 ,....,Ｃi-1 の特徴の中のいずれかと同じであればステップＳ１９へ進み、いずれにも一致しなければステップＳ１５へ進む。
【００５７】
ステップＳ１５では、メモリ領域Ｒをサーチし、変換すべき対象Ｃi に対してプログラムＰ内でユニークな手続名ｆi を生成する。ステップＳ１６では、図６のステップＳ４と同様に、変換すべき対象Ｃi を手続ｆi の呼出に置換する。ステップＳ１７では、図６のステップＳ５と同様に、特徴Ａi に対応する手続コードＳi を生成する。この手続コードＳi の手続名としてｆi が指定される。さらに、ステップＳ１８において、変換すべき対象Ｃi の特徴Ａi および対応する手続コードＳi を呼び出すための手続名としてのｆi がメモリ領域Ｒに登録される。
【００５８】
一方、ステップＳ１９では、変換すべき対象Ｃi を、特徴Ａj に対応する手続コードＳj を呼び出すための手続ｆi の呼出に置換する。なお、ステップＳ１９が実行された場合は、新たな手続コードが生成されず、また、メモリ領域Ｒへの新たな登録も行われない。
【００５９】
上記ステップＳ１３〜Ｓ１９の処理を全ての変換すべき対象Ｃ1 ,....,Ｃn について実行すると、プログラムＰにおいて各変換すべき対象Ｃ1 ,....,Ｃn が手続ｆ1 ,....,ｆm （ｍ≦ｎ）の呼出に置換され、また、各手続ｆ1 ,....,ｆm の呼出にそれぞれ対応して手続コードＳ1 ,....,Ｓm が生成される。そして、ステップＳ２０において、変換すべき対象を手続の呼出に置き換えることにより得られるプログラムＰ' 、および生成された手続コードが出力される。なお、プログラムＰ' および手続コードＳ1 ,....,Ｓm は、互いに同じファイルに出力されてもよいし、互いに異なるファイルに出力されてもよい。
【００６０】
このように、コンパイラ３０によれば、あるソースプログラム内に存在する互いに重複した変換すべき対象に対して、重複して手続コードを生成することなく、必要最小限の手続コードを生成するので、コンパイラの総出力コード量が減少する。
【００６１】
次に、具体的な実施例を説明する。以下では、コンパイラ３０に対して図１２Ａに示すソースプログラムが入力された場合を想定し、関数SUM の呼出を変換対象として説明する。なお、コンパイラ３０は、図８に示したテンプレートを利用するものとする。
【００６２】
ソースプログラムが入力されると、コンパイラ３０は、そのソースプログラムをスキャンすることによって関数SUM の呼出を検出する。図１２Ａに示す例においては、関数SUM は、４行目の「SUM(A)」および「SUM(A2) 」、５行目の「SUM(N(51:100))」、および６行目の「SUM(M(51:200))」により呼ばれていることが検出される。
【００６３】
コンパイラ３０は、まず、「SUM(A)」についてその特徴を抽出し、その特徴に従ってオンライン展開を実行する。このオンライン展開の結果は、上述したコンパイラ１０による展開結果と同じであり、図９Ａに示した手続コードを生成する。また、「SUM(A)」が「SUM  SAMPLE 1(A)」に置き換えられる動作も上述した通りである。
【００６４】
ただし、コンパイラ３０においては、同じ手続コードを重複して生成することを回避するために、順次、生成した手続コードを呼び出すための呼出の名前と、その手続の特徴が管理テーブルに登録される。なお、「特徴」は、引数の型、引数の次元数、引数の各次元の下限値および上限値である。したがって、「SUM(A)」についてオンライン展開が実行されると、図１３Ａに示すように、「SUM(A)」に対応するレコードが登録される。
【００６５】
続いて、コンパイラ３０は、「SUM(A2) 」の特徴を抽出し、図１３Ｂに示すように、管理テーブルに既に登録されている呼出の特徴とその抽出した特徴とを比較する。ここでは、「SUM ＿SAMPLE＿1(A)」および「SUM(A2) 」の特徴が互いに完全に一致しているので、「SUM(A2) 」に対しては新たに手続コードを生成することなく、「SUM(A)」に対して生成された手続コードを「SUM(A2) 」から呼び出すようにするために、「SUM(A2) 」を「SUM  SAMPLE 1(A2) 」に変換する。この結果、ソースプログラムの４行目は、以下にように変換されることになる。
【００６６】
B=SUM(A)+SUM(A2)  →  B=SUM  SAMPLE 1(A)+SUM SAMPLE 1(A2)
したがって、この行が実行されると、「SUM  SAMPLE 1(A)」により図９Ａに示した手続コードが呼び出され、さらに、「SUM  SAMPLE 1(A2) 」によってもその同じ手続コードが呼び出されることになる。
【００６７】
なお、「SUM  SAMPLE 1(A)」および「SUM(A2) 」の特徴が互いに完全に一致していたので、管理テーブルには新たなレコードは追加されず、管理テーブルは図１３Ａに示す状態を保持する。
【００６８】
続いて、コンパイラ３０は、「SUM(N(51:100))」の特徴を抽出し、図１３Ｃに示すように、管理テーブルに既に登録されている呼出の特徴とその抽出した特徴とを比較する。ここでは、「SUM  SAMPLE 1(A)」及び「SUM(N(51:100))」の特徴が互いに一致していないので、「SUM(N(51:100))」に対応する手続コードを新たに生成する。この手続コードは、図９Ｂに示した手続コードと同じである。
【００６９】
そして、コンパイラ３０は、管理テーブルをサーチし、先に登録されていない名前（ここでは、「SUM ＿SAMPLE＿2 」）を決定し、それを「SUM(N(51:100))」に割り当てる。この後、ソースプログラムの５行目が下記のように書き換えられる。この処理は、図５〜図９を参照しながら説明した処理と同じである。
【００７０】
WRITE(*,*) SUM(N(51:100)) →  WRITE(*,*) SUM SAMPLE 2(N(51:100))
なお、新たに使用されることとなった名前および対応する特徴は、管理テーブルに登録される。
【００７１】
さらに、コンパイラ３０は、「SUM(M(51:200))」に対して同様の処理を実行する。この場合、図１３Ｄに示すように、「SUM(M(51:200))」の特徴は、先に登録されている「SUM ＿SAMPLE＿2 」の特徴と類似しているが、完全には一致していないので、「SUM(M(51:200))」に対応する手続コードを新たに生成する。この新たに生成される手続コードを図１４に示す。
【００７２】
そして、コンパイラ３０は、管理テーブルをサーチし、先に登録されていない１つの名前（「SUM ＿SAMPLE＿3 」）を決定し、それを「SUM(M(51:200))」に対して割り当てる。この後、ソースプログラムの６行目が下記のように書き換えられる。
【００７３】
WRITE(*,*) SUM(M(51:200)) →  WRITE(*,*) SUM SAMPLE 3(M(51:200))
このように、コンパイラ３０は、図１２Ａに示すソースプログラムが入力されると、図１２Ｂに示すオブジェクトコード、および図９Ａ、図９Ｂ、および図１４に示す手続コードを出力する。ここで、図９Ａに示す手続コードは、２つの呼出により共有的に呼び出される。すなわち、上記実施例では、ソースプログラムから変換すべき対象が４つ検出されたが、生成された手続コードは３つである。このように、ソースプログラムの中に複数の互いに同じ変換対象があった場合、コンパイラ３０の総出力コード量は図５に示したコンパイラ１０と比較して減少する。
【００７４】
なお、図１０〜図１４に示した実施例では、図８に示したテンプレートを用いて関数SUM の手続コードを生成したが、テンプレートの表現の抽象度を高めると、生成される手続コードの数をさらに減少させることができる。
【００７５】
図１５は、図８に示したテンプレートと比較して抽象度の高い表現で作成したテンプレートの例である。図８に示したテンプレートは、引数の型、引数の次元数、および引数の各次元の下限値および上限値をパラメータとして手続を展開するフォーマットであったが、図１５に示すテンプレートは、引数の型および引数の次元数のみををパラメータとして手続を展開するフォーマットである。したがって、図１５に示すテンプレートを用いた場合、引数の型および引数の次元数が互いに同じであれば、引数の各次元の下限値および上限値の不一致は無視され、配列の大きさに因らない手続コードが作成される。
【００７６】
図１６は、図１５に示すテンプレートを用いて変換すべき対象を展開する際に比較されるパラメータを示す図である。ここでは、図１２Ａに示したソースプログラムから検出された４つの変換すべき対象について示している。
【００７７】
図１５に示すテンプレートを用いる場合、比較すべきパラメータは、上述したように、変換すべき対象の「引数の型」および「引数の次元数」である。従って、「SUM(A)」および「SUM(A2) 」に対して互いに同じ手続コードが生成されることになり、同様に、「SUM(N(51:100))」および「SUM(M(51:200))」に対して互いに同じ手続コードが生成されることになる。すなわち、コンパイラ３０は、「SUM(A)」および「SUM(A2) 」に対して１つの手続コードを生成し、同様に、「SUM(N(51:100))」および「SUM(M(51:200))」に対しても１つの手続コードを生成する。このとき、「SUM(A)」および「SUM(A2) 」は、互いに同じ手続呼出（ここでは、「SUM  SAMPLE １」とする。）に変換される。同様に、「SUM(N(51:100))」および「SUM(M(51:200))」も互いに同じ手続呼出（ここでは、「SUM ＿SAMPLE＿2 」とする。）に変換される。
【００７８】
図１７は、図１５に示すテンプレートを用いた場合のコンパイラ３０の出力を示す図である。コンパイラ３０は、図１２Ａに示したソースプログラムが入力されると、図１５に示したテンプレートを用いた場合、図１７に示すオブジェクトコード、および２つの手続コード（オンラインコード）を出力する。ここで、手続コードＡは、「SUM  SAMPLE １」により呼び出され、また、手続コードＢは、「SUM  SAMPLE ２」により呼び出される。
【００７９】
なお、図１７に示す例では省略されているが、実際には、オブジェクトコードにおいて手続コードに対するインタフェース宣言が記述される必要がある。例えば、Fortran90 プログラムとしてオブジェクトコードを生成する場合は、ソースプログラム中の変換すべき対象を新たな手続呼出に変換する際、コンパイラが、その新たな手続呼出に関するインタフェース宣言を生成する。このことは、他の実施例においても同様である。
【００８０】
上記図５および図１０に示した実施例では、コンパイラへの入力が１つのプログラムであることを前提としていたが、実際には、複数のソースプログラムを含むファイルを一括してコンパイルしたい場合が多々ある。以下では、複数のソースプログラムを含むファイルを一括してコンパイルするコンパイラについて説明する。
【００８１】
図１８は、本発明のさらに他の形態のコンパイラの機能ブロック図である。図１８において使用する符号のうち、図５または図１０において先に使用しているものは同じ機能のユニットを表す。
【００８２】
コンパイラ４０は、基本的には、図１０に示したコンパイラ３０と同じである。ただし、コンパイラ３０に設けられる重複判定部３１は、各ソースプログラム中に重複する変換すべき対象が存在するか否かを調べるのに対し、コンパイラ４０に設けられる重複判定部４１は、入力ファイル毎に重複する変換すべき対象が存在するか否かを調べる。重複判定部４１による判定結果は、変換部１２および展開部１３に通知される。この通知を受けた変換部１２および展開部１３の動作は、基本的に、図１０を参照しながら説明した通りである。
【００８３】
図１９は、図１８に示したコンパイラの動作を説明するためのフローチャートである。ここでは、コンパイラ４０に入力されるソースファイルをファイルＦ、コンパイラ４０によりコンパイルされたオブジェクトファイルをファイルＦ' と呼ぶことにする。なお、以下では、ファイルＦは、１以上のソースプログラムＰ1 ,....,Ｐt を含むものとする。また、この処理は、１つのソースファイルが入力されるごとに実行される。
【００８４】
ステップＳ２１〜Ｓ３０の各処理は、基本的に、図１１に示したステップＳ１１〜Ｓ２０とそれぞれ同じである。ただし、ステップＳ２１〜Ｓ３０では、ファイル単位で処理が行われる。すなわち、ステップＳ２２では、ファイルＦに含まれている１以上のソースプログラムから変換すべき対象が検出される。また、ステップＳ２５では、変換すべき対象に対してファイルＦ内でユニークな名前を生成する。
【００８５】
コンパイラ４０は、ソースプログラムＰ1 ,....,Ｐt を含むファイルＦが入力されると、上記ステップＳ２１〜Ｓ３０の処理を実行することにより、各変換すべき対象がそれぞれ手続の呼出に置き換えられたオブジェクトプログラムＰ' 1,...., Ｐ' t を生成し、また、各手続の呼出にそれぞれ対応して手続コードＳ1 ,....,Ｓm を生成する。そして、これらのオブジェクトプログラムおよび生成された手続コードは、同一のファイルに出力される。
【００８６】
なお、手続コードは、生成される毎に、順次、１つずつ出力してもよいし、プログラム単位の処理が終了する毎に出力してもよいし、あるいはファイル単位の処理が終了した時点で一括して出力してもよい。また、ソースコードが複数のファイルから構成される場合には、各ファイル毎に上記処理を繰り返し実行すればよい。
【００８７】
このように、コンパイラ４０によれば、複数のソースプログラムを含むファイル内に存在する互いに重複した変換すべき対象に対して、重複して手続コードを生成することなく、必要最小限の手続コードを生成するので、コンパイラの総出力コード量がさらに減少する。
【００８８】
次に、具体的な実施例を説明する。以下では、コンパイラ４０に対して図２０に示すソースファイル（tiny.f）が入力された場合を想定し、関数SUM の呼出を変換対象として説明する。なお、コンパイラ４０は、図８に示したテンプレートを利用するものとする。
【００８９】
ソースファイルが入力されると、コンパイラ４０は、そのソースファイルに含まれている２つのプログラム（メインプログラムおよびサブプログラム）をスキャンすることにより関数SUM の呼出を検出する。図２０に示す例においては、関数SUM は、メインプログラムの「SUM(A)」及び「SUM(N(51:100))」、およびサブプログラムの「SUM(Q)」により呼ばれていることが検出される。
【００９０】
続いて、コンパイラ４０は、検出した各変換すべき対象の特徴（引数の型、引数の次元数など）に基づいて、生成すべき手続コードが同一になるものが存在するか否かを調べる。ここでは、「SUM(A)」および「SUM(Q)」の特徴が互いに同じである。従って、「SUM(A)」および「SUM(Q)」に対しては、これらにより共有される１つの手続コードが生成される。なお、「SUM(N(51:100))」に対しては、１つの独立した手続コードが生成される。
【００９１】
図２１は、図２０に示すソースファイルが入力されたときのコンパイラ４０の出力である。ここでは、呼出の名前は、手続の名前と、ファイル名と、そのファイルの中での登場順番との組合せにより決定されるものとしている。従って、「SUM(A)」および「SUM(Q)」は「SUM  TINY １」に置き換えられている。また、「SUM(N(51:100))」は「SUM  TINY ２」に置き換えられている。そして、手続コードＡ及び手続コードＢは、それぞれ「SUM  TINY １」及び「SUM  TINY ２」により呼び出されることになる。
【００９２】
このように、コンパイラ４０によれば、互いに同じ変換すべき対象が同一ファイル内に存在する場合、それらにより共有される手続コードが生成される。このため、生成した手続コードをオブジェクトプログラムと同じファイルに出力するようにすれば、ファイルの取り扱いが簡単になる。例えば、入力ファイルのファイル名が「tiny.f」であるときは、出力ファイルのファイル名を「tiny.o」とする。そして、そのファイルにオブジェクトプログラムおよび手続コードの双方を出力する。
【００９３】
図２２は、本発明のさらに他の形態のコンパイラの機能ブロック図である。コンパイラ５０は、複数のファイルが一括して入力されることを考慮し、入力された複数のファイルに存在する互いに同じ変換すべき対象を同一の手続呼出に変換すると共に、その手続呼出に対して１つの手続コードを生成する。この手続コードは、複数のファイルにより共通化され、複数の手続呼出により共有的に呼び出される。
【００９４】
上記機能を実現するために、重複判定部５１は、複数の入力ファイル中に重複する変換すべき対象が存在するか否かを調べ、その判定結果を変換部１２および展開部１３に通知する。この通知を受けた変換部１２および展開部１３の動作は、基本的に、図１０を参照しながら説明した通りである。
【００９５】
リンク編集部２３は、既存の一般的なプログラムにより実現可能であり、コンパイル済みのコードとデータファイルとをリンクさせることにより実行可能プログラムを生成するプログラムである。１つのファイルは、一般に１つ以上のプログラム単位（サブルーチンや関数等）を含み、１つの実行可能ファイルは、１つ以上のファイルのソースコードをコンパイルし、それらをリンク編集して作成される。また、リンク編集部２３は、ライブラリの生成機能も持っている。
【００９６】
図２３は、図２２に示したコンパイラの動作を説明するためのフローチャートである。ここでは、コンパイラ５０に入力される複数のソースファイルをファイルＦ1 ,....,Ｆs 、コンパイラ５０によりコンパイルされたオブジェクトファイルをファイルＦ' 1,...., Ｆ' s と呼ぶことにする。また、各ソースファイルは、それぞれ１以上のソースプログラムを含むものとする。なお、図２３に示す処理は、一連の複数のソースファイルが入力されるごとに実行される。
【００９７】
ステップＳ３１〜Ｓ４０の各処理は、基本的に、図１１に示したステップＳ１１〜Ｓ２０とそれぞれ同じである。ただし、ステップＳ３１〜Ｓ４０では、一連の複数のファイルを単位として処理が行われる。すなわち、ステップＳ３２では、ファイルＦ1 ,....,Ｆs に含まれている複数のソースプログラムから変換すべき対象が検出される。また、ステップＳ３５では、変換すべき対象に対して一連のファイルＦ1 ,....,Ｆs 内でユニークな名前を生成する。なお、出力ファイルをユーザが扱う通常のファイルとする場合には、オブジェクトコードと手続コード（オンラインコード）とが対応付けられる。
【００９８】
コンパイラ５０は、ファイルＦ1 ,....,Ｆs が入力されると、上記ステップＳ３１〜Ｓ４０の処理を実行することにより、各変換すべき対象がそれぞれ手続の呼出に置き換えられたオブジェクトプログラムを生成し、これらのオブジェクトプログラムを含むファイルＦ' 1,...., Ｆ' s を出力する。また、コンパイラ５０は、各手続の呼出にそれぞれ対応する手続コードを生成し、これらの手続コードを共通ファイルＦ0 に出力する。
【００９９】
なお、手続コードは、生成される毎に、順次、１つずつ出力してもよいし、プログラム単位の処理が終了する毎あるいはファイル単位の処理が終了する毎に出力してもよい。また、手続コードは、オブジェクトファイルを含むファイルと同じファイルに出力してもよい。また、コンパイラ５０は、出力ファイルを一時ファイルとして管理し、リンク編集処理をも行うことによって実行ファイルを生成してもよい。
【０１００】
このように、コンパイラ５０によれば、複数のソースファイル内に存在する互いに重複した変換すべき対象に対して、重複して手続コードを生成することなく、必要最小限の手続コードを生成するので、コンパイラの総出力コード量がさらに減少する。
【０１０１】
次に、具体的な実施例を説明する。以下では、コンパイラ５０に対して図２４に示す２つのソースファイル（tiny1.f およびtiny2.f ）が入力された場合を想定し、関数SUM の呼出を変換対象として説明する。なお、コンパイラ５０は、図８に示したテンプレートを利用するものとする。
【０１０２】
ソースファイルが入力されると、コンパイラ５０は、ファイルtiny1.f に含まれているプログラム（メインプログラム）、およびファイルtiny2.f に含まれているプログラム（サブプログラム）をスキャンすることにより関数SUM の呼出を検出する。図２４に示す例においては、関数SUM は、ファイルtiny1.f の「SUM(A)」及び「SUM(N(51:100))」、およびファイルtiny2.f 「SUM(Q)」により呼ばれていることが検出される。
【０１０３】
続いて、コンパイラ４０は、検出した各変換すべき対象の特徴（引数の型、引数の次元数など）に基づいて、生成すべき手続コードが同一になるものが存在するか否かを調べる。ここでは、「SUM(A)」および「SUM(Q)」の特徴が互いに同じである。従って、「SUM(A)」および「SUM(Q)」に対しては、これらにより共有される１つの手続コードが生成される。なお、「SUM(N(51:100))」に対しては、１つの独立した手続コードが生成される。
【０１０４】
図２５は、図２４に示すソースファイルが入力されたときのコンパイラ５０の出力である。ここでは、呼出の名前は、手続の名前と、一連の複数の入力ファイルの中での登場順番との組合せにより決定されるものとしている。したがって、「SUM(A)」及び「SUM(Q)」は「SUM  １」に置き換えられている。また、「SUM(N(51:100))」は「SUM  ２」に置き換えられている。そして、手続コードＡおよび手続コードＢは、それぞれ「SUM  １」及び「SUM  ２」により呼び出されることになる。
【０１０５】
このように、コンパイラ５０は、手続コードは同時にコンパイルされる一連のファイルにより共有される。なお、リンク編集処理では、オブジェクトファイルにおいて手続コードが格納されているファイルが指定される。このリンク処理は、コンパイラ５０により実行されてもよいし、あるいは、図２２に示した構成のように、コンパイラとは別のモジュールにより実行されてもよい。コンパイラによりリンク編集処理が実行される場合には、手続コードを一時ファイルに格納し、コンパイル後にその一時ファイルを削除するようにすれば、ソースとの対応付けにおいて問題が生じにくくなる。
【０１０６】
上記実施例では、変換すべき対象として「関数SUM 」を採り上げたが、他の関数やサブルーチンなどであっても同様に処理される。以下では、図５に示したコンパイラ１０に図２６Ａに示すソースプログラムが入力された場合を想定し、「Ａ＊＊Ｎ」を変換すべき対象とする。「Ａ＊＊Ｎ」は、「ＡのＮ乗」を表す。ここで、「Ａ」は、実数型、複素数型、または整数型のスカラであり、「Ｎ」は、整数型のスカラであるものとする。
【０１０７】
コンパイラ１０は、ソースプログラムから「Ａ＊＊Ｎ」を検出すると、それを「ＰＯＷ（Ａ，Ｎ）」に変換することによりオブジェクトプログラムを生成すると共に、「ＰＯＷ（Ａ，Ｎ）」により呼び出されるべき手続コード（オンラインコード）を出力する。この手続の定義は、例えば、「Ｎが３以下のときに掛け算を実行し、Ｎが３よりも大きいときには巾乗演算を実行する。」である。
【０１０８】
コンパイラ１０は、「ＰＯＷ（Ａ，Ｎ）」に対応する手続コードを生成する際、以下の３つの特徴を参照する。
特徴１：Ａの型
特徴２：Ｎの値が得られるか否か
特徴３：Ｎの値が得られたとき、その値
コンパイラ１０は、「ＰＯＷ（Ａ，Ｎ）」に対応する手続コードを生成する際に利用するサンプルデータとして図２７Ａ〜図２７Ｄ、および図２８Ａおよび図２８Ｂに示すテンプレートを備える。これらのテンプレートでは、上記特徴１が抽象化されている。
【０１０９】
図２７Ａに示すテンプレートは、「Ｎ」が「０」の場合に対応して記述されている。すなわち、「Ｎ＝０」の場合は、「Ａの０乗」は常に「１」なので、テンプレートには予め「Ｒ＝１」が記述されている。
【０１１０】
図２７Ｂ〜図２７Ｄに示す各テンプレートは、それぞれ「Ｎ」が「１」から「３」の場合に対応して記述されている。ここでは、「Ｎが小さいときには、巾乗演算を実行するよりも掛け算を実行した方が有利である」という前提に立ち、各テンプレートには、それぞれ掛け算式（「Ｒ＝Ａ」「Ｒ＝Ａ＊Ａ」および「Ｒ＝Ａ＊Ａ＊Ａ」）が予め記述されている。
【０１１１】
図２８Ａに示すテンプレートは、「Ｎ」が３よりも大きい場合に対応して記述されている。即ち、テンプレートには、巾乗演算式（「Ｒ＝Ａ＊＊Ａ」）が予め記述されている。
図２８Ｂに示すテンプレートは、ソースプログラムがコンパイルされる際に「Ｎ」の値が不明である場合に対応して記述されている。この場合、テンプレートには、「Ｎ」の値が決まった時点でその値に対応する演算式が選択されるような記述となっている。
【０１１２】
コンパイラ１０は、ソースプログラムが入力されると、各行をサーチすることにより「Ａ＊＊Ｎ」という表現を検出する。図２６Ａに示すプログラムが入力された場合、４行目の「２＊＊LEN 」および５行目の「（Ｒ＊２）＊＊２」が検出される。
【０１１３】
まず、「２＊＊LEN 」がオンライン展開される。「２＊＊LEN 」は、プログラムSUBROUTINEの中で最初に登場した変換すべき対象なので、「POW ＿SUBP＿1 」という名前が割り当てられる。続いて、上述した変換規則に従って以下の変換を行う。
【０１１４】
REAL::S(2**LEN-1) →  REAL::S(POW  SUBP 1(2,LEN)-1)
そして、引数を解析することによって以下の情報を得る。
特徴１：型＝INTEGER
特徴２：Ｎの値は得られず
特徴３：なし
コンパイラ１０は、上記得られた情報により適切なテンプレートを選択してオンラインコードを生成する。すなわち、ここでは、「Ｎ」の値が得られていないので、図２８Ｂに示したテンプレートが選択され、図２６Ｂに示すオンラインコードＡが生成される。
【０１１５】
同様に、「（Ｒ＊２）＊＊２」がオンライン展開される。「（Ｒ＊２）＊＊２」は、プログラムSUBROUTINEの中で第２番目に登場した変換すべき対象なので、「POW  SUBP ２」という名前が割り当てられ、以下の変換が行われる。
【０１１６】
M=PAI*(R*2)**2  →  M=PAI*POW  SUBP 2((R*2),2)
そして、引数を解析することによって以下の情報を得る。
特徴１：型＝REAL
特徴２：Ｎの値は得られた
特徴３：Ｎ＝２
コンパイラ１０は、上記得られた情報に従って図２７Ｃに示すテンプレートを選択し、図２６Ｂに示すオンラインコードＢを生成する。そして、コンパイラ１０は、オブジェクトプログラムと共に、オンラインコードＡおよびＢを出力する。
【０１１７】
なお、プログラムの実行時にオンラインコードを呼び出すためのオーバーヘッドを減少させるためには、本実施例のコンパレータで生成したオンラインコードを後続のコンパイラ（オブジェクト言語が機械後又はアセンブラ等であるコンパイラ）によりインライン展開してもよい。インライン展開は、上述したように、プリプロセッサ方式のコンパイラで高級言語を対象とすると問題が生じることが多いが、オブジェクト言語が機械後又はアセンブラ等である通常のコンパイラでは、問題なくインライン展開を実行できることが多い。
【０１１８】
上記コンパイラの機能は、コンピュータを用いて図６、図１１、図１９、または図２３のフローチャートに示した処理を記述したプログラムを実行することにより実現される。そのプログラムを実行するコンピュータ６０のブロック図を図２９に示す。
【０１１９】
ＣＰＵ６１は、図６、図１１、図１９、または図２３のフローチャートに示した処理を記述したプログラムを記憶装置６２からメモリ６３にロードして実行する。記憶装置６２は、例えばハードディスクであり、上記プログラム、および各種テンプレートを格納する。一方、メモリ６３は、例えば半導体メモリであり、ＣＰＵ６１の作業領域として使用される。図１３Ａなどに示した管理テーブルは、このメモリ６３に作成される。
【０１２０】
記憶媒体ドライバ６４は、ＣＰＵ６１の指示に従って可搬性記憶媒体６５にアクセスする。可搬性記憶媒体６５は、半導体デバイス（ＩＣカード等）、磁気的作用により情報が入出力される媒体（フロッピーディスク、磁気テープなど）、光学的作用により情報が入出力される媒体（光ディスクなど）を含む。通信制御装置６６は、ＣＰＵ６１の指示に従って網との間でデータを送受信する。
【０１２１】
図３０は、本発明に係わるソフトウェアプログラムなど（テンプレートを含む）の提供方法を説明する図である。本発明に係わるプログラムは、例えば、以下の３つの方法の中の任意の方法により提供される。
【０１２２】
(a) コンピュータ６０にインストールされて提供される。この場合、プログラム等は、たとえば、出荷前にプレインストールされる。
(b) 可搬性記憶媒体に格納されて提供される。この場合、可搬性記憶媒体６５に格納されているプログラム等は、基本的に、記憶媒体ドライバ６４を介して記憶装置６２にインストールされる。
【０１２３】
(c) 網上のサーバから提供される。この場合、基本的には、コンピュータ６０がサーバに格納されているプログラム等をダウンロードすることによってそのプログラム等を取得する。
【０１２４】
このように、本実施例のコンパイラは、プリプロセッサ方式であっても、ソースプログラム中における変換すべき対象の出現位置に係わらず、その変換すべき対象を容易に展開することができる。
【０１２５】
また、手続呼出をインライン展開できる場合であっても、総出力コード量、およびコンパイル時間の点で本実施例のコンパイラの方が有利である。
(a) 出力コードの総量
図１０、図１８、および図２２に示したコンパイラによれば、互いに同種の変換すべき対象が複数存在する場合には、それらに対して１つのオンラインコードが生成され、複数の手続呼出によりその生成されたオンラインコードが共有的に呼び出されるので、オブジェクトの総量が小さくなる。なお、図５に示したコンパイラの出力の総量は、インライン展開の場合のそれと比較して同程度である。
(b) コンパイル時間
一般に、コンパイラ内での最適化処理に要する時間は、コンパイル単位（１つの関数やサブルーチン等）の大きさの２乗〜３乗に比例することが多い。このため、コンパイル単位のコード量が数倍になると、最適化のための処理時間は数十倍になることがある。
【０１２６】
図５に示したコンパイラによれば、上述したように、出力コードの総量はインライン展開の場合と同程度だが、展開コード（オンラインコード）は独立したコンパイル単位として分割されて生成されるため、全体のコンパイル時間が短縮される。
【０１２７】
また、図１０、図１８、および図２２に示したコンパイラの場合は、生成されるオンラインコードの数が減少するので、コンパイル時間はさらに短縮される。
さらに、本実施例のコンパイラを使用した場合、オンライン展開後、入力コードのコンパイルをオンラインコードのコンパイルよりも先に実行するようにすれば、入力コードのエラーを速く検出することができる。インライン展開を使用した場合には、入力コードが大きくなるので、エラー検出に長い時間を要することが予想される。
【産業上の利用可能性】
【０１２８】
本発明は、プリプロセッサ方式のコンパイラとして広く利用され得る。
【図面の簡単な説明】
【０１２９】
【図１】図１Ａおよび図１Ｂは、従来のコンパイラによってインライン展開できない例（その１）である。
【図２】図２Ａおよび図２Ｂは、従来のコンパイラによってインライン展開できない例（その２）である。
【図３】図３Ａおよび図３Ｂは、従来のコンパイラによってインライン展開が複雑になる例である。
【図４】本実施例のコンパイラの概略動作の一例を説明する図である。
【図５】本実施例のコンパイラの機能ブロック図である。
【図６】図５に示したコンパイラの動作を説明するためのフローチャートである。
【図７】図７Ａは図５に示したコンパイラへの入力コードの例であり、図７Ｂは図５に示したコンパイラからの出力コードの例である。
【図８】関数SUM を展開するためのテンプレートの例である。
【図９】図９Ａおよび図９Ｂは、テンプレートを用いて関数SUM を展開した結果を示す図である。
【図１０】本発明の他の形態のコンパイラの機能ブロック図である。
【図１１】図１０に示したコンパイラの動作を説明するためのフローチャートである。
【図１２】図１２Ａは図１０に示したコンパイラへの入力コードの例であり、図１２Ｂは図１０に示したコンパイラからの出力コードの例である。
【図１３】図１３Ａ〜図１３Ｄは重複判定において使用する管理テーブルを説明する図である。
【図１４】関数SUM を展開した結果を示す図である。
【図１５】抽象度の高い表現で作成したテンプレートの例である。
【図１６】図１５に示すテンプレートを用いて変換すべき対象を展開する際に比較されるパラメータを示す図である。
【図１７】図１５に示すテンプレートを用いた場合のコンパイラの出力を示す図である。
【図１８】本発明の更に他の形態のコンパイラの機能ブロック図である。
【図１９】図１８に示したコンパイラの動作を説明するためのフローチャートである。
【図２０】図１８に示したコンパイラへの入力コードの例である。
【図２１】図１８に示したコンパイラからの出力コードの例である。
【図２２】本発明の更に他の形態のコンパイラの機能ブロック図である。
【図２３】図２２に示したコンパイラの動作を説明するためのフローチャートである。
【図２４】図２２に示したコンパイラへの入力コードの例である。
【図２５】図２２に示したコンパイラからの出力コードの例である。
【図２６】図２６Ａは入力コードの例であり、図２６Ｂは図２６Ａに示す入力コードに対応する出力の例である。
【図２７】図２７Ａ〜図２７Ｄテンプレートの例である。
【図２８】図２８Ａ、および図２８Ｂはテンプレートの例である。
【図２９】本発明に係わるソフトウェアプログラムを実行するコンピュータのブロック図である。
【図３０】本発明に係わるソフトウェアプログラムの提供方法を説明する図である。
【図１Ａ】
0003762867.tif 000002
【図１Ｂ】
0003762867.tif 000003
【図２Ａ】
0003762867.tif 000004
【図２Ｂ】
0003762867.tif 000005
【図３Ａ】
0003762867.tif 000006
【図３Ｂ】
0003762867.tif 000007
【図４】
0003762867.tif 000008
【図５】
0003762867.tif 000009
【図６】
0003762867.tif 000010
【図７Ａ】
0003762867.tif 000011
【図７Ｂ】
0003762867.tif 000012
【図８】
0003762867.tif 000013
【図９Ａ】
0003762867.tif 000014
【図９Ｂ】
0003762867.tif 000015
【図１０】
0003762867.tif 000016
【図１１】
0003762867.tif 000017
【図１２Ａ】
0003762867.tif 000018
【図１２Ｂ】
0003762867.tif 000019
【図１３Ａ】
0003762867.tif 000020
【図１３Ｂ】
0003762867.tif 000021
【図１３Ｃ】
0003762867.tif 000022
【図１３Ｄ】
0003762867.tif 000023
【図１４】
0003762867.tif 000024
【図１５】
0003762867.tif 000025
【図１６】
0003762867.tif 000026
【図１７】
0003762867.tif 000027
【図１８】
0003762867.tif 000028
【図１９】
0003762867.tif 000029
【図２０】
0003762867.tif 000030
【図２１】
0003762867.tif 000031
【図２２】
0003762867.tif 000032
【図２３】
0003762867.tif 000033
【図２４】
0003762867.tif 000034
【図２５】
0003762867.tif 000035
【図２６Ａ】
0003762867.tif 000036
【図２６Ｂ】
0003762867.tif 000037
【図２７Ａ】
0003762867.tif 000038
【図２７Ｂ】
0003762867.tif 000039
【図２７Ｃ】
0003762867.tif 000040
【図２７Ｄ】
0003762867.tif 000041
【図２８Ａ】
0003762867.tif 000042
【図２８Ｂ】
0003762867.tif 000043
【図２９】
0003762867.tif 000044
【図３０】
0003762867.tif 000045