Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Update LoongArch psABI and toolchain conventions. #24

Merged
merged 1 commit into from
Nov 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
279 changes: 195 additions & 84 deletions docs/LoongArch-ELF-ABI-CN.adoc

Large diffs are not rendered by default.

285 changes: 198 additions & 87 deletions docs/LoongArch-ELF-ABI-EN.adoc

Large diffs are not rendered by default.

383 changes: 383 additions & 0 deletions docs/LoongArch-toolchain-conventions-CN.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,383 @@
= 龙芯架构工具链约定
龙芯中科技术股份有限公司
v1.00
:docinfodir: ../themes
:docinfo: shared
:doctype: book
Copy link
Collaborator

@FreeFlyingSheep FreeFlyingSheep Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

因为后面直接引用了images文件夹中的图片,所以要添加:imagesdir: ../images设置图片根路径。

:toc: left
:toc-title: 目录
:scripts: cjk

__注:在本文档中,"架构"、"指令集架构"、"ISA" 均表示某一指令集和可操作的寄存器集合。__


== 编译器命令行选项

=== 概述

与龙芯架构相关的编译器选项含义包括以下三方面:

1. *配置目标架构*:允许使用的指令集和寄存器范围;

2. *配置目标 ABI*:标准数据类型的表示方法,函数调用传参、返回的实现方式;

3. *配置优化参数*:用于指导编译器优化的微架构特性。

为此,编译器应实现以下两类命令行选项:

1. *基础选项*:选择编译目标的基本配置,包括 `-march` `-mabi` `-mtune`;

2. *扩展选项*:对基础选项或基础选项默认值的配置进行增量调整。

.基础选项
[%header,cols="^1m,^2,^7"]
|===
|选项
|可用值
|描述

|-march=
|`native` `loongarch64` `la464`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

仍然不建议使用未分版本的 loongarch64 取值,原因见 #23 不再重复。

目前的取值可以在实现中予以保留,但不建议在各类文档中显著体现,为得是渐渐能将该用法退出使用。

Copy link
Contributor Author

@scylaac scylaac Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个 loongarch64 包含的基础架构(也是它使能的全部指令集模块)就是 la64v100,确定不包括未来的版本更新。它假设的目标是一个指令集最小的LA64处理器,兼容性最强。

(文档里的 la64v100 实际上是一个内部抽象名称,不是命令行选项参数。)

-march 的含义是一组 ISA 模块构成的指令集范围,但不是什么组合都常用。如果指令集有更新,至少会对应一款新处理器。所以用实际的处理器核名称作为参数比较合适。这样 -mtune 的大部分取值也就不用分开枚举了,可以减少记忆负担。(版本多了可能会晕)

配置目标 ISA 时,首先从 -march 选项给出的指令集模块出发,然后叠加其他 ISA 相关选项的效应,得到编译器最终使用的指令集。如果有声明特定指令集特定版本的需求,可以考虑在后面这一种"递增配置选项"里面体现(比如可以叫 "-mver" "-msxver" 一类的名字)。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不同意向用户隐藏这些有用的细节,另外 loongarch64 表示 baseline (基线 = 所有龙芯平台功能的最大公约数)也值得商榷:从自然语言的角度,所有具体的 LA64 实现都满足 LA64,那么此处只写 loongarch64 就不提供任何额外信息。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

但是 x86-64 也有 -march=x86-64 这种东西……

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

而且对于 32 位平台上的编译器,或者是配置 -mabi=ilp32* 的情况,-march=loongarch64 其实是提供额外信息的。

|选择目标架构:设定默认可用的指令集和寄存器范围
(即默认使用的 <<isa-modules,指令集模块>> 集合)

|-mabi=
|`lp64d` `lp64f` `lp64s` `ilp32d` `ilp32f` `ilp32s`
|选择基础 ABI 类型

|-mtune=
|`native` `loongarch64` `la464`
|选择目标微架构:设定微架构相关的性能调优参数;
取值范围是 `-march` 选项的超集,默认值与 `-march` 值相同
|===

.扩展选项
[%header,cols="^1m,^2,^7"]
|===
|选项
|可用值
|描述

|-mfpu=
|`64` `32` `none` (等同于 `0`)
|选择可用的基础浮点数指令和寄存器范围

|-msoft-float
|
|`-mfpu=none` 的别名

|-msingle-float
|
|`-mfpu=32` 的别名

|-mdouble-float
|
|`-mfpu=64` 的别名
|===

=== 目标指令集架构 (ISA) 的构成

