Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/reader/src/sourcemap.rs
2450 views
1
//! Source map associating entities with their source locations.
2
//!
3
//! When the parser reads in a source file, it records the locations of the
4
//! definitions of entities like instructions, blocks, and values.
5
//!
6
//! The `SourceMap` struct defined in this module makes this mapping available
7
//! to parser clients.
8
9
use crate::error::{Location, ParseResult};
10
use crate::lexer::split_entity_name;
11
use cranelift_codegen::ir::entities::{AnyEntity, DynamicType};
12
use cranelift_codegen::ir::{
13
Block, Constant, DynamicStackSlot, FuncRef, GlobalValue, JumpTable, MemoryType, SigRef,
14
StackSlot, Value,
15
};
16
use std::collections::HashMap;
17
18
/// Mapping from entity names to source locations.
19
#[derive(Debug, Default)]
20
pub struct SourceMap {
21
// Store locations for entities, including instructions.
22
locations: HashMap<AnyEntity, Location>,
23
}
24
25
/// Read-only interface which is exposed outside the parser crate.
26
impl SourceMap {
27
/// Look up a value entity.
28
pub fn contains_value(&self, v: Value) -> bool {
29
self.locations.contains_key(&v.into())
30
}
31
32
/// Look up a block entity.
33
pub fn contains_block(&self, block: Block) -> bool {
34
self.locations.contains_key(&block.into())
35
}
36
37
/// Look up a stack slot entity.
38
pub fn contains_ss(&self, ss: StackSlot) -> bool {
39
self.locations.contains_key(&ss.into())
40
}
41
42
/// Look up a dynamic stack slot entity.
43
pub fn contains_dss(&self, dss: DynamicStackSlot) -> bool {
44
self.locations.contains_key(&dss.into())
45
}
46
47
/// Look up a global value entity.
48
pub fn contains_gv(&self, gv: GlobalValue) -> bool {
49
self.locations.contains_key(&gv.into())
50
}
51
52
/// Look up a signature entity.
53
pub fn contains_sig(&self, sig: SigRef) -> bool {
54
self.locations.contains_key(&sig.into())
55
}
56
57
/// Look up a function entity.
58
pub fn contains_fn(&self, fn_: FuncRef) -> bool {
59
self.locations.contains_key(&fn_.into())
60
}
61
62
/// Look up a jump table entity.
63
pub fn contains_jt(&self, jt: JumpTable) -> bool {
64
self.locations.contains_key(&jt.into())
65
}
66
67
/// Look up a constant entity.
68
pub fn contains_constant(&self, c: Constant) -> bool {
69
self.locations.contains_key(&c.into())
70
}
71
72
/// Look up an entity by source name.
73
/// Returns the entity reference corresponding to `name`, if it exists.
74
pub fn lookup_str(&self, name: &str) -> Option<AnyEntity> {
75
split_entity_name(name).and_then(|(ent, num)| match ent {
76
"v" => Value::with_number(num).and_then(|v| {
77
if !self.contains_value(v) {
78
None
79
} else {
80
Some(v.into())
81
}
82
}),
83
"block" => Block::with_number(num).and_then(|block| {
84
if !self.contains_block(block) {
85
None
86
} else {
87
Some(block.into())
88
}
89
}),
90
"ss" => StackSlot::with_number(num).and_then(|ss| {
91
if !self.contains_ss(ss) {
92
None
93
} else {
94
Some(ss.into())
95
}
96
}),
97
"gv" => GlobalValue::with_number(num).and_then(|gv| {
98
if !self.contains_gv(gv) {
99
None
100
} else {
101
Some(gv.into())
102
}
103
}),
104
"sig" => SigRef::with_number(num).and_then(|sig| {
105
if !self.contains_sig(sig) {
106
None
107
} else {
108
Some(sig.into())
109
}
110
}),
111
"fn" => FuncRef::with_number(num).and_then(|fn_| {
112
if !self.contains_fn(fn_) {
113
None
114
} else {
115
Some(fn_.into())
116
}
117
}),
118
"jt" => JumpTable::with_number(num).and_then(|jt| {
119
if !self.contains_jt(jt) {
120
None
121
} else {
122
Some(jt.into())
123
}
124
}),
125
_ => None,
126
})
127
}
128
129
/// Get the source location where an entity was defined.
130
pub fn location(&self, entity: AnyEntity) -> Option<Location> {
131
self.locations.get(&entity).cloned()
132
}
133
}
134
135
impl SourceMap {
136
/// Create a new empty `SourceMap`.
137
pub fn new() -> Self {
138
Self {
139
locations: HashMap::new(),
140
}
141
}
142
143
/// Define the value `entity`.
144
pub fn def_value(&mut self, entity: Value, loc: Location) -> ParseResult<()> {
145
self.def_entity(entity.into(), loc)
146
}
147
148
/// Define the block `entity`.
149
pub fn def_block(&mut self, entity: Block, loc: Location) -> ParseResult<()> {
150
self.def_entity(entity.into(), loc)
151
}
152
153
/// Define the stack slot `entity`.
154
pub fn def_ss(&mut self, entity: StackSlot, loc: Location) -> ParseResult<()> {
155
self.def_entity(entity.into(), loc)
156
}
157
158
/// Define the dynamic stack slot `entity`.
159
pub fn def_dss(&mut self, entity: DynamicStackSlot, loc: Location) -> ParseResult<()> {
160
self.def_entity(entity.into(), loc)
161
}
162
163
/// Define the dynamic type `entity`.
164
pub fn def_dt(&mut self, entity: DynamicType, loc: Location) -> ParseResult<()> {
165
self.def_entity(entity.into(), loc)
166
}
167
168
/// Define the global value `entity`.
169
pub fn def_gv(&mut self, entity: GlobalValue, loc: Location) -> ParseResult<()> {
170
self.def_entity(entity.into(), loc)
171
}
172
173
/// Define the memory type `entity`.
174
pub fn def_mt(&mut self, entity: MemoryType, loc: Location) -> ParseResult<()> {
175
self.def_entity(entity.into(), loc)
176
}
177
178
/// Define the signature `entity`.
179
pub fn def_sig(&mut self, entity: SigRef, loc: Location) -> ParseResult<()> {
180
self.def_entity(entity.into(), loc)
181
}
182
183
/// Define the external function `entity`.
184
pub fn def_fn(&mut self, entity: FuncRef, loc: Location) -> ParseResult<()> {
185
self.def_entity(entity.into(), loc)
186
}
187
188
/// Define the jump table `entity`.
189
pub fn def_jt(&mut self, entity: JumpTable, loc: Location) -> ParseResult<()> {
190
self.def_entity(entity.into(), loc)
191
}
192
193
/// Define the jump table `entity`.
194
pub fn def_constant(&mut self, entity: Constant, loc: Location) -> ParseResult<()> {
195
self.def_entity(entity.into(), loc)
196
}
197
198
/// Define an entity. This can be used for instructions whose numbers never
199
/// appear in source, or implicitly defined signatures.
200
pub fn def_entity(&mut self, entity: AnyEntity, loc: Location) -> ParseResult<()> {
201
if self.locations.insert(entity, loc).is_some() {
202
err!(loc, "duplicate entity: {}", entity)
203
} else {
204
Ok(())
205
}
206
}
207
}
208
209
#[cfg(test)]
210
mod tests {
211
use crate::{ParseOptions, parse_test};
212
213
#[test]
214
fn details() {
215
let tf = parse_test(
216
"function %detail() {
217
ss10 = explicit_slot 13
218
block0(v4: i32, v7: i32):
219
v10 = iadd v4, v7
220
}",
221
ParseOptions::default(),
222
)
223
.unwrap();
224
let map = &tf.functions[0].1.map;
225
226
assert_eq!(map.lookup_str("v0"), None);
227
assert_eq!(map.lookup_str("ss1"), None);
228
assert_eq!(map.lookup_str("ss10").unwrap().to_string(), "ss10");
229
assert_eq!(map.lookup_str("block0").unwrap().to_string(), "block0");
230
assert_eq!(map.lookup_str("v4").unwrap().to_string(), "v4");
231
assert_eq!(map.lookup_str("v7").unwrap().to_string(), "v7");
232
assert_eq!(map.lookup_str("v10").unwrap().to_string(), "v10");
233
}
234
}
235
236