llhd/
ty.rs

1// Copyright (c) 2017-2021 Fabian Schuiki
2
3//! Types of values.
4
5use itertools::Itertools;
6use std::sync::Arc;
7
8pub use self::TypeKind::*;
9
10/// An LLHD type.
11pub type Type = Arc<TypeKind>;
12
13/// The different kinds of types.
14#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
15pub enum TypeKind {
16    /// The `void` type.
17    VoidType,
18    /// The `time` type.
19    TimeType,
20    /// Integer types like `i32`.
21    IntType(usize),
22    /// Enumerated types like `n42`.
23    EnumType(usize),
24    /// Pointer types like `i32*`.
25    PointerType(Type),
26    /// Signal types like `i32$`.
27    SignalType(Type),
28    /// Array types like `[4 x i32]`.
29    ArrayType(usize, Type),
30    /// Struct types like `{i8, i32}`.
31    StructType(Vec<Type>),
32    /// Function types like `(i32) void`.
33    FuncType(Vec<Type>, Type),
34    /// Entity types like `(i8, i8; i32)`.
35    EntityType(Vec<Type>, Vec<Type>),
36}
37
38impl std::fmt::Display for TypeKind {
39    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40        match *self {
41            VoidType => write!(f, "void"),
42            TimeType => write!(f, "time"),
43            IntType(l) => write!(f, "i{}", l),
44            EnumType(l) => write!(f, "n{}", l),
45            PointerType(ref ty) => write!(f, "{}*", ty),
46            SignalType(ref ty) => write!(f, "{}$", ty),
47            ArrayType(l, ref ty) => write!(f, "[{} x {}]", l, ty),
48            StructType(ref tys) => write!(f, "{{{}}}", tys.iter().format(", ")),
49            FuncType(ref args, ref ret) => write!(f, "({}) {}", args.iter().format(", "), ret),
50            EntityType(ref ins, ref outs) => write!(
51                f,
52                "({}) -> ({})",
53                ins.iter().format(", "),
54                outs.iter().format(", ")
55            ),
56        }
57    }
58}
59
60impl TypeKind {
61    /// Unwrap the type to its integer bit width, or panic if the type is not an
62    /// integer.
63    pub fn unwrap_int(&self) -> usize {
64        match *self {
65            IntType(size) => size,
66            _ => panic!("unwrap_int called on {}", self),
67        }
68    }
69
70    /// Unwrap the type to its number of enumerated states, or panic if the type
71    /// is not an enum.
72    pub fn unwrap_enum(&self) -> usize {
73        match *self {
74            EnumType(size) => size,
75            _ => panic!("unwrap_enum called on {}", self),
76        }
77    }
78
79    /// Unwrap the type to its pointer data type, or panic if the type is not a
80    /// pointer. E.g. yields the `i8` type in `i8*`.
81    pub fn unwrap_pointer(&self) -> &Type {
82        match *self {
83            PointerType(ref ty) => ty,
84            _ => panic!("unwrap_pointer called on {}", self),
85        }
86    }
87
88    /// Unwrap the type to its signal data type, or panic if the type is not an
89    /// integer. E.g. yields the `i8` type in `i8$`.
90    pub fn unwrap_signal(&self) -> &Type {
91        match *self {
92            SignalType(ref ty) => ty,
93            _ => panic!("unwrap_signal called on {}", self),
94        }
95    }
96
97    /// Unwrap the type to its array length and element type, or panic if the
98    /// type is not an array. E.g. yields the `(16, i32)` in `[16 x i32]`.
99    pub fn unwrap_array(&self) -> (usize, &Type) {
100        match *self {
101            ArrayType(len, ref ty) => (len, ty),
102            _ => panic!("unwrap_array called on {}", self),
103        }
104    }
105
106    /// Unwrap the type to its struct fields, or panic if the type is not a
107    /// struct. E.g. yields the `[i8, i16]` in `{i8, i16}`.
108    pub fn unwrap_struct(&self) -> &[Type] {
109        match *self {
110            StructType(ref fields) => fields,
111            _ => panic!("unwrap_struct called on {}", self),
112        }
113    }
114
115    /// Unwrap the type into arguments and return type, or panic if the type is
116    /// not a function.
117    pub fn unwrap_func(&self) -> (&[Type], &Type) {
118        match *self {
119            FuncType(ref args, ref ret) => (args, ret),
120            _ => panic!("unwrap_func called on {}", self),
121        }
122    }
123
124    /// Unwrap the type into input and output arguments, or panic if the type is
125    /// not an entity.
126    pub fn unwrap_entity(&self) -> (&[Type], &[Type]) {
127        match *self {
128            EntityType(ref ins, ref outs) => (ins, outs),
129            _ => panic!("unwrap_entity called on {}", self),
130        }
131    }
132
133    /// Check if this is a void type.
134    pub fn is_void(&self) -> bool {
135        match *self {
136            VoidType => true,
137            _ => false,
138        }
139    }
140
141    /// Check if this is a time type.
142    pub fn is_time(&self) -> bool {
143        match *self {
144            TimeType => true,
145            _ => false,
146        }
147    }
148
149    /// Check if this is an integer type.
150    pub fn is_int(&self) -> bool {
151        match *self {
152            IntType(..) => true,
153            _ => false,
154        }
155    }
156
157    /// Check if this is an enum type.
158    pub fn is_enum(&self) -> bool {
159        match *self {
160            EnumType(..) => true,
161            _ => false,
162        }
163    }
164
165    /// Check if this is a pointer type.
166    pub fn is_pointer(&self) -> bool {
167        match *self {
168            PointerType(..) => true,
169            _ => false,
170        }
171    }
172
173    /// Check if this is a signal type.
174    pub fn is_signal(&self) -> bool {
175        match *self {
176            SignalType(..) => true,
177            _ => false,
178        }
179    }
180
181    /// Check if this is an array type.
182    pub fn is_array(&self) -> bool {
183        match *self {
184            ArrayType(..) => true,
185            _ => false,
186        }
187    }
188
189    /// Check if this is a struct type.
190    pub fn is_struct(&self) -> bool {
191        match *self {
192            StructType(..) => true,
193            _ => false,
194        }
195    }
196
197    /// Check if this is a func type.
198    pub fn is_func(&self) -> bool {
199        match *self {
200            FuncType(..) => true,
201            _ => false,
202        }
203    }
204
205    /// Check if this is an entity type.
206    pub fn is_entity(&self) -> bool {
207        match *self {
208            EntityType(..) => true,
209            _ => false,
210        }
211    }
212
213    /// Extract the length of the type.
214    ///
215    /// This is the number of:
216    /// - bits in an integer
217    /// - states in an enum
218    /// - elements in an array
219    /// - fields in a struct
220    ///
221    /// Returns zero for all other types.
222    pub fn len(&self) -> usize {
223        match *self {
224            IntType(l) | EnumType(l) | ArrayType(l, _) => l,
225            StructType(ref f) => f.len(),
226            _ => 0,
227        }
228    }
229}
230
231/// Create a void type.
232pub fn void_ty() -> Type {
233    Type::new(VoidType)
234}
235
236/// Create a time type.
237pub fn time_ty() -> Type {
238    Type::new(TimeType)
239}
240
241/// Create an integer type of the requested size.
242pub fn int_ty(size: usize) -> Type {
243    Type::new(IntType(size))
244}
245
246/// Create an enum type of the requested size.
247pub fn enum_ty(size: usize) -> Type {
248    Type::new(EnumType(size))
249}
250
251/// Create a pointer type with the requested data type.
252pub fn pointer_ty(ty: Type) -> Type {
253    Type::new(PointerType(ty))
254}
255
256/// Create a signal type with the requested data type.
257pub fn signal_ty(ty: Type) -> Type {
258    Type::new(SignalType(ty))
259}
260
261/// Create a array type. `size` is the number of elements in the array, and `ty`
262/// the type of each individual element.
263pub fn array_ty(size: usize, ty: Type) -> Type {
264    Type::new(ArrayType(size, ty))
265}
266
267/// Create a struct type. `fields` is an list of types, one for each field.
268pub fn struct_ty(fields: Vec<Type>) -> Type {
269    Type::new(StructType(fields))
270}
271
272/// Create a function type with the given arguments and return type.
273pub fn func_ty(args: Vec<Type>, ret: Type) -> Type {
274    Type::new(FuncType(args, ret))
275}
276
277/// Create an entity type with the given input and output arguments.
278pub fn entity_ty(ins: Vec<Type>, outs: Vec<Type>) -> Type {
279    Type::new(EntityType(ins, outs))
280}