龙芯架构采用 *基础部分* 加 *扩展部分* 的组织形式,
在后续更新过程中,基础部分或扩展部分中的各功能子集都可以独立地演进,
并保证高版本总是二进制兼容低版本。

[[isa-modules]]
针对这一特点,编译器应当对目标 ISA 进行模块化抽象。
约定 ISA 模块分为两类: *基础架构* 和 *ISA 扩展特性* 。

其中,*基础架构* 为目标 ISA 的核心部分,包含基础整数指令、基础浮点数指令等功能,
由 `-march` 选项的取值唯一确定。*ISA 扩展特性* 可能对应一种单独的指令集扩展,
也可能对应基础架构或指令集扩展的增量/演进部分,由扩展选项控制是否开启。

在确定目标 ISA 配置时,应以 *基础架构* 隐含的 ISA 模块为基础,
再根据选用 / 关闭 ISA 扩展的命令行选项进行调整,得出结果。

image::compiler-isa-config-model-CN.svg[]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

svg 图片有更多的属性可以控制,具体可以参考 https://docs.asciidoctor.org/asciidoc/latest/macros/image-svg/ ,当然现在这样默认的也行。


在以下列举的所有的 ISA 模块中,编译器必须至少实现一种基础架构。

.基础架构
[%header,cols="^1,^3,^2"]
|===
|名称
|选择该基础架构的 `-march` 值
|描述

|LA64 基础架构 v1.00 (`la64v100`)
|`loongarch64` `la464`
|由 https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-CN.html[《龙芯架构参考手册 - 卷1 - 基础架构》]
v1.00 定义的指令集架构
|===

下表列举了由编译器抽象的全体 ISA 扩展特性,以及选用/关闭这些特性的命令行选项。

.ISA 扩展特性
[%header,cols="^1,^3,^2"]
|===
|名称
|编译器选项
|描述

|基础浮点运算单元 (`fpu*`)
|`-mfpu=\*` (`*` 可能取值为 `none` `32` `64`)
|选择编译器可用的基础浮点数指令和浮点寄存器,属于基础架构的一部分,
默认值由基础架构决定。
|===

下表列举了所有可同时作为 `-march` 和 `-mtune` 选项参数的目标 CPU 类型
及其相关属性。

.目标 CPU
[%header,cols="^1,^3,^2"]
|===
|名称 / 选项值
|默认选择的 ISA 模块
|性能调优目标

|`native`
|由 `cpucfg` 指令自动检测(仅适用于本地编译器)
|由 `cpucfg` 自动检测的处理器类型

|`loongarch64`
|`la64v100` [`fpu64`]
|通用 64 位龙芯架构 (LA64) 处理器

|`la464`
|`la64v100` [`fpu64`]
|LA464 处理器核
|===

[[abi-types]]
=== 应用二进制接口 (ABI) 的构成

对于龙芯架构编译器,完整的 ABI 配置应包含两个部分:
*基础 ABI* 和 *ABI 扩展特性* 。前者描述了 ABI 中整型和浮点数据的表示、
传参和返回方式,后者则代表对基础 ABI 进行的总体调整,可能需要特定 ISA 扩展支持。

需要注意的是,不同 ABI 扩展特性之间是 *互斥* 的,不能相互叠加;
具有不同扩展特性的 ABI 配置之间也 *互不兼容* 。

原则上本文档不会增加新的 ABI 扩展特性,除非它能提供
其他编译器优化技术不能单独实现的功能或性能优势。

基础 ABI 共有六种,编译器可根据实现的目标架构范围,选择实现其中的一种或多种,
其标准名称和对应的 `-mabi` 选项值一致。

.基础 ABI 类型
[%header,cols="^1,^1,^1"]
|===
|标准名称 |数据模型 |可用于传参、返回的通用/浮点寄存器宽度
|`lp64d` |lp64 |64 / 64
|`lp64f` |lp64 |64 / 32
|`lp64s` |lp64 |64 / (无)
|`ilp32d` |ilp32 |32 / 64
|`ilp32f` |ilp32 |32 / 32
|`ilp32s` |ilp32 |32 / (无)
Comment on lines +170 to +175
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“数据模型”一栏的大小写 fix 一下,用大写(“LP64”、“ILP32”)?

|===

下表列举了全体 ABI 扩展特性类型及其相关命令行选项,除 `default` 必须实现之外,
编译器可选择实现或不实现其中任何一种。

.ABI 扩展特性类型
[%header,cols="^1,^1,^1"]
|===
|名称
|编译器选项
|含义

|`default`
|(无)
|符合 https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-CN.html[龙芯架构 ELF psABI 规范]
|===

