变量命名方案

此方案为临时方案。尚未达成一致。编写此方案的目的是捕捉 LLVM 社区的愿望和顾虑,并将它们形成一个可以达成一致的方案。最初的作者对 LLVM 的运作方式有些生疏,因此不可避免地会有一些细节存在缺陷。您可以提供帮助 - 您可以编辑此页面(对于较大的更改,最好使用 Phabricator 进行审查)或回复征求意见邮件线程

太长不看

提高 LLVM 代码的可读性。

简介

当前的变量命名规则规定

变量名应为名词(因为它们表示状态)。名称应使用驼峰命名法,并以大写字母开头(例如 Leader 或 Boats)。

此规则与类型名相同。这是一个问题,因为类型名不能重复用作变量名[*]。LLVM 开发人员倾向于通过以下两种方式解决此问题:在类型名前添加The

Triple TheTriple;

…或者更常见的是使用缩略词,尽管编码标准规定“除非是众所周知的缩略词,否则避免使用缩略词”

Triple T;

缩略词的泛滥导致代码难以阅读,例如此处

InnerLoopVectorizer LB(L, PSE, LI, DT, TLI, TTI, AC, ORE, VF.Width, IC,
                       &LVL, &CM);

许多其他编码指南[LLDB] [Google] [WebKit] [Qt] [Rust] [Swift] [Python] 要求变量名以小写字母开头,而类名则以大写字母开头。此约定意味着最易读的变量名也需要最少的思考

Triple triple;

有些人一致认为当前规则存在问题[LattnerAgree] [ArsenaultAgree] [RobinsonAgree],并且缩略词是阅读新代码的障碍[MalyutinDistinguish] [CarruthAcronym] [PicusAcronym]。也有一些相反的观点[ParzyszekAcronym2] [RicciAcronyms]

此正在进行中的提案是为了更改变量名的编码标准,要求它们以小写字母开头。

变量命名编码标准选项

对于以小写字母开头的变量名,主要有两个选项:camelBacklower_case。(这些也以其他名称而闻名,但这里我们使用 clang-tidy 中的术语)。

camelBack[WebKit][Qt][Swift] 一致,而 lower_case[LLDB][Google][Rust][Python] 一致。

camelBack 已经用于函数名,这可能被认为是一个优势[LattnerFunction] 或一个劣势[CarruthFunction]

camelBack 的批准由[DenisovCamelBack] [LattnerFunction] [IvanovicDistinguish] 表达。对 camelBack 的反对由[CarruthCamelBack] [TurnerCamelBack] 表达。对 lower_case 的批准由[CarruthLower] [CarruthCamelBack] [TurnerLLDB] 表达。对 lower_case 的反对由[LattnerLower] 表达。

区分变量类型

另一个请求的更改是区分不同类型的变量[RobinsonDistinguish] [RobinsonDistinguish2] [JonesDistinguish] [IvanovicDistinguish] [CarruthDistinguish] [MalyutinDistinguish]

其他人反对这个想法[HähnleDistinguish] [GreeneDistinguish] [HendersonPrefix]

一种可能性是为成员变量添加 m_ 前缀,为全局变量添加 g_ 前缀,以将它们与局部变量区分开来。这与[LLDB] 一致。m_ 前缀与[WebKit] 一致。

另一种变体是为成员变量添加 m 前缀[IvanovicDistinguish] [BeylsDistinguish]。这与[Mozilla] 一致。

另一个选项是为成员变量添加 _ 后缀,这与[Google] 一致,并且类似于[Python]。遭到[ParzyszekDistinguish] 反对。

减少缩略词的数量

虽然切换编码标准将使新代码更容易使用非缩略词名称,但它并不能改善现有的广泛使用缩略词的代码库,从而损害其可读性。此外,新代码自然且通常鼓励以周围代码的风格编写。因此,尽管编码标准怎么说,许多新编写的代码也可能使用缩略词,就像今天一样。

除了更改变量名的大小写之外,还可以将它们扩展为非缩略词形式,例如 Triple TTriple triple

有些人支持扩展许多缩略词[CarruthAcronym] [PicusAcronym],但也有人更倾向于延迟扩展缩略词[ParzyszekAcronym] [CarruthAcronym]

社区内部的共识似乎是,至少某些缩略词是有价值的[ParzyszekAcronym] [LattnerAcronym]。最常引用的缩略词是 TLI,但它同时用于指代 TargetLoweringTargetLibraryInfo[GreeneDistinguish]

以下是被认为足够有用,以至于使用它们的益处大于学习它们的成本的缩略词列表。不在列表中或用于指代不同类型的缩略词应予以扩展。

类名

变量名

DeterministicFiniteAutomaton

dfa

DominatorTree

dt

LoopInfo

li

MachineFunction

mf

MachineInstr

mi

MachineRegisterInfo

mri

ScalarEvolution

se

TargetInstrInfo

tii

TargetLibraryInfo

tli

TargetRegisterInfo

tri

在某些情况下,将缩略词重命名为完整类型名称会导致代码过于冗长。与大多数类不同,变量的作用域是有限的,因此它的一些目的可以从该作用域中推断出来,这意味着不需要太多单词即可为其提供清晰的名称。例如,在优化过程中,读者可以假设变量的目的与优化有关,因此 OptimizationRemarkEmitter 变量可以命名为 remarkEmitter 甚至 remarker

