跳到主要内容
版本:4.x

ZCC 4.x 使用手册

ZCC 是兆松科技基于 LLVM 开源框架开发的 RISC-V 高性能 C/C++ 编译器,支持最新的 C 和 C++ 语言标准,包括 C17、C99、C11、C++17、C++14 和 C++11 等,此外,ZCC 编译器还具有以下优势:

  • 支持 RVV 自动向量化及多项优化

  • 支持 RISC-V 基本指令集、标准扩展以及 XuanTie、Nuclei、Andes 厂商自定义扩展指令集

下载安装

高性能 RISC-V 工具链 ZCC 提供 Windows 和 Linux 版本。

系统要求

请查看系统要求以确认您的计算机是否符合工具链支持的运行环境。

  • Windows : Windows 10 (32-bit and 64-bit) 及以上

  • Linux :

    • Ubuntu 18, Ubuntu 20, Ubuntu 22.04 and Ubuntu 24.04

    • Centos 6, CentOS 7 and Centos8

    • Fedora 42

    • openSUSE Leap 15.5

使用 Terapines Installer 安装

推荐使用 Terapines Installer 便捷地安装兆松科技的产品。对于无图形界面的用户,请使用命令行安装器(CLI Installer)。

  1. ZCC 下载页面选择 Windows 平台的安装器可执行文件 .exe

  2. 使用管理员权限运行 Installer 并选择需要安装的 ZCC 版本。

  3. ZCC 工具链默认包含 LibZCC,如需要额外的扩展功能,请选择合适的软件库进行安装。所有安装的 ZCC 软件包都将直接安装进工具链中并应用于全局。

    • LibDSP: 专门设计用于数字信号处理(DSP)的函数和工具。

    • LibNN: 专门用于实现和运行神经网络(NN)算法的库。

安装完成后可以打开 Product Manager 进行多版本管理。社区版用户无需登录即可使用,商业版用户在 Product Manager 中登录 Terapines 账号即可激活授权许可。

open product manager

product manager main menu

更新 ZCC

用户可以通过 Terapines Product Manager(产品管理器)更新 ZCC 并进行多版本管理。保持 ZCC 版本更新,可以确保获得最新的功能和性能优化。

  1. 打开电脑上的 Terapines 产品管理器,在左侧导航栏展开可用版本(Available)
  2. 找到列表中的最新 ZCC 版本,选择该版本并点击安装(Install)

开启邮件通知

推荐开启自动邮件提醒,及时获取最新 ZCC 更新信息。点击产品管理器右上角的设置图标。进入个人资料(Profile)页面,打开邮件通知开关。

toggle on email notification

email notification

开启后,每当有新版本发布时将收到邮件通知。前往 Terapines Product Manager(产品管理器)即可及时更新 ZCC。

语言标准支持

ZCC 编译器支持最新的 C 和 C++ 语言标准。

  • -x <language>

    用于将输入文件看待为 C 文件或者 C++ 文件。<language> 可选项是 C 和 C++。

  • -std=<standard>

    选择用来编译的语言标准,目前 ZCC 支持的语言标准如下表所示。ZCC 支持的所有语言标准规则及细则与上游保持一致。请参考 C++ Support in ClangC Support in Clang

  • -ansi

    等同于 "-std=c89",用于将语言标准设置为 c89。

StandardsVersions
C Standardc18; c17; c11; c99; c90; c89
C++ Standardc++17; c++14; c++11; c++03; c++98
GNU Cgnu18; gnu17; gnu11; gnu89; gnu++17; gnu++14; gnu++11; gnu++98
ISO Ciso9899:2018; iso9899:2017; iso9899:2011; iso9899:1999; iso9899:199409; iso9899:1990
提示
  • C17 & C18:C18 也被称为 C17。它于 2017 年编写并于 2018 年发布。
  • C89 & C90:C89 和 C90 通常指同一种语言。C89 在 1989 年完成,1990 年被国际标准化组织采用并带有一些小改动。

