To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

types.rs 10.9 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
2
3
use ptr::P;
use ir::*;

qinsoon's avatar
qinsoon committed
4
use utils::POINTER_SIZE;
qinsoon's avatar
qinsoon committed
5
use utils::vec_utils;
6
7

use std::fmt;
qinsoon's avatar
qinsoon committed
8
9
use std::collections::HashMap;
use std::sync::RwLock;
qinsoon's avatar
qinsoon committed
10

qinsoon's avatar
qinsoon committed
11
12
13
14
lazy_static! {
    pub static ref ADDRESS_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(POINTER_SIZE * 8))
    );
qinsoon's avatar
qinsoon committed
15
16
17
18
19
20
21
22

    pub static ref UINT8_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(8))
    );

    pub static ref UINT16_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(16))
    );
qinsoon's avatar
qinsoon committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    
    pub static ref UINT32_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(32))
    );
    
    pub static ref UINT64_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(64))
    );
    
    pub static ref DOUBLE_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::double())
    );
    
    pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![
        ADDRESS_TYPE.clone(),
qinsoon's avatar
qinsoon committed
38
39
        UINT8_TYPE.clone(),
        UINT16_TYPE.clone(),
qinsoon's avatar
qinsoon committed
40
41
42
43
44
45
        UINT32_TYPE.clone(),
        UINT64_TYPE.clone(),
        DOUBLE_TYPE.clone()
    ];    
}

qinsoon's avatar
qinsoon committed
46
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
47
pub struct MuType {
48
    pub hdr: MuEntityHeader,
qinsoon's avatar
qinsoon committed
49
50
51
52
53
54
    pub v: MuType_
}

impl MuType {
    pub fn new(id: MuID, v: MuType_) -> MuType {
        MuType {
55
            hdr: MuEntityHeader::unnamed(id),
qinsoon's avatar
qinsoon committed
56
57
58
59
            v: v
        }
    }
}
qinsoon's avatar
qinsoon committed
60

qinsoon's avatar
qinsoon committed
61
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
62
pub enum MuType_ {
qinsoon's avatar
qinsoon committed
63
    /// int <length>
qinsoon's avatar
qinsoon committed
64
    Int          (usize),
qinsoon's avatar
qinsoon committed
65
    /// float
qinsoon's avatar
qinsoon committed
66
    Float,
qinsoon's avatar
qinsoon committed
67
    /// double
qinsoon's avatar
qinsoon committed
68
    Double,
qinsoon's avatar
qinsoon committed
69

qinsoon's avatar
qinsoon committed
70
    /// ref<T>
qinsoon's avatar
qinsoon committed
71
    Ref          (P<MuType>),    // Box is needed for non-recursive enum
qinsoon's avatar
qinsoon committed
72
    /// iref<T>: internal reference
qinsoon's avatar
qinsoon committed
73
    IRef         (P<MuType>),
qinsoon's avatar
qinsoon committed
74
    /// weakref<T>
qinsoon's avatar
qinsoon committed
75
    WeakRef      (P<MuType>),
qinsoon's avatar
qinsoon committed
76

qinsoon's avatar
qinsoon committed
77
    /// uptr<T>: unsafe pointer
qinsoon's avatar
qinsoon committed
78
    UPtr         (P<MuType>),
qinsoon's avatar
qinsoon committed
79

qinsoon's avatar
qinsoon committed
80
    /// struct<T1 T2 ...>
qinsoon's avatar
qinsoon committed
81
    Struct       (MuName),
qinsoon's avatar
qinsoon committed
82

qinsoon's avatar
qinsoon committed
83
    /// array<T length>
qinsoon's avatar
qinsoon committed
84
    Array        (P<MuType>, usize),
qinsoon's avatar
qinsoon committed
85

qinsoon's avatar
qinsoon committed
86
    /// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part
qinsoon's avatar
qinsoon committed
87
    Hybrid       (Vec<P<MuType>>, P<MuType>),
qinsoon's avatar
qinsoon committed
88

qinsoon's avatar
qinsoon committed
89
    /// void
qinsoon's avatar
qinsoon committed
90
    Void,
qinsoon's avatar
qinsoon committed
91

qinsoon's avatar
qinsoon committed
92
    /// threadref
qinsoon's avatar
qinsoon committed
93
    ThreadRef,
qinsoon's avatar
qinsoon committed
94
    /// stackref
qinsoon's avatar
qinsoon committed
95
    StackRef,
qinsoon's avatar
qinsoon committed
96

qinsoon's avatar
qinsoon committed
97
    /// tagref64: hold a double or an int or an ref<void>
qinsoon's avatar
qinsoon committed
98
    Tagref64,
qinsoon's avatar
qinsoon committed
99

qinsoon's avatar
qinsoon committed
100
    /// vector<T length>
qinsoon's avatar
qinsoon committed
101
    Vector       (P<MuType>, usize),
qinsoon's avatar
qinsoon committed
102

qinsoon's avatar
qinsoon committed
103
    /// funcref<@sig>
104
    FuncRef      (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
105

qinsoon's avatar
qinsoon committed
106
    /// ufuncptr<@sig>
107
    UFuncPtr     (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
108
109
}

qinsoon's avatar
qinsoon committed
110
111
112
113
114
115
impl fmt::Display for MuType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.v)        
    }
}

