컴파일러

[컴파일러/LLVM] 2. Module, Function, Basic Block 순회하며 Instruction 출력하기

용성군 2021. 8. 1. 10:24
728x90
반응형

 

이번 글에서LLVM의 기본적인 Module 구조를 보고, IR파일 내의 명령어들을 출력해보도록 하겠다.

Module은 하나의 IR 파일이라고 생각하면 편하다. 그리고 LLVM IR에서는 llvm::Module -> llvm::Function -> llvm::BasicBlock -> llvm::Instruction의 계층구조로 IR 프로그램을 관리한다.

 

출처 : https://deepai.org/publication/an-llvm-instrumentation-plug-in-for-score-p

 

Module은 여러 개의 Function으로 구성되어 있고, Function은 다시 여러 개의 Basic Block 으로 구성되어 있으며, Basic Block Instruction로 구성되어 있다.

  • Module = 모듈, 일반적으로 하나의 소스 파일
  • Function = 함수
  • Basic Block = BranchReturn같은 제어 명령어로 끝남(다른 위치로 이동하지 않고 순서대로 실행되는 코드의 Block들을 의미)
  • Instruction = 명령어

다음 그림은 빨간색은 Module, 진한 파란색은 Function, 초록색은 Basic Block, 하늘색은 Instruction을 의미한다.

전역 변수를 나타내는 llvm::GlobalVariable와 Metadata 등은 llvm::Module 내에서 따로 관리된다.


명령어 출력

IR파일은 계층구조로 되어있기 때문에 3중 for문을 이용해서 명령어에 접근한다. 첫번째는 Module, 두번째 Function을 iterator로 접근한다. 

llvm::raw_os_ostream raw_cout( std::cout );
// Module::iterator --> Function
for( llvm::Module::iterator ModIter = TheModule->begin(); ModIter != TheModule->end(); ++ModIter )
{
    llvm::Function* Func = llvm::cast<llvm::Function>(ModIter);
    // Print Function Name
    raw_cout << Func->getName() << '\n';
    // Function::iterator --> BasicBlock
    for( llvm::Function::iterator FuncIter = Func->begin(); FuncIter != Func->end(); ++FuncIter )
    {
        llvm::BasicBlock* BB = llvm::cast<llvm::BasicBlock>(FuncIter);
        // BasicBlock::iterator --> Instruction
        for( llvm::BasicBlock::iterator BBIter = BB->begin(); BBIter != BB->end(); ++BBIter )
        {
          llvm::Instruction* Inst = llvm::cast<llvm::Instruction>(BBIter);
          // Print Instruction
          raw_cout << '\t';
          Inst->print(raw_cout);
          raw_cout << '\n';
        }
    }
}
728x90
반응형