目标平台支持

使用 -print-supported-extensions 打印 ZCC 所支持的所有扩展指令集选项。

RISC-V 基础 ISAs

ZCC 支持了三种基础指令集 RV32I,RV64I,RV32E。

支持的 target triple:

  • riscv32 XLEN=32 的 RISC-V(即 RV32I 或 RV32E)
  • riscv64 XLEN=64 的 RISC-V(即 RV64I)

要选择 E 扩展 ISA(例如 RV32E 而不是 RV32I),请使用基本架构字符串(例如 riscv32)与扩展名 e。

RISC-V 扩展

下表提供了 ZCC 中保证了兼容性的扩展,其中包括官方标准扩展以及部分旧版本的实验性扩展。

提示

例如,Zp052b 扩展是 P 扩展的 0.52 版本,是一个旧版本的实验性扩展。ZCC 将该版本提取成一个标准版本,并且给予命名 Zp052b。使用此扩展时,不需要添加版本号,直接使用 zp052b 即可。

zcc -march=rv32imaczp052b -c hello.c
zcc -march=rv32imafdc -c hello.c
ExtensionVersionFeatureDescription
I2.1iBase Integer Instruction Set
E2.0eImplements RV64E (provides 16 rather than 32 GPRs)
M2.0mInteger Multiplication and Division
A2.1aAtomic Instructions
F2.2fSingle-Precision Floating-Point
D2.2dDouble-Precision Floating-Point
C2.0cCompressed Instructions
B1.0bThe collection of the Zba, Zbb, Zbs extensions
V1.0vVector Extension for Application Processors
H1.0hHypervisor
Zic64b1.0zic64bCache Block Size Is 64 Bytes
Zicbom1.0zicbomCache-Block Management Instructions
Zicbop1.0zicbopCache-Block Prefetch Instructions
Zicboz1.0zicbozCache-Block Zero Instructions
Ziccamoa1.0ziccamoaMain Memory Supports All Atomics in A
Ziccif1.0ziccifMain Memory Supports Instruction Fetch with Atomicity Requirement
Zicclsm1.0zicclsmMain Memory Supports Misaligned Loads/Stores
Ziccrse1.0ziccrseMain Memory Supports Forward Progress on LR/SC Sequences
Zicntr2.0zicntrBase Counters and Timers
Zicond1.0zicondInteger Conditional Operations
Zicsr2.0zicsrControl and Status Register (CSR) Instructions
Zifencei2.0zifenceifence.i
Zihintntl1.0zihintntlNon-Temporal Locality Hints
Zihintpause2.0zihintpausePause Hint
Zihpm2.0zihpmHardware Performance Counters
Zilsd1.0zilsdLoad/Store Pair Instructions
Zimop1.0zimopMay-Be-Operations
Zmmul1.0zmmulInteger Multiplication
Za128rs1.0za128rsReservation Set Size of at Most 128 Bytes
Za64rs1.0za64rsReservation Set Size of at Most 64 Bytes
Zaamo1.0zaamoAtomic Memory Operations
Zabha1.0zabhaByte and Halfword Atomic Memory Operations
Zacas1.0zacasAtomic Compare-And-Swap Instructions
Zalrsc1.0zalrscLoad-Reserved/Store-Conditional
Zama16b1.0zama16bAtomic 16-byte misaligned loads, stores and AMOs
Zawrs1.0zawrsWait on Reservation Set
Zfa1.0zfaAdditional Floating-Point
Zfbfmin1.0zfbfminScalar BF16 Converts
Zfh1.0zfhHalf-Precision Floating-Point
Zfhmin1.0zfhminHalf-Precision Floating-Point Minimal
Zfinx1.0zfinxFloat in Integer
Zdinx1.0zdinxDouble in Integer
Zca1.0zcaPart of the C extension, excluding compressed floating point loads/stores
Zcb1.0zcbCompressed basic bit manipulation instructions
Zcd1.0zcdCompressed Double-Precision Floating-Point Instructions
Zce1.0zceCompressed extensions for microcontrollers
Zcf1.0zcfCompressed Single-Precision Floating-Point Instructions
Zclsd1.0zclsdCompressed Load/Store Pair Instructions
Zcmop1.0zcmopCompressed May-Be-Operations
Zcmp1.0zcmpSequenced instructions for code-size reduction
Zcmt1.0zcmtTable jump instructions for code-size reduction
Zba1.0zbaAddress Generation Instructions
Zbb1.0zbbBasic Bit-Manipulation
Zbc1.0zbcCarry-Less Multiplication
Zbkb1.0zbkbBitmanip instructions for Cryptography
Zbkc1.0zbkcCarry-less multiply instructions for Cryptography
Zbkx1.0zbkxCrossbar permutation instructions
Zbs1.0zbsSingle-Bit Instructions
Zk1.0zkStandard scalar cryptography extension
Zkn1.0zknNIST Algorithm Suite
Zknd1.0zkndNIST Suite: AES Decryption
Zkne1.0zkneNIST Suite: AES Encryption
Zknh1.0zknhNIST Suite: Hash Function Instructions
Zkr1.0zkrEntropy Source Extension
Zks1.0zksShangMi Algorithm Suite
Zksed1.0zksedShangMi Suite: SM4 Block Cipher Instructions
Zksh1.0zkshShangMi Suite: SM3 Hash Function Instructions
Zkt1.0zktData Independent Execution Latency
Ztso1.0ztsoMemory Model - Total Store Order
Zp052b0.5zp052bPacked-SIMD Instructions
Zp053b0.5zp053bPacked-SIMD Instructions
Zp054b0.5zp054bPacked-SIMD Instructions
Zp095b1.0zp095bRV32 only 'P' Instructions
Zp64054b0.5zp64054bPacked-SIMD Instructions
Zpn095b1.0zpn095bNormal 'P' Instructions
Zprvsfextra095b1.0zprvsfextra095bRV64 only 'P' Instructions
Zpsfoperand095b1.0zpsfoperand095bPaired-register operand 'P' Instructions
Zvbb1.0zvbbVector basic bit-manipulation instructions
Zvbc1.0zvbcVector Carryless Multiplication
Zve32f1.0zve32fVector Extensions for Embedded Processors with maximal 32 EEW and F ex
Zve32x1.0zve32xVector Extensions for Embedded Processors with maximal 32 EEW
Zve64d1.0zve64dVector Extensions for Embedded Processors with maximal 64 EEW, F and D
Zve64f1.0zve64fVector Extensions for Embedded Processors with maximal 64 EEW and F ex
Zve64x1.0zve64xVector Extensions for Embedded Processors with maximal 64 EEW
Zvbfmin1.0zvfbfminVector BF16 Converts
Zvfbfwma1.0zvfbfwmaVector BF16 widening mul-add
Zvfh1.0zvfhVector Half-Precision Floating-Point
Zvfhmin1.0zvfhminVector Half-Precision Floating-Point Minimal
Zvkb1.0zvkbVector Bit-manipulation used in Cryptography
Zvkg1.0zvkgVector GCM instructions for Cryptography
Zvkn1.0zvknShorthand for 'Zvkned', 'Zvknhb', 'Zvkb', and 'Zvkt'
Zvknc1.0zvkncShorthand for 'Zvknc' and 'Zvbc'
Zvkned1.0zvknedVector AES Encryption & Decryption (Single Round)
Zvkng1.0zvkngShorthand for 'Zvkn' and 'Zvkg'
Zvknha1.0zvknhaVector SHA-2 (SHA-256 only)
Zvknhb1.0zvknhbVector SHA-2 (SHA-256 and SHA-512)
Zvks1.0zvksShorthand for 'Zvksed', 'Zvksh', 'Zvkb', and 'Zvkt'
Zvksc1.0zvkscShorthand for 'Zvks' and 'Zvbc'
Zvksed1.0zvksedSM4 Block Cipher Instructions
Zvksg1.0zvksgShorthand for 'Zvks' and 'Zvkg'
Zvksh1.0zvkshSM3 Hash Function Instructions
Zvkt1.0zvktVector Data-Independent Execution Latency
Zvl1.0zvl1024bZvl (Minimum Vector Length) 1024
Zvl1.0zvl128bZvl (Minimum Vector Length) 128
Zvl1.0zvl16384bZvl (Minimum Vector Length) 16384
Zvl1.0zvl2048bZvl (Minimum Vector Length) 2048
Zvl1.0zvl256bZvl (Minimum Vector Length) 256
Zvl1.0zvl32768bZvl (Minimum Vector Length) 32768
Zvl1.0zvl32bZvl (Minimum Vector Length) 32
Zvl1.0zvl4096bZvl (Minimum Vector Length) 4096
Zvl1.0zvl512bZvl (Minimum Vector Length) 512
Zvl1.0zvl64bZvl (Minimum Vector Length) 64
Zvl1.0zvl65536bZvl (Minimum Vector Length) 65536
Zvl1.0zvl8192bZvl (Minimum Vector Length) 8192
Zhinx1.0zhinxZhinx (Half Float in Integer)
Zhinxmin1.0zhinxminZhinxmin (Half Float in Integer Minimal)
Shcounterenw1.0shcounterenwSupport writeable hcounteren enable bit for any hpmcounter that is not read-only zero
Sgatpa1.0shgatpaSvNNx4 mode supported for all modes supported by satp, as well as Bare
Shtvala1.0shtvalahtval provides all needed values
Svsatpa1.0shvsatpavsatp supports all modes supported by satp
Shvstvala1.0shvstvalavstval provides all needed values
Shvstvecd1.0shvstvecdvstvec supports Direct mode
Smaia1.0smaiaAdvanced Interrupt Architecture Machine Level
Smcdeleg1.0smcdelegCounter Delegation Machine Level
Smcsrind1.0smcsrindIndirect CSR Access Machine Level
Smepmp1.0smepmpEnhanced Physical Memory Protection
Smrnmi1.0smrnmiResumable Non-Maskable Interrupts
Smstateen1.0smstateenMachine-mode view of the state-enable extension
Ssaia1.0ssaiaAdvanced Interrupt Architecture Supervisor Level
Ssccfg1.0ssccfgCounter Configuration Supervisor Level
Ssccptr1.0ssccptrMain memory supports page table reads
Sscofpmf1.0sscofpmfCount Overflow and Mode-Based Filtering
Sscounterenw1.0sscounterenwSupport writeable scounteren enable bit for any hpmcounter that is not read-only zero
Sscsrind1.0sscsrindIndirect CSR Access Supervisor Level
Ssqosid1.0ssqosidQuality-of-Service (QoS) Identifiers
Ssstateen1.0ssstateenSupervisor-mode view of the state-enable extension
Ssstrict1.0ssstrictNo non-conforming extensions are present
Sstc1.0sstcSupervisor-mode timer interrupts
Sstvala1.0sstvalastval provides all needed values
Sstvecd1.0sstvecdstvec supports Direct mode
Ssu64xl1.0ssu64xlUXLEN=64 supported
Svade1.0svadeRaise exceptions on improper A/D bits
Svadu1.0svaduHardware A/D updates
Svbare1.0svbare$(satp mode Bare supported)
Svinval1.0svinvalFine-Grained Address-Translation Cache Invalidation
Svnapot1.0svnapotNAPOT Translation Contiguity
Svpbmt1.0svpbmtPage-Based Memory Types
Svvptc1.0svvptcObviating Memory-Management Instructions after Marking PTEs Valid

