clang 01.clang简介


前言

Clang的官方网站是 http://clang.llvm.org,它被认为是C家族的LLVM前端。

Clang可能指代三种不同的实体:

  1. 前端(由Clang程序库实现)。
  2. 编译器驱动器(由Clang命令和Clang驱动器程序库实现)。
  3. 实际的编译器(由clang -cc1 命令实现)。clang -cc1中的编译器不单用Clang程序库实现,还大量用到了LLVM程序库来实现编译器的中端和后端,还有集成的汇编器。

本章中主要将clang作为前端,并使用它的程序库构建自己的编译器


1. Clang的工作流程

前面我们说clang可能指代三种不同的实体:

  1. 它可以指代编译器前端是因为它实现了词法分析、语法分析、语义分析和中间代码生成这些步骤,并且把它们封装成libclang(模块化)。这些库是为clang外部用户设计的重要接口,可以单独使用,并将他们跟你的项目链接在一起。如下是相关的程序库:
  • libclangLex:这个库用于预处理和词法分析,处理宏、标记、pragma构造;
  • libclangAST:这个库提供编译、操作、遍历抽象语法树的功能;
  • libclangParse:这个库用于解析程序逻辑,利用此法阶段的结果;
  • libclangSema:这个库用于语义分析,为AST验证提供Action(动作)。
  • libclangAnalysis:这个库包含静态分析的资源;
  • libclangRewrite:这个库支持代码重写,为编译器代码重构工具提供基础设施(如LibTooling这个后面再参阅);
  • libclangBasic:这个库提供一系列实用工具-内存分配抽象、源代码位置、诊断,等。
  1. 编译器驱动器,该代码在clang/tools/driver/driver.cpp中实现,clang(这里指编译器前端)和llvm前后分离,编译器驱动器将命令行参数解析,并调用实际的编译器clang -cc1对source进行编译链接。
    clang hello.c -o hello就是调用编译器驱动器;
    clang hello.c -###,可以在驱动器命令行后面加-###来查看驱动器的调用清单;

    $ clang main.c -###
    clang version 15.0.7
    Target: x86_64-unknown-linux-gnu
    Thread model: posix
    InstalledDir: /usr/local/bin
     "/usr/local/bin/clang-15" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "main.c" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-mllvm" "-treat-scalable-fixed-error-as-warning" "-debugger-tuning=gdb" "-fcoverage-compilation-dir=/home/zhimin/compiler/Clang-Learning/Lexer" "-resource-dir" "/usr/local/lib/clang/15.0.7" "-internal-isystem" "/usr/local/lib/clang/15.0.7/include" "-internal-isystem" "/usr/local/include" "-internal-isystem" "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include" "-internal-externc-isystem" "/usr/include/x86_64-linux-gnu" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-fdebug-compilation-dir=/home/zhimin/compiler/Clang-Learning/Lexer" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcolor-diagnostics" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "/tmp/main-2715fb.o" "-x" "c" "main.c"
     "/usr/bin/ld" "-pie" "-z" "relro" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "a.out" "/lib/x86_64-linux-gnu/Scrt1.o" "/lib/x86_64-linux-gnu/crti.o" "/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o" "-L/usr/lib/gcc/x86_64-linux-gnu/9" "-L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib64" "-L/lib/x86_64-linux-gnu" "-L/lib/../lib64" "-L/usr/lib/x86_64-linux-gnu" "-L/usr/lib/../lib64" "-L/lib" "-L/usr/lib" "/tmp/main-2715fb.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o" "/lib/x86_64-linux-gnu/crtn.o"
    

    通过上述结果,编译驱动器调用实际的编译器clang -cc1将clang和llvm拼接起来实现了整个编译器(注意:ld这里还是使用GNU的,原因是llvm的链接器还没有集成进来,所以clang -cc1,将source code生成目标文件后就终止了)。

    当然也可以不通过驱动器来调用clang -cc1,结果就是需要自己手动指定系统头文件的位置,通过-I 选项。

    在编译驱动器中使用-Xclang <option>可以向这个工具输入具体的参数来激活clang -cc1中的某些隐藏技能。例如clang -cc1工具有一个特殊的选项,可以打印Clang抽象语法树(AST)。可以用clang -Xclang -ast-dump main.c来激活这个功能。当然也可以直接调用clang -cc1而不是驱动器:clang -cc1 -ast-dump main.c

  2. 实际的编译器:实际的编译器就是上述所说的clang -cc1,每次调用clang -cc1都是由一种主要前端Action来控制的。完整的Action集合定义在源文件clang/include/clang/FrontendOptions.h中,如下:描述了clang -cc1可能执行的不同任务:
    在这里插入图片描述
    在这里插入图片描述
    选项 -cc1触发cc1_main函数的执行(源代码文件:clang/tools/driver/cc1_main.cpp)。例如,当通过clang hello.c -o hello间接调用-cc1时,这个函数初始化目标特定的信息,建立诊断基础设施,执行EmitObj活动。这个活动由CodeGenAction(源代码文件:clang/CodeGen/CodeGenAction.h)实现,ASTFrontendAction的一个子类。此代码实例化了所有的clang和llvm组件,指挥它们生成目标文件 。
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值