qbe-reader

A parser for the QBE intermediate language in Rust

git clone https://git.8pit.net/qbe-reader.git

  1use std::collections::HashMap;
  2
  3#[derive(Debug, PartialEq, Clone, Copy)]
  4pub enum BaseType {
  5    Word,
  6    Long,
  7    Single,
  8    Double,
  9}
 10
 11#[derive(Debug, PartialEq, Clone, Copy)]
 12pub enum ExtType {
 13    Base(BaseType),
 14    Byte,
 15    Halfword,
 16}
 17
 18#[derive(Debug, PartialEq, Clone, Copy)]
 19pub enum SubWordType {
 20    SignedByte,
 21    UnsignedByte,
 22    SignedHalf,
 23    UnsignedHalf,
 24}
 25
 26impl SubWordType {
 27    pub fn is_signed(&self) -> bool {
 28        match self {
 29            SubWordType::SignedByte => true,
 30            SubWordType::UnsignedByte => false,
 31            SubWordType::SignedHalf => true,
 32            SubWordType::UnsignedHalf => false,
 33        }
 34    }
 35}
 36
 37#[derive(Debug, PartialEq, Clone, Copy)]
 38pub enum SubLongType {
 39    SubWord(SubWordType),
 40    SignedWord,
 41    UnsignedWord,
 42}
 43
 44impl SubLongType {
 45    pub fn is_signed(&self) -> bool {
 46        match self {
 47            SubLongType::SubWord(x) => x.is_signed(),
 48            SubLongType::SignedWord => true,
 49            SubLongType::UnsignedWord => false,
 50        }
 51    }
 52}
 53
 54#[derive(Debug, PartialEq)]
 55pub enum SubType {
 56    ExtType(ExtType),
 57    UserDef(String),
 58}
 59
 60#[derive(Debug, PartialEq)]
 61pub enum Type {
 62    Base(BaseType),
 63    SubWordType(SubWordType),
 64    UserDef(String),
 65}
 66
 67#[derive(Debug, PartialEq, Clone, Copy)]
 68pub enum LoadType {
 69    Base(BaseType),
 70    SubLong(SubLongType),
 71}
 72
 73impl LoadType {
 74    pub fn is_signed(&self) -> bool {
 75        match self {
 76            LoadType::Base(_) => false,
 77            LoadType::SubLong(x) => x.is_signed(),
 78        }
 79    }
 80}
 81
 82#[derive(Debug, PartialEq)]
 83pub enum Const {
 84    Number(i64),
 85    SFP(f32),
 86    DFP(f64),
 87    Global(String),
 88}
 89
 90#[derive(Debug, PartialEq)]
 91pub enum DynConst {
 92    Const(Const),
 93    Thread(String),
 94}
 95
 96#[derive(Debug, PartialEq)]
 97pub enum Linkage {
 98    Export,
 99    Thread,
100    Section(String, Option<String>),
101}
102
103#[derive(Debug, PartialEq)]
104pub struct TypeDef {
105    pub name: String,
106    pub defn: AggregateType,
107}
108
109#[derive(Debug, PartialEq)]
110pub enum AggregateType {
111    Regular(Option<u64>, Vec<(SubType, u64)>),
112    Opaque(u64, u64),
113}
114
115#[derive(Debug, PartialEq)]
116pub struct DataDef {
117    pub linkage: Vec<Linkage>,
118    pub name: String,
119    pub align: Option<u64>,
120    pub objs: Vec<DataObj>,
121}
122
123#[derive(Debug, PartialEq)]
124pub enum DataObj {
125    DataItem(ExtType, Vec<DataItem>),
126    ZeroFill(u64),
127}
128
129#[derive(Debug, PartialEq)]
130pub enum DataItem {
131    Symbol(String, Option<u64>),
132    String(String),
133    Const(Const),
134}
135
136#[derive(Debug, PartialEq)]
137pub struct FuncDef {
138    pub linkage: Vec<Linkage>,
139    pub name: String,
140    pub abity: Option<Type>,
141    pub params: Vec<FuncParam>,
142    pub body: Vec<Block>,
143}
144
145#[derive(Debug, PartialEq)]
146pub enum FuncParam {
147    Regular(Type, String),
148    Env(String),
149    Variadic,
150}
151
152impl FuncParam {
153    pub fn get_name(&self) -> Option<&str> {
154        match self {
155            FuncParam::Regular(_, n) => Some(n),
156            FuncParam::Env(n) => Some(n),
157            FuncParam::Variadic => None,
158        }
159    }
160}
161
162#[derive(Debug, PartialEq)]
163pub struct Block {
164    pub label: String,
165    pub phi: Vec<Phi>,
166    pub inst: Vec<Statement>,
167    pub jump: Option<JumpInstr>,
168}
169
170#[derive(Debug, PartialEq)]
171pub enum Value {
172    LocalVar(String),
173    Const(DynConst),
174}
175
176#[derive(Debug, PartialEq)]
177pub enum JumpInstr {
178    Jump(String),               // jmp
179    Jnz(Value, String, String), // jnz
180    Return(Option<Value>),      // ret
181    Halt,                       // hlt
182}
183
184#[derive(Debug, PartialEq, Clone, Copy)]
185pub enum CmpOp {
186    Eq,
187    Ne,
188    Sle,
189    Slt,
190    Sge,
191    Sgt,
192    Ule,
193    Ult,
194    Uge,
195    Ugt,
196}
197
198#[derive(Debug, PartialEq, Copy, Clone)]
199pub enum AllocAlign {
200    Word,     // Align on 4-byte boundary
201    Long,     // Align on 8-byte boundary
202    LongLong, // Align on 16-byte boundary
203}
204
205impl AllocAlign {
206    pub fn byte_align(&self) -> u8 {
207        match self {
208            AllocAlign::Word => 4,
209            AllocAlign::Long => 8,
210            AllocAlign::LongLong => 16,
211        }
212    }
213}
214
215#[derive(Debug, PartialEq)]
216pub struct Phi {
217    pub ident: String,
218    pub base_type: BaseType,
219    pub labels: HashMap<String, Value>,
220}
221
222#[derive(Debug, PartialEq)]
223pub enum Instr {
224    // Arithmetic and Bits
225    Add(Value, Value),
226    Sub(Value, Value),
227    Mul(Value, Value),
228    Neg(Value),
229    UDiv(Value, Value),
230    Rem(Value, Value),
231    URem(Value, Value),
232    Or(Value, Value),
233    Xor(Value, Value),
234    And(Value, Value),
235    Sar(Value, Value),
236    Shr(Value, Value),
237    Shl(Value, Value),
238
239    // Memory
240    Load(LoadType, Value),
241
242    // Stack Allocation
243    Alloc(AllocAlign, u64),
244
245    // Comparision
246    Compare(BaseType, CmpOp, Value, Value),
247
248    // Conversions
249    Ext(SubLongType, Value),
250}
251
252#[derive(Debug, PartialEq)]
253pub enum VolatileInstr {
254    Store(ExtType, Value, Value),
255    Blit(Value, Value, u64),
256}
257
258#[derive(Debug, PartialEq)]
259pub enum Statement {
260    Assign(String, BaseType, Instr),
261    Call(String, Type, String, Vec<FuncParam>),
262    Volatile(VolatileInstr),
263}