[[default-arch-abi]]
编译器的默认 ABI 应在构建时确定。此时若未明确配置 ABI 扩展类型,
则默认采用 `default` 。

若运行编译器时未给出 `-mabi` 或 ABI 扩展类型相关选项,
则应当使用构建时确定的基础 ABI 类型或 ABI 扩展类型。

原则上,实际配置的目标架构不应该对目标 ABI 的确定造成影响,
除非构建时配置或命令行选项对 ABI 的约束导致实现它所需的指令集特性
超出了编译选项对 ISA 配置的约束范围。此时编译器应报错退出。

当编译选项不能唯一确定目标架构时,
在选择默认值之前,编译器应根据下表,从命令行显式给出的 ABI 配置
推断 *基础架构* 和 *ISA 扩展特性* 的默认配置,
但不违反已给出编译选项对目标架构的明确约束。

.目标架构和默认 ABI 类型对应关系
[%header,cols="^1,^1,^1"]
|===
|目标架构包含的 ISA 模块
|基础 ABI
|ABI 扩展特性

|`la64v100` [`fpu64`]
|`lp64d`
|`default`

|`la64v100` `fpu32`
|`lp64f`
|`default`

|`la64v100` `fpunone`
|`lp64s`
|`default`
|===


== GNU 目标三元组和 Multiarch 架构标识符

*GNU 目标三元组* (target triplet) 是 GNU 构建系统用于描述目标平台的字符串,
一般包含三个字段:处理器类型 (`machine`) ,系统厂商 (`vendor`),操作系统 (`os`)。

*Multiarch 架构标识符* 是用于 multiarch 库安装路径的目录名称,
可以看作规范的 GNU 目标三元组,参见 https://wiki.debian.org/Multiarch/Tuples[Debian 文档] 。

对于龙芯架构的合法 GNU 目标三元组,约定 `machine` 字段的取值范围及其含义如下:

[[machine-strings]]
.龙芯架构 `machine` 字符串
[%header,cols="^1,^2"]
|===
|`machine` 字符串
|含义

|`loongarch64`
|LA64 基础架构,基础 ABI 为 `lp64*`

|`loongarch32`
|LA32 基础架构,基础 ABI 为 `ilp32*`
|===

作为标准的库路径名称,龙芯架构的标准 multiarch 架构标识符至少应该反映
发行到对应目录的二进制库 <<abi-types, ABI 类型>>。

原则上,在编译以二进制形式发行的库时,应当采用
<<default-arch-abi,所选 ABI 对应的默认目标指令集架构>>,
因此 multiarch 架构标识符应与目标 ABI 配置一一对应。
其中,关于整型 ABI 的部分由 `machine` 字段隐含,
基础 ABI 的浮点部分和 ABI 扩展特性则分别由连续附加在 multiarch 标识符
`os` 字段后的两个字符串后缀 (`<fabi_suffix><abiext_suffix>`) 标记。

.龙芯架构 Mulitarch 架构标识符
[%header,cols="^1,^2"]
|===
|Multiarch 架构标识符
|含义

|`<machine>-linux-gnu<fabi_suffix><abiext_suffix>`
|GNU/Linux 系统,使用 GNU C Library (glibc) 作为标准 C 库,系统内核为 Linux
|===