RISC-V 实验性扩展

包含还未批准的实验性指令扩展,工具链版本之间不保证兼容性。使用这些扩展时需要添加版本号。

提示

例如,在使用 Zalasr 扩展时,需要添加版本号,即使用 zalasr0p1 而不是 zalasr

  zcc -march=rv32imaczalasr0p1 -c hello.c
zcc -march=rv32imaczicfiss1p0 -c hello.c
ExtensionVersionFeatureDescription
Zicfiss1.0zicfissShadow stack
Zalasr0.1zalasrLoad-Acquire and Store-Release Instructions
Smmpm1.0smmpmMachine-level Pointer Masking for M-mode
Smnpm1.0smnpmMachine-level Pointer Masking for next lower privilege mode
Ssnpm1.0ssnpmSupervisor-level Pointer Masking for next lower privilege mode
Sspm1.0sspmIndicates Supervisor-mode Pointer Masking

RISC-V 供应商扩展

下表列举了硬件厂商定义的非标准的自定义扩展在 ZCC 中的支持情况。

ExtensionVersionFeatureDescription
Xandes5.0xandesAndeStar V5 Extension Specification
XCValu1.0xcvaluCORE-V ALU Operations
XCVbi1.0xcvbiCORE-V Immediate Branching
XCVbitmanip1.0xcvbitmanipCORE-V Bit Manipulation
XCVelw1.0xcvelwCORE-V Event Load Word
XCVmac1.0xcvmacCORE-V Multiply-Accumulate
XCVmem1.0xcvmemCORE-V Post-incrementing Load & Store
XCVsimd1.0xcvsimdCORE-V SIMD ALU
Xp4.0xgap8dspGAP8 DSP extension
Xm4.0xgap8mGAP8 Integer Multiplication
Xv4.0xgap8vGAP8 Vector extension
XSfcease1.0xsfceaseSiFive sf.cease Instruction
XSfvcp1.0xsfvcpSiFive Custom Vector Coprocessor Interface Instructions
XSfvfnrclipxfqf1.0xsfvfnrclipxfqfSiFive FP32-to-int8 Ranged Clip Instructions
XSfvfwmaccqqq1.0xsfvfwmaccqqqSiFive Matrix Multiply Accumulate Instruction and 4-by-4
XSfvqmaccdod1.0xsfvqmaccdodSiFive Int8 Matrix Multiplication Instructions 2-by-8 and 8-by-2
XSfvqmaccqoq1.0xsfvqmaccqoqSiFive Int8 Matrix Multiplication Instructions 4-by-8 and 8-by-4
XSiFivecdiscarddlone1.0xsifivecdiscarddloneSiFive sf.cdiscard.d.l1 Instruction
XSiFivecflushdlone1.0xsifivecflushdloneSiFive sf.cflush.d.l1 Instruction
XTHeadBa1.0xtheadbaT-Head address calculation instructions
XTHeadBb1.0xtheadbbT-Head basic bit-manipulation instructions
XTHeadBs1.0xtheadbsT-Head single-bit instructions
XTHeadC2.0xtheadcT-Head C series performance-enhanced instruction set
XTHeadCBI1.0xtheadcbiXuantie coprocessor basic integer intruction
XTHeadCEI1.0xtheadceiXuantie coprocessor enhanced integer intruction
XTHeadCF1.0xtheadcfXuantie coprocessor float intruction
XTHeadCmo1.0xtheadcmoT-Head cache management instructions
XTHeadCondMov1.0xtheadcondmovT-Head conditional move instructions
XTHeadCV1.0xtheadcvXuantie coprocessor vector intruction
XTHeadE2.0xtheadeT-Head E series performance-enhanced instruction set
XTHeadFMemIdx1.0xtheadfmemidxT-Head FP Indexed Memory Operations
XTHeadFMv1.0xtheadfmvT-Head FP Move Instructions
XTHeadInt1.0xtheadintT-Head Acceleration Interruption Instructions
XTHeadLPW1.0xtheadlpwT-Head Low Power Wait Instructions
XTHeadMac1.0xtheadmacT-Head Multiply-Accumulate Instructions
XTHeadMemIdx1.0xtheadmemidxT-Head Indexed Memory Operations
XTHeadMemPair1.0xtheadmempairT-Head two-GPR Memory Operations
XTHeadSE2.0xtheadseT-Head Small E series performance-enhanced instruction set
XTHeadSync1.0xtheadsyncT-Head multicore synchronization instructions
XTHeadVdot1.0xtheadvdotT-Head Vector Extensions for Dot
XVentanaCondOps1.0xventanacondopsVentana Conditional Ops
Xwchc2.2xwchcWCH/QingKe additional compressed opcodes
Xxlcz1.0xxlczNuclei Additional Xlcz Instruction for Codesize
Xxldsp1.0xxldspNuclei customized DSP instructions for both RV32 and RV64
Xxldspn1x1.0xxldspn1xNuclei customized DSP N1 instructions only for RV32
Xxldspn2x1.0xxldspn2xNuclei customized DSP N2 instructions only for RV32
Xxldspn3x1.0xxldspn3xNuclei customized DSP N3 instructions only for RV32
Xxlvqmacc1.0xxlvqmaccNuclei Int8 Matrix Multiplication Instructions

