Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/ir/globalvalue.rs
Line
Count
Source (jump to first uncovered line)
1
//! Global values.
2
3
use crate::ir::immediates::{Imm64, Offset32};
4
use crate::ir::{ExternalName, GlobalValue, Type};
5
use crate::isa::TargetIsa;
6
use crate::machinst::RelocDistance;
7
use core::fmt;
8
9
#[cfg(feature = "enable-serde")]
10
use serde::{Deserialize, Serialize};
11
12
/// Information about a global value declaration.
13
#[derive(Clone, PartialEq, Hash)]
14
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
15
pub enum GlobalValueData {
16
    /// Value is the address of the VM context struct.
17
    VMContext,
18
19
    /// Value is pointed to by another global value.
20
    ///
21
    /// The `base` global value is assumed to contain a pointer. This global value is computed
22
    /// by loading from memory at that pointer value. The memory must be accessible, and
23
    /// naturally aligned to hold a value of the type. The data at this address is assumed
24
    /// to never change while the current function is executing.
25
    Load {
26
        /// The base pointer global value.
27
        base: GlobalValue,
28
29
        /// Offset added to the base pointer before doing the load.
30
        offset: Offset32,
31
32
        /// Type of the loaded value.
33
        global_type: Type,
34
35
        /// Specifies whether the memory that this refers to is readonly, allowing for the
36
        /// elimination of redundant loads.
37
        readonly: bool,
38
    },
39
40
    /// Value is an offset from another global value.
41
    IAddImm {
42
        /// The base pointer global value.
43
        base: GlobalValue,
44
45
        /// Byte offset to be added to the value.
46
        offset: Imm64,
47
48
        /// Type of the iadd.
49
        global_type: Type,
50
    },
51
52
    /// Value is symbolic, meaning it's a name which will be resolved to an
53
    /// actual value later (eg. by linking). Cranelift itself does not interpret
54
    /// this name; it's used by embedders to link with other data structures.
55
    ///
56
    /// For now, symbolic values always have pointer type, and represent
57
    /// addresses, however in the future they could be used to represent other
58
    /// things as well.
59
    Symbol {
60
        /// The symbolic name.
61
        name: ExternalName,
62
63
        /// Offset from the symbol. This can be used instead of IAddImm to represent folding an
64
        /// offset into a symbol.
65
        offset: Imm64,
66
67
        /// Will this symbol be defined nearby, such that it will always be a certain distance
68
        /// away, after linking? If so, references to it can avoid going through a GOT. Note that
69
        /// symbols meant to be preemptible cannot be colocated.
70
        ///
71
        /// If `true`, some backends may use relocation forms that have limited range: for example,
72
        /// a +/- 2^27-byte range on AArch64. See the documentation for
73
        /// `RelocDistance` for more details.
74
        colocated: bool,
75
76
        /// Does this symbol refer to a thread local storage value?
77
        tls: bool,
78
    },
79
80
    /// Value is a multiple of how many instances of `vector_type` will fit in
81
    /// a target vector register.
82
    DynScaleTargetConst {
83
        /// Base vector type.
84
        vector_type: Type,
85
    },
86
}
87
88
impl GlobalValueData {
89
    /// Assume that `self` is an `GlobalValueData::Symbol` and return its name.
90
0
    pub fn symbol_name(&self) -> &ExternalName {
91
0
        match *self {
92
0
            Self::Symbol { ref name, .. } => name,
93
0
            _ => panic!("only symbols have names"),
94
        }
95
0
    }
96
97
    /// Return the type of this global.
98
345k
    pub fn global_type(&self, isa: &dyn TargetIsa) -> Type {
99
345k
        match *self {
100
210k
            Self::VMContext { .. } | Self::Symbol { .. } => isa.pointer_type(),
101
135k
            Self::IAddImm { global_type, .. } | Self::Load { global_type, .. } => global_type,
102
0
            Self::DynScaleTargetConst { .. } => isa.pointer_type(),
103
        }
104
345k
    }
105
106
    /// If this global references a symbol, return an estimate of the relocation distance,
107
    /// based on the `colocated` flag.
108
0
    pub fn maybe_reloc_distance(&self) -> Option<RelocDistance> {
109
0
        match self {
110
            &GlobalValueData::Symbol {
111
                colocated: true, ..
112
0
            } => Some(RelocDistance::Near),
113
            &GlobalValueData::Symbol {
114
                colocated: false, ..
115
0
            } => Some(RelocDistance::Far),
116
0
            _ => None,
117
        }
118
0
    }
119
}
120
121
impl fmt::Display for GlobalValueData {
122
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123
0
        match *self {
124
0
            Self::VMContext => write!(f, "vmctx"),
125
            Self::Load {
126
0
                base,
127
0
                offset,
128
0
                global_type,
129
0
                readonly,
130
0
            } => write!(
131
0
                f,
132
0
                "load.{} notrap aligned {}{}{}",
133
0
                global_type,
134
0
                if readonly { "readonly " } else { "" },
135
                base,
136
                offset
137
            ),
138
            Self::IAddImm {
139
0
                global_type,
140
0
                base,
141
0
                offset,
142
0
            } => write!(f, "iadd_imm.{} {}, {}", global_type, base, offset),
143
            Self::Symbol {
144
0
                ref name,
145
0
                offset,
146
0
                colocated,
147
0
                tls,
148
            } => {
149
0
                write!(
150
0
                    f,
151
0
                    "symbol {}{}{}",
152
0
                    if colocated { "colocated " } else { "" },
153
0
                    if tls { "tls " } else { "" },
154
0
                    name.display(None)
155
0
                )?;
156
0
                let offset_val: i64 = offset.into();
157
0
                if offset_val > 0 {
158
0
                    write!(f, "+")?;
159
0
                }
160
0
                if offset_val != 0 {
161
0
                    write!(f, "{}", offset)?;
162
0
                }
163
0
                Ok(())
164
            }
165
0
            Self::DynScaleTargetConst { vector_type } => {
166
0
                write!(f, "dyn_scale_target_const.{}", vector_type)
167
            }
168
        }
169
0
    }
170
}