116
impl fmt::Display for MuType_ {
117
118
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
qinsoon's avatar
qinsoon committed
119
120
121
            &MuType_::Int(n)                          => write!(f, "int<{}>", n),
            &MuType_::Float                           => write!(f, "float"),
            &MuType_::Double                          => write!(f, "double"),
122
123
124
125
126
            &MuType_::Ref(ref ty)                     => write!(f, "ref<{}>", ty),
            &MuType_::IRef(ref ty)                    => write!(f, "iref<{}>", ty),
            &MuType_::WeakRef(ref ty)                 => write!(f, "weakref<{}>", ty),
            &MuType_::UPtr(ref ty)                    => write!(f, "uptr<{}>", ty),
            &MuType_::Array(ref ty, size)             => write!(f, "array<{} {}>", ty, size),
qinsoon's avatar
qinsoon committed
127
            &MuType_::Hybrid(ref fix_tys, ref var_ty) => write!(f, "hybrid<[{}] {}>", vec_utils::as_str(fix_tys), var_ty),
qinsoon's avatar
qinsoon committed
128
129
130
131
            &MuType_::Void                            => write!(f, "void"),
            &MuType_::ThreadRef                       => write!(f, "threadref"),
            &MuType_::StackRef                        => write!(f, "stackref"),
            &MuType_::Tagref64                        => write!(f, "tagref64"),
132
133
134
            &MuType_::Vector(ref ty, size)            => write!(f, "vector<{} {}>", ty, size),
            &MuType_::FuncRef(ref sig)                => write!(f, "funcref<{}>", sig),
            &MuType_::UFuncPtr(ref sig)               => write!(f, "ufuncref<{}>", sig),
135
            &MuType_::Struct(ref tag)                     => write!(f, "{}(struct)", tag)
136
137
138
139
        }
    }
}

qinsoon's avatar
qinsoon committed
140
lazy_static! {
qinsoon's avatar
qinsoon committed
141
142
    /// storing a map from MuName to StructType_
    pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuName, StructType_>> = RwLock::new(HashMap::new());
qinsoon's avatar
qinsoon committed
143
144
}

qinsoon's avatar
qinsoon committed
145
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
146
pub struct StructType_ {
qinsoon's avatar
qinsoon committed
147
    tys: Vec<P<MuType>>
qinsoon's avatar
qinsoon committed
148
149
}

150
impl fmt::Display for StructType_ {
151
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
152
153
154
        write!(f, "struct<").unwrap();
        for i in 0..self.tys.len() {
            let ty = &self.tys[i];
155
            write!(f, "{}", ty).unwrap();
qinsoon's avatar
qinsoon committed
156
157
158
            if i != self.tys.len() - 1 {
                write!(f, " ").unwrap();
            }
159
        }
qinsoon's avatar
qinsoon committed
160
        write!(f, ">")
qinsoon's avatar
qinsoon committed
161
    }
162
163
}

qinsoon's avatar
qinsoon committed
164
impl StructType_ {
165
166
167
168
    // The IR builder needs to create StructType objects, too.
    pub fn new(tys: Vec<P<MuType>>) -> StructType_ {
        StructType_ { tys: tys }
    }
qinsoon's avatar
qinsoon committed
169
    pub fn set_tys(&mut self, mut list: Vec<P<MuType>>) {
qinsoon's avatar
qinsoon committed
170
        self.tys.clear();
qinsoon's avatar
qinsoon committed
171
        self.tys.append(&mut list);
qinsoon's avatar
qinsoon committed
172
    }
qinsoon's avatar
qinsoon committed
173
    
qinsoon's avatar
qinsoon committed
174
    pub fn get_tys(&self) -> &Vec<P<MuType>> {
qinsoon's avatar
qinsoon committed
175
176
        &self.tys
    }
qinsoon's avatar
qinsoon committed
177
178
}

