求教彦祖们, c++ 想深入, LLVM 源码有没有学习的必要,怎么学? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hehedaozuiteng
V2EX    问与答

求教彦祖们, c++ 想深入, LLVM 源码有没有学习的必要,怎么学?

  •  
  •   hehedaozuiteng 2021-05-22 17:43:35 +08:00 2929 次点击
    这是一个创建于 1605 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近刚刚看完了 《 stL 源码解析》。 想进一步学习一下 c++,之前有个同事推荐我去看 LLVM 的源码。

    但是直接上 github 上看源码又有点硬核。

    向大佬们请教一下,怎么通过阅读 LLVM 的源码来提高自己 c++的水平。有没有什么系统性的方法或者相关的书推荐的?

    7 条回复    2021-05-23 23:35:41 +08:00
    efen
        1
    efen  
       2021-05-22 18:17:09 +08:00 via iPhone   2
    学 cpp 去看 llvm,就和学开车去看发动机制造原理一样
    学好 cpp 需要的是不断的练习
    纯粹想玩的话就去玩模版元编程♂
    kilasuelika
        2
    kilasuelika  
       2021-05-23 02:07:53 +08:00 via Android
    代码主要是给机器看的,不是给人看的。
    真要想非常非常深入,那应该去学编译原理一类的。
    penguinWWY
        3
    penguinWWY  
       2021-05-23 03:18:15 +08:00
    LLVM 作为编译框架跟 C++没啥关系(除了它本身是 C++写的之外。。。
    可能你同事想说的是 clang ?看 clang 的 AST 或许可以解答一些你对 C++的困惑,但这个也不见得能提高你的 C++水平
    James369
        4
    James369  
       2021-05-23 09:18:31 +08:00
    我看现在 Go 的趋势很火,冲击了服务器后端,冲击了 JAVA,真有点怕会冲击到 C++。
    jones2000
        5
    jones2000  
       2021-05-23 14:32:53 +08:00
    多做项目, 多写代码就可以。
    agagega
        6
    agagega  
       2021-05-23 20:24:03 +08:00
    看 LLVM 有点舍近求远,不过还是有点点用的。LLVM 是一个非常标志性的百万行级别 C++项目,可以学到很多工程化和模块化的经验。
    secondwtq
        7
    secondwtq  
       2021-05-23 23:35:41 +08:00   2
    作为做 LLVM 的来说一下吧,学 C++ 看 GCC 更像是“学开车去看发动机制造原理”,GCC 代码是 C 的底子,本身确实“跟 C++ 没啥关系”,LLVM 则是个彻底的现代 C++ 项目

    首先,LLVM 早已经不是一个简单的“编译框架”,现在的 LLVM 既可以指狭义的“LLVM Proper”(这词是我自己 coin 的,只是为了区分,社区没这说法),即“基于 LLVM IR,提供优化和代码生成的框架”,也可以指广义的“LLVM Project”,即“以 LLVM Proper 为中心,由 LLVM 社区所管理的一系列项目”,LLVM Project 包含 “LLVM Proper” 编译框架,Clang C/C++/Objective-C/OpenCL/CUDA ... 前端,LLD 链接器,LLDB 调试器,libc++ C++ 标准库,compiler-rt 运行库,llvm-libc C 标准库,Flang Fortran 前端和 MLIR 等一系列项目,一起构成一个 monorepo,但是每个项目的实践都有或大或小的不同

    对于一个非编译器相关的开发者而言,我认为 LLVM 最值得学习的是它的基础设施
    LLVM 的核心理念之一是“把一切功能封装成一个库”,也就是说 LLVM 本体是“库”。LLVM 会编译出许多 executable,但是这些 executable 绝大多数都是对库的简单 CLI 封装( Clang 除外,因为要与其他编译器兼容,Clang 的 Driver 层做得格外重),也就是说你自己的程序里面也可以调同样的库来实现类似的功能。举个例子,比如 clang 带一个程序叫 clang-rename,实现了“重命名符号”的代码重构操作,但是这个程序只有几百行,功能实际是在 clang/Tooling/Refactoring/Rename 这个库里实现,而这个库又依赖于 Clang 的 Refactoring 库和语义分析库 ... 我自己就利用这个特性做过简单的代码生成小工具: https://github.com/secondwtq/einstein/blob/master/Einstein.cpp
    把一切封装为“库”的目的就是最大化复用,也就是说这个理念背后的隐含意思是“基础设施能帮你做的都会尽量帮你做,你只需要写你自己需要的东西就行”
    比如说 LLVM 提供了一整套的容器和数据结构,这些基本上都是通用的,很值得一看
    LLVM 的若干公用模块大量使用了模板
    LLVM 大多数模块都天生非常适合自动化测试,LLVM 也有完整的测试设施,常用的有 gtest 单元测试,LIT 测试和运行时集成测试三级。做编译器经常出现改东边的东西影响到西边的测试的情况,针对这种状况 LLVM 给你准备好了自动更新测试用例的脚本。
    作为一个通用的编译器框架,LLVM 支持很多指令集,不同指令集通用的算法(如指令选择、寄存器分配等)被封装成了一个叫做 CodeGen 的库,而针对每一个指令集的支持都是一个单独的模块(前两个月刚有人搞了个 68000 的支持 ...),每一个指令集都需要定义大量的指令,为了解决这个问题,LLVM 搞了一个叫 TableGen 的 DSL 做代码生成,这个东西统一地解决了指令集定义、指令选择、调用约定、微架构细节定义、CLI 选项定义等一系列问题。这么一整套框架做下来,添加新指令集,添加新指令,很大程度上都是重复性工作。

    另外,抛开 LLVM 源码来说,学习 C++,不可不学各种新的工具,而 Clang 占据了半壁江山;不可不了解编译器优化,一般非编译器开发者研究优化都是看汇编,也就是看个一头一尾,但是了解 LLVM IR 就能看中间;不可不看 CppCon 等前沿实践,而其中最有趣的之一就是 LLVM 社区大佬 Chandler Carruth 的基于自己开发经验的系列演讲

    不足的地方:
    LLVM 作为传统的编译器(也就是说还是主要面向 C/C++)整体设计并没有偏离传统太多,后果之一是里面跟多线程有关的东西很少(因为传统编译器不需要这玩意,直接多进程点到为止就行了),还有一堆全局状态,学这方面的你得另请高明
    编译时间太 TM 长 ... 普通 PC 少说半小时吧,我用服务器也得 10 分钟,而且还很大,GCC 就很快(但是好处是需要的依赖很少,只是吃 CPU 而已,基本不用折腾,浏览器则是真正的 worst case,代码量和依赖都很多)
    说是把所有东西都做成了库,实际上不同的库之间是互相依赖的,加起来光库就有好几十 M,也就是说很难做到单独拿出一个东西能用。这个理念的意义更主要还是在于,只要你依赖了 LLVM,里面的东西可以随便单独拿出来调用但是前提是你依赖了 LLVM,这个逻辑就好像“你如果入了苹果的坑,很多东西都会看上去很好(之所以‘看上去很好’是因为金玉其外败絮其中),但是你必须听苹果的话”( GitHub 上甚至有人做把 LLVM 项目里面特定模块单独拎出来的项目)
    如果你是 LLVM 的用户,你会发现它的 API 也不是很稳定,很多老项目都直接钉死某一个 LLVM 版本,因为维护成本不低(这进一步说明了 LLVM 的“现代性”:写程序一把梭,刷版本号就得了)
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1059 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 82ms UTC 18:25 PVG 02:25 LAX 11:25 JFK 14:25
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86