Path: blob/main/cranelift/codegen/src/ir/sourceloc.rs
1693 views
//! Source locations.1//!2//! Cranelift tracks the original source location of each instruction, and preserves the source3//! location when instructions are transformed.45use core::fmt;6#[cfg(feature = "enable-serde")]7use serde_derive::{Deserialize, Serialize};89/// A source location.10///11/// This is an opaque 32-bit number attached to each Cranelift IR instruction. Cranelift does not12/// interpret source locations in any way, they are simply preserved from the input to the output.13///14/// The default source location uses the all-ones bit pattern `!0`. It is used for instructions15/// that can't be given a real source location.16#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]17#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]18pub struct SourceLoc(u32);1920impl SourceLoc {21/// Create a new source location with the given bits.22pub fn new(bits: u32) -> Self {23Self(bits)24}2526/// Is this the default source location?27pub fn is_default(self) -> bool {28self == Default::default()29}3031/// Read the bits of this source location.32pub fn bits(self) -> u32 {33self.034}35}3637impl Default for SourceLoc {38fn default() -> Self {39Self(!0)40}41}4243impl fmt::Display for SourceLoc {44fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {45if self.is_default() {46write!(f, "@-")47} else {48write!(f, "@{:04x}", self.0)49}50}51}5253/// Source location relative to another base source location.54#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]55#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]56pub struct RelSourceLoc(u32);5758impl RelSourceLoc {59/// Create a new relative source location with the given bits.60pub fn new(bits: u32) -> Self {61Self(bits)62}6364/// Creates a new `RelSourceLoc` based on the given base and offset.65pub fn from_base_offset(base: SourceLoc, offset: SourceLoc) -> Self {66if base.is_default() || offset.is_default() {67Self::default()68} else {69Self(offset.bits().wrapping_sub(base.bits()))70}71}7273/// Expands the relative source location into an absolute one, using the given base.74pub fn expand(&self, base: SourceLoc) -> SourceLoc {75if self.is_default() || base.is_default() {76Default::default()77} else {78SourceLoc::new(self.0.wrapping_add(base.bits()))79}80}8182/// Is this the default relative source location?83pub fn is_default(self) -> bool {84self == Default::default()85}86}8788impl Default for RelSourceLoc {89fn default() -> Self {90Self(!0)91}92}9394impl fmt::Display for RelSourceLoc {95fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {96if self.is_default() {97write!(f, "@-")98} else {99write!(f, "@+{:04x}", self.0)100}101}102}103104#[cfg(test)]105mod tests {106use crate::ir::SourceLoc;107use alloc::string::ToString;108109#[test]110fn display() {111assert_eq!(SourceLoc::default().to_string(), "@-");112assert_eq!(SourceLoc::new(0).to_string(), "@0000");113assert_eq!(SourceLoc::new(16).to_string(), "@0010");114assert_eq!(SourceLoc::new(0xabcdef).to_string(), "@abcdef");115}116}117118119