变量名方案

此计划是临时的。尚未达成一致。编写它的目的是为了捕捉 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,然而它既用于指代TargetLowering,也用于指代TargetLibraryInfo [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可以忽略或“穿透”给定的提交集。可以向 LLVM git 仓库根目录添加一个.git-blame-ignore-revs文件,以标识变量重命名提交。正在调查是否可以将类似的功能添加到git blame本身。

最大限度地减少下游合并的成本

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

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

临时计划

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

  1. 研究改进git blame。它可以“穿透”提交的程度可能会影响可以进行的更改有多大。

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

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

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

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

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

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

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

    2. clang-tidy应用于项目的文件,仅启用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