获取结构体信息
LLVM Pass 的内容, Hello.cpp
如下:
#include "llvm/IR/Function.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
// llvm::TypeFinder
#include "llvm/IR/TypeFinder.h"
using namespace llvm;
namespace {
struct SkeletonPass : public FunctionPass {
static char ID;
SkeletonPass() : FunctionPass(ID) {}
virtual bool runOnFunction(llvm::Function& F) {
// 解析 AST
llvm::TypeFinder StructTypes;
const Module& M = *F.getParent();
StructTypes.run(M, true);
// 迭代所有的结构体
for (auto* STy : StructTypes) {
// 迭代结构体中的成员
for (auto field : STy->elements()) {
errs() << *STy << " ==> " << *field << "\n";
}
}
return false;
}
};
} // namespace
char SkeletonPass::ID = 0;
static RegisterPass<SkeletonPass> X("rhpass", "Hello World Pass");
// Automatically enable the pass.
// http://adriansampson.net/blog/clangpass.html
static void registerSkeletonPass(const PassManagerBuilder&,
legacy::PassManagerBase& PM) {
PM.add(new SkeletonPass());
}
static RegisterStandardPasses RegisterMyPass(
PassManagerBuilder::EP_EarlyAsPossible,
registerSkeletonPass);
用于测试结构体的样本 main.c
的内容如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Human {
size_t age;
char name[32];
} Human;
typedef struct Student {
Human man;
size_t score;
} Student;
typedef struct Teacher {
Human man;
char title[32];
size_t salary;
} Teacher;
typedef struct ClassRoom {
size_t id;
Teacher teacher;
Student student[50];
} ClassRoom;
typedef struct School {
char name[100];
ClassRoom classrooms[100];
} School;
int main(int argc, const char** argv) {
printf("====== Start ======\n");
Human p1, p2;
Student s1;
Teacher t1;
ClassRoom c;
School s;
p1.age = 18;
strncpy(p1.name, "JERRY", sizeof("JERRY"));
p2.age = 42;
strncpy(p2.name, "TOM", sizeof("TOM"));
s1.man = p1;
s1.score = 90;
t1.man = p2;
strncpy(t1.title, "Professor", sizeof("Professor"));
t1.salary = 500000;
c.id = 5;
c.teacher = t1;
c.student[0] = s1;
strncpy(s.name, "Harvard University", sizeof("Harvard University"));
s.classrooms[0] = c;
printf("====== Finish ======\n");
return 0;
}
使用以下命令构建并测试 Pass:
# 删除生成的中间文件
rm -f *.so *.elf *.ll
# 构建 LLVM Pass
clang `llvm-config --cxxflags` -Wl,-znodelete -fno-rtti -fPIC -shared Hello.cpp -o LLVMHello.so `llvm-config --ldflags`
# 使用 Pass 编译样本
clang -flegacy-pass-manager -g -Xclang -load -Xclang ./LLVMHello.so main.c -o main.elf
# 运行样本
./main.elf
输出如下:
%struct.Human = type { i64, [32 x i8] } ==> i64
%struct.Human = type { i64, [32 x i8] } ==> [32 x i8]
%struct.Student = type { %struct.Human, i64 } ==> %struct.Human = type { i64, [32 x i8] }
%struct.Student = type { %struct.Human, i64 } ==> i64
%struct.Teacher = type { %struct.Human, [32 x i8], i64 } ==> %struct.Human = type { i64, [32 x i8] }
%struct.Teacher = type { %struct.Human, [32 x i8], i64 } ==> [32 x i8]
%struct.Teacher = type { %struct.Human, [32 x i8], i64 } ==> i64
%struct.ClassRoom = type { i64, %struct.Teacher, [50 x %struct.Student] } ==> i64
%struct.ClassRoom = type { i64, %struct.Teacher, [50 x %struct.Student] } ==> %struct.Teacher = type { %struct.Human, [32 x i8], i64 }
%struct.ClassRoom = type { i64, %struct.Teacher, [50 x %struct.Student] } ==> [50 x %struct.Student]
%struct.School = type { [100 x i8], [100 x %struct.ClassRoom] } ==> [100 x i8]
%struct.School = type { [100 x i8], [100 x %struct.ClassRoom] } ==> [100 x %struct.ClassRoom]
====== Start ======
====== Finish ======
关键 API 说明
llvm::TypeFinder StructTypes;
// 获取 Function 的 parent, 也就是当前所在模块
const Module& M = *F.getParent();
// 这里不知道为啥不能直接用 runOnModule 中的 Module
// 获取模块中的所有结构体, 第二个参数表示是否只寻找明明结构体
StructTypes.run(M, true);
// 迭代所有的结构体
for (auto* STy : StructTypes) {
// 迭代结构体中的成员
for (auto field : STy->elements()) {
errs() << *STy << " ==> " << *field << "\n";
}
}