RISC-V 预设组合

可以使用 -march 指定支持的 RISC-V 设定扩展组合,目前支持的扩展组合如下表:

Supported ProfilesExperimental Profiles
rva20s64rva23s64
rva20u64rva23u64
rva22s64rvb23s64
rva22u64rvb23u64
rvi20u32rvm23u32
rvi20u64

用户也可以在设定扩展组合之后附加其他扩展,例如 rva20u64_zicond 将启用 zicond 扩展以及 rva20u64 设定扩展组合中的功能。

编译选项和参数

ZCC 4.x 基于 LLVM 19.1.6 版本进行开发,所以大部分 LLVM 的编译器选项都适用于 ZCC。

-target 参数

使用 -target <architecture> 选择需要将源代码编译到可以在 <architecture> 平台运行的二进制文件,可用参数如下:

  • riscv64-unknown-elf
  • riscv32-unknown-elf
  • riscv64-unknown-linux-gnu

-march 参数

使用 -march=<architecture> 指定生成代码的目标处理器架构。

对于 march 的检测规则采用 -march=rv[32|64][i|e][extensions],使用时不限定先后顺序,同时最后链接时将会按照指定 march 进行指令生成。举例:使用 -march=rv32imafc 找的是 rv32ifa 的库,但是最终依旧可以成功生成 M 扩展的指令。

