Skip to main content
Version: 4.x

ZCC 4.x User Manual

Terapines compiler ZCC is a high-performance C/C++ compiler for RISC-V based on LLVM. It supports the most recent C and C++ standards, including C17, C99, C11, C++17, C++14 and C++11 etc and brings the following key features.

  • RVV auto-vectorization and other compiler optimizations.

  • Support RISC-V ISAs, including extensions and vendor extensions from XuanTie,Nuclei and Andes.

Download and Installation

ZCC is a high performance RISC-V toolchain that provides consistent experience on Windows and Linux.

System requirements

You can review the system requirements to check if your computer configuration is supported.

  • Windows : Windows 10 and above

  • Linux:

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

    • Centos 6, CentOS 7 and Centos8

    • Fedora 42

    • openSUSE Leap 15.5

Setup using the Terapines Installer

The Terapines Installer is the recommended tool to setup Terapines products. For users without a graphical interface, please use the Command Line Interface (CLI) installer.

  1. Select Windows from pull-down box to download the Installer .exe from ZCC download page.

  2. Run the Installer with administrator privileges and select the product that you want to install.

  3. ZCC toolchain by default included LibZCC. For additional libraries, choose to install. The installed libraries would be added in toolchain and apply globally.

    • LibDSP: It offers a collection of functions and tools specifically designed for digital signal processing (DSP).

    • LibNN: Specialized library for implementing and running neural network (NN) algorithms.

Once installed, you can open the Product Manager to handle multiple versions of your product.

  • Community Edition: Use immediately without logging in.
  • Commercial Edition: Activate your license by following the instructions in the License Management Manual.

open product manager

product manager main menu

Update ZCC

You can update ZCC in the Terapines Product Manager whenever a new version is released. Keeping ZCC up to date ensures you always have the latest features and performance improvements.

  1. Launch Terapines Product Manager, expand Available.
  2. Locate the most recent ZCC version in the list to install.

Enable email notifications

To stay informed about new ZCC updates:

Click the Settings icon in the top-right corner of Terapines Product Manager. Go to the Profile page and toggle on Email Notifications.

toggle on email notification

email notification

You will now receive automatic alerts whenever a new version of ZCC becomes available. To update ZCC, please go to Terapines Product Manager.

Language standards

  • -x <language>

    Treat subsequent input files as having type <language>. The optional <language> is C or C++.

  • -std=<standard>

    Select the language standard to compile for. Supported values are listed in the table below. The supported language standards maintain with the specifications and details provided by the upstream source. Please refer to C++ Support in Clang and C Support in Clang.

  • -ansi

    Same as "-std=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
tip
  • C17 & C18: Since it was under development in 2017, and officially published in 2018, C17 is sometimes referred to as C18.
  • C89 & C90: C90 is the same standard as C89 was ratified by ISO/IEC as ISO/IEC 9899:1990, with only formatting changes. Therefore, the terms "C89" and "C90" refer to essentially the same language.

RISC-V target support

Use -print-supported-extensions to print the list of all extensions that are supported in ZCC.

Base ISAs

Currently, ZCC fully supports three base instruction sets: RV32I, RV32E and RV64I.

To specify the target triple:

  • riscv32 RISC-V with XLEN=32 (i.e. RV32I or RV32E)
  • riscv64 RISC-V with XLEN=64 (i.e. RV64I)

To select an E variant ISA (e.g. RV32E instead of RV32I), use the base architecture string (e.g. riscv32) with the extension e.

Extensions

The table below provides the extensions in ZCC that ensure compatibility, including standard extensions as well as some experimental extensions from older versions.

tip

The Zp052b extension is version 0.52 of the P extension, which is an older experimental version. ZCC has extracted and designated it as a standard extension named Zp052b. When using this extension, there is no need to specify a version number—simply use 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

Experimental Extensions

Experimental extensions are expected to either transition to ratified status, or the old version. The compatibility of extensions between toolchain versions is not guaranteed. When using these extensions, version numbers must be added.

tip

For example, when using the Zalasr extension, you need to add the version number, that is, use zalasr0p1 instead of 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

Vendor Extensions

Vendor extensions are extensions which are defined by a hardware vendor.

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

