ZCC 使用手册
ZCC 是兆松科技基于 LLVM 开源框架开发的 RISC-V 高性能 C/C++ 编译器,支持最新的 C 和 C++ 语言标准,包括 C17、C99、C11、C++17、C++14 和 C++11 等,此外,ZCC 编译器还具有以下优势:
-
提供多版本以及定制化服务
-
支持 RVV 自动向量化及多项优化
-
支持 RISC-V 基本指令集、标准扩展以及 Nuclei、Andes 厂商自定义扩展指令集
本手册记录了 ZCC 编译器入门使用的基本方法和注意事项,因为 ZCC 是基于 LLVM 18.1.0 开发分支进行开发的编译器,所以大部分 LLVM 的编译器选项都适用于 ZCC,本文特别列出和 LLVM/GCC 不兼容的内容。
License 授权
兆松提供 ZStudio GUI 授权、CLI 在线授权以及 CLI 离线三种授权方式,三种授权都需要使用 Terapines 的账号和密码。
- 在线授权
- 离线授权
- ZStudio IDE
适用于不使用 ZStudio,使用命令行工具进行联网在线授权的用户
ZCC 工具链的 ./bin
目录下提供了用于 Linux 环境的 license.sh
脚本和用于 Windows 环境的 license.ps1
脚本用于在线授权。用户需要按照提示设置自己的账号和密码,以及 zcc 可执行文件的路径,然后运行脚本即可完成在线授权。脚本提供如下参数:
-
-d, --daemon
设置每 30 分钟自动执行一次的后台定时任务。(Windows 环境下请确保用户有管理员权限以使用
license.ps1
设置定时任务) -
-r, --remove-daemon
清除已设置的定时任务。
-
-c, --clear
清除之前的绑定,以便在不同的机器之间切换。该参数的使用限制为每小时三次。
-
-h, --help
查看使用脚本的帮助信息。
离线授权适用于只能在离线环境使用 ZCC 的用户
-
用户需要在 ZCC 工具链的 bin 目录下,运行
zcc --gen-id
生成和计算机绑定的 ID。 -
通过邮件将该 ID 发送给我们,我们会为您生成包含授权信息的文件:
TERAPINES_LICENSE_TERA
。 -
用户需将该文件存放到用户目录的
.terapines
文件夹内即可完成授权,保存的路径参考~/.terapines/TERAPINES_LICENSE_TERA
。
适用于使用 ZStudio 的用户
使用 ZStudio 的用户,在首次成功运行 ZStudio 后,点击左下角"用户" > "登录"跳转至Terapines 登录页面,输入已注册账号的用户名邮箱和密码完成授权。请参考ZStudio 登录运行
C/C++ 编译选项
-
ZCC 的自动向量化实现得非常激进,对于绝大部分的最内层循环的自动向量化,基本上可以达到和手写同等性能,甚至超过手写 intrinsic 的性能;对于多层(外层)循环向量化,效果也非常可观,对于一些实际场景当中遇到的 AI 算子,比如 correlation, resize 等,ZCC 自动向量化产生的代码性能也非常接近手写 intrinic 版本的性能。
在使用选项
-march=rv32/64gcv -O3
启用自动向量化时,如果应用程序中使用了小于 32 位(或 64 位)的运算,可以通过添加选项-mllvm --no-integer-promotions
来启用更激进的优化。开启此选项的时候需要注意,源代码当中不能出现隐式类型转换,不然编译出来的代码会有未定义行为,使用此选项的正确和错误例子分别如下所示:-
正确例子
void foo(size_t count, int8_t* channel1, int8_t* channel2, int16_t* output) {
for (size_t i = 0; i < count; i++) {
// 开启--no-integer-promotions之后,只存在int8_t到int16_t的强制类型提升
output[i] = (int16_t)channel1[i] * (int16_t)channel2[i];
}
} -
错误例子
void foo(size_t count, int8_t* channel1, int8_t* channel2, int16_t* output) {
for (size_t i = 0; i < count; i++) {
// 存在 int16_t, int8_t 到 int32_t 的隐式类型提升
output[i] = channel1[i] * channel2[i];
}
-
-
让编译器来决定哪些循环需要什么样的向量化,有时候是做不到的,特别是多层循环向量化,这个时候就需要用户使用
#pragma
来告诉编译器,需要向量化那一层循环,最大的寄存器分组应该怎么设置等等,参考下面例子://Currently, multi-level loop vectors only support loops without dependencies, or the user can ensure that the program will not have dependencies when vectorizing loops at this level.
// The option vectorize(assume_safety) is required. It mainly tells the compiler that the memory accesses in the loop will not overlap (pointer alias or partial alias). This option can also ignore unknown accesses like a[idx[i]] Due to memory limitations, please ensure that loops do not have dependencies.
//The option vectorize_width(16, scalable) optionally determines the number of RVV register groups, based on the width of the widest element in the loop multiplied by 16. If not selected, the compiler will automatically calculate an appropriate number of RVV register groups.
// as follows
// mf8 # LMUL=1/8 base on 8bit
// mf4 # LMUL=1/4 base on 16bit
// mf2 # LMUL=1/2 base on 32bit
// m1 # LMUL=1 base on 64bit
// m2 # LMUL=2 base on 128bit
// m4 # LMUL=4 base on 256bit
// m8 # LMUL=8 base on 512bit
#pragma clang loop vectorize(assume_safety) vectorize_width(16, scalable)
for (uint16_t w = 0; w < width: w++) {
.......
}信息具体使用例子可以参考 LLVM 官方手册
-
开启多层 (外层) 循环自动向量化需要添加额外选项:
-mllvm --enable-vplan-native-path
。提示此选项处于开发阶段,只有外层循环使用 pragma 才需要添加此选项,等多层自动向量化成熟之后,此选项会被移除。
-
ZCC 默认开启链接时优化,所以生成的中间结果文件(使用
-c
选项)为 llvm bytecode,如果需要分析中间结果的汇编代码,或者关闭链接时优化,可以添加-fno-lto
选项。 -
更激进的 code size 优化选项
-
-mllvm --riscv-machine-outliner=true
在 lto 的情况下(ZCC 默认开启 lto)需要使用-Wl,-mllvm,--riscv-machine-outliner=true
。该优化仅针对 code size,会导致程序性能变差。 -
--config size.cfg
选项会让 ZCC 链接有 code size 优化的库函数。
-
-
ZCC 默认情况下没有开启
fp-contract
优化,在有 F 和 D 扩展的情况下,可以手动使用选项-ffp-contract
开启此优化,可以生成更多的 FMAD 类型的指令。 -
-munaligned-access
选项可以生成非对齐内存访问指令,并将全局变量按 1 字节对齐。 -
ZCC 默认不生成 RVV strided/index load 指令,
-mllvm --riscv-enable-gather
选项可以生成 RVV strided/index load 指令。 -
ZCC RVV 自动向量化寄存器分组 lmul 为 8,
-mllvm --riscv-v-register-bit-width-lmul
选项可指定向量寄存器分组,支持 LMUL 为 1,2,4,8。 -
数据局部性优化
-fdlo
会开启数据局部性优化,这个参数在编译选项和链接选项都需要添加,目前该优化选项还在测试中。 -
RVV 循环向量化循环次数的下限,默认为 5。
-mllvm --rvv-vectorizer-min-trip-count
选项可指定循环次数下限 ,当循环小于此值时,循环不会被向量化。 -
延迟循环展开优化,使用
-flate-loop-unroll
选项打开延迟循环展开优化。它允许 ZCC 在编译和链接过程中使用更高效的循环展开算法。
Fortran 编译选项
使用 Fortran 编译器 ZFC 时,需要添加以下选项来指定 target, 需要链接的 libraries 及其在文件系统中的路径。
--target=riscv64-unknown-linux-gnu -L ./install-zcc_protected/riscv64-unknown-linux-gnu/lib -lFortran_main -lFortranRuntime -lpthread -lm
目前兆松提供的 Fortran 编译器 ZFC 仅支持 Linux rv64imafdc ,后续版本将添加非 Linux 和其他架构支持。
和 GCC 不兼容的链接选项
gcc -specs
GCC 可以使用多个 --specs
来指定复杂的编译选项文件来覆盖默认的编译选项,针对 newlib 而言,可以使用的 spec 文件包括 nano.specs, nosys.specs, simihost.specs 等等。
ZCC 则通过 --config
使用单一组合的 cfg 文件来指定,由于不允许给 ZCC 指定多个 --config
选项,所以 ZCC 工具链针对 newlib 的 cfg 文件包含 nano-nosys.cfg, nano.cfg, nosys.cfg, sim.cfg 和 semihost.cfg。
Multi target
ZCC 是 multi-target, multi-arch, multi-abi 的编译器。默认情况下,ZCC
会生成 rv32imafdc/ilp32d 的目标代码,如果需要使用 ZCC 生成其他类型的 目标代码,需要同时使用 -march=<arch>
和 -mabi=<abi>
选项,不然有可能导致链接错误,可用的 arch/abi 选项组合见 Multilib
如果使用 ZCC 生成 rv64 的代码,需要同时指定 --target=riscv64-unknown-elf
,否则会导致链接错误。
Code model
ZCC 使用 -mcmodel
设置代码模型,ZCC 编译器目前支持 medany
, medlow
选项,在 RISC-V 架构中分别等效于 GCC 编译器的 medium
, small
选项。
Align arguments (RISC-V)
align target | GCC | ZCC |
---|---|---|
align function | -falign-functions=n:m:n2:m2 ;--align-functions=n:m:n2:m2 | -falign-functions=N ;-mllvm --align-all-functions=unit |
align all branch targets | -falign-labels=n:m:n2:m2 ;--align-labels=n:m:n2:m2 | -falign-labels=N(ignore) ;--align-labels=N(ignore) ;-mllvm --align-all-blocks=unit |
align loops | -falign-loops=n:m:n2:m2 ; --align-loops=n:m:n2:m2 | -falign-loops=N ;--align-loops=N(ignore) |
align branch target can only be reached by jumping | -falign-jumps=n:m:n2:m2 ;--align-jumps=n:m:n2:m2 | -falign-jumps=N(ignore) ; --align-jumps=N(ignore) ;-mllvm --align-all-nofallthru-blocks=unit |
-
ignore: ZCC 接受该参数,但不会执行任何操作
-
N: 必须是 2 的幂。(例如,4 表示按 4 字节边界对齐,
-falign-functions=8
表示函数将对齐到 8 字节边界。) -
unit: 强制以 log2 格式进行对齐。(例如,4 表示按 16 字节边界对齐,
-mllvm --align-all-functions=8
表示函数将对齐到 256 字节边界。)
链接脚本
-
ZCC 的 linker 不支持链接脚本里面的
DEFINED
宏,对于使用了DEFINED
的 linker script,目前需要做类似的修改:- __stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
+ __stack_size = 2K; -
GNU 的 ld 对 linker script 的 MEMORY command 支持情况见 sourceware 文档,目前 ZCC 支持绝大多数 MEMORY command, 但是不支持"I"属性,所以对于使用了
I
命令的 ldscript,我们需要做如下类型的修改:MEMORY
{
- ilm (rxai!w) : ORIGIN = 0x80000000, LENGTH = 64K
- ram (wxa!ri) : ORIGIN = 0x90000000, LENGTH = 64K
+ ilm (rxa!w) : ORIGIN = 0x80000000, LENGTH = 64K
+ ram (wxa!r) : ORIGIN = 0x90000000, LENGTH = 64K
} -
ZCC 的链接脚本不支持 GNU ld 的 output section 基于当前位置的累加操作,所以如果需要定义当前位置在 output section 的偏移,需要使用绝对地址,例如,需要把原有的
.= __stack_size;
替换为.+= __stack_size;
。例子如下:.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( _heap_end = . );
- . = __stack_size;
+ . += __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram -
ZCC 会默认把 ldscripts 里面的非内建 section 给编译到
.data
段,如果需要把这些 section 放到.bss
,可以使用NOLOAD
属性,例如nuclei_sdk
里面的gcc_demosoc_ilm.ld
编译脚本关于.stack
部分,可以做如下修改适配 ZCC:- .stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
+ .stack ORIGIN(ram) + LENGTH(ram) - __stack_size (NOLOAD) :
{
PROVIDE( _heap_end = . );
- . = __stack_size;
+ . += __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram
} -
如果手动使用
_attribute_((section(".sec_abc")))
告诉 linker 保留特 定的初始化函数指针在指定的 section,但是 C/C++ 的源代码并没有使用这个包含函数指针的对象,编译器会把这个对象给优化掉,所以需要手动添加used
属性强制编译器不要优化掉这个未使用的对象,例如_attribute_((section(".sec_abc"), used))
。 -
汇编代码/内联汇编的负数表示
GNU as 会分别针对 32/64 位的数,在对应的 32/64 位平台做 sign extend,比如 GNU as 在 rv32 情况下,会识别
0xFFFFF800
为-2048
,GNU as 在 rv64 情况下会对下面代码报错。但是 ZCC 的 as 无论在 rv32 还是 rv64 的情况下,都认为0xFFFFF800
是一个正数。and a0, a0, 0xFFFFF800
并且,GNU assembler user guide 里面有明确说明,如果要在汇编代码里面使用负数,需要明确使用负号“-”前缀,如下所示:
and a0, a0, -0x800
-
lld 不支持对于 output section 层级的 ALIGN_WITH_INPUT 的属性,我们可以用 ALIGN(x) 的属性来指定,比如
- .data : ALIGN_WITH_INPUT
+ .data : ALIGN(8)
{
. = ALIGN(8)
...
} -
linker 中
-M
与-Map
参数同时使用时的问题-
GCC 的行为是最后一个参数生效,如
-Wl,-M,-Map
时-Map
生效,-Wl,-Map,-M
时-M
生效。 -
Clang 的行为是只要两个参数同时使用,一定会是
-M
生效,目前 ZCC 的行为与 Clang 一致。
-
-
ZCC 使用的 libunwind 库中引用了
eh_frame_start
,eh_frame_end
,eh_frame_hdr_start
,eh_frame_hdr_end
这些符号的值,使用自己的链接器脚本时需要加上以下代码来设置这些符号的值:eh_frame :
{
__eh_frame_start = .;
KEEP(*(.eh_frame))
__eh_frame_end = .;
}
.eh_frame_hdr :
{
KEEP(*(.eh_frame_hdr))
}
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
Multilib
ZCC 对 RISC-V Multiarch/ABI 目前支持以下列表:
march=rv32eac/ilp32e@march=rv32eac@mabi=ilp32e
march=rv32ea_zca_zcb_zcmp_zcmt/ilp32e@march=rv32ea_zca_zcb_zcmp_zcmt@mabi=ilp32e
march=rv32ec/ilp32e@march=rv32ec@mabi=ilp32e
march=rv32ec_zmmul/ilp32e@march=rv32ec_zmmul@mabi=ilp32e
march=rv32emac/ilp32e@march=rv32emac@mabi=ilp32e
march=rv32ema_zca_zcb_zcmp_zcmt/ilp32e@march=rv32ema_zca_zcb_zcmp_zcmt@mabi=ilp32e
march=rv32emc/ilp32e@march=rv32emc@mabi=ilp32e
march=rv32em_zca_zcb_zcmp_zcmt/ilp32e@march=rv32em_zca_zcb_zcmp_zcmt@mabi=ilp32e
march=rv32e_zca_zcb_zcmp_zcmt/ilp32e@march=rv32e_zca_zcb_zcmp_zcmt@mabi=ilp32e
march=rv32e_zmmul_zca_zcb_zcmp_zcmt/ilp32e@march=rv32e_zmmul_zca_zcb_zcmp_zcmt@mabi=ilp32e
march=rv32imafdc/ilp32d@march=rv32imafdc@mabi=ilp32d
march=rv32iac/ilp32@march=rv32iac@mabi=ilp32
march=rv32ia_zca_zcb_zcmp_zcmt/ilp32@march=rv32ia_zca_zcb_zcmp_zcmt@mabi=ilp32
march=rv32ic/ilp32@march=rv32ic@mabi=ilp32
march=rv32ic_zmmul/ilp32@march=rv32ic_zmmul@mabi=ilp32
march=rv32imac/ilp32@march=rv32imac@mabi=ilp32
march=rv32imac_xxldsp/ilp32@march=rv32imac_xxldsp@mabi=ilp32
march=rv32imac_zba_zbb_zbc_zbs/ilp32@march=rv32imac_zba_zbb_zbc_zbs@mabi=ilp32
march=rv32imac_zba_zbb_zbc_zbs_xxldsp/ilp32@march=rv32imac_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32
march=rv32imafc/ilp32f@march=rv32imafc@mabi=ilp32f
march=rv32imafc_xxldsp/ilp32f@march=rv32imafc_xxldsp@mabi=ilp32f
march=rv32imafc_zba_zbb_zbc_zbs/ilp32f@march=rv32imafc_zba_zbb_zbc_zbs@mabi=ilp32f
march=rv32imafc_zba_zbb_zbc_zbs_xxldsp/ilp32f@march=rv32imafc_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32f
march=rv32imafc_zp052b/ilp32f@march=rv32imafc_zp052b@mabi=ilp32f
march=rv32imafc_zp052b_xandes/ilp32f@march=rv32imafc_zp052b_xandes@mabi=ilp32f
march=rv32imafdc/ilp32d@march=rv32imafdc@mabi=ilp32d
march=rv32imafdc_xxldsp/ilp32d@march=rv32imafdc_xxldsp@mabi=ilp32d
march=rv32imafdc_zba_zbb_zbc_zbs/ilp32d@march=rv32imafdc_zba_zbb_zbc_zbs@mabi=ilp32d
march=rv32imafdc_zba_zbb_zbc_zbs_xxldsp/ilp32d@march=rv32imafdc_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32d
march=rv32imafdc_zp052b/ilp32d@march=rv32imafdc_zp052b@mabi=ilp32d
march=rv32imafdc_zp052b_xandes/ilp32d@march=rv32imafdc_zp052b_xandes@mabi=ilp32d
march=rv32imafd_zca_zcb_zcd_zcf/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf@mabi=ilp32d
march=rv32imafd_zca_zcb_zcd_zcf_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf_xxldsp@mabi=ilp32d
march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs@mabi=ilp32d
march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcd_zcf_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32d
march=rv32imafd_zca_zcb_zcf_zcmp_zcmt/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt@mabi=ilp32d
march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_xxldsp@mabi=ilp32d
march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=ilp32d
march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp/ilp32d@march=rv32imafd_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32d
march=rv32imaf_zca_zcb_zcf_zcmp_zcmt/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt@mabi=ilp32f
march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_xxldsp/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_xxldsp@mabi=ilp32f
march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=ilp32f
march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp/ilp32f@march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32f
march=rv32ima_zca_zcb_zcmp_zcmt/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt@mabi=ilp32
march=rv32ima_zca_zcb_zcmp_zcmt_xxldsp/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt_xxldsp@mabi=ilp32
march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=ilp32
march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp/ilp32@march=rv32ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs_xxldsp@mabi=ilp32
march=rv32imc/ilp32@march=rv32imc@mabi=ilp32
march=rv32im_zca_zcb_zcmp_zcmt/ilp32@march=rv32im_zca_zcb_zcmp_zcmt@mabi=ilp32
march=rv32i_zca_zcb_zcmp_zcmt/ilp32@march=rv32i_zca_zcb_zcmp_zcmt@mabi=ilp32
march=rv32i_zmmul_zca_zcb_zcmp_zcmt/ilp32@march=rv32i_zmmul_zca_zcb_zcmp_zcmt@mabi=ilp32
march=rv64imafdc/lp64d@march=rv64imafdc@mabi=lp64d
march=rv64imafdcv/lp64d@march=rv64imafdcv@mabi=lp64d
march=rv64imafdv/lp64d@march=rv64imafdv@mabi=lp64d
march=rv64imac/lp64@march=rv64imac@mabi=lp64
march=rv64imac_zba_zbb_zbc_zbs/lp64@march=rv64imac_zba_zbb_zbc_zbs@mabi=lp64
march=rv64imafc/lp64f@march=rv64imafc@mabi=lp64f
march=rv64imafc_zba_zbb_zbc_zbs/lp64f@march=rv64imafc_zba_zbb_zbc_zbs@mabi=lp64f
march=rv64imafdc/lp64d@march=rv64imafdc@mabi=lp64d
march=rv64imafdc_zba_zbb_zbc_zbs/lp64d@march=rv64imafdc_zba_zbb_zbc_zbs@mabi=lp64d
march=rv64imafd_zca_zcb_zcd/lp64d@march=rv64imafd_zca_zcb_zcd@mabi=lp64d
march=rv64imafd_zca_zcb_zcd_zba_zbb_zbc_zbs/lp64d@march=rv64imafd_zca_zcb_zcd_zba_zbb_zbc_zbs@mabi=lp64d
march=rv64imafd_zca_zcb_zcmp_zcmt/lp64d@march=rv64imafd_zca_zcb_zcmp_zcmt@mabi=lp64d
march=rv64imafd_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/lp64d@march=rv64imafd_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=lp64d
march=rv64imaf_zca_zcb_zcmp_zcmt/lp64f@march=rv64imaf_zca_zcb_zcmp_zcmt@mabi=lp64f
march=rv64imaf_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/lp64f@march=rv64imaf_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=lp64f
march=rv64ima_zca_zcb_zcmp_zcmt/lp64@march=rv64ima_zca_zcb_zcmp_zcmt@mabi=lp64
march=rv64ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs/lp64@march=rv64ima_zca_zcb_zcmp_zcmt_zba_zbb_zbc_zbs@mabi=lp64
获取帮助
ZCC Lite
关于 ZCC Lite 的任何使用体验,欢迎大家前往无限智域(1nfinite)开发者社区针对使用体验展开话题,我们团队将及时答疑并尽力改进用户体验。
ZCC Pro/ZCC FuSa
我们为 ZCC Pro/ZCC FuSa 用户开放了 Issue 追踪平台,使用 ZCC 过程中发现任何 BUG 请通过 ticket 入口向我们提供反馈。