Multilib

ZCC 将根据用户所指定的 arch/abi 组合,选择兼容的函数库添加到应用程序中。例如:

指定的 arch/abi 组合应用的函数库
-march=rv32imafc -mabi=ilp32frv32ifa/ilp32f
-march=rv32imafc_zba_zbb_zbc_zbs_zp052b -mabi=ilp32frv32iafzp/ilp32f

对于应用程序使用到函数库中不存在的 Arch,如 M 和 C 扩展,其优化将在 IR 翻译到汇编的阶段进行,因此优化不会缺失。对于某些 Arch,如 P 和 V 扩展,因为其优化在 C 源码翻译到 IR 时进行,必须为其单独做库。

-mtune 参数

添加 -mtune= 参数后,编译器会将代码优化为在目标系列 CPU 上性能更优的版本。 -mtune= 参数的可用选项如下:

  • THead
    • thead-c908-series
  • Andes
    • andes-kavalan
    • andes-vicuna
    • andes-23-series
    • andes-25-series
    • andes-45-series
    • andes-d25-series
    • andes-d45-series
  • Tenstorrent
    • ascalon
  • Nuclei
    • nuclei-100-series
    • nuclei-200-series
    • nuclei-300-series
    • nuclei-310-series
    • nuclei-600-series
    • nuclei-900-series
    • nuclei-1000-series
  • Rocket
    • rocket
  • Imagination
    • rtxm2200
  • Sifive
    • sifive-7-series
  • Syntacore
    • syntacore-scr1-series

