原文在此
所有D编译器分为两部分:前端和后端
前端:词法和解析d语法,实例化模板.ldc(llvm)/gdc(gcc)/dmd(boost)共享.
后端:生成代码,优化,输出目标文件
胶水层:连接前后端.

这里是源码结构

编译周期

词法(令牌数组(lexer))–构建简单语法树(parser)–然后三阶段语义处理(mars中,语义1,2,3)依次接近最终表示(解析类型,实例化模板)–

阶段 任务
1语义 分析所有声明的完整签名(聚集类型成员,函数参数和返回及变量类型,求值(pragma(msg))).
2语义 声明的其他部分(如变量声明初化器,静断条件下求值)
3语义 分析函数声明主体.如果函数不在直接声明模块中编译(不在命令行),则不分析

由于解析前向引用,每个阶段可能调用后阶段函数.

immutable string x = "hello";
static if (x == "hello") { ... }
//static if调用`x`的2语义阶段
auto foo() { ... }
typeof(&foo) fp;
//1阶段`fp`运行`3阶段foo`来推导返回类型
string foo() { ... }
mixin(foo());//ctfe,调用`3阶段foo`.

最后,传递语法树胶水层,然后交给后端产生机器码/目标文件.

运行时互操作

d运行时分配内存/操作数组,编译器用_d_样的勾挂函数来整合运行时.细节在此

细节(可能过时)
类型 意义
符号 链接器相关
dt_t 目标文件中待加数据.
元素 内部表示节点

在各种语法树节点中生成代码

节点类型 必须定义方法
语句类 toIR,
表达式 toElem.
初化器和特定子类 toDt.
声明 toObjFile.
D符号 toSymbol.

在跑了3个语义段后,如何快速遍历dmd的ir.只晓得有个符号表.

内联器

内联器前端,其遍历语法树来查找函数.通过计算是否值得再内联.
其中,一些语句不能为表达式(如循环/抛),因而,内联分两种,分别转换函数为语句(忽略返回值/调用(空/void)函数)/表达式(返回值时).这两种按不同路径内联.因为一些语句不能转成表达式.
内联器,分为四部分.

部分 细节
主入口点 利用InlineScanVisitor类expandInline函数的inlineScan.
分析成本(确定是否内联) canInline和InlineCostVisitor类
按语句 inlineAsStatement及其嵌入类
按表达式 doInline及其嵌入类InlineStatement

inlineScan入口,主要工作由expandInline完成.InlineScanVisitor找到可内联函数时,调用扩展内联.根据式/语句来相应内联.如ExpStatement/CallExp.最后由inlineAsStatement(语句)/doInline(式)来搞.

后端

DMDel元素来表示,枚举OPER看操作.列举表达式树中所有节点类型,用-O --c编译.得到各种优化.其余未文档标志:

标志 意思
--b 显示优化块
--f 完整输出
--r 显示分配寄存器
--x 抑制预定义的C++内容
--y 显示中间语言(IL)缓冲区输出

前端到后端最重要入口为优化及生成代码writefunc

序号 动作
1 writefunc设置参数,然后调用codgen来生成函数体代码.
2 为每块生成代码,然后把变量放进寄存器.
3 生成启动代码,窥孔优化.
4 优化跳
5 codout中发射代码.
6 开关表
7 异常表

cgcodblcodgen生成块代码.处理块结束中/猜/如
生成块中,cod1.gencodelem,只是调用codelem.
cgcod.codelem根据类型,为元素生成代码.
cod1,cod2, cod3, cod4, and cod5.c生成x86整.cg87生成浮点.x87比较简单,不能处理公共子表达式,因而效率低.

优化器

主要在go中的optfunc中.调用:

函数 作用
blockopt(iter) 优化基本块
constprop 常折叠
copyprop 复制
rmdeadass 删死码
verybusyexp 忙式
deadvar(gother.c) 死变量
loopopt 优化循环,删不变归纳变量,旋转循环
boolopt 优化极
builddags 公共子
el_convert 浮串至数据段
el_combine 合并两表达式
localize 改进本地性
pinholeopt 窥孔优化
生成代码

单独生成每个函数代码.每个函数,放进自己的COMDAT段.划分函数为,按跳/其他控制指令连接.

注意idgen用来生成id.h/c,表示内置符号.
impcvngen用来描述原语间转换规则.生成impcnvtab表.root.h定义基类.用指针传递类实例,在上分配.

常见缩写

这里更详细
词汇表

缩写 意思
stc 存储类
ILS 内联状态
ir 中间表示
AE 可用式
CP 复制传播
CSE 消公子,消除公共子表达式
VBE 很忙式
FFI 外部接口
DbI 自省设计
ICE 内部编译错误
IFTI 隐式函数模板实例化
NVI 非虚口
UDA 用定属
UDT 用定型
技巧

instantiatingModule(模板字段)查找,哪个模块实例化了模板.
-vcg-ast输出生成代码前最后语法树表示.用来调试模板/查找问题.dmd -vcg-ast test.d
resolve来确定Type实际类型/表达式/符号.traits.d中有示例.
DSymboltoChars/toPrettyChars来调试.
DSymbolkind来得到类型.
asttypename打印语法树节点动态名.
表达式有个令牌op字段,可Token.toChars(e.op)这样输出.
打印浮字面:toReal.
isConst检查是否为编译时已知字面.
注意编译时声明与语句的区别.

mixin("int x;");
//上面为声明
void main()
{
    mixin("int y;");//为语句.
}