2017-04-09 10 views
0

私はLLVMチュートリアルの万華鏡に従っています。今、私はPascalに似た言語のためにこのフロントエンドコンパイラをexternしようとしています。私はこのコードを持っている:LLVM 'ret'の指示

program main; 

function rett(): integer; 
begin 
    rett := 1; 
    exit; 
    rett := 5; 
end; 

var a: integer; 
begin 
    a := rett();  
    writeln(a); 
end. 

このプログラムの出力は、単一の整数であるべきである「1」、なぜならexitコマンドの(したがって線rett := 5;を実行することshould'n)。しかし、出力は '5'です。この入力に対して、私はこのLLVM IRを生成しています:

define i32 @rett() { 
entry: 
    %rett = alloca i32 
    store i32 0, i32* %rett 
    store i32 1, i32* %rett 
    %rett1 = load i32, i32* %rett 
    ret i32 %rett1 
    store i32 5, i32* %rett 
    %rett2 = load i32, i32* %rett 
    ret i32 %rett2 
} 

define i32 @main() { 
entry: 
    %a = alloca i32 
    %main = alloca i32 
    store i32 0, i32* %main 
    store i32 0, i32* %a 
    %calltmp = call i32 @rett() 
    store i32 %calltmp, i32* %a 
    %a1 = load i32, i32* %a 
    %calltmp2 = call i32 (i8*, ...) @printf([4 x i8]* @.str, i32 %a1) 
    %main3 = load i32, i32* %main 
    ret i32 %main3 
} 

なぜ最初の 'ret'コマンドを実行しないのですか?私は何が欠けているのですか?


更新:ドキュメンテーションにおいて 書き込み:

各基本ブロックは、必要に応じて(基本ブロックにシンボル・テーブル・エントリを与える)ラベルで開始することができる、命令のリストを含み、そしてターミネータ命令(分岐や関数の復帰など)で終了します。

"ターミネーター"命令は、基本ブロックの最後でのみ使用できますか?そしてもしそうなら、私はどのように私の言語の復帰とブレークコマンドを実装する必要がありますか?

答えて

0

私は問題を再現できませんでしたが(あなたの出力例1)、とにかく質問に回答します。

"ターミネーター"命令は、基本ブロックの最後にしか使えないということですか?

これは正しいです。

CFG for @rett

そして、どのように私はリターンを実装し、私の言語のためのコマンドを破る必要がありそうであれば:実際には、optはあなたの例では@rett機能は、これら2つの基本的なブロックで構成されていることを示していますか?

retおよびbrである。

基本ブロック内にターミネータを生成する必要はありません。これまでの説明は実行されないため、生成しない可能性があります。

+0

ありがとうございます。 –