优化选项

  • -O0, -O1, -O2, -O3, -Os

    用于控制优化等级。

    • -O0: 无优化。生成可读性最好的代码,编译速度最快,用于调试目的。

    • -O1: 基本优化。执行一些常见的优化,如删除未引用的函数和数据、复制传递、简单的常数传播等。

    • -O2: 常用优化。执行更多的优化,包括内联函数、循环展开、常量折叠等,可能会增加编译时间。

    • -O3: 高级优化。执行更激进的优化,可能会增加编译时间,但生成的代码通常更快。

    • -Os: 优化代码大小,以减小生成的可执行文件的大小。

常见问题及解决办法

和 GCC 不兼容的链接选项

指定编译选项文件

  • GCC 支持通过多个 --specs 选项加载复杂的编译选项文件,以覆盖默认的编译行为。以 newlib 为例,常用的 specs 文件包括 nano.specsnosys.specssemihost.specs 等,可灵活组合使用。

  • ZCC 采用 --config 选项加载单个组合配置(*.cfg)文件来指定编译选项。由于 ZCC 不支持同时使用多个 --config,因此其针对 newlib 提供了包含组合配置的单一 .cfg 文件,例如:nano-nosys.cfgnano.cfgnosys.cfgsim.cfgsemihost.cfg,以满足不同运行环境下的使用需求。

