V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
andyJado
V2EX  ›  程序员

非 CS, 想弄弄编译, 还啃龙书吗?

  •  1
     
  •   andyJado ·
    AndyJado · 2022-09-29 09:22:07 +08:00 · 6244 次点击
    这是一个创建于 568 天前的主题,其中的信息可能已经有所发展或是发生改变。
    31 条回复    2022-10-30 15:54:27 +08:00
    xtreme1
        1
    xtreme1  
       2022-09-29 09:30:03 +08:00   ❤️ 1
    你是要搞哪一块..
    如果只是想快速了解一下, 可以找一些 LLVM 教程看一看
    Lax
        2
    Lax  
       2022-09-29 09:38:26 +08:00
    书店随便买一套普通教材看看吧
    离散数学-形式语言与自动机-编译原理
    Mithril
        3
    Mithril  
       2022-09-29 09:41:01 +08:00   ❤️ 1
    不建议直接啃。
    如果你会写代码的话,可以找找教程用你熟悉的语言实现个简单的编译器。弄个 JSON 解析器,或者做个简单的 DSL 等等。遇到哪里不懂的名词去查或者直接翻书就行。
    这样你对于编译这个过程有个直观的理解以后,再去啃就会容易很多。
    而且你也能知道自己想要学的那部分,对应的是哪些技术。学起来也更有目的性。
    shijingshijing
        4
    shijingshijing  
       2022-09-29 09:43:21 +08:00   ❤️ 1
    其实现在编译器开发也有划分了前端( Front End )与后端( Back End ),前端偏算法和数据结构;后端偏硬件底层和系统架构。看你准备弄哪一块?

    而且搞编译器出来工作岗位也不多吧。。。 搞这个的都是大牛。
    heyjei
        5
    heyjei  
       2022-09-29 09:44:31 +08:00   ❤️ 1
    非专业人士,看看 Antlr 就足够了,而且还有一定的实用性
    zsj950618
        6
    zsj950618  
       2022-09-29 12:07:55 +08:00 via Android
    龙书只是入门吧。。。你要是连一些名词都不知道,其他直接上手的教程估计看不懂。。。
    zsj950618
        7
    zsj950618  
       2022-09-29 12:09:54 +08:00 via Android
    或者说看龙书的时候,一些算法没看懂可以不着急研究,但书总归要先翻一遍
    SmiteChow
        8
    SmiteChow  
       2022-09-29 12:13:53 +08:00
    编译原理是基础,跳不过的,概念要清楚,要不然你可能连最基本的文法一关都过不去。
    billlee
        9
    billlee  
       2022-09-29 12:26:24 +08:00 via Android   ❤️ 1
    快速上手建议看 antlr 手册,跑起来以后要加高级特性的时候再看龙书
    DianQK
        10
    DianQK  
       2022-09-29 13:17:44 +08:00   ❤️ 6
    我当前学习的路线供参考


    - Computer Systems: A Programmer's Perspective
    - Crafting Interpreters (替代 自己动手实现 Lua 虚拟机、编译器和标准库)
    - 程序员的自我修养:链接、装载与库(替代 上面的 CSAPP )


    - 清华大学的《数据结构( C++ 语言版)》邓俊辉(看了一部分,很棒!)学习中


    - **南京大学 软件分析 [**https://tai-e.pascal-lab.net/**]( https://tai-e.pascal-lab.net/) 国内顶级的静态分析课程,最近看完了所有的视频,也完成了 OJ 作业,非常棒的课程**
    - Compilers: Principles, Techniques, and Tools (以下几章可以算是上面的软件分析的下一步学习的扩展)
    - 6.2 Three-Address Code
    - 8 Code Generation
    - 9 Machine-Independent Optimizations
    - 12 Interprocedural Analysis (还没开始看)计划待看
    - CS 6120: Advanced Compilers γ https://www.cs.cornell.edu/courses/cs6120/2020fa/ 看了一半搁置了


    - **LLVM Techniques, Tips, and Best Practices Clang and Middle-End Libraries 上手 LLVM 前一定要看**
    - https://github.com/banach-space/llvm-tutor ​学习中
    - Learn LLVM 12: A Beginner's Guide to Learning LLVM Compiler Tools and Core Libraries With C++

    其他参考
    - [编译高级教程|学习笔记]( https://leiblog.wang/%E7%BC%96%E8%AF%91%E9%AB%98%E7%BA%A7%E6%95%99%E7%A8%8B%EF%BD%9C%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/)
    - [2019 EuroLLVM Developers’ Meeting: V. Bridgers & F. Piovezan “LLVM IR Tutorial - Phis, GEPs ...”](
    )
    - [Creating the Bolt Complier 系列]( https://mukulrathi.com/create-your-own-programming-language/intro-to-compiler/)
    Ta0Ta0Ta0
        11
    Ta0Ta0Ta0  
       2022-09-29 13:38:08 +08:00   ❤️ 1
    我推荐一下哈工大姜守旭老师的编译原理视频课程吧,思路清晰,这门课靠他的讲述拿了个不错的分
    gengjiawen
        12
    gengjiawen  
       2022-09-29 14:03:46 +08:00   ❤️ 1
    推荐 https://book.douban.com/review/13617730/, 已经有中文版。
    andyJado
        13
    andyJado  
    OP
       2022-09-29 14:26:49 +08:00
    @DianQK
    我目前的进展:

    wow, bit and context, 我悟了.

    @gengjiawen

    https://book.douban.com/review/13617730/

    已标记, 但, 也许我心中真正好奇的是, 编译是他妈的在干嘛, 为啥要整那些呢? AST 放松了什么痛苦? MIR 呢?
    littlewing
        14
    littlewing  
       2022-09-29 14:29:15 +08:00   ❤️ 1
    直接搞 llvm
    hk3475
        15
    hk3475  
       2022-09-29 14:37:36 +08:00   ❤️ 1
    看 crafting interpreter 就够了 还有龙书太重 parse 了 你不搞学术的话 搞懂 recursive decent 就行了 后面可能也是用 antlr 之类的多
    Origami404
        16
    Origami404  
       2022-09-29 15:01:56 +08:00 via Android   ❤️ 1
    我的理解是编译即翻译,是数据结构跟特性的变化。

    数据结构的变化的话主要有:文本->词法流,词法流->ast ,文本->ast ,ast->各种类型的 ir 。

    特性的变化主要是有无变量,有无语句还是纯表达式,有无非局部控制流,有无闭包,有无宏,有无可直接访问的线性内存,有无模板之类的。

    要学哪一步就要学特定的实现方法,比如词法流->ast 就有一堆 ll ,lr ,parser combinator 之类的。然后各个特性的翻译也是有要学的
    Origami404
        17
    Origami404  
       2022-09-29 15:05:47 +08:00 via Android   ❤️ 1
    实践上我觉得最难的是从有变量的语言转到无变量的语言 /ir 的实现,这意味着将表述程序的重心从内存位置转移到值,需要做很多分析。
    Origami404
        18
    Origami404  
       2022-09-29 15:08:04 +08:00 via Android   ❤️ 1
    当然要实现特定的大的特性,比如基于原型的 oop ,类似 Java 那样的 oop ,惰性运算,条件系统那种的话,还要再深入具体体系看看设计。
    Origami404
        19
    Origami404  
       2022-09-29 15:11:27 +08:00 via Android   ❤️ 1
    做多趟编译器的话感觉首先是要想好 ir 形式,是指令变量分离的三地址,还是类似 llvm 跟 graal 的图状 ir ,又或者是 lisp 系的 cps 。很多时候理解了 ir 跟源语言之后从 ast 到 ir 这一步就都迎刃而解了
    Origami404
        20
    Origami404  
       2022-09-29 15:20:46 +08:00 via Android   ❤️ 1
    @andyJado AST 是程序结构的抽象表示,使用 ast 可以完全将语义部分(即遇到什么程序结构要干什么)跟解析部分(从词法流中解析出程序结构)分离开来。在早期不分的情况下,必须在解析部分就指定解析出的程序结构的语义,就会导致代码耦合。

    其实换一种角度想,你可以将 AST 视作一种“所有语言都具有的语义”,因为它表达且只表达了程序结构,没有任何多余信息。

    其实可以各种各样的 IR 就是各种各样的数据结构。我们使用数据结构的目的就是为了方便插入 /提取某些信息,方便一些算法的使用。使用某种 IR 的目的也是这样,不同种类的 IR 能方便地获取源程序中不同的信息,从而方便不同的优化算法使用。

    当然了,IR 本身作为一个 AST 跟实际汇编语言后端之间的抽象层这个作用也是很重要的,它能极大方便多后端编译器的开发。
    FYFX
        21
    FYFX  
       2022-09-29 15:21:17 +08:00   ❤️ 1
    看了 OP 13 楼的进一步说明,那就 https://craftinginterpreters.com/
    nightwitch
        22
    nightwitch  
       2022-09-29 15:38:45 +08:00   ❤️ 1
    parser 只掌握递归下降 LL1 可以解决 90%的问题了。
    重点在后端求值和优化部分,从字符串到 ast 都是体力活,换着花样解析没太大意义。
    dog82
        23
    dog82  
       2022-09-29 15:50:27 +08:00
    炸出一堆大神,我编译原理只肝到语法分析,我天资差感觉太难了
    bruce0
        24
    bruce0  
       2022-09-29 17:27:58 +08:00
    @dog82 我都没去肝过, 我自认为不是那块料🐶
    andyJado
        25
    andyJado  
    OP
       2022-09-29 17:39:20 +08:00
    @FYFX 啊啊 我看过他写的那个那个那个代码有蓝色有红色的!

    https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/

    您函数啥颜色呀?
    penguinWWY
        26
    penguinWWY  
       2022-09-29 18:12:54 +08:00
    啃龙书没啥意义。
    如果你想整体了解编译,不要在 parser 上浪费时间,parser 是一个非常“符合直觉”的事情,本质上就是如何把一段文本变成结构化的数据,所以不要被各种名词唬住,自己写一个简单的表达式解析器,就能大概明白了。同时 parser 在整个编译过程中只占了很小的一部分,基本没啥值得关注的东西。

    编译整体看是一个不断 lower ( desuger )的过程,用简单代替复杂,具体代替抽象。所以整体看的话,你需要大概了解一下体系结构和指令集,也就是编译的终点是什么样的。中间的过程不管是 AST 也好,IR 也好,no-target machine code 还是 target machine code ,从认知上来讲,都不是必须的(你完全可以设计一个非常简单的表达式语言,然后直接翻译成汇编指令),这些步骤只是为了满足某种需求( native code or Interpreter ? JIT or AOT ? interprocedural or intraprocedural ?)而增加的、便于使用的中间层。

    明确输入(语言、特性、功能)和输出(目标指令集),剩下的就是取舍和拼接。现在编译体系复杂之处在于为了某些目标(性能、功能、复杂的语言特性)而在不同层次间不得不产生耦合,使用某些约定(而不是设计)。当这种情况越多,原本清晰的结构就会变成一坨。。。
    andyJado
        27
    andyJado  
    OP
       2022-09-29 18:31:21 +08:00
    > 这意味着将表述程序的重心从内存位置转移到值

    @Origami404 谢谢老师! 我也去体会体会🏃
    andyJado
        28
    andyJado  
    OP
       2022-09-29 18:41:53 +08:00
    @penguinWWY 挠到了! 谢谢老师!
    woctordho
        29
    woctordho  
       2022-09-29 19:17:39 +08:00   ❤️ 1
    建议边做边学,你可以先试试发明一门新的语言,比如用东北话编程 https://github.com/zhanyong-wan/dongbei

    先用土办法写一个解释器,然后再看编译原理里的那些概念,就知道你自己在干什么了
    fengjianxinghun
        30
    fengjianxinghun  
       2022-09-30 11:10:35 +08:00   ❤️ 1
    前端毫无技术含量,随便用什么,手写 LL(N)都能解决 99%的编程语言问题。
    至于后端有 llvm 在,任何重头开发的都是造瘪轮子。
    pocarisweat
        31
    pocarisweat  
       2022-10-30 15:54:27 +08:00
    入门学习的话,龙书不如橡书(《 Engineering a Compiler 》,第二版有中文版,第三版英文版刚出),差不多理解了自动机和递归下降那一套东西,就可以尝试自己写 Parser 了。

    中后端还是建议从 LLVM 入手,先用 Clang 编译一些常见的 C 代码到 LLVM IR 了解 IR 是个什么结构( IR 本身的结构就和汇编有些接近,如果不懂汇编的话这一步也有利于了解汇编),然后通过改 IR 看 opt (中端)和 llc (后端)的输出学习常见的优化。LLVM 有大量的回归测试,通过它们能弄明白每个优化 Pass 到底是干嘛的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3637 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:19 · PVG 12:19 · LAX 21:19 · JFK 00:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.