FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LLVMのバックエンドを作るための第一歩 (42. LLVM IRをサポートするためのIntrinsicsを実装する)

f:id:msyksphinz:20190425001356p:plain

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