继续上一篇,同样的hello.c,同样的执行过程,只不过继续添加了一些log信息,而且对代码进行了更近一步的挖掘。先看输入和输出的log信息(前半部分):
shining@shining-VirtualBox:~/llvm-3.9.0/build/bin$ ./clang hello.c -o hello
clang/tools/driver/driver.cpp/main()_begin/shining_add
clang/lib/Driver/Driver.cpp/BuildCompilation()_begin/shining_add
clang/lib/Driver/ToolChains.cpp/Linux()_begin/shining_add
clang/lib/Driver/Tools.cpp/Clang::ConstructJob()_beforeCC1/shining_add
clang/lib/Driver/Driver.cpp/ExecuteCompilation()_begin/shining_add
clang/lib/Driver/Compilation.cpp/ExecuteJobs()_begin/shining_add
clang/lib/Driver/Compilation.cpp/ExecuteCommand()_begin/shining_add
clang/lib/Driver/Job.cpp/Execute()_begin/shining_add
llvm/lib/Support/Program.cpp/ExecuteAndWait()_begin/shining_add
llvm/lib/Support/Unix/Program.inc/Execute()_begin/shining_add
llvm/lib/Support/Unix/Program.inc/Execute()_begin/shining_add333
llvm/lib/Support/Unix/Program.inc/Execute()_begin/shining_add444
clang/tools/driver/driver.cpp/main()_begin/shining_add
clang/tools/driver/driver.cpp/ExecuteCC1Tool()/shining_add
clang/tools/driver/cc1_main.cpp/cc1_main()/shining_add

-----------------------------------------------------------------------------------------------------

这个时候,程序已经通过了对命令行输入的第一次初步执行,执行了clang/tools/driver/driver.cpp中的main()函数,并且添加了很多命令行的具体参数,并且新建线程开始第二次执行clang/tools/driver/driver.cpp中的main()函数。在第二次执行main()函数的时候,选择了和第一次执行完全不同的路径,这是因为第一遍执行main()函数的调用过程中,已经为命令行添加了-cc1的参数选项。所以,第二次执行main()函数的时候,会选择执行main()函数的调用ExecuteCC1Tool()的分支,具体代码如下:
  if (FirstArg != argv.end() && StringRef(*FirstArg).startswith("-cc1")) {// If -cc1 came from a response file, remove the EOL sentinels.if (MarkEOLs) {auto newEnd = std::remove(argv.begin(), argv.end(), nullptr);argv.resize(newEnd - argv.begin());}return ExecuteCC1Tool(argv, argv[1] + 4);}

-------------------------------------------------------------------------------------------------------

现在再回头对这个过程中的代码进行分析,第一次执行clang/tools/driver/driver.cpp中的main()函数的时候,下面的代码是核心部分:
  std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));int Res = 0;SmallVector<std::pair<int, const Command *>, 4> FailingCommands;if (C.get())Res = TheDriver.ExecuteCompilation(*C, FailingCommands);

主要是TheDriver的BuildCompilation和ExecuteCompilation的两个函数的执行,而且这两个是一个顺序的过程,先build再execute。其中,TheDriver是Driver类的一个具体对象,而Driver类的具体实现是在clang/lib/Driver/Driver.cpp中。也就是说,其实clang的代码里面,有两个driver相关目录,并各自包含一些文件,以driver直接命名的cpp文件举例:tools/driver/driver.cpp和lib/Driver/Driver.cpp,前者是驱动编译器的驱动,而后者是Driver类的具体实现。这两个具体文件的差别,基本上也代表了两个目录的主要用途。
------------------------------------------------------------------------------------------------------
Driver类的BuildCompilation方法,通过调用关系,最终调用了clang/lib/Driver/Tools.cpp里的Clang::ConstructJob()函数,这个函数很重要的一个动作就是为了命令行的参数列表添加了“-cc1”参数,这个动作为第二次执行clang/tools/driver/driver.cpp中的main()函数的路径起了决定性的作用。
  // Invoke ourselves in -cc1 mode.//// FIXME: Implement custom jobs for internal actions.CmdArgs.push_back("-cc1");

------------------------------------------------------------------------------------------------------
Driver类的ExecuteCompilation方法,通过调用关系,最终调用Compilation类的几个方法,并且在clang/lib/Driver/Job.cpp/Command::Execute()函数的内部,开始调用llvm部分的support代码llvm/lib/Support/Program.cpp中的llvm::sys::ExecuteAndWait()。

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//
static bool Execute(ProcessInfo &PI, StringRef Program, const char **args,const char **env, const StringRef **Redirects,unsigned memoryLimit, std::string *ErrMsg);int sys::ExecuteAndWait(StringRef Program, const char **args, const char **envp,const StringRef **redirects, unsigned secondsToWait,unsigned memoryLimit, std::string *ErrMsg,bool *ExecutionFailed) {ProcessInfo PI;if (Execute(PI, Program, args, envp, redirects, memoryLimit, ErrMsg)) {if (ExecutionFailed)*ExecutionFailed = false;ProcessInfo Result = Wait(PI, secondsToWait, /*WaitUntilTerminates=*/secondsToWait == 0, ErrMsg);return Result.ReturnCode;}if (ExecutionFailed)*ExecutionFailed = true;return -1;
}

llvm::sys::ExecuteAndWait()调用了Execute()函数,而Execute()函数则会根据不同的操作系统有不同的实现。我使用的环境是Ubuntu16.10,所以Execute()函数的具体实现就在llvm/lib/Support/Unix/Program.inc中。相应的此处也有一个llvm/lib/Support/Windows/目录,存放Windows操作系统所对应的相关代码实现。在llvm/lib/Support/Unix/Program.inc中Execute()函数的具体实现过程中有
#ifdef HAVE_POSIX_SPAWN
......
#endif
这样的宏开关,这个宏开关在我的本地环境是可用的,所以具体执行了其中的
    int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,/*attrp*/nullptr, const_cast<char **>(args),const_cast<char **>(envp));

