深入RUST标准库内核—基础类型之整形初步

Rust
415
0
0
2022-09-05

本文摘自 inside-rust-std-library

RUST的固有(intrinsic)函数库

代码路径:

%USER%.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\intrinsic.rs

intrinsic库函数是指由编译器内置实现的函数,一般如下特点的函数用固有函数:

  1. 与CPU架构相关性很大,必须利用汇编实现或者利用汇编才能具备最高性能的函数,
  2. 和编译器密切相关的函数,由编译器来实现最为合适。

上面内存库章节中已经介绍了内存部分的intrinsic库函数,本节对其他部分做简略介绍

intrinsic 原子操作函数

原子操作函数主要用于多核CPU,多线程CPU时对数据的原子操作。intrinsic库中atomic_xxx及atomic_xxx_xxx类型的函数即为原子操作函数。原子操作函数主要用于并发编程中做临界保护,并且是其他临界保护机制的基础,如Mutex,RWlock等。

数学函数及位操作函数

各种整数及浮点的数学函数实现。这一部分放在intrinsic主要是因为现代CPU对浮点计算由很多支持,这些数学函数由汇编语言来实现更具备效率,那就有必要由编译器来内置实现。

intrinsic 指令优化及调试函数

断言类: assert_xxxx 类型的函数

函数栈:caller_location

小结

intrinsic函数库是从编译器层面完成跨CPU架构的一个手段,intrinsic通常被上层的库所封装。但在操作系统编程和框架编程时,仍然会不可避免的需要接触。

RUST数据类型代码分析

原生数据类型,Option类型,Result类型的某些代码是分析其他模块的基础,因此先对这些类型的部分代码做个基础分析。

整形数据类型

代码目录如下:

%USER%.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\num

无符号整形类型相关库代码分析

标准库用宏简化了无符号整形类型的代码部分。 本节给出若干价值较大的函数,如大小端转换,其他代码则做一个分类简略。代码如下:

macro_rules! uint_impl {
    ($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr,
        $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
        $reversed:expr, $le_bytes:expr, $be_bytes:expr,
        $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
        pub const MIN: Self = 0;
        pub const MAX: Self = !0;
        pub const BITS: u32 = $BITS;
        //利用intrinsics的位函数完成整数的位操作相关函数,这里仅分析一个,其他请参考标准库手册 
        pub const fn count_ones(self) -> u32 {
            intrinsics::ctpop(self as $ActualT) as u32
        }

        //其他位操作函数
        ...
        ...
        //内部字节交换,后继大小端变换使用 
        pub const fn swap_bytes(self) -> Self {
            intrinsics::bswap(self as $ActualT) as Self
        }

        //big endian 到硬件架构字节序 
        pub const fn from_be(x: Self) -> Self {
            #[cfg(target_endian = "big")]
            {
                x
            }

            #[cfg(not(target_endian = "big"))]
            {
                x.swap_bytes()
            }

        }

        //little endian 转换为硬件架构字节序

        pub const fn from_le(x: Self) -> Self {

            #[cfg(target_endian = "little")]
            {
                x
            }

            #[cfg(not(target_endian = "little"))]
            {
                x.swap_bytes()
            }
        }

        //硬件架构字节序到big endian

        pub const fn to_be(self) -> Self { // or not to be? 
            #[cfg(target_endian = "big")]
            {
                self
            }

            #[cfg(not(target_endian = "big"))]
            {
                self.swap_bytes()
            }
        }

        //硬件架构字节序到little endian

        pub const fn to_le(self) -> Self {
            #[cfg(target_endian = "little")]
            {
                self
            }

            #[cfg(not(target_endian = "little"))]

            {
                self.swap_bytes()
            }
        }

        //获得大端字节序字节数组 
        pub const fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
            self.to_be().to_ne_bytes()
        }

        //获得小端 
        pub const fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
            self.to_le().to_ne_bytes()
        }

        //硬件平台字节序 
        pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
            unsafe { mem::transmute(self) }
        }

        //从big endian 字节数组获得类型值 
        pub const fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
            Self::from_be(Self::from_ne_bytes(bytes))
        }

        //从little endian 字节数组获得类型值 
        pub const fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
            Self::from_le(Self::from_ne_bytes(bytes))
        }

        //从硬件架构字节序字节数组获得类型值 
        pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
            unsafe { mem::transmute(bytes) }
        }

        //对溢出做检查的加法运算 
        //这里每种类型运算都以加法为例,其他诸如减、乘、除、幂次请参考官方标准库手册 
        pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
            let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
            (a as Self, b)
        }

        //其他的对溢出做检查的数学运算,略
        ...
        ...
        //以边界值取余的加法 
        pub const fn wrapping_add(self, rhs: Self) -> Self {
            intrinsics::wrapping_add(self, rhs)
        }

        //以边界值取余的其他数学运算方法,略
        ...
        ...
        //饱和加法,超过边界值结果为边界值 
        pub const fn saturating_add(self, rhs: Self) -> Self {
            intrinsics::saturating_add(self, rhs)
        }

        //其他饱和型的数学运算,略
        ...
        ...
        //对加法有效性检查的加法运算,如发生溢出,则返回异常 
        pub const fn checked_add(self, rhs: Self) -> Option<Self> {
            let (a, b) = self.overflowing_add(rhs);
            if unlikely!(b) {None} else {Some(a)}
        }

        //无检查add,  是 + 符号的默认调用函数。 
        pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
            // 调用者要保证不发生错误 
            unsafe { intrinsics::unchecked_add(self, rhs) }
        }

        //其他对有效性检查的数学运算, 略
        ...
        ...
        pub const fn min_value() -> Self { Self::MIN }
        pub const fn max_value() -> Self { Self::MAX }
}

impl u8 {
    //利用宏实现 u8类型的方法
    uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" }
    pub const fn is_ascii(&self) -> bool {
        *self & 128 == 0
    }
    //其他ASCII相关函数,请参考标准库手册,略
    ...
    ...
}

//u16 数学函数方法 实现
impl u16 {
    uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
    widening_impl! { u16, u32, 16, unsigned }
}

//其他无符号整形的实现,略
...
...

有符号整形数据

与无符号整形数据类似,略。