LLVM pass로 코드의 변수 타입 개수 세기
프로그램에서 사용된 변수들의 타입들을 카운트 하시오.
(Integer 타입과 Pointer 타입만 고려한다.)
Ex)
코드가 있으면 그 코드 안에서 만들어진 변수들에서 타입별로 개수를 세서 알려주면 된다.
여기서 포인트는 Alloca instruction만 검사하면 된다는 것이다.
어짜피 변수 할당은 무조건 Alloca instruction으로만 이루어지기 때문이다.
흥미로우면서 짜증나는 점은 llvm 비트코드 수준에서의 변수들은 모두 포인터로 되어있다고 한다.
그 이유는 llvm IR의 기능이자 존재 의미에서 찾아볼 수 있는 것 같다.
어셈블리어와 코드를 매칭시켜야 하므로 포인터처럼 활용되는 수밖에 없다는 것 같다.
(내가 이해한게 맞는지는 잘 모르겠다. 박사오빠한테 다시 물어봐야겠다.)
어찌됐든 코드가 실제로 실행될 때에는 로컬 변수라고 하더라도 메모리에 할당되어야 하기 때문에 코드상에서 생각하는 로컬 변수 느낌으로
구현이 불가능한 것 같다.
(+ 그럼 포인터 변수는 어떻게 하나? 포인터의 포인터로 그냥 똑같이 포인터로 한다. 허헣..)
내 코드
나는 이렇게 코드를 짜보았다.
이 test.c 코드로 확인해봤는데 잘 세지긴한다.
무슨 아래에 이상한 에러가 난다. 이유는 모르겠다.
LLVM 타입들
- LLVM에는 다양한 타입이 존재하며, 각 타입 마다 크기에 맞는 bit size를 할당받으며 명령어를 통해 자유롭게 형 변환 할 수 있다. (Ex. Bitcast, PtrToInt, IntToPtr 등)
- Integer type은 i1, i16, i32 등으로 표시하며 숫자는 bit의 크기를 의미한다.
- Pointer type은 C언어처럼 *로 표시하고 포인터 타입만이 메모리에 공간을 차지하는 변수이며 그 이외의 타입 변수들은 임시 변수이다.
필요한 LLVM pass code
AllocaInst* ai = dyn_cast<AllocaInst>(&I);
Type* allocType = ai->getAllocatedType();
if(ai->isPointerTy()) ....
else if (ai->isIntegerTy()) .....
C언어에서 지역 변수를 선언하면, 이러한 변수들은 메모리에 할당된다.
따라서, LLVM의 중간언어에서도 프로그램에서 선언된 변수들은 모두 Alloca 명령어를 사용하여 메모리에 할당 받는다.
(단, 최적화가 안 되었을 경우에 한정한다. 컴파일러의 최적화가 사용되면 메모리 할당이 안 되는 경우도 존재할 수 있다.)
Ex) int a; -> %a = alloca i32
따라서, 프로그램에 사용된 변수들의 타입에 관하여 조사하면, Alloca 명령어에 대해서만 조사하면 된다.