以下是较长的类名与其对应的较短变量名的列表。

类名

变量名

BasicBlock

block

ConstantExpr

expr

ExecutionEngine

engine

MachineOperand

operand

OptimizationRemarkEmitter

remarker

PreservedAnalyses

analyses

PreservedAnalysesChecker

checker

TargetLowering

lowering

TargetMachine

machine

转换选项

有三种主要的转换选项

  1. 保留当前编码标准

  2. 自由放任

  3. 大爆炸式迁移

保留当前的编码规范

保留当前编码规范的支持者(即根本不进行转换)质疑转换的成本是否超过了收益 [EmersonConcern] [ReamesConcern] [BradburyConcern]。成本在于 git blame 将变得不太可用;并且合并更改对于下游维护者来说成本很高。有关潜在的缓解措施,请参阅 大爆炸

自由放任

编码规范可以允许 CamelCasecamelBack 两种样式的变量名 [LattnerTransition]

实施此项的代码审查位于 https://reviews.llvm.org/D57896

优点

  • 最初实施起来非常容易。

缺点

大爆炸

使用这种方法,变量将通过一系列大型提交中的自动化脚本进行重命名。

这种方法的主要优点是它最大程度地降低了不一致的成本 [BradburyTransition] [RobinsonTransition]

它违反了避免对现有代码进行大规模重新格式化的策略 [GreeneDistinguish]

有人建议 LLD 将成为重命名的良好入门项目 [Ueyama]

保持 git blame 可用

git blame(或 git annotate)允许快速识别更改文件中给定行的提交。在重命名变量后,许多行将显示为由该提交更改,需要进一步调用 git blame 来识别之前更有趣的提交 [GreeneGitBlame] [RicciAcronyms]

缓解措施git-hyper-blame 可以忽略或“查看”给定的提交集。可以将一个 .git-blame-ignore-revs 文件添加到 LLVM git 存储库的根目录中,该文件标识变量重命名提交。正在调查是否可以向 git blame 本身添加类似的功能。

最大程度地降低下游合并的成本

LLVM 有许多带有下游更改的分支。合并大规模重命名更改对于分支维护者来说可能很困难。

缓解措施:大规模重命名将是自动化的。分支维护者可以从重命名之前的提交合并,然后将重命名脚本应用到他们自己的分支。然后,他们可以再次从重命名提交合并,通过选择他们自己的版本来解决所有冲突。这可以在 [SVE] 分支上进行测试。

临时计划

这是 大爆炸 方法的临时计划。尚未达成一致。

  1. 调查改进 git blame。它可以“查看”提交的程度可能会影响可以进行多大更改。

  2. 编写一个脚本以扩展首字母缩略词。

  3. 试验并执行各种重构选项的预运行。结果可以在 LLVM Git 存储库的分支中发布。

  4. 考虑证据并就新策略达成一致。

  5. 商定并宣布入门项目 (LLD) 重命名的日期。

  6. 更新 策略页面。这将解释旧规则和新规则,以及每个规则适用于哪些项目。

  7. 在两个提交中重构入门项目

    1. 添加或更改项目的 .clang-tidy 以反映商定的规则。(这在单独的提交中,以启用 最大程度地降低下游合并的成本 中描述的合并过程)。还在策略页面上更新项目列表。

    2. clang-tidy 应用于项目的files,仅启用 readability-identifier-naming 规则。clang-tidy 还会根据 .clang-format 中的规则重新格式化受影响的行。预计这将是 clang-tidy 的一个很好的试用机会,并且在此过程中应修复错误,可能包括

  8. 收集反馈并根据需要改进流程。

  9. 将此流程应用于以下项目,并在每个项目之间设置适当的延迟(至少在第一次更改后 4 周,之后至少 2 周),以便收集更多反馈。此列表应排除必须遵守外部定义标准(例如 libcxx)的项目。此列表大致按重命名的顺序排列。某些项目可能没有意义单独重命名 - 预计此列表将在试验后发生变化

    • TableGen

    • llvm/tools

    • clang-tools-extra

    • clang

    • ARM 后端

    • AArch64 后端

    • AMDGPU 后端

    • ARC 后端

    • AVR 后端

    • BPF 后端

    • Hexagon 后端

    • Lanai 后端

    • MIPS 后端

    • NVPTX 后端

    • PowerPC 后端

    • RISC-V 后端

    • Sparc 后端

    • SystemZ 后端

    • WebAssembly 后端

    • X86 后端

    • XCore 后端

    • libLTO

    • 调试信息

    • llvm 的其余部分

    • compiler-rt

    • libunwind

    • openmp

    • parallel-libs

    • polly

    • lldb

  10. 从策略页面中删除旧的变量名规则。

  11. 重复序列中的许多步骤,使用脚本扩展首字母缩略词。

参考文献

[WebKit] (1,2,3)

WebKit 代码样式指南 https://webkit.org/code-style-guidelines/#names

[IvanovicDistinguish] (1,2,3)

Nemanja Ivanovic,http://lists.llvm.org/pipermail/llvm-dev/2019-February/130249.html

[ParzyszekAcronym] (1,2)

Krzysztof Parzyszek,http://lists.llvm.org/pipermail/llvm-dev/2019-February/130306.html