FPGA開発日記

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

LLVMのバックエンドを作るための第一歩 (18. emitPrologue, emitEpilogue)

f:id:msyksphinz:20190425001356p:plain

最終的に関数をコンパイルして命令を出力するためには、関数のプロローグ・エピローグを生成する必要がある。 関数のプロローグは関数に入った時の最初に行う処理、関数のエピローグは関数から出るときに最後に行う処理である。

基本的には

  • Callee Saved Registerの退避
  • スタックポインタの移動

が必要になる。これらを実行するのが、LLVM

  • MYRISCVXSEFrameLowering::emitPrologue()
  • MYRISCVXSEFrameLowering::emitEpilogue()

である。それぞれについて内部の実装を確認していく。

MYRISCVXSEFrameLowering::emitPrologue()

emitPrologueは関数のエピローグのコードを生成する。

  • llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXSEFrameLowering.cpp
void MYRISCVXSEFrameLowering::emitPrologue(MachineFunction &MF,
                                           MachineBasicBlock &MBB) const {

引数としては2つ用意されている。MachineFunction MFは変換対象となる関数の実体で、関数内部のBasicBlockなどを含んでいる。 MachieBasicBlockのインスタンスのリストを含んでおり、MachineFunctionにはMachineControlPool, MachineFrameInfo, MachineFunctionInfo, MachineRegisterInfoクラスが含まれている。

MachineBasicBlock MBBは変換後のBasicBlockだ。MachineBasicBlockにはマシン命令のリストであるMachineInstrのリストが含まれている。

実際には、EmitPrologue内では関数内で使用されるスタックのサイズを計算し、そのその分だけスタックポインタの量を調整する。

  • llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXSEFrameLowering.cpp
void MYRISCVXSEFrameLowering::emitPrologue(MachineFunction &MF,
                                           MachineBasicBlock &MBB) const {
...
  // First, compute final stack size.
  uint64_t StackSize = MFI.getStackSize();

  // No need to allocate space on the stack.
  if (StackSize == 0 && !MFI.adjustsStack()) return;

  MachineModuleInfo &MMI = MF.getMMI();
  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();

  // Adjust stack.
  TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
...

また、EmitEpilogueではその逆で、関数内のスタックサイズの分だけスタックポインタを元に戻す。

  • llvm-myriscvx/lib/Target/MYRISCVX/MYRISCVXSEFrameLowering.cpp
//@emitEpilogue {
void MYRISCVXSEFrameLowering::emitEpilogue(MachineFunction &MF,
                                           MachineBasicBlock &MBB) const {
...
  unsigned SP = MYRISCVX::SP;

  // Get the number of bytes from FrameInfo
  uint64_t StackSize = MFI.getStackSize();

  if (!StackSize)
    return;

  // Adjust stack.
  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
...