Profiles

Supported RISC-V profile names can be passed using -march instead of a standard ISA naming string. Currently supported profiles:

Supported ProfilesExperimental Profiles
rva20s64rva23s64
rva20u64rva23u64
rva22s64rvb23s64
rva22u64rvb23u64
rvi20u32rvm23u32
rvi20u64

Note that you can also append additional extension names to be enabled, e.g. rva20u64_zicond will enable the zicond extension in addition to those in the rva20u64 profile.

Compilation Options

Since ZCC 4.x is based on LLVM 19.1.6, most of the LLVM compiler options are applicable to ZCC.

-target option

Specify the -target <architecture> to build for. Arguments that can be used are listed below:

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

-march option

specify -march=<architecture> to generate code for a specific processor architectures.

For the detection rules of march, the format follows -march=rv[32|64][i|e][extensions]. The order of components is not strictly enforced when using it, and the final linking will generate instructions according to the specified march. For example: when using -march=rv32imafc, ZCC will look for libraries with rv32ifa and also generate instructions for the M extension.

Multilib

ZCC will select compatible zcc libraries to add to the application based on the arch/abi combination specified by the user. For example:

Specified arch/abi combinationApplied zcc library
-march=rv32imafc -mabi=ilp32frv32ifa/ilp32f
-march=rv32imafc_zba_zbb_zbc_zbs_zp052b -mabi=ilp32frv32iafzp/ilp32f

For applications using Arch extensions that do not exist in the library, such as M and C extensions, their optimizations will be performed during the IR to assembly translation stage, so no optimizations will be missing. For certain Arch extensions, such as P and V extensions, since their optimizations are performed during C source code to IR translation, separate libraries must be created for them.

-mtune option

When specify -mtune=, ZCC will perform optimization on the target CPU. Arguments that can be used by -mtune= are listed below:

  • 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

Optimization options

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

    Specify which optimization level to use:

    • O0: Means “no optimization”: this level compiles the fastest and generates the most debuggable code.

    • O1: Somewhere between -O0 and -O2.

    • O2: Moderate level of optimization which enables most optimizations.

    • O3: Like -O2, except that it enables optimizations that take longer to perform or that may generate larger code (in an attempt to make the program run faster).

    • Os: Like -O2 with extra optimizations to reduce code size.

Troubleshooting

Specify compilation option files

  • GCC supports loading complex compilation option files through multiple --specs options to override the default compilation behavior. Taking mculib as an example, commonly used specs files include nano.cfg, nosys.cfg, small.cfg and semihost.specs, etc., which can be flexibly combined.

  • ZCC uses the --config option to load a single combined configuration (*.cfg) file to specify compilation options. Since ZCC does not support using multiple --config options simultaneously, it provides single .cfg files containing combined configurations for newlib, such as nano-nosys.cfg, nano.cfg, nosys.cfg, sim.cfg, and semihost.cfg, to meet the usage needs under different runtime environments.

Multi target

ZCC supports multi-target architectures, multi-instruction sets (multi-arch), and multiple ABIs (multi-abi). By default, it generates rv64imafdc/lp64d target code. To generate other types of target code, both -march= and -mabi= must be specified; otherwise, linking may fail.

Code model

ZCC supports the medany and medlow options, which are equivalent to the medium and small options in the GCC compiler for the RISC-V architecture, as shown in the table below.

Supported code models of ZCC for RV32 and RV64
Code ModelZCCGCCtext/data/rodata
RISC-V architecturemedlowsmallFull 32-bit addressing space & The highest 2 GiB and the lowest 2 GiB in 64-bit addressing space
RISC-V architecturemedanymediumFull 32-bit addressing space & PC ± 2 GiB in 64-bit addressing space

