primitives.rs - source
Description: Source of the Rust file `library/core/src/ffi/primitives.rs`.

#
core/ffi/
primitives.rs

    1//! Defines primitive types that match C's type definitions for FFI compatibility.
    2//!
    3//! This module is intentionally standalone to facilitate parsing when retrieving
    4//! core C types.
    5
    6macro_rules! type_alias {
    7    {
    8      $Docfile:tt, $Alias:ident = $Real:ty;
    9      $( $Cfg:tt )*
    10    } => {
    11        #[doc = include_str!($Docfile)]
    12        $( $Cfg )*
    13        #[stable(feature = "core_ffi_c", since = "1.64.0")]
    14        pub type $Alias = $Real;
    15    }
    16}
    17
    18type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] }
    19
    20type_alias! { "c_schar.md", c_schar = i8; }
    21type_alias! { "c_uchar.md", c_uchar = u8; }
    22type_alias! { "c_short.md", c_short = i16; }
    23type_alias! { "c_ushort.md", c_ushort = u16; }
    24
    25type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] }
    26type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] }
    27
    28type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] }
    29type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] }
    30
    31type_alias! { "c_longlong.md", c_longlong = i64; }
    32type_alias! { "c_ulonglong.md", c_ulonglong = u64; }
    33
    34type_alias! { "c_float.md", c_float = f32; }
    35type_alias! { "c_double.md", c_double = f64; }
    36
    37mod c_char_definition {
    38    crate::cfg_select! {
    39        // These are the targets on which c_char is unsigned. Usually the
    40        // signedness is the same for all target_os values on a given architecture
    41        // but there are some exceptions (see isSignedCharDefault() in clang).
    42        // aarch64:
    43        //   Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the Arm®
    44        //   64-bit Architecture (AArch64) says C/C++ char is unsigned byte.
    45        //   https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#arm-c-and-c-language-mappings
    46        // arm:
    47        //   Section 8 "Arm C and C++ Language Mappings" in Procedure Call Standard for the Arm®
    48        //   Architecture says C/C++ char is unsigned byte.
    49        //   https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs32/aapcs32.rst#arm-c-and-c-language-mappings
    50        // csky:
    51        //   Section 2.1.2 "Primary Data Type" in C-SKY V2 CPU Applications Binary Interface
    52        //   Standards Manual says ANSI C char is unsigned byte.
    53        //   https://github.com/c-sky/csky-doc/blob/9f7121f7d40970ba5cc0f15716da033db2bb9d07/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf
    54        //   Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945).
    55        // hexagon:
    56        //   Section 3.1 "Basic data type" in Qualcomm Hexagon™ Application
    57        //   Binary Interface User Guide says "By default, the `char` data type is unsigned."
    58        //   https://docs.qualcomm.com/bundle/publicresource/80-N2040-23_REV_K_Qualcomm_Hexagon_Application_Binary_Interface_User_Guide.pdf
    59        // msp430:
    60        //   Section 2.1 "Basic Types" in MSP430 Embedded Application Binary
    61        //   Interface says "The char type is unsigned by default".
    62        //   https://www.ti.com/lit/an/slaa534a/slaa534a.pdf
    63        // powerpc/powerpc64:
    64        //   - PPC32 SysV: "Table 3-1 Scalar Types" in System V Application Binary Interface PowerPC
    65        //     Processor Supplement says ANSI C char is unsigned byte
    66        //     https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
    67        //   - PPC64 ELFv1: Section 3.1.4 "Fundamental Types" in 64-bit PowerPC ELF Application
    68        //     Binary Interface Supplement 1.9 says ANSI C is unsigned byte
    69        //     https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUND-TYPE
    70        //   - PPC64 ELFv2: Section 2.1.2.2 "Fundamental Types" in 64-Bit ELF V2 ABI Specification
    71        //     says char is unsigned byte
    72        //     https://openpowerfoundation.org/specifications/64bitelfabi/
    73        //   - AIX: XL C for AIX Language Reference says "By default, char behaves like an unsigned char."
    74        //     https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=specifiers-character-types
    75        // riscv32/riscv64:
    76        //   C/C++ type representations section in RISC-V Calling Conventions
    77        //   page in RISC-V ELF psABI Document says "char is unsigned."
    78        //   https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#cc-type-representations
    79        // s390x:
    80        //   - ELF: "Table 1.1.: Scalar types" in ELF Application Binary Interface s390x Supplement
    81        //     Version 1.6.1 categorize ISO C char in unsigned integer
    82        //     https://github.com/IBM/s390x-abi/releases/tag/v1.6.1
    83        //   - z/OS: XL C/C++ Language Reference says: "By default, char behaves like an unsigned char."
    84        //     https://www.ibm.com/docs/en/zos/3.1.0?topic=specifiers-character-types
    85        // xtensa:
    86        //   Section 2.17.1 "Data Types and Alignment" of Xtensa LX Microprocessor Overview handbook
    87        //   says "`char` type is unsigned by default".
    88        //   https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf
    89        //
    90        // On the following operating systems, c_char is signed by default, regardless of architecture.
    91        // Darwin (macOS, iOS, etc.):
    92        //   Apple targets' c_char is signed by default even on arm
    93        //   https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-data-types-and-data-alignment-properly
    94        // Windows:
    95        //   Windows MSVC C++ Language Reference says "Microsoft-specific: Variables of type char
    96        //   are promoted to int as if from type signed char by default, unless the /J compilation
    97        //   option is used."
    98        //   https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types
    99        // Vita:
    100        //   Chars are signed by default on the Vita, and VITASDK follows that convention.
    101        //   https://github.com/vitasdk/buildscripts/blob/09c533b771591ecde88864b6acad28ffb688dbd4/patches/gcc/0001-gcc-10.patch#L33-L34
    102        //
    103        // L4Re:
    104        //   The kernel builds with -funsigned-char on all targets (but userspace follows the
    105        //   architecture defaults). As we only have a target for userspace apps so there are no
    106        //   special cases for L4Re below.
    107        //   https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240
    108        all(
    109            not(windows),
    110            not(target_vendor = "apple"),
    111            not(target_os = "vita"),
    112            any(
    113                target_arch = "aarch64",
    114                target_arch = "arm",
    115                target_arch = "csky",
    116                target_arch = "hexagon",
    117                target_arch = "msp430",
    118                target_arch = "powerpc",
    119                target_arch = "powerpc64",
    120                target_arch = "riscv32",
    121                target_arch = "riscv64",
    122                target_arch = "s390x",
    123                target_arch = "xtensa",
    124            )
    125        ) => {
    126            pub(super) type c_char = u8;
    127        }
    128        // On every other target, c_char is signed.
    129        _ => {
    130            pub(super) type c_char = i8;
    131        }
    132    }
    133}
    134
    135mod c_long_definition {
    136    crate::cfg_select! {
    137        any(
    138            all(target_pointer_width = "64", not(windows)),
    139            // wasm32 Linux ABI uses 64-bit long
    140            all(target_arch = "wasm32", target_os = "linux")
    141        ) => {
    142            pub(super) type c_long = i64;
    143            pub(super) type c_ulong = u64;
    144        }
    145        _ => {
    146            // The minimal size of `long` in the C standard is 32 bits
    147            pub(super) type c_long = i32;
    148            pub(super) type c_ulong = u32;
    149        }
    150    }
    151}
    152
    153/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
    154///
    155/// This type is currently always [`usize`], however in the future there may be
    156/// platforms where this is not the case.
    157#[unstable(feature = "c_size_t", issue = "88345")]
    158pub type c_size_t = usize;
    159
    160/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
    161///
    162/// This type is currently always [`isize`], however in the future there may be
    163/// platforms where this is not the case.
    164#[unstable(feature = "c_size_t", issue = "88345")]
    165pub type c_ptrdiff_t = isize;
    166
    167/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
    168///
    169/// This type is currently always [`isize`], however in the future there may be
    170/// platforms where this is not the case.
    171#[unstable(feature = "c_size_t", issue = "88345")]
    172pub type c_ssize_t = isize;
    173
    174mod c_int_definition {
    175    crate::cfg_select! {
    176        any(target_arch = "avr", target_arch = "msp430") => {
    177            pub(super) type c_int = i16;
    178            pub(super) type c_uint = u16;
    179        }
    180        _ => {
    181            pub(super) type c_int = i32;
    182            pub(super) type c_uint = u32;
    183        }
    184    }
    185}