trap 0.1.0

Bare metal traps.
Documentation
// Copyright 2025 Gabriel Bjørnager Jensen.

//! Bare metal traps.

#![no_std]

#![allow(unused_imports)]

#![cfg_attr(feature = "nightly", allow(internal_features))]

#![cfg_attr(feature = "nightly", feature(core_intrinsics))]

#[cfg(doc)]
extern crate std;

use cfg_if::cfg_if;
use core::arch::asm;
use core::hint::unreachable_unchecked;

/// Traps the machine.
///
/// This function serves as a replacement for [`std::process::abort`]() on platforms that don't support it and for users want to avoid panicking.
///
/// # Machine-specific behaviour
///
/// Currently, this function only has special behaviour on the following target architectures:
///
/// * `aarch64`
/// * `arm`
/// * `riscv32`
/// * `riscv64`
/// * `x86`
/// * `x86_64`
///
/// On all other architectures, calling `trap` will result in an infinite loop.
/// Enabling the `nightly` feature, however, makes this function behave equivalently to [`core::intrinsics::abort`] on all platforms.
#[cold]
#[inline(never)]
pub fn trap() -> ! {
	// powerpc: trap
	// powerpc64: trap

	cfg_if! {
		if #[cfg(feature = "nightly")] {
			core::intrinsics::abort();
		} else if #[cfg(target_arch = "aarch64")] {
			unsafe {
				asm!("brk #1");
				unreachable_unchecked();
			}
		} else if #[cfg(target_arch = "arm")] {
			unsafe {
				// `0xE7FFDEFE` is conventially seen as the "trap"
				// instruction, although it is just an undefined
				// instruction.
				asm!(".inst 0xE7FFDEFE");
				unreachable_unchecked();
			}
		} else if #[cfg(target_arch = "riscv32")] {
			unsafe {
				asm!("unimp");
				unreachable_unchecked();
			}
		} else if #[cfg(target_arch = "riscv64")] {
			unsafe {
				asm!("unimp");
				unreachable_unchecked();
			}
		} else if #[cfg(target_arch = "x86")] {
			unsafe {
				asm!("ud2");
				unreachable_unchecked();
			}
		} else if #[cfg(target_arch = "x86_64")] {
			unsafe {
				asm!("ud2");
				unreachable_unchecked();
			}
		} else {
			loop {}
		}
	}
}