linker script

  1. The linker does not support the DEFINED macro in the link script. For linker scripts that use DEFINED, modifications as below example need to be made:

    - __stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
    + __stack_size = 2K;
  2. The GNU ld support for the MEMORY command in linker scripts can be referenced in the official documentation. Currently, ZCC supports most attributes of the MEMORYcommand, but does not yet support the I (initialization) attribute. Therefore, for linker scripts that use the I attribute, the following types of modifications are required to ensure compatibility:

    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. The linker scripts do not support the cumulative assignment syntax based on the current location (.) used in GNU ld output sections. Therefore, if you need to set an offset based on the current location within an output section, you must explicitly use absolute address expressions. For example, make adjustments as follows:

    .stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
    {
    PROVIDE( _heap_end = . );
    - . = __stack_size;
    + . += __stack_size;
    PROVIDE( _sp = . );
    } >ram AT>ram
  4. ZCC will compile the non-built-in sections in ldscripts into the .data section by default. If you need to put these sections into .bss, you can use the NOLOAD attribute. For example, the gcc_demosoc_ilm.ldcompilation script in nuclei_sdk can do the following for the .stack part. Modify as below:

    -   .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. When an initialization function pointer is explicitly placed in a specific section via __attribute__((section(".sec_abc"))), the compiler may treat the object as unused and remove it during optimization if it is not explicitly referenced in the C/C++ source. To prevent it from being optimized out, also add the used attribute to force the compiler to retain the object, e.g., __attribute__((section(".sec_abc"), used)).

  6. When negative constants are used, GNU as (GNU assembler) automatically sign-extends the immediate value based on the target architecture’s bit-width (32-bit or 64-bit). For example:

  • On RV32, 0xFFFFF800 is interpreted as -2048.

  • On RV64, GNU as reports an error because the immediate value is out of range.

In contrast, the assembler in ZCC behaves differently: regardless of whether the target is RV32 or RV64, 0xFFFFF800 is always treated as a positive number, without automatic sign extension.

and a0, a0, 0xFFFFF800

Therefore, when writing assembly code with ZCC, negative immediates must be expressed explicitly with a - prefix. This usage also aligns with the description in the GNU Assembler User Guide

and a0, a0, -0x800
  1. When using the lld linker, it does not support the ALIGN_WITH_INPUT attribute at the output section level. If you need to control the alignment of an output section, you have to explicitly use ALIGN(x) to specify it. For example

    -   .data : ALIGN_WITH_INPUT
    + .data : ALIGN(8)
    {
    . = ALIGN(8)
    ...
    }
  2. Behavioral differences when using linker options -M and -Map together.

  • With GCC, the behavior depends on the last option specified in the command line. For example:

    • -Wl,-M,-Map: -Map takes effect.
    • -Wl,-Map,-M: -M takes effect.
  • The behavior of ZCC is consistent with Clang: when both -M and -Map are specified, -M takes precedence.

  1. The libunwind library used by ZCCdepends on the addresses of the symbols __eh_frame_start, __eh_frame_end, __eh_frame_hdr_start, and __eh_frame_hdr_end. When using a custom linker script, these symbols must be explicitly defined and initialized in the script to ensure proper runtime exception handling.

    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;

Behavior different from GCC

Uninitialized local variables

Using uninitialized local variables in C/C++ results in undefined behavior because the value of uninitialized local variables may be 0, random memory values, or arbitrary values. If the source code makes use of uninitialized local variables, the assignment from different compilers might legitimately be different.

For example, in the code below, a is an uninitialized local variable. GCC initializes a to 0, while ZCC initializes a to 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);
}

Additionally, it's important to note that compilers' treatment of uninitialized local variables is not consistent. Therefore, you should not rely on compiler-specific behavior for variable initialization. For instance, in the example below, ZCC initializes a to 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);
}

To avoid undefined behavior, you can use the -Wuninitialized flag during compilation. This enables warnings for the use of uninitialized local variables, allowing the compiler to notify you about potential issues.

Inline Behavior

By default, ZCC does not inline functions residing in different sections, even when they meet the inlining criteria. This restriction prevents potential runtime errors caused by address changes resulting from cross-section inlining, though it may impact performance.

If cross-section inlining is required, compile with the -mllvm --inline-func-from-different-sections flag. When this option is enabled, ZCC will inline eligible functions regardless of their section placement.

Get help

If you need help or have a question with any aspect of ZCC, feel free to discuss on 1nfinite developer forum. Our team is here to provide responses and enhance your user experience.

ZCC (Commercial)

We open issue tracking system for ZCC (Commercial) users. Please report bugs on ticket page of Terapines Support.