根据Execute()函数中的相关注释:
  // If this OS has posix_spawn and there is no memory limit being implied, use// posix_spawn.  It is more efficient than fork/exec.

可以看出,这个实现方式是要比fork/exec的执行效率要高,所以在我的环境下,代码走的就是这个路径,而没有执行下面的
#endif// Create a child process.int child = fork();switch (child) {

这部分代码。posix_spawn或者fork就是为了建立新的线程,从而重新执行clang/tools/driver/driver.cpp中的main()函数,所以才有了第二次执行clang/tools/driver/driver.cpp中的main()函数的出发点。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
代码和修改后的代码,我也见了一个代码库,地址:https://github.com/shining1984/clang_code_comment

深入研究Clang(九) Clang代码阅读之打log读流程2相关推荐

  1. OpenFace代码阅读笔记(1) ------FeatureExtraction的程序流程

    OpenFace代码阅读笔记 ------FeatureExtraction的程序流程 1. Init 1.1 解析main函数的输入参数 1.2 读取txt文件中的配置参数 1.3 load mod ...

  2. 课堂教学实践研究之人教版九年级上册“阅读与思考”《旋转对称》

    2022年9月20日,"初中数学'阅读材料'教学实践"课题组在海门区树勋初中一起研讨如何有效利用人教版初中数学"阅读与思考"的材料培养学生的数学阅读能力,活动分 ...

  3. 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(九)—— 预测与校验

    系列目录: 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(一)--数据 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(二)-- 介绍及分词 菜鸟笔记-DuReader阅读理解基线模 ...

  4. clang --version clang: error while loading shared libraries: libtinfo.so.5: cannot open shared objec

    安装llvm时出现 clang --version clang: error while loading shared libraries: libtinfo.so.5: cannot open sh ...

  5. ORB_SLAM2代码阅读(4)——LoopClosing线程

    ORB_SLAM2代码阅读(4)--LoopClosing线程 1.说明 2.简介 3.检测回环 4.计算Sim3 4.1 为什么在进行回环检测的时候需要计算相似变换矩阵,而不是等距变换? 4.2 累 ...

  6. 深度学习项目代码阅读建议

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|机器学习实验室 犹豫很久要不要把读代码这个事情专门挑出来写 ...

  7. 如何将深度学习研究论文实现为代码的几个要点

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:Bipin Krishnan P 编译:ronghuaiyang 导读 如果深度学习是一种超能力 ...

  8. JavaScript权威Douglas Crockford:代码阅读和每个人都该学的编程

    作者:Peter Seibel 关于JavaScript Seibel:在程序学习之路上有哪些令你后悔的事情? Crockford:我了解一些语言,但却一直没有机会使用.我花了不少时间学习APL并了解 ...

  9. 《代码阅读方法与实践》阅读笔记一

    第三本书我选择了代码阅读方法与实践,说实话,觉得三本书里面最好的就是这一本书了,每一段话,每一段代码打偶让我受益匪浅.下面是我的收获: 1.1为什么以及如何阅读代码  将代码作为文献:要养成一个习惯, ...

最新文章

  1. CVPR 2021 | 记录SCRFD人脸检测C++工程化(含docker镜像)
  2. 赛森机器人_对比评测3款最贵的扫地机器人,戴森性能太强了
  3. cocos2d-x3.6 连连看连通画线
  4. LeetCode 2020 力扣杯全国春季编程大赛(1644/4093,前40.2%)
  5. 云+X案例展 | 民生类:浪潮云打卡人间仙境张家界
  6. 触摸事件touchevent
  7. 【个人笔记】OpenCV4 C++ 快速入门 00课
  8. Shell脚本中dirname命令的使用
  9. 会员卡券领取 小程序_新增卡券功能在哪 微信小程序内直接领取卡券方法
  10. 数据库之区分DB\DBMS\DBS
  11. 微信朋友圈点赞设计测试用例
  12. html2canvas以及domtoimage的使用踩坑总结 动态获取的二维码失效如何生成海报
  13. java video src请求视频流,视频不能拖拽快进问题解决方案
  14. 跨设备链路聚合 M-LAG
  15. .c和.h文件的区别
  16. C - Recursive sequence (矩阵ksm)
  17. Excel技能培训之十六自动高亮重复值,满足条件的值,自定义高亮条件,自动高亮前三名,显示数据条,色阶
  18. 常用的webservice接口 .
  19. 输出《易经》六十四卦的卦象符号
  20. rz waiting to receive. Starting zmodem transfer. Press Ctrl+C to cancel.

热门文章

  1. linux查找用户前三进程_查看 Linux 系统中进程和用户的内存使用情况 | Linux 中国...
  2. python猜年龄代码_python入门教程NO.7用python来写一个猜数字游戏
  3. python资本市场财务数据分析_Python对股票财务数据进行可视化分析
  4. Paddle 环境中 使用LeNet在MNIST数据集实现图像分类
  5. 广东线上比赛过程集锦
  6. 第16届智能车竞赛参赛队员提问-05-24
  7. 一键将Word转换为MarkDown
  8. 带你认识清华标杆课教师 | 卓晴:自带BGM的硬核“技术流”教师
  9. win10商店打不开_PS打不开Raw格式?更新ACR新方式!【第05期 三分钟聊摄影】
  10. java中sizeof函数,C语言中,sizeof运算符有什么作用?