WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

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
    }
}