多目标架构

ZCC 支持多目标架构(multi-target)、多指令集(multi-arch)和多 ABI(multi-abi)。默认生成 rv64imafdc/lp64d 目标代码。如需生成其他类型的目标代码,需同时指定 -march=<arch>-mabi=<abi>,否则可能导致链接失败。

代码模型

ZCC 使用 -mcmodel 选项来设置代码模型(code model)。目前支持的取值包括 medanymedlow,它们分别对应于 RISC-V GCC 中的 mediumsmall 模型,参考下表。

ZCC 编译器支持的 RV32 及 RV64 代码模型
Code ModelZCCGCCtext/data/rodata
RISC-V 架构medlowsmall整个 RV32 地址空间或 RV64 地址空间最低 2GiB 和最高 2GiB 的范围
RISC-V 架构medanymedium整个 RV32 地址空间或 RV64 地址空间基于当前 PC ± 2GiB 的寻址范围

链接脚本

  1. 链接器目前不支持链接脚本中的 DEFINED 宏。因此,对于使用了 DEFINED 的链接脚本,需进行相应修改以确保兼容。例如按以下方式进行调整:

    - __stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
    + __stack_size = 2K;
  2. GNU ld 对链接脚本中的 MEMORY 命令支持情况可参考官方文档。目前已支持 MEMORY 命令的大多数属性,但尚不支持 I(initialization)属性。因此,对于使用了 I 属性的链接脚本,需进行如下类型的修改以保证兼容性:

    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
    }
  3. 链接脚本不支持 GNU ld 中在 output section 中基于当前位置(.)的累加赋值语法。因此,如果需要在 output section 中设置基于当前位置的偏移,必须显式使用绝对地址表达式。例如按以下方式进行调整:

    .stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
    {
    PROVIDE( _heap_end = . );
    - . = __stack_size;
    + . += __stack_size;
    PROVIDE( _sp = . );
    } >ram AT>ram
  4. 链接脚本中非内建 section 默认会编译到 .data 段,如需要将这些 section 放到 .bss 段中,可以通过添加 NOLOAD 属性进行控制。例如 nuclei_sdk 中的 gcc_demosoc_ilm.ld脚本中,为适配 .stack 段的处理方式,可以将其定按照如下方式修改进行适配。

    -   .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
    }
  5. 当通过 _attribute_((section(".sec_abc"))) 显式指定某个初始化函数指针应保留在特定的 section 中时,如果该对象在 C/C++ 源码中未被显式引用,编译器可能会将其视为未使用对象并在优化阶段将其移除。为防止该对象被优化掉,应同时添加 used 属性,告知编译器强制保留该对象,例如_attribute_((section(".sec_abc"), used))

  6. 在汇编代码或内联汇编中使用负数常量时,GNU as(GNU assembler)会根据目标架构的位数(32 位或 64 位)自动对立即数进行符号扩展(sign-extend)。例如:

  • 在 RV32 架构下,0xFFFFF800 会被识别为 -2048
  • 在 RV64 架构下,GNU as 会因立即数超出合法范围而报错。

