2009年07月03日

gccのビルトイン関数 (printf)

gccのtipsを紹介します。主にgcc3.x からgcc4.x で変わっているところです。

#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
}

このプログラムはgcc3では普通にprintfを呼び出すコードを生成しますが、gcc4ではどうなるでしょうか。ARM版のexeGCC4でちょっと試してみます。



> gcc -S hello.c

生成されたhello.s を見てみると

        ...
.LC0:
	.ascii	"Hello, world!\000"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
	@ args = 0, pretend = 0, frame = 8
	@ frame_needed = 0, uses_anonymous_args = 0
	str	lr, [sp, #-4]!
	sub	sp, sp, #12
	ldr	r0, .L3
	bl	puts
	add	sp, sp, #12
	ldmfd	sp!, {pc}

printfでなくてputsが呼ばれています。これはgccがprintfがどういう関数かを知っていて、

引数が一つしかなくて、なおかつその引数の文字列が改行で終わっている時はputsに

置き換えているのです。このようにgccが知っている関数をビルトイン関数と呼びます。

ビルトイン関数の最適化は、特に -O オプションをつけなくても行われます。

逆にこれをやってほしくない場合には -fno-builtin オプションをつけます。

特定のビルトイン関数だけを無効にする場合は -fno-builtin-<関数名> とします。

例えば printf のビルトイン関数を無効にするには -fno-builtin-printf です。

ちょっと試してみましょう。

> gcc -S -fno-builtin-printf hello.c
        ...
.LC0:
	.ascii	"Hello, world!\012\000"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
	@ args = 0, pretend = 0, frame = 8
	@ frame_needed = 0, uses_anonymous_args = 0
	str	lr, [sp, #-4]!
	sub	sp, sp, #12
	ldr	r0, .L3
	bl	printf
	add	sp, sp, #12
	ldmfd	sp!, {pc}

今度はそのままprintfが呼ばれるコードが生成されました。

プログラムをちょっと変更してみます。

#include <stdio.h>

int main()
{
    printf("Hello, world!");
    printf("\n");
}

これをまたexegcc4 でコンパイルしてコードを見てみます。

> gcc -S hello2.c
        ...
.LC0:
	.ascii	"Hello, world!\000"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
	@ args = 0, pretend = 0, frame = 8
	@ frame_needed = 0, uses_anonymous_args = 0
	str	lr, [sp, #-4]!
	sub	sp, sp, #12
	ldr	r0, .L3
	bl	printf
	mov	r0, #10
	bl	putchar
	add	sp, sp, #12
	ldmfd	sp!, {pc}

ひとつめのprintfは引数が一つですが、それが改行で終わっていないために、putsにならずにそのままprintfが呼ばれるコードになりました。

ふたつめのprintfは引数が一つで、一文字だけなのでputchar に変換されました。

このようにgcc4ではとりあえずprintfで書いておけば、コンパイラが適切に置き換えてくれます。

(追記)

このあたりのprintfの変換はgccのソースコード

gcc/builtins.c の関数fold_builtin_printf

をみるとわかります。

フォーマットが "%s\n" のときにputsに変換とか、"%c"のときにputcharに変換するパターンもあるようです。



トラックバックURL

コメント一覧

1. Posted by n   2009年07月15日 23:37
以下が気になりました。
-libcに改行なしのputsが無い
-gccが二つ以上のprintfやputs、putcharの合成をしない
何か理由があるのかな
2. Posted by 管理者   2009年07月17日 09:51
管理者です。koba さんが追記記事を書いてくださいました。
ご参考までに。

http://blog.kmckk.com/archives/1118756.html

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード