1747ad3c4Slazypassion //! Source map associating entities with their source locations. 2747ad3c4Slazypassion //! 3747ad3c4Slazypassion //! When the parser reads in a source file, it records the locations of the 4832666c4SRyan Hunt //! definitions of entities like instructions, blocks, and values. 5747ad3c4Slazypassion //! 6747ad3c4Slazypassion //! The `SourceMap` struct defined in this module makes this mapping available 7747ad3c4Slazypassion //! to parser clients. 8747ad3c4Slazypassion 9747ad3c4Slazypassion use crate::error::{Location, ParseResult}; 10747ad3c4Slazypassion use crate::lexer::split_entity_name; 119c43749dSSam Parker use cranelift_codegen::ir::entities::{AnyEntity, DynamicType}; 12747ad3c4Slazypassion use cranelift_codegen::ir::{ 13*2f7dbd61SChris Fallin Block, Constant, DynamicStackSlot, FuncRef, GlobalValue, JumpTable, SigRef, StackSlot, Value, 14747ad3c4Slazypassion }; 15747ad3c4Slazypassion use std::collections::HashMap; 16747ad3c4Slazypassion 17747ad3c4Slazypassion /// Mapping from entity names to source locations. 18747ad3c4Slazypassion #[derive(Debug, Default)] 19747ad3c4Slazypassion pub struct SourceMap { 20747ad3c4Slazypassion // Store locations for entities, including instructions. 21747ad3c4Slazypassion locations: HashMap<AnyEntity, Location>, 22747ad3c4Slazypassion } 23747ad3c4Slazypassion 24747ad3c4Slazypassion /// Read-only interface which is exposed outside the parser crate. 25747ad3c4Slazypassion impl SourceMap { 26747ad3c4Slazypassion /// Look up a value entity. contains_value(&self, v: Value) -> bool27747ad3c4Slazypassion pub fn contains_value(&self, v: Value) -> bool { 28747ad3c4Slazypassion self.locations.contains_key(&v.into()) 29747ad3c4Slazypassion } 30747ad3c4Slazypassion 31832666c4SRyan Hunt /// Look up a block entity. contains_block(&self, block: Block) -> bool32832666c4SRyan Hunt pub fn contains_block(&self, block: Block) -> bool { 33832666c4SRyan Hunt self.locations.contains_key(&block.into()) 34747ad3c4Slazypassion } 35747ad3c4Slazypassion 36747ad3c4Slazypassion /// Look up a stack slot entity. contains_ss(&self, ss: StackSlot) -> bool37747ad3c4Slazypassion pub fn contains_ss(&self, ss: StackSlot) -> bool { 38747ad3c4Slazypassion self.locations.contains_key(&ss.into()) 39747ad3c4Slazypassion } 40747ad3c4Slazypassion 419c43749dSSam Parker /// Look up a dynamic stack slot entity. contains_dss(&self, dss: DynamicStackSlot) -> bool429c43749dSSam Parker pub fn contains_dss(&self, dss: DynamicStackSlot) -> bool { 439c43749dSSam Parker self.locations.contains_key(&dss.into()) 449c43749dSSam Parker } 459c43749dSSam Parker 46747ad3c4Slazypassion /// Look up a global value entity. contains_gv(&self, gv: GlobalValue) -> bool47747ad3c4Slazypassion pub fn contains_gv(&self, gv: GlobalValue) -> bool { 48747ad3c4Slazypassion self.locations.contains_key(&gv.into()) 49747ad3c4Slazypassion } 50747ad3c4Slazypassion 51747ad3c4Slazypassion /// Look up a signature entity. contains_sig(&self, sig: SigRef) -> bool52747ad3c4Slazypassion pub fn contains_sig(&self, sig: SigRef) -> bool { 53747ad3c4Slazypassion self.locations.contains_key(&sig.into()) 54747ad3c4Slazypassion } 55747ad3c4Slazypassion 56747ad3c4Slazypassion /// Look up a function entity. contains_fn(&self, fn_: FuncRef) -> bool57747ad3c4Slazypassion pub fn contains_fn(&self, fn_: FuncRef) -> bool { 58747ad3c4Slazypassion self.locations.contains_key(&fn_.into()) 59747ad3c4Slazypassion } 60747ad3c4Slazypassion 61747ad3c4Slazypassion /// Look up a jump table entity. contains_jt(&self, jt: JumpTable) -> bool62747ad3c4Slazypassion pub fn contains_jt(&self, jt: JumpTable) -> bool { 63747ad3c4Slazypassion self.locations.contains_key(&jt.into()) 64747ad3c4Slazypassion } 65747ad3c4Slazypassion 660672d1dcSAndrew Brown /// Look up a constant entity. contains_constant(&self, c: Constant) -> bool670672d1dcSAndrew Brown pub fn contains_constant(&self, c: Constant) -> bool { 680672d1dcSAndrew Brown self.locations.contains_key(&c.into()) 690672d1dcSAndrew Brown } 700672d1dcSAndrew Brown 71747ad3c4Slazypassion /// Look up an entity by source name. 72747ad3c4Slazypassion /// Returns the entity reference corresponding to `name`, if it exists. lookup_str(&self, name: &str) -> Option<AnyEntity>73747ad3c4Slazypassion pub fn lookup_str(&self, name: &str) -> Option<AnyEntity> { 74747ad3c4Slazypassion split_entity_name(name).and_then(|(ent, num)| match ent { 75747ad3c4Slazypassion "v" => Value::with_number(num).and_then(|v| { 76747ad3c4Slazypassion if !self.contains_value(v) { 77747ad3c4Slazypassion None 78747ad3c4Slazypassion } else { 79747ad3c4Slazypassion Some(v.into()) 80747ad3c4Slazypassion } 81747ad3c4Slazypassion }), 82832666c4SRyan Hunt "block" => Block::with_number(num).and_then(|block| { 83832666c4SRyan Hunt if !self.contains_block(block) { 84747ad3c4Slazypassion None 85747ad3c4Slazypassion } else { 86832666c4SRyan Hunt Some(block.into()) 87747ad3c4Slazypassion } 88747ad3c4Slazypassion }), 89747ad3c4Slazypassion "ss" => StackSlot::with_number(num).and_then(|ss| { 90747ad3c4Slazypassion if !self.contains_ss(ss) { 91747ad3c4Slazypassion None 92747ad3c4Slazypassion } else { 93747ad3c4Slazypassion Some(ss.into()) 94747ad3c4Slazypassion } 95747ad3c4Slazypassion }), 96747ad3c4Slazypassion "gv" => GlobalValue::with_number(num).and_then(|gv| { 97747ad3c4Slazypassion if !self.contains_gv(gv) { 98747ad3c4Slazypassion None 99747ad3c4Slazypassion } else { 100747ad3c4Slazypassion Some(gv.into()) 101747ad3c4Slazypassion } 102747ad3c4Slazypassion }), 103747ad3c4Slazypassion "sig" => SigRef::with_number(num).and_then(|sig| { 104747ad3c4Slazypassion if !self.contains_sig(sig) { 105747ad3c4Slazypassion None 106747ad3c4Slazypassion } else { 107747ad3c4Slazypassion Some(sig.into()) 108747ad3c4Slazypassion } 109747ad3c4Slazypassion }), 110747ad3c4Slazypassion "fn" => FuncRef::with_number(num).and_then(|fn_| { 111747ad3c4Slazypassion if !self.contains_fn(fn_) { 112747ad3c4Slazypassion None 113747ad3c4Slazypassion } else { 114747ad3c4Slazypassion Some(fn_.into()) 115747ad3c4Slazypassion } 116747ad3c4Slazypassion }), 117747ad3c4Slazypassion "jt" => JumpTable::with_number(num).and_then(|jt| { 118747ad3c4Slazypassion if !self.contains_jt(jt) { 119747ad3c4Slazypassion None 120747ad3c4Slazypassion } else { 121747ad3c4Slazypassion Some(jt.into()) 122747ad3c4Slazypassion } 123747ad3c4Slazypassion }), 124747ad3c4Slazypassion _ => None, 125747ad3c4Slazypassion }) 126747ad3c4Slazypassion } 127747ad3c4Slazypassion 128747ad3c4Slazypassion /// Get the source location where an entity was defined. location(&self, entity: AnyEntity) -> Option<Location>129747ad3c4Slazypassion pub fn location(&self, entity: AnyEntity) -> Option<Location> { 130747ad3c4Slazypassion self.locations.get(&entity).cloned() 131747ad3c4Slazypassion } 132747ad3c4Slazypassion } 133747ad3c4Slazypassion 134747ad3c4Slazypassion impl SourceMap { 135747ad3c4Slazypassion /// Create a new empty `SourceMap`. new() -> Self136747ad3c4Slazypassion pub fn new() -> Self { 137747ad3c4Slazypassion Self { 138747ad3c4Slazypassion locations: HashMap::new(), 139747ad3c4Slazypassion } 140747ad3c4Slazypassion } 141747ad3c4Slazypassion 142747ad3c4Slazypassion /// Define the value `entity`. def_value(&mut self, entity: Value, loc: Location) -> ParseResult<()>143747ad3c4Slazypassion pub fn def_value(&mut self, entity: Value, loc: Location) -> ParseResult<()> { 144747ad3c4Slazypassion self.def_entity(entity.into(), loc) 145747ad3c4Slazypassion } 146747ad3c4Slazypassion 147832666c4SRyan Hunt /// Define the block `entity`. def_block(&mut self, entity: Block, loc: Location) -> ParseResult<()>148832666c4SRyan Hunt pub fn def_block(&mut self, entity: Block, loc: Location) -> ParseResult<()> { 149747ad3c4Slazypassion self.def_entity(entity.into(), loc) 150747ad3c4Slazypassion } 151747ad3c4Slazypassion 152747ad3c4Slazypassion /// Define the stack slot `entity`. def_ss(&mut self, entity: StackSlot, loc: Location) -> ParseResult<()>153747ad3c4Slazypassion pub fn def_ss(&mut self, entity: StackSlot, loc: Location) -> ParseResult<()> { 154747ad3c4Slazypassion self.def_entity(entity.into(), loc) 155747ad3c4Slazypassion } 156747ad3c4Slazypassion 1579c43749dSSam Parker /// Define the dynamic stack slot `entity`. def_dss(&mut self, entity: DynamicStackSlot, loc: Location) -> ParseResult<()>1589c43749dSSam Parker pub fn def_dss(&mut self, entity: DynamicStackSlot, loc: Location) -> ParseResult<()> { 1599c43749dSSam Parker self.def_entity(entity.into(), loc) 1609c43749dSSam Parker } 1619c43749dSSam Parker 1629c43749dSSam Parker /// Define the dynamic type `entity`. def_dt(&mut self, entity: DynamicType, loc: Location) -> ParseResult<()>1639c43749dSSam Parker pub fn def_dt(&mut self, entity: DynamicType, loc: Location) -> ParseResult<()> { 1649c43749dSSam Parker self.def_entity(entity.into(), loc) 1659c43749dSSam Parker } 1669c43749dSSam Parker 167747ad3c4Slazypassion /// Define the global value `entity`. def_gv(&mut self, entity: GlobalValue, loc: Location) -> ParseResult<()>168747ad3c4Slazypassion pub fn def_gv(&mut self, entity: GlobalValue, loc: Location) -> ParseResult<()> { 169747ad3c4Slazypassion self.def_entity(entity.into(), loc) 170747ad3c4Slazypassion } 171747ad3c4Slazypassion 172747ad3c4Slazypassion /// Define the signature `entity`. def_sig(&mut self, entity: SigRef, loc: Location) -> ParseResult<()>173747ad3c4Slazypassion pub fn def_sig(&mut self, entity: SigRef, loc: Location) -> ParseResult<()> { 174747ad3c4Slazypassion self.def_entity(entity.into(), loc) 175747ad3c4Slazypassion } 176747ad3c4Slazypassion 177747ad3c4Slazypassion /// Define the external function `entity`. def_fn(&mut self, entity: FuncRef, loc: Location) -> ParseResult<()>178747ad3c4Slazypassion pub fn def_fn(&mut self, entity: FuncRef, loc: Location) -> ParseResult<()> { 179747ad3c4Slazypassion self.def_entity(entity.into(), loc) 180747ad3c4Slazypassion } 181747ad3c4Slazypassion 182747ad3c4Slazypassion /// Define the jump table `entity`. def_jt(&mut self, entity: JumpTable, loc: Location) -> ParseResult<()>183747ad3c4Slazypassion pub fn def_jt(&mut self, entity: JumpTable, loc: Location) -> ParseResult<()> { 184747ad3c4Slazypassion self.def_entity(entity.into(), loc) 185747ad3c4Slazypassion } 186747ad3c4Slazypassion 1870672d1dcSAndrew Brown /// Define the jump table `entity`. def_constant(&mut self, entity: Constant, loc: Location) -> ParseResult<()>1880672d1dcSAndrew Brown pub fn def_constant(&mut self, entity: Constant, loc: Location) -> ParseResult<()> { 1890672d1dcSAndrew Brown self.def_entity(entity.into(), loc) 1900672d1dcSAndrew Brown } 1910672d1dcSAndrew Brown 192747ad3c4Slazypassion /// Define an entity. This can be used for instructions whose numbers never 193747ad3c4Slazypassion /// appear in source, or implicitly defined signatures. def_entity(&mut self, entity: AnyEntity, loc: Location) -> ParseResult<()>194747ad3c4Slazypassion pub fn def_entity(&mut self, entity: AnyEntity, loc: Location) -> ParseResult<()> { 195747ad3c4Slazypassion if self.locations.insert(entity, loc).is_some() { 196747ad3c4Slazypassion err!(loc, "duplicate entity: {}", entity) 197747ad3c4Slazypassion } else { 198747ad3c4Slazypassion Ok(()) 199747ad3c4Slazypassion } 200747ad3c4Slazypassion } 201747ad3c4Slazypassion } 202747ad3c4Slazypassion 203747ad3c4Slazypassion #[cfg(test)] 204747ad3c4Slazypassion mod tests { 20590ac295eSAlex Crichton use crate::{ParseOptions, parse_test}; 206747ad3c4Slazypassion 207747ad3c4Slazypassion #[test] details()208747ad3c4Slazypassion fn details() { 209747ad3c4Slazypassion let tf = parse_test( 210747ad3c4Slazypassion "function %detail() { 211a894594aSbjorn3 ss10 = explicit_slot 13 212832666c4SRyan Hunt block0(v4: i32, v7: i32): 213747ad3c4Slazypassion v10 = iadd v4, v7 214747ad3c4Slazypassion }", 2156fdc69ffSAndrew Brown ParseOptions::default(), 216747ad3c4Slazypassion ) 217747ad3c4Slazypassion .unwrap(); 218747ad3c4Slazypassion let map = &tf.functions[0].1.map; 219747ad3c4Slazypassion 220747ad3c4Slazypassion assert_eq!(map.lookup_str("v0"), None); 221747ad3c4Slazypassion assert_eq!(map.lookup_str("ss1"), None); 222747ad3c4Slazypassion assert_eq!(map.lookup_str("ss10").unwrap().to_string(), "ss10"); 223832666c4SRyan Hunt assert_eq!(map.lookup_str("block0").unwrap().to_string(), "block0"); 224747ad3c4Slazypassion assert_eq!(map.lookup_str("v4").unwrap().to_string(), "v4"); 225747ad3c4Slazypassion assert_eq!(map.lookup_str("v7").unwrap().to_string(), "v7"); 226747ad3c4Slazypassion assert_eq!(map.lookup_str("v10").unwrap().to_string(), "v10"); 227747ad3c4Slazypassion } 228747ad3c4Slazypassion } 229