15

stdinLLVMで、、、stoutおよびstderr(できれば C バージョン) をどのように宣言しますか? 私が作成しているおもちゃの言語でいくつかの stdio 関数を使用しようとしています。そのような関数の 1 つが次のfgetsとおりです。

char * fgets ( char * str, int num, FILE * stream );

それを使用するには、 が必要でしstdinた。そこで、見つけた FILE の定義を生成する LLVM API コードを書きstdin、外部グローバルを宣言しました。コードはこれを生成しました:

%file = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %marker*, %file*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] }
%marker = type { %marker*, %file*, i32 }

@stdin = external global %file*

ただし、結果のモジュールを実行すると、次のエラーが発生しました。

Undefined symbols for architecture x86_64:
"_stdin", referenced from:
    _main in cc9A5m3z.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

どうやら、私が書いたものはうまくいかなかったようです。だから私の質問は、おもちゃの言語コンパイラのような関数のstdinstout、およびを宣言するために、LLVM API に何を書かなければならないかということです。stderrfgets

4

3 に答える 3

11

誰かが興味を持っているなら、私は私の質問に対する答えを見つけました. いくつかの激しい検索の後stdin、C 拡張を作成せずにストリームを取得する方法を見つけました。それは、不透明な構造体fdopenを作成することです。FILE

FILE* fdopen (int fildes, const char *mode)

ファイル記述子 ( ) に対して fdopen が 0 を渡された場合、ストリームfildesを返します。stdinLLVM API を使用して、次の LLVM アセンブリを生成しました。

%FILE = type opaque
declare %FILE* @fdopen(i32, i8*)
@r = constant [2 x i8] c"r\00"

stdin次に、この call ステートメントで取得できました。

%stdin = call %FILE* @fdopen(i32 0, i8* getelementptr inbounds ([2 x i8]* @r, i32 0, i32 0))
于 2012-06-03T17:54:38.053 に答える
4

putchar、、、、、などの関数を使用する場合は、printfgetsは必要ありません。私はおもちゃのコンパイラを書きました、そしてそれらは文字列と整数でのI/Oのために十分でした。nullで呼び出され、フラッシュされます。strtolputsfflushstdinstdoutfflushstdout

%struct._IO_FILE = type opaque
declare i32 @fflush(%struct._IO_FILE*)
...
call i32 @fflush(%struct._IO_FILE* null)
...
于 2012-10-18T11:54:50.837 に答える
1

プラットフォーム固有です。stdin が別のシンボル名へのマクロである場合があります。

たとえば、Android では stdin は#define stdin (&__sF[0]).

Microsoft Visual C++ の場合、stdin は#define stdin (&__iob_func()[0])

stdio.hしたがって、それを理解するには、プラットフォームのヘッダーを調べる必要があります。

于 2012-06-03T04:23:35.773 に答える