我正在研究的工具需要采用编译器生成的中间格式,向其中添加一些代码,然后将修改后的中间代码提供给编译器的后端以生成最终代码。
通过对gcc进行一些研究,我发现GIMPLE格式很容易理解,但我不确定修改GIMPLE代码的复杂性,也不知道从那里重新启动编译的任何方法除了使用插件并添加自己的传递。还有人警告我,文档很少,当你在使用gcc时遇到困难时会发生变化。
另一种选择是使用LLVM字节码。但我从未使用LLVM,所以不知道我的任务与LLVM有多复杂。可能还有更好的选择,我不知道。因此,我只想知道最好的选择。我的偏好如下。
答案 0 :(得分:1)
正如您可能已经知道的那样,MELT是一种用于扩展GCC的高级域特定语言。你可以很容易地使用它来处理Gimple(等...)(并修改Gcc中的内部表示)
然而,扩展GCC意味着一些工作,因为Gimple(以及树)表示(与其他人一起,例如边缘......)很复杂......
答案 1 :(得分:1)
根据您的描述,LLVM完全符合要求。其主要目标之一是作为操纵IR代码的灵活库和框架。无数的优化,转换和分析“通过”它既可以作为证明,也可以作为很好的例子。 IMO LLVM也很好地回答了你在问题中列出的4个要点:
答案 2 :(得分:0)
这可能没什么用,但我想知道gcc
的处理过程。从strace -f -o gcc.strace gcc -c tstamp.c
输出的删节(主要是减去exec / fork调用):
7141 execve("/usr/bin/gcc", ["gcc", "-c", "tstamp.c"], [/* 52 vars */]) = 0
7141 open("/tmp/ccqzaCI4.s", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 3
7141 close(3) = 0
7141 vfork( <unfinished ...>
7142 execve("/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1", ["/usr/libexec/gcc/i686-redhat-lin"..., "-quiet", "tstamp.c", "-quiet", "-dumpbase", "tstamp.c", "-mtune=generic", "-march=i686", "-auxbase", "tstamp", "-o", "/tmp/ccqzaCI4.s"], [/* 55 vars */] <unfinished ...>
7141 <... vfork resumed> ) = 7142
7141 waitpid(7142, <unfinished ...>
7142 <... execve resumed> ) = 0
7142 open("tstamp.c", O_RDONLY|O_NOCTTY|O_LARGEFILE) = 3
7142 close(3) = 0
7142 open("/tmp/ccqzaCI4.s", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
7142 open("/usr/include/stdio.h", O_RDONLY|O_NOCTTY|O_LARGEFILE) = 4
... (opens and closes every include file)
7142 close(4) = 0
7142 close(3) = 0
7142 exit_group(0) = ?
7141 <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 7142
7141 vfork( <unfinished ...>
7143 execve("/usr/bin/as", ["as", "--32", "-o", "tstamp.o", "/tmp/ccqzaCI4.s"], [/* 55 vars */] <unfinished ...>
7141 <... vfork resumed> ) = 7143
7141 waitpid(7143, <unfinished ...>
7143 <... execve resumed> ) = 0
7143 unlink("tstamp.o") = 0
7143 open("tstamp.o", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
7143 open("/tmp/ccqzaCI4.s", O_RDONLY|O_LARGEFILE) = 4
7143 close(4) = 0
7143 close(3) = 0
7143 exit_group(0) = ?
7141 <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 7143
7141 unlink("/tmp/ccqzaCI4.s") = 0
7141 exit_group(0) = ?
cc1
具有所有适用的逻辑。我想这是一个复杂的程序,尤其是输入后:
/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1 --help
和
/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1 --help=C