qinsoon's avatar
qinsoon committed
179
180
181
impl MuType_ {
    pub fn int(len: usize) -> MuType_ {
        MuType_::Int(len)
qinsoon's avatar
qinsoon committed
182
    }
qinsoon's avatar
qinsoon committed
183
184
    pub fn float() -> MuType_ {
        MuType_::Float
qinsoon's avatar
qinsoon committed
185
    }
qinsoon's avatar
qinsoon committed
186
187
    pub fn double() -> MuType_ {
        MuType_::Double
qinsoon's avatar
qinsoon committed
188
    }
qinsoon's avatar
qinsoon committed
189
    pub fn muref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
190
        MuType_::Ref(referent)
qinsoon's avatar
qinsoon committed
191
    }
qinsoon's avatar
qinsoon committed
192
    pub fn iref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
193
        MuType_::IRef(referent)
qinsoon's avatar
qinsoon committed
194
    }
qinsoon's avatar
qinsoon committed
195
    pub fn weakref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
196
        MuType_::WeakRef(referent)
qinsoon's avatar
qinsoon committed
197
    }
qinsoon's avatar
qinsoon committed
198
    pub fn uptr(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
199
        MuType_::UPtr(referent)
qinsoon's avatar
qinsoon committed
200
    }
qinsoon's avatar
qinsoon committed
201
    pub fn mustruct_empty(tag: MuName) -> MuType_ {
qinsoon's avatar
qinsoon committed
202
        let struct_ty_ = StructType_{tys: vec![]};
203
        STRUCT_TAG_MAP.write().unwrap().insert(tag.clone(), struct_ty_);
qinsoon's avatar
qinsoon committed
204

qinsoon's avatar
qinsoon committed
205
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
206
    }
qinsoon's avatar
qinsoon committed
207
    pub fn mustruct(tag: MuName, list: Vec<P<MuType>>) -> MuType_ {
qinsoon's avatar
qinsoon committed
208
        let struct_ty_ = StructType_{tys: list};
qinsoon's avatar
qinsoon committed
209
210
211

        // if there is an attempt to use a same tag for different struct,
        // we panic
212
        match STRUCT_TAG_MAP.read().unwrap().get(&tag) {
qinsoon's avatar
qinsoon committed
213
214
215
216
217
218
219
220
221
222
            Some(old_struct_ty_) => {
                if struct_ty_ != *old_struct_ty_ {
                    panic!(format!(
                            "trying to insert {:?} as {}, while the old struct is defined as {:?}",
                            struct_ty_, tag, old_struct_ty_))
                }
            },
            None => {}
        }
        // otherwise, store the tag
223
        STRUCT_TAG_MAP.write().unwrap().insert(tag.clone(), struct_ty_);
qinsoon's avatar
qinsoon committed
224

qinsoon's avatar
qinsoon committed
225
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
226
    }
qinsoon's avatar
qinsoon committed
227
    pub fn array(ty: P<MuType>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
228
        MuType_::Array(ty, len)
qinsoon's avatar
qinsoon committed
229
    }
qinsoon's avatar
qinsoon committed
230
    pub fn hybrid(fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
231
        MuType_::Hybrid(fix_tys, var_ty)
qinsoon's avatar
qinsoon committed
232
    }
qinsoon's avatar
qinsoon committed
233
234
    pub fn void() -> MuType_ {
        MuType_::Void
qinsoon's avatar
qinsoon committed
235
    }
qinsoon's avatar
qinsoon committed
236
237
    pub fn threadref() -> MuType_ {
        MuType_::ThreadRef
qinsoon's avatar
qinsoon committed
238
    }
qinsoon's avatar
qinsoon committed
239
240
    pub fn stackref() -> MuType_ {
        MuType_::StackRef
qinsoon's avatar
qinsoon committed
241
    }
qinsoon's avatar
qinsoon committed
242
243
    pub fn tagref64() -> MuType_ {
        MuType_::Tagref64
qinsoon's avatar
qinsoon committed
244
    }
qinsoon's avatar
qinsoon committed
245
    pub fn vector(ty: P<MuType>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
246
        MuType_::Vector(ty, len)
qinsoon's avatar
qinsoon committed
247
    }
248
    pub fn funcref(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
249
        MuType_::FuncRef(sig)
qinsoon's avatar
qinsoon committed
250
    }
251
    pub fn ufuncptr(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
252
        MuType_::UFuncPtr(sig)
qinsoon's avatar
qinsoon committed
253
254
255
256
    }
}

/// is a type floating-point type?
qinsoon's avatar
qinsoon committed
257
pub fn is_fp(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
258
    match ty.v {
qinsoon's avatar
qinsoon committed
259
        MuType_::Float | MuType_::Double => true,
qinsoon's avatar
qinsoon committed
260
261
262
263
264
        _ => false
    }
}

/// is a type raw pointer?
qinsoon's avatar
qinsoon committed
265
pub fn is_ptr(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
266
    match ty.v {
qinsoon's avatar
qinsoon committed
267
        MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
qinsoon's avatar
qinsoon committed
268
269
270
271
272
        _ => false
    }
}

