pcb_core/
function.rs

1use common::Context;
2use ty;
3use std::fmt::{self, Debug, Display, Formatter};
4use std::hash::{Hash, Hasher};
5use std::cell::{Cell, RefCell};
6
7pub type FuncContext<'c> = Context<Function<'c>>;
8
9pub struct Function<'c> {
10  pub name: String,
11  pub ty: ty::Function<'c>,
12  pub blocks: BlockContext<'c>,
13  pub values: ValueContext<'c>,
14}
15
16impl<'c> Function<'c> {
17  pub fn add_block(&'c self) -> &'c Block<'c> {
18    self.blocks.push(
19      Block {
20        number: self.blocks.len() as u32,
21        terminator: Cell::new(Terminator::None),
22        block_values: RefCell::new(vec![]),
23        func: self,
24      })
25  }
26
27  #[inline(always)]
28  pub fn ty(&self) -> &ty::Function<'c> {
29    &self.ty
30  }
31}
32
33impl<'c> Display for Function<'c> {
34  fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
35    try!(writeln!(f, "define {}{} {{", self.name, self.ty));
36    for blk in &self.blocks {
37      try!(write!(f, "{:?}", blk));
38    }
39    write!(f, "}}")
40  }
41}
42
43impl<'c> PartialEq for Function<'c> {
44  fn eq(&self, rhs: &Self) -> bool {
45    self.name == rhs.name
46  }
47}
48impl<'c> Eq for Function<'c> { }
49impl<'c> Hash for Function<'c> {
50  fn hash<H>(&self, state: &mut H) where H: Hasher {
51    self.name.hash(state)
52  }
53}
54
55pub type BlockContext<'c> = Context<Block<'c>>;
56
57#[derive(Copy, Clone)]
58pub enum Terminator<'c> {
59  Branch(&'c Block<'c>),
60  // final return in a function
61  Return(&'c Value<'c>),
62  None,
63}
64
65impl<'c> Terminator<'c> {
66  pub fn is_none(self) -> bool {
67    if let Terminator::None = self {
68      true
69    } else {
70      false
71    }
72  }
73}
74
75impl<'c> Display for Terminator<'c> {
76  fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
77    match *self {
78      Terminator::Branch(b) => {
79        write!(f, "branch {}", b)
80      },
81      Terminator::Return(r) => {
82        write!(f, "return {}", r)
83      }
84      Terminator::None => { Ok(()) }
85    }
86  }
87}
88
89// TODO(ubsan): don't allow terminators to be re-set, and stop allowing stuff to
90// build after setting terminator
91// .build_return, .build_branch, etc.
92pub struct Block<'c> {
93  pub number: u32,
94  pub terminator: Cell<Terminator<'c>>,
95  pub block_values: RefCell<Vec<&'c Value<'c>>>,
96  pub func: &'c Function<'c>,
97}
98
99impl<'c> Block<'c> {
100  pub fn add_value(&'c self, kind: ValueKind<'c>) -> &'c Value<'c> {
101    let ret = self.func.values.push(
102      Value {
103        number: self.func.values.len() as u32,
104        kind: kind,
105        func: &self.func,
106      });
107    self.block_values.borrow_mut().push(ret);
108    ret
109  }
110}
111
112impl<'c> Debug for Block<'c> {
113  fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
114    try!(writeln!(f, "{}:", self));
115    for value in &*self.block_values.borrow() {
116      try!(writeln!(f, "  {}: {} = {:?}", value, value.ty(), value));
117    }
118    try!(writeln!(f, "  {}", self.terminator.get()));
119    Ok(())
120  }
121}
122
123impl<'c> Display for Block<'c> {
124  fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
125    write!(f, "bb{}", self.number)
126  }
127}
128
129pub type ValueContext<'c> = Context<Value<'c>>;
130
131pub struct Value<'c> {
132  pub number: u32,
133  pub kind: ValueKind<'c>,
134  pub func: &'c Function<'c>,
135}
136impl<'c> Value<'c> {
137  pub fn ty(&self) -> &'c ty::Type {
138    match self.kind {
139      ValueKind::ConstInt {
140        ty,
141        ..
142      } => ty,
143      ValueKind::Call {
144        function,
145        ..
146      } => function.ty.output,
147      ValueKind::Mul(lhs, _) => lhs.ty(),
148      ValueKind::UDiv(lhs, _) => lhs.ty(),
149      ValueKind::SDiv(lhs, _) => lhs.ty(),
150      ValueKind::URem(lhs, _) => lhs.ty(),
151      ValueKind::SRem(lhs, _) => lhs.ty(),
152
153      ValueKind::Add(lhs, _) => lhs.ty(),
154      ValueKind::Sub(lhs, _) => lhs.ty(),
155
156      ValueKind::Shl(lhs, _) => lhs.ty(),
157      ValueKind::ZShr(lhs, _) => lhs.ty(),
158      ValueKind::SShr(lhs, _) => lhs.ty(),
159
160      ValueKind::And(lhs, _) => lhs.ty(),
161      ValueKind::Xor(lhs, _) => lhs.ty(),
162      ValueKind::Or(lhs, _) => lhs.ty(),
163
164      ValueKind::Eq(_, _) => unimplemented!(),
165      ValueKind::Neq(_, _) => unimplemented!(),
166      ValueKind::Lt(_, _) => unimplemented!(),
167      ValueKind::Gt(_, _) => unimplemented!(),
168      ValueKind::Lte(_, _) => unimplemented!(),
169      ValueKind::Gte(_, _) => unimplemented!(),
170      ValueKind::Parameter(ty) => ty,
171    }
172  }
173
174}
175
176pub enum ValueKind<'c> {
177  ConstInt {
178    ty: &'c ty::Type,
179    value: u64,
180  },
181  Call {
182    function: &'c Function<'c>,
183    parameters: Box<[&'c Value<'c>]>
184  },
185
186  // -- binops --
187  Mul(&'c Value<'c>, &'c Value<'c>),
188  UDiv(&'c Value<'c>, &'c Value<'c>),
189  SDiv(&'c Value<'c>, &'c Value<'c>),
190  URem(&'c Value<'c>, &'c Value<'c>),
191  SRem(&'c Value<'c>, &'c Value<'c>),
192
193  Add(&'c Value<'c>, &'c Value<'c>),
194  Sub(&'c Value<'c>, &'c Value<'c>),
195
196  Shl(&'c Value<'c>, &'c Value<'c>),
197  ZShr(&'c Value<'c>, &'c Value<'c>), // zero-extend
198  SShr(&'c Value<'c>, &'c Value<'c>), // sign-extend
199
200  And(&'c Value<'c>, &'c Value<'c>),
201  Xor(&'c Value<'c>, &'c Value<'c>),
202  Or(&'c Value<'c>, &'c Value<'c>),
203
204  Eq(&'c Value<'c>, &'c Value<'c>),
205  Neq(&'c Value<'c>, &'c Value<'c>),
206  Lt(&'c Value<'c>, &'c Value<'c>),
207  Gt(&'c Value<'c>, &'c Value<'c>),
208  Lte(&'c Value<'c>, &'c Value<'c>),
209  Gte(&'c Value<'c>, &'c Value<'c>),
210
211  // parameter (this *may not* be built; it's simply a placeholder)
212  Parameter(&'c ty::Type),
213}
214
215impl<'c> Debug for Value<'c> {
216  fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
217    match self.kind {
218      ValueKind::ConstInt {
219        value,
220        ..
221      } => {
222        try!(write!(f, "{}", value));
223      }
224      ValueKind::Call {
225        function,
226        ref parameters
227      } => {
228        try!(write!(f, "call {}(", function.name));
229        if !parameters.is_empty() {
230          for i in 0..parameters.len() - 1 {
231            try!(write!(f, "%{}, ", i));
232          }
233          try!(write!(f, "%{}", parameters.len() - 1));
234        }
235        try!(write!(f, ")"));
236      }
237      ValueKind::Mul(lhs, rhs) => try!(write!(f, "mul {} {}", lhs, rhs)),
238      ValueKind::UDiv(lhs, rhs) => try!(write!(f, "udiv {} {}", lhs, rhs)),
239      ValueKind::SDiv(lhs, rhs) => try!(write!(f, "sdiv {} {}", lhs, rhs)),
240      ValueKind::URem(lhs, rhs) => try!(write!(f, "urem {} {}", lhs, rhs)),
241      ValueKind::SRem(lhs, rhs) => try!(write!(f, "srem {} {}", lhs, rhs)),
242
243      ValueKind::Add(lhs, rhs) => try!(write!(f, "add {} {}", lhs, rhs)),
244      ValueKind::Sub(lhs, rhs) => try!(write!(f, "sub {} {}", lhs, rhs)),
245
246      ValueKind::Shl(lhs, rhs) => try!(write!(f, "shl {} {}", lhs, rhs)),
247      ValueKind::ZShr(lhs, rhs) => try!(write!(f, "zshr {} {}", lhs, rhs)), // zero-extend
248      ValueKind::SShr(lhs, rhs) => try!(write!(f, "sshr {} {}", lhs, rhs)), // sign-extend
249
250      ValueKind::And(lhs, rhs) => try!(write!(f, "and {} {}", lhs, rhs)),
251      ValueKind::Xor(lhs, rhs) => try!(write!(f, "xor {} {}", lhs, rhs)),
252      ValueKind::Or(lhs, rhs) => try!(write!(f, "or {} {}", lhs, rhs)),
253
254      ValueKind::Eq(lhs, rhs) => try!(write!(f, "eq {} {}", lhs, rhs)),
255      ValueKind::Neq(lhs, rhs) => try!(write!(f, "neq {} {}", lhs, rhs)),
256      ValueKind::Lt(lhs, rhs) => try!(write!(f, "lt {} {}", lhs, rhs)),
257      ValueKind::Gt(lhs, rhs) => try!(write!(f, "gt {} {}", lhs, rhs)),
258      ValueKind::Lte(lhs, rhs) => try!(write!(f, "lte {} {}", lhs, rhs)),
259      ValueKind::Gte(lhs, rhs) => try!(write!(f, "gte {} {}", lhs, rhs)),
260
261      ValueKind::Parameter(_) => panic!("pcb_ice: Parameters should not be \
262        displayed"),
263    }
264    Ok(())
265  }
266}
267
268impl<'c> Display for Value<'c> {
269  fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
270    write!(f, "%{}", self.number)
271  }
272}