.Multiarch `os` 字段,`<fabi_suffix>` 后缀标记及其含义
[%header,cols="^1,^2"]
|===
|`<fabi_suffix>` 字符串 |含义
|`f64` |基础 ABI 使用 64 位浮点寄存器传参 (`lp64d` `ilp32d`)
|`f32` |基础 ABI 使用 32 位浮点寄存器传参 (`lp64f` `ilp32f`)
|`sfp` |基础 ABI 不使用浮点寄存器传参 (`lp64s` `ilp32s`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sf 即可吧?加 p 只是为了凑齐三个字符吗?从文字叙述中看不出。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是的,主要是为了对称。

|===

.Multiarch `os` 字段,`<abiext_suffix>` 后缀标记及其对应的 ABI 扩展特性
[%header,cols="^1,^2"]
|===
|`<abiext_suffix>` 字符串 |ABI 扩展特性
|(空) |`default`
|===

.全体 Mulitarch 标识符列表
[%header,cols="^1,^1,^1"]
|===
|ABI 类型(基础 ABI / ABI 扩展特性)
|操作系统类型
|Multiarch 架构标识符

|`lp64d` / `default`
|GNU/Linux
|`loongarch64-linux-gnuf64`
Copy link
Contributor

@xen0n xen0n Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

之前上游工作参考的取值应该都是 loongarch64-linux-gnu,需要做打包、上游生态工作的同学们来确认下,如果现在再改一次成这个样子,工作量有多大。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@xry111 xry111 Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以额外规定没有 suffix 的时候默认为 f64 吗?这样现有的脚本之类还能继续用。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--target=loongarch64-linux-gnu 默认为 f64 完全没问题,这里约束的主要是 multiarch 发行版的库路径名称。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗷,那不会引入除了重新编译以外的其他问题 (反正 ld.so 改名已经得重新编译了 :)


|`lp64f` / `default`
|GNU/Linux
|`loongarch64-linux-gnuf32`

|`lp64s` / `default`
|GNU/Linux
|`loongarch64-linux-gnusfp`

|`ilp32d` / `default`
|GNU/Linux
|`loongarch32-linux-gnuf64`

|`ilp32f` / `default`
|GNU/Linux
|`loongarch32-linux-gnuf32`

|`ilp32s` / `default`
|GNU/Linux
|`loongarch32-linux-gnusfp`
|===


== C/C++ 预处理器内建宏定义

.龙芯架构相关 C/C++ 预处理器内建宏
[%header,cols="^1,^3,^3"]
|===
|名称
|值
|描述

|`\\__loongarch__`
|(无)
|目标为龙芯架构

|`__loongarch_grlen`
|`64` `32`
|通用寄存器位宽

|`__loongarch_frlen`
|`0` `32` `64`
|浮点寄存器位宽(无 fpu 则为 `0` )

|`_LOONGARCH_ARCH`
|`"loongarch64"` `"la464"`
|相当于 `--with-arch` / `-march` 指定的目标 CPU 名称
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这边明确一下,如果命令行给的值是语法糖或者兼容名字,此处的值是命令行的原值还是标准化后的值,会影响代码写作和前向兼容性的。

例如,如果我们将 -march=loongarch64 实现为严格等价于 -march=la64v100,那么:

  • 如果我们此处拿到的是原值,那么使用该值的程序库为了兼容下游用户多样的编译参数,将不得不自行进行一次标准化,或者冗余写 #if _LOONGARCH_ARCH == "loongarch64" || _LOONGARCH_ARCH == "la64v100" 这样的东西;
  • 如果我们此处拿到的是标准化后的值,且没有办法拿到原值,那么万一未来的编译器将用户现在使用的取值对应的标准值变化了(例如用户给定 -march=foo,几个版本后 -march=foo 变成了 -march=bar 的别名),将 break 用户代码。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可能这里没说清楚,这个"相当"的意思是"取原值,如果没有给命令行选项,就取编译器构建时配置的默认值",不会做标准化。不同的 -march 选项值含义应当不一样。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

据我所知 gcc 的命令行参数可以有各种各样的变换(形如 %{xxx} 的写法,具体有点忘了,我开发机仍然跪着),现在这里不区分处理前后的值的话,会约束以后的代码实现。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里表达的意思其实是,如果命令行给了,就按照原文转达(包括"native"),不会做额外处理。


|`_LOONGARCH_TUNE`
|`"loongarch64"` `"la464"`
|相当于 `-mtune` 指定的目标 CPU 名称

|`__loongarch_lp64`
|(无)
|ABI 使用 64 位通用寄存器传参,采用 `lp64` 数据模型

|`__loongarch_hard_float`
|(无)
|ABI 使用浮点寄存器传参

|`__loongarch_soft_float`
|(无)
|ABI 不使用浮点寄存器传参

|`__loongarch_single_float`
|(无)
|ABI 仅使用 32 位浮点寄存器传参

|`__loongarch_double_float`
|(无)
|ABI 使用 64 位浮点寄存器传参

|`_LOONGARCH_SZINT`
|(略)
|C/C++ `int` 类型位宽

|`_LOONGARCH_SZLONG`
|(略)
|C/C++ `long int` 类型位宽

|`_LOONGARCH_SZPTR`
Comment on lines +372 to +380
Copy link
Contributor

@xen0n xen0n Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些是从旧世界带过来的预处理器符号,全大写是因为 MIPS 的这几个符号是全大写,只有 1 个前缀的下划线也是这个原因。对于新的 LoongArch 开发者而言,这部分历史是陌生的,他们只会觉得 LoongArch 甫一出世便充满了不一致。

建议起一些符合 __loongarch_xxx 的新名字。这些旧名字(包括上面 _LOONGARCH_ARCH 这些)另外列个表,说明这些名字仅用来兼容架构研发早期即写作的老代码。

|(略)
|C/C++ 指针类型位宽
|===
Loading