/// is a type scalar type?
qinsoon's avatar
qinsoon committed
273
pub fn is_scalar(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
274
    match ty.v {
qinsoon's avatar
qinsoon committed
275
276
277
278
279
280
281
282
283
284
285
286
        MuType_::Int(_)
        | MuType_::Float
        | MuType_::Double
        | MuType_::Ref(_)
        | MuType_::IRef(_)
        | MuType_::WeakRef(_)
        | MuType_::FuncRef(_)
        | MuType_::UFuncPtr(_)
        | MuType_::ThreadRef
        | MuType_::StackRef
        | MuType_::Tagref64
        | MuType_::UPtr(_) => true,
qinsoon's avatar
qinsoon committed
287
288
289
290
291
        _ => false
    }
}

/// is a type traced by the garbage collector?
qinsoon's avatar
qinsoon committed
292
/// Note: An aggregated type is traced if any of its part is traced.
qinsoon's avatar
qinsoon committed
293
pub fn is_traced(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
294
    match ty.v {
qinsoon's avatar
qinsoon committed
295
296
297
298
299
300
301
302
303
        MuType_::Ref(_) => true,
        MuType_::IRef(_) => true,
        MuType_::WeakRef(_) => true,
        MuType_::Array(ref elem_ty, _)
        | MuType_::Vector(ref elem_ty, _) => is_traced(elem_ty),
        MuType_::ThreadRef
        | MuType_::StackRef
        | MuType_::Tagref64 => true,
        MuType_::Hybrid(ref fix_tys, ref var_ty) => {
qinsoon's avatar
qinsoon committed
304
305
            is_traced(var_ty) ||
            fix_tys.into_iter().map(|ty| is_traced(ty))
qinsoon's avatar
qinsoon committed
306
                .fold(false, |ret, this| ret || this)
qinsoon's avatar
qinsoon committed
307
            },
308
        MuType_::Struct(ref tag) => {
qinsoon's avatar
qinsoon committed
309
310
311
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
qinsoon's avatar
qinsoon committed
312

qinsoon's avatar
qinsoon committed
313
314
315
316
317
318
319
320
321
            field_tys.into_iter().map(|ty| is_traced(&ty))
                .fold(false, |ret, this| ret || this)
        },
        _ => false
    }
}

/// is a type native safe?
/// Note: An aggregated type is native safe if all of its parts are native safe.
qinsoon's avatar
qinsoon committed
322
pub fn is_native_safe(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
323
    match ty.v {
qinsoon's avatar
qinsoon committed
324
325
326
327
328
329
330
331
332
        MuType_::Int(_) => true,
        MuType_::Float => true,
        MuType_::Double => true,
        MuType_::Void => true,
        MuType_::Array(ref elem_ty, _)
        | MuType_::Vector(ref elem_ty, _) => is_native_safe(elem_ty),
        MuType_::UPtr(_) => true,
        MuType_::UFuncPtr(_) => true,
        MuType_::Hybrid(ref fix_tys, ref var_ty) => {
qinsoon's avatar
qinsoon committed
333
            is_native_safe(var_ty) &&
qinsoon's avatar
qinsoon committed
334
335
336
            fix_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
337
        MuType_::Struct(ref tag) => {
qinsoon's avatar
qinsoon committed
338
339
340
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
qinsoon's avatar
qinsoon committed
341

qinsoon's avatar
qinsoon committed
342
343
344
345
            field_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
        _ => false
qinsoon's avatar
qinsoon committed
346
347
348
    }
}

349
pub fn get_referent_ty(ty: &MuType) -> Option<P<MuType>> {
qinsoon's avatar
qinsoon committed
350
351
352
353
    match ty.v {
        MuType_::Ref(ref referent)
        | MuType_::IRef(ref referent)
        | MuType_::WeakRef(ref referent) => Some(referent.clone()),
354
355
356
357
        _ => None
    }
}

qinsoon's avatar
qinsoon committed
358
359
360
361
362
363
364
365
366
macro_rules! is_type (
    ($e:expr, $p:pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
);

367
368
pub type CFuncSig = MuFuncSig;

qinsoon's avatar
qinsoon committed
369
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
370
pub struct MuFuncSig {
371
    pub hdr: MuEntityHeader,
qinsoon's avatar
qinsoon committed
372
373
    pub ret_tys : Vec<P<MuType>>,
    pub arg_tys: Vec<P<MuType>>
374
375
}

376
impl fmt::Display for MuFuncSig {
377
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
378
        write!(f, "[{}] -> [{}]", vec_utils::as_str(&self.ret_tys), vec_utils::as_str(&self.arg_tys))
qinsoon's avatar
qinsoon committed
379
380
    }
}