为gcc源代码生成tags

LLVM的td文件使用的是tablegen语言,所以,它可以增加一个tablegen后端,来输出td文件的tags。

gcc的def文件使用的是宏定义,格式比较随意,很难通过类似llvm这样的方式,来为def文件生成tags。好在,大多def文件都是这样的一个格式:

DEF (ENUM, NAME, ...)

例如:

DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_NUM_THREADS, "omp_get_num_threads",
                  BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)

通过如下的ctags命令,可以粗略的为这些def文件生成tags索引:

$ ctags --langdef=def --langmap=def:.def --regex-def="/^[ \t]*[a-zA-Z0-9_]+[ \t]*\([ \t]*([a-zA-Z0-9_]+)/\1/d,definition/" -R .

可以看到tags文件里生成了如下内容:

BUILT_IN_OMP_GET_NUM_THREADS    omp-builtins.def        /^DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_NUM_THREADS, "omp_get_num_threads",$/;"    d

目前gcc的代码虽然是c++实现,但是后缀名还是“.c”。所以,需要加上一个额外选项告诉ctags:

--langmap=c++:+.c

去掉testsuite目录:

--exclude=testsuite

过滤掉代码中一些宏的干扰:

-I GTY+ -I VEC+ -I DEF_VEC_P+

把build目录加进来,合起来的命令如下:

$ ctags --langdef=def --langmap=def:.def --regex-def="/^[ \t]*[a-zA-Z0-9_]+[ \t]*\([ \t]*([a-zA-Z0-9_]+)/\1/d,definition/" --langmap=c++:+.c --exclude=testsuite -I GTY+ -I VEC+ -I DEF_VEC_P+ -R . ~/build/build-gcc-trunk/gcc

使用gcc-6.1.0编译SPEC2006错误参考

一堆错误,还好逐个都解决了,其中:

400.perlbench,编译出错,一堆重定义,是inline的不同实现标准造成的,需要加上一个选项-std=gnu90。gnu90和c99的对extern函数的inline实现方式不同。
416.gamess 运行出错,需要加上一个选项-funconstrained-commons,参考https://gcc.gnu.org/ml/gcc-patches/2016-03/msg00465.html,gfortran文档中没有提到这个选项。
其它还有一些是strcat,memcp之类的函数,没有显式的include相应的头文件。还有的,是不在std namespace中,代码中竟然有std::。

为td文件生成tags

LLVM的TableGen可以用来为td文件生成tags,方便在vim中查看。该功能的svn信息如下:

------------------------------------------------------------------------
r177682 | silvas | 2013-03-22 07:40:38 +0800 (Fri, 22 Mar 2013) | 18 lines
Changed paths:
   M /llvm/trunk/utils/TableGen/CMakeLists.txt
   A /llvm/trunk/utils/TableGen/CTagsEmitter.cpp
   M /llvm/trunk/utils/TableGen/TableGen.cpp
   M /llvm/trunk/utils/TableGen/TableGenBackends.h
   A /llvm/trunk/utils/TableGen/tdtags

Add TableGen ctags(1) emitter and helper script.

To use this in conjunction with exuberant ctags to generate a single
combined tags file, run tblgen first and then
  $ ctags --append [...]

Since some identifiers have corresponding definitions in C++ code,
it can be useful (if using vim) to also use cscope, and
  :set cscopetagorder=1
so that
  :tag X
will preferentially select the tablegen symbol, while
  :cscope find g X
will always find the C++ symbol.

Patch by Kevin Schoedel!

(a couple small formatting changes courtesy of clang-format)
------------------------------------------------------------------------

使用方法如下:

xmj@xmj-OptiPlex-9020:~/project/llvm-trunk$ bash utils/TableGen/tdtags -q -x all

生成的tags文件:

xmj@xmj-OptiPlex-9020:~/project/llvm-trunk$ find ./ -name tags
./unittests/Option/tags
./lib/IR/tags
./lib/LibDriver/tags
./lib/Target/AVR/tags
./lib/Target/XCore/tags
./lib/Target/WebAssembly/tags
./lib/Target/BPF/tags
./lib/Target/Sparc/tags
./lib/Target/Mips/tags
./lib/Target/NVPTX/tags
./lib/Target/SystemZ/tags
./lib/Target/PowerPC/tags
./lib/Target/Lanai/tags
./lib/Target/MSP430/tags
./lib/Target/X86/tags
./lib/Target/AArch64/tags
./lib/Target/Hexagon/tags
./lib/Target/ARM/tags
./lib/Target/AMDGPU/tags
./test/TableGen/tags
./include/llvm/IR/tags
./include/llvm/Option/tags
./include/llvm/Target/tags
./include/llvm/CodeGen/tags
./tools/clang/tags
./tools/clang/lib/StaticAnalyzer/Checkers/tags
./tools/clang/test/TableGen/tags
./tools/clang/include/clang/AST/tags
./tools/clang/include/clang/Driver/tags
./tools/clang/include/clang/Basic/tags
./tools/clang/include/clang/StaticAnalyzer/Checkers/tags

回路搜索算法

Gcc和LLVM中的软流水优化,都是基于Swing Modulo Scheduling算法(翻译成摆动模调度?)实现的,参见[1]。其中,需要在依赖图(dependency graph)上搜索所有的简单回路(elementary circuits)。

LLVM中的软流水代码里,提到了“Identify all the elementary circuits in the dependence graph using Johnson’s circuit algorithm.”,这个算法源自论文[2]。

为了更好的理解回路搜索算法,我也基于论文[2]做个实现,放在了github上,参见[3]。

[1] Josep Llosa, Antonio Gonzalez, Eduard Ayguade, and Mateo Valero. Swing Modulo Scheduling: A Lifetime Sensitive Approach. In Pact96 , pages 80-87, October 1996 (Boston – Massachusetts – USA).
[2] Donald B. Johnson, Finding all the elementary circuits of a directed graph, SIAM Journal on Computing, 1975.
[3] https://github.com/hellogcc/circuit-finding-algorithm

[资源] 中科院开源协会的GCC等GNU软件镜像站点上线

中科院开源协会最近上线了一个开源软件镜像站点, 提供包括GCC在内的众多GNU软件源代码的镜像. 服务器部署在中国科技网上, 国内访问的速度还可以, 可以尝试下.

镜像地址: http://mirrors.opencas.cn/gnu/gcc/

中科院开源协会地址: http://www.opencas.org/

看了一下, 还有一个有吸引力的地方是提供了Android相关SDK的下载. 这点对于希望接触Android开发的爱好者帮助很大 🙂