MacでClang(ARM用)

昨日Mac OS X 10.6.5上でClangを使って、Intel x86用のコンパイルを行いました。


今日はMac OS X 10.6.5上でClangを使って、iOS 3.0以上&ARM Cortex-A8用のコンパイルを行います。
手探りでコンパイルできた状況をメモと残したものです。ARMアセンブリは昨日始めたばかりだし、実機上で動作確認できないので、間違ってる可能性大です。そのつもりでご覧下さい。


まずGCCコンパイルする方法です。

$ /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/arm-apple-darwin10-gcc-4.2.1 -I/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/include/ -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/lib -mcpu=cortex-a8 -miphoneos-version-min=3.0 hello.c -O3

生成する中間アセンブリ言語ソースはこんな感じです。_putsをコールするためのベニアが生成されています。

        .cstring
        .align 2
LC0:
        .ascii "Hello world\0"
        .text
        .align 2
        .globl _main
        .thumb
        .thumb_func _main
_main:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 1, uses_anonymous_args = 0
        push    {r7, lr}
        add     r7, sp, #0
        ldr     r0, L4
L2:
        add     r0, pc
        blx     L_puts$stub
        movs    r0, #0
        pop     {r7, pc}
        .p2align 2
L5:
        .align 2
L4:
        .long   LC0-4-(L2)
        .section __TEXT,__picsymbolstub4,symbol_stubs,none,16
        .align 2
        .code 32
L_puts$stub:
        .indirect_symbol _puts
        ldr     ip, L_puts$slp
L1$scv: add     ip, pc, ip
        ldr     pc, [ip, #0]
L_puts$slp:
        .long   L_puts$lazy_ptr - (L1$scv + 8)
        .lazy_symbol_pointer
L_puts$lazy_ptr:
        .indirect_symbol        _puts
        .long   dyld_stub_binding_helper
        .subsections_via_symbols


次にClangでコンパイルする方法です。

$ /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang -I/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/include/ -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/lib -arch armv7 -mcpu=cortex-a8 -miphoneos-version-min=3.0 hello.c -O3

生成する中間アセンブリ言語ソースはこんな感じです。_pusをコールするためのベニアが生成されてません。

        .globl  _main
        .align  2
        .code   16
        .thumb_func     _main
_main:
        push    {r7, lr}
        ldr.n   r0, LCPI0_0
        mov     r7, sp
        
LPC0_0:
        add     r0, pc
        blx     _puts
        movs    r0, #0
        mov     sp, r7
        pop     {r7, pc}
        .align  2
LCPI0_0:
        .long   _str-(LPC0_0+4)
         

        .section        __TEXT,__cstring,cstring_literals
        .align  2
_str:
        .asciz   "Hello world"


気付いた違いをまとめると...

  • ARMの場合、分岐命令で指定できる即値アドレスの範囲が小さいので、必要ならベニアを生成して二段階で分岐する必要があります。GCCアセンブリの出力段階でベニアを生成し、Clangはリンカの配置段階でベニアを生成するようです。
  • GCCの方はSPレジスタをリストアしてません。_puts呼び出し後には上位を含めてSPレジスタを使用しないので、そこまで見越したということかも知れません。


今はお金がないので無理ですが、そのうちiOS Developer Programを購入したら実機で確認したいと思います。


                                    以上です。