而 ZCC 的汇编器在处理立即数时行为不同:无论是 RV32 还是 RV64 架构,0xFFFFF800 都会被视为一个正数,不会自动进行符号扩展。

and a0, a0, 0xFFFFF800

因此,在使用 ZCC 编写汇编代码时,若希望表达负数立即数,必须显式加上负号 - 前缀。这一用法也符合 GNU Assembler User Guide 的说明。

and a0, a0, -0x800
  1. 链接器 lld 不支持在输出节(output section)层级使用 ALIGN_WITH_INPUT 属性。在需要对输出节(output section)进行对齐控制的场景中,可使用 ALIGN(x) 来指定对齐方式。例如:

    -   .data : ALIGN_WITH_INPUT
    + .data : ALIGN(8)
    {
    . = ALIGN(8)
    ...
    }
  2. 链接器参数 -M-Map 同时使用时的行为差异

  • GCC 的行为是以命令行中出现的最后一个参数为准,例如:

    • -Wl, -M, -Map 时, -Map 生效;
    • -Wl, -Map, -M 时, -M 生效。
  • ZCC 当前的实现行为与 Clang 保持一致,即一旦同时指定 -M-Map,优先使用 -M

  1. ZCC 所使用的 libunwind 库依赖符号 __eh_frame_start__eh_frame_endeh_frame_hdr_starteh_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;

与 GCC 不同的默认行为

未初始化的局部变量

未初始化的局部变量其值为未知的,对于未初始化的局部变量的使用在 C/C++ 中属于未定义行为,在使用时其值可能为 0、内存中的随机值或者任意值。不同编译器会给予未初始化的局部变量不同的值。

比如在下面这个例子中,a 是一个未初始化的局部变量,GCC 会将 a 初始化为 0,而 ZCC 会将 a 初始化为 0xFFFFFFFF

#include <stdio.h>
#include <stdlib.h>

void main()
{
unsigned int a, b;
b = 1;
a |= b;
printf("a %d, b %d\n", a, b);
}

另外需要注意的是编译器对于未初始化局部变量的设置并非是固定的,所以不要依赖编译器行为来对变量进行初始化。比如在下面这个例子中,ZCC 就会将 a 初始化为 0。

#include <stdio.h>
#include <stdlib.h>

void main()
{
unsigned int a, b;
b = 1;
a &= b;
printf("a %d, b %d\n", a, b);
}

为了避免未定义行为,可以在编译时加上 -Wuninitialized 参数来开启对于未初始化局部变量使用的检测。编译器将对未初始化局部变量的使用报出警告。

获取帮助

关于 ZCC 的任何使用体验,欢迎大家前往无限智域(1nfinite)开发者社区针对使用体验展开话题,我们团队将及时答疑并尽力改进用户体验。

ZCC (Commecial)

我们为 ZCC 商业版用户开放了 Issue 追踪平台,使用 ZCC 过程中发现任何 BUG 请通过 ticket 入口向我们提供反馈。