1use std::io::Read;
10use std::path::Path;
11
12pub mod desc;
13pub mod instruction;
14pub mod parse;
15
16use desc::Id;
17use instruction::Instruction;
18use parse::Result;
19
20pub struct RawModule {
24 instructions: Vec<Instruction>,
25 def_map: Box<[usize]>,
26 use_map: Box<[Vec<usize>]>
27}
28
29impl RawModule {
30
31 pub fn load_module<P: AsRef<Path>>(path: P) -> Result<RawModule> {
35 let file = try!(std::fs::File::open(path));
36
37 RawModule::read_module(file)
38 }
39
40 pub fn read_module<R: Read>(reader: R) -> Result<RawModule> {
44 let mut reader = try!(parse::Reader::new(reader));
45
46 let header = try!(reader.read_header());
47
48 let ids = header.id_bound as usize;
49 let mut def_map = (vec![!0; ids]).into_boxed_slice();
50 let mut use_map = (vec![Vec::new(); ids]).into_boxed_slice();
51
52 let mut instructions = Vec::with_capacity(ids);
53
54 while let Some(raw_inst) = try!(reader.read_instruction()) {
55 let inst = try!(parse::parse_raw_instruction(raw_inst));
56 let inst_idx = instructions.len();
57
58 if let Some(id) = inst.defines_value() {
59 let idx = id.0 as usize;
60 def_map[idx] = inst_idx;
61 } else if let Some(id) = inst.defines_type() {
62 let idx = id.0 as usize;
63 def_map[idx] = inst_idx;
64 }
65
66 let uses = inst.uses();
67 for id in uses {
68 let idx = id.0 as usize;
69 if idx == 0 { continue; }
70 use_map[idx].push(inst_idx);
71 }
72
73 instructions.push(inst);
74 }
75
76 Ok(RawModule {
77 instructions: instructions,
78 def_map: def_map,
79 use_map: use_map
80 })
81 }
82
83 pub fn instructions<'a>(&'a self) -> &'a [Instruction] {
87 &self.instructions[..]
88 }
89
90 pub fn def_index<I: Into<Id>>(&self, id: I) -> Option<usize> {
95 let idx = id.into().0 as usize;
96 if idx == 0 { return None; }
97
98 self.def_map.get(idx).and_then(|&idx| {
99 if idx == !0 {
100 None
101 } else {
102 Some(idx)
103 }
104 })
105 }
106
107 pub fn use_indices<'a, I: Into<Id>>(&'a self, id: I) -> Option<&'a [usize]> {
111 let idx = id.into().0 as usize;
112 if idx == 0 { return None; }
113
114 self.use_map.get(idx).map(|indices| {
115 &indices[..]
116 })
117 }
118
119 pub fn def<'a, I: Into<Id>>(&'a self, id: I) -> Option<&'a Instruction> {
123 self.def_index(id).map(|idx| {
124 &self.instructions[idx]
125 })
126 }
127
128 pub fn uses<'a, I: Into<Id>>(&'a self, id: I) -> Uses<'a> {
132 let indices = self.use_indices(id).unwrap_or(&[]);
133
134 Uses {
135 instructions: self.instructions(),
136 indices: indices
137 }
138 }
139}
140
141pub struct Uses<'a> {
142 instructions: &'a [Instruction],
143 indices: &'a [usize],
144}
145
146impl<'a> Iterator for Uses<'a> {
147 type Item = &'a Instruction;
148
149 fn next(&mut self) -> Option<&'a Instruction> {
150 if self.indices.len() == 0 {
151 return None;
152 }
153
154 let idx = self.indices[0];
155 self.indices = &self.indices[1..];
156
157 self.instructions.get(idx)
158 }
159
160 fn size_hint(&self) -> (usize, Option<usize>) {
161 let len = self.indices.len();
162 (len, Some(len))
163 }
164}