LLVM IRをサポートするためのIntrinsicsのサポート
LLVM IRには、いくつかの特殊な構文が存在し、これらをサポートすることでより多くのコードを生成できるようになる。 これらについては、clang側からIntrinsic関数を呼び出すことでLLVM IRを生成し、llcに渡してテストすることができる。
FRAMEADDR
関数のフレームポインタを取得する。C言語では、__builtin_frame_address()
により取得することができる。
int display_frameaddress() { return (int)__builtin_frame_address(0); }
- コンパイル結果
_Z20display_frameaddressv: .cfi_startproc .frame $x8,0,$x1 .mask 0x00000000,0 .set noreorder .set nomacro # %bb.0: # %entry addi x11, zero, 0 addi x10, x8, 0 ret x1
RETURNADDR
関数の戻りアドレスを取得する。C言語では、__builtin_return_address()
により取得することができる。
extern int fn(); int display_returnaddress() { int a = (int)__builtin_return_address(0); fn(); return a; }
- コンパイル結果
addi x2, x2, -16 .cfi_def_cfa_offset 16 sw x2, 12(x2) # 4-byte Folded Spill ... lw x2, 12(x2) # 4-byte Folded Reload addi x2, x2, 16 ret
BSWAP
データのビットスワップを行う。C言語では、__builtin_bswap16
, __builtin_bswap32
, __builtin_bswap64
により取得することができる。これらはそのまま命令に落とし込めないので、IRの生成を抑制する。
int test_bswap16() { volatile int a = 0x1234; int result = (__builtin_bswap16(a) ^ 0x3412); return result; } int test_bswap32() { volatile int a = 0x1234; int result = (__builtin_bswap32(a) ^ 0x34120000); return result; } int test_bswap64() { volatile int a = 0x1234; int result = (__builtin_bswap64(a) ^ 0x3412000000000000); return result; } int test_bswap() { int result = test_bswap16() + test_bswap32() + test_bswap64(); return result; }
BSWAPのコンパイル結果。
_Z12test_bswap16v: .cfi_startproc .frame $x8,8,$x1 .mask 0x00000000,0 .set noreorder .set nomacro # %bb.0: # %entry addi x2, x2, -8 .cfi_def_cfa_offset 8 ori x10, zero, 4660 sw x10, 4(x2) lw x10, 4(x2) xori x10, x10, 564 slli x11, x10, 8 lui x12, 4080 and x11, x11, x12 slli x10, x10, 24 or x10, x10, x11 srli x10, x10, 16 addi x2, x2, 8 ret x1