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.2% of users enabled 2FA.

types.rs 32.3 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
// Copyright 2017 The Australian National University
2
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
3 4 5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
6
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
9 10 11 12 13 14
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

qinsoon's avatar
qinsoon committed
15
use ir::*;
16
use ptr::P;
qinsoon's avatar
qinsoon committed
17 18

use utils::vec_utils;
19
use utils::POINTER_SIZE;
20

21 22
use std;
use std::collections::HashMap;
23 24 25
use std::fmt;
use std::ptr;
use std::sync::atomic::{AtomicPtr, Ordering};
qinsoon's avatar
qinsoon committed
26
use std::sync::RwLock;
qinsoon's avatar
qinsoon committed
27

28
// some common types that the compiler may use internally
29
//#[cfg(not(feature = "realtime"))]
qinsoon's avatar
qinsoon committed
30
lazy_static! {
31 32 33 34
    pub static ref ADDRESS_TYPE: P<MuType> = P(MuType::new(
        new_internal_id(),
        MuType_::int(POINTER_SIZE * 8)
    ));
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    pub static ref UINT1_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::int(1)));
    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)));
    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 UINT128_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::int(128)));
    pub static ref FLOAT_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::float()));
    pub static ref DOUBLE_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::double()));
    pub static ref VOID_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::void()));
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    pub static ref REF_VOID_TYPE: P<MuType> = P(MuType::new(
        new_internal_id(),
        MuType_::muref(VOID_TYPE.clone())
    ));
    pub static ref IREF_VOID_TYPE: P<MuType> = P(MuType::new(
        new_internal_id(),
        MuType_::iref(VOID_TYPE.clone())
    ));
    pub static ref UPTR_U8_TYPE: P<MuType> = P(MuType::new(
        new_internal_id(),
        MuType_::uptr(UINT8_TYPE.clone())
    ));
    pub static ref UPTR_U64_TYPE: P<MuType> = P(MuType::new(
        new_internal_id(),
        MuType_::uptr(UINT64_TYPE.clone())
    ));
69 70
    pub static ref STACKREF_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::stackref()));
71
    pub static ref THREADREF_TYPE: P<MuType> =
72
        P(MuType::new(new_internal_id(), MuType_::threadref()));
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
73 74
    pub static ref FUTEXREF_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::futexref()));
75 76 77 78
}

#[cfg(not(feature = "realtime"))]
lazy_static! {
79
    pub static ref INTERNAL_TYPES: Vec<P<MuType>> = vec![
qinsoon's avatar
qinsoon committed
80
        ADDRESS_TYPE.clone(),
81
        UINT1_TYPE.clone(),
qinsoon's avatar
qinsoon committed
82 83
        UINT8_TYPE.clone(),
        UINT16_TYPE.clone(),
qinsoon's avatar
qinsoon committed
84 85
        UINT32_TYPE.clone(),
        UINT64_TYPE.clone(),
86 87
        UINT128_TYPE.clone(),
        FLOAT_TYPE.clone(),
qinsoon's avatar
qinsoon committed
88
        DOUBLE_TYPE.clone(),
89
        FLOAT_TYPE.clone(),
90 91
        VOID_TYPE.clone(),
        REF_VOID_TYPE.clone(),
92
        IREF_VOID_TYPE.clone(),
93 94
        STACKREF_TYPE.clone(),
        THREADREF_TYPE.clone(),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
95
        FUTEXREF_TYPE.clone(),
qinsoon's avatar
qinsoon committed
96 97
        UPTR_U8_TYPE.clone(),
        UPTR_U64_TYPE.clone()
98
    ];
qinsoon's avatar
qinsoon committed
99 100
}

101 102
#[cfg(feature = "realtime")]
lazy_static! {
103 104
    pub static ref RTATTR_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::rtattr()));
105
    pub static ref UPTR_RTATTR_TYPE: P<MuType> = P(MuType::new(
106
        new_internal_id(),
107
        MuType_::uptr(RTATTR_TYPE.clone())
108
    ));
109 110
    pub static ref REGREF_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::regionref()));
111 112 113 114
    pub static ref TIMERREF_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::timerref()));
    pub static ref TIMEVAL_TYPE: P<MuType> =
        P(MuType::new(new_internal_id(), MuType_::timeval()));
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    pub static ref INTERNAL_TYPES: Vec<P<MuType>> = vec![
        ADDRESS_TYPE.clone(),
        UINT1_TYPE.clone(),
        UINT8_TYPE.clone(),
        UINT16_TYPE.clone(),
        UINT32_TYPE.clone(),
        UINT64_TYPE.clone(),
        UINT128_TYPE.clone(),
        FLOAT_TYPE.clone(),
        DOUBLE_TYPE.clone(),
        FLOAT_TYPE.clone(),
        VOID_TYPE.clone(),
        REF_VOID_TYPE.clone(),
        IREF_VOID_TYPE.clone(),
        STACKREF_TYPE.clone(),
        THREADREF_TYPE.clone(),
        UPTR_U8_TYPE.clone(),
        UPTR_U64_TYPE.clone(),
133
        RTATTR_TYPE.clone(),
134 135
        UPTR_RTATTR_TYPE.clone(),
        REGREF_TYPE.clone(),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
136
        FUTEXREF_TYPE.clone(),
137 138 139
    ];
}

140
/// clear struct/hybrid maps, called when creating new VM
141 142 143 144 145 146 147 148 149 150 151 152
pub fn init_types() {
    {
        let mut map_lock = STRUCT_TAG_MAP.write().unwrap();
        map_lock.clear();
    }

    {
        let mut map_lock = HYBRID_TAG_MAP.write().unwrap();
        map_lock.clear();
    }
}

153
/// MuType represents a Mu type
154
#[derive(Debug)]
qinsoon's avatar
qinsoon committed
155
pub struct MuType {
156
    pub hdr: MuEntityHeader,
157
    pub v: MuType_
qinsoon's avatar
qinsoon committed
158 159
}

qinsoon's avatar
qinsoon committed
160
rodal_struct!(MuType { hdr, v });
161

162
impl PartialEq for MuType {
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
163 164 165 166 167 168
    fn eq(&self, other: &MuType) -> bool {
        self.v == other.v
    }
    fn ne(&self, other: &MuType) -> bool {
        self.v != other.v
    }
169 170
}

qinsoon's avatar
qinsoon committed
171
impl MuType {
172
    /// creates a new Mu type
qinsoon's avatar
qinsoon committed
173 174
    pub fn new(id: MuID, v: MuType_) -> MuType {
        MuType {
175
            hdr: MuEntityHeader::unnamed(id),
176
            v: v
qinsoon's avatar
qinsoon committed
177 178
        }
    }
qinsoon's avatar
qinsoon committed
179

180 181 182
    pub fn is_tagref64(&self) -> bool {
        match self.v {
            MuType_::Tagref64 => true,
183
            _ => false
184 185
        }
    }
186 187 188 189

    pub fn is_stackref(&self) -> bool {
        match self.v {
            MuType_::StackRef => true,
190
            _ => false
191 192 193
        }
    }

194 195
    pub fn is_funcref(&self) -> bool {
        match self.v {
qinsoon's avatar
fix  
qinsoon committed
196
            MuType_::FuncRef(_) => true,
197
            _ => false
198 199 200
        }
    }

201
    /// is this type struct type?
qinsoon's avatar
qinsoon committed
202 203 204
    pub fn is_struct(&self) -> bool {
        match self.v {
            MuType_::Struct(_) => true,
205
            _ => false
qinsoon's avatar
qinsoon committed
206 207 208
        }
    }

209 210 211
    pub fn is_void(&self) -> bool {
        match self.v {
            MuType_::Void => true,
212
            _ => false
213 214 215
        }
    }

216
    /// is this type hybrid type?
qinsoon's avatar
qinsoon committed
217 218 219
    pub fn is_hybrid(&self) -> bool {
        match self.v {
            MuType_::Hybrid(_) => true,
220
            _ => false
qinsoon's avatar
qinsoon committed
221 222 223
        }
    }

qinsoon's avatar
qinsoon committed
224 225 226 227
    /// is this type an integer type?
    pub fn is_int(&self) -> bool {
        match self.v {
            MuType_::Int(_) => true,
228
            _ => false
qinsoon's avatar
qinsoon committed
229 230 231
        }
    }

232 233 234 235 236 237 238 239 240
    /// is this type an integer type of certain width
    pub fn is_int_n(&self, n: usize) -> bool {
        if let Some(width) = self.get_int_length() {
            width == n
        } else {
            false
        }
    }

241 242
    /// is this type a floating point type? (float/double)
    pub fn is_fp(&self) -> bool {
qinsoon's avatar
qinsoon committed
243
        match self.v {
244
            MuType_::Float | MuType_::Double => true,
245
            _ => false
qinsoon's avatar
qinsoon committed
246 247 248
        }
    }

249 250
    pub fn is_opaque_reference(&self) -> bool {
        match self.v {
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
251
            MuType_::FuncRef(_) | MuType_::StackRef | MuType_::ThreadRef | MuType_::FutexRef => {
252 253 254 255 256 257 258
                true
            }

            #[cfg(feature = "realtime")]
            MuType_::RegionRef => true,

            _ => false
259 260 261
        }
    }

262 263 264 265 266
    #[cfg(feature = "realtime")]
    pub fn is_rtattr(&self) -> bool {
        match self.v {
            //            #[cfg(realtime)]
            MuType_::RTAttr => true,
267
            _ => false
268 269 270
        }
    }

271
    pub fn is_eq_comparable(&self) -> bool {
272 273 274 275 276
        self.is_int()
            || self.is_ptr()
            || self.is_iref()
            || self.is_ref()
            || self.is_opaque_reference()
277 278 279 280 281 282
    }

    pub fn is_ult_comparable(&self) -> bool {
        self.is_int() || self.is_ptr() || self.is_iref()
    }

283 284
    /// is this type a float type (single-precision floating point)
    pub fn is_float(&self) -> bool {
qinsoon's avatar
qinsoon committed
285
        match self.v {
286
            MuType_::Float => true,
287
            _ => false
qinsoon's avatar
qinsoon committed
288 289 290
        }
    }

291 292
    /// is this type a double type (double-precision floating point)
    pub fn is_double(&self) -> bool {
293
        match self.v {
294
            MuType_::Double => true,
295
            _ => false
296 297 298
        }
    }

299 300
    /// is this type a scalar type?
    pub fn is_scalar(&self) -> bool {
301
        match self.v {
302 303 304 305 306 307 308 309 310 311 312
            MuType_::Int(_)
            | MuType_::Float
            | MuType_::Double
            | MuType_::Ref(_)
            | MuType_::IRef(_)
            | MuType_::WeakRef(_)
            | MuType_::FuncRef(_)
            | MuType_::UFuncPtr(_)
            | MuType_::ThreadRef
            | MuType_::StackRef
            | MuType_::Tagref64
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
313
            | MuType_::FutexRef
314
            | MuType_::UPtr(_) => true,
315
            #[cfg(feature = "realtime")]
316 317 318 319
            MuType_::RTAttr
            | MuType_::RegionRef
            | MuType_::TimeVal
            | MuType_::TimerRef => true,
320
            _ => false
321 322 323
        }
    }

324 325 326
    /// gets the tag of a struct/hybrid type, returns None if the type is not
    /// hybrid/struct We use tag to resolve recursive types, and maintains a
    /// map between tag and struct types
qinsoon's avatar
qinsoon committed
327
    pub fn get_struct_hybrid_tag(&self) -> Option<MuName> {
328
        match self.v {
329 330 331 332
            MuType_::Hybrid(ref name) | MuType_::Struct(ref name) => {
                Some(name.clone())
            }
            _ => None
333 334 335
        }
    }

336
    /// is this type a reference type?
337 338
    /// (only reference type, which does not include iref, or other opaque
    /// reference types)
qinsoon's avatar
qinsoon committed
339 340 341
    pub fn is_ref(&self) -> bool {
        match self.v {
            MuType_::Ref(_) => true,
342
            _ => false
343 344 345
        }
    }

346 347
    /// is this type any reference type pointing to the heap? (including
    /// ref/iref/weakref)
348
    pub fn is_heap_reference(&self) -> bool {
349
        match self.v {
qinsoon's avatar
qinsoon committed
350
            MuType_::Ref(_) | MuType_::IRef(_) | MuType_::WeakRef(_) => true,
351
            _ => false
352 353 354
        }
    }

355
    /// is this type an internal reference type?
qinsoon's avatar
qinsoon committed
356
    pub fn is_iref(&self) -> bool {
357
        match self.v {
qinsoon's avatar
qinsoon committed
358
            MuType_::IRef(_) => true,
359
            _ => false
360 361 362
        }
    }

363 364
    /// is a type raw pointer?
    pub fn is_ptr(&self) -> bool {
365
        match self.v {
366
            MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
367
            _ => false
368 369 370
        }
    }

371 372 373
    /// is this type an aggregated type? (consisted of other types)
    pub fn is_aggregate(&self) -> bool {
        match self.v {
374 375 376 377
            MuType_::Struct(_) | MuType_::Hybrid(_) | MuType_::Array(_, _) => {
                true
            }
            _ => false
378 379 380
        }
    }

381
    /// is this type a type traced by the garbage collector?
382
    /// Note: An aggregated type is traced if any of its part is traced.
383
    #[allow(dead_code)]
384 385 386
    pub fn is_traced(&self) -> bool {
        match self.v {
            MuType_::Ref(_) => true,
qinsoon's avatar
qinsoon committed
387
            MuType_::IRef(_) => true,
388
            MuType_::WeakRef(_) => true,
389 390
            MuType_::Array(ref elem_ty, _)
            | MuType_::Vector(ref elem_ty, _) => elem_ty.is_traced(),
qinsoon's avatar
qinsoon committed
391
            MuType_::ThreadRef | MuType_::StackRef | MuType_::Tagref64 => true,
392 393 394 395 396
            MuType_::Hybrid(ref tag) => {
                let map = HYBRID_TAG_MAP.read().unwrap();
                let hybrid_ty = map.get(tag).unwrap();

                let ref fix_tys = hybrid_ty.fix_tys;
qinsoon's avatar
qinsoon committed
397
                let ref var_ty = hybrid_ty.var_ty;
398

399 400
                var_ty.is_traced()
                    || fix_tys
qinsoon's avatar
qinsoon committed
401 402
                        .into_iter()
                        .map(|ty| ty.is_traced())
403
                        .fold(false, |ret, this| ret || this)
qinsoon's avatar
qinsoon committed
404
            }
405 406 407 408 409
            MuType_::Struct(ref tag) => {
                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
410 411 412
                field_tys
                    .into_iter()
                    .map(|ty| ty.is_traced())
413
                    .fold(false, |ret, this| ret || this)
qinsoon's avatar
qinsoon committed
414
            }
415
            _ => false
416 417 418
        }
    }

419
    /// is this type native safe?
420 421
    /// Note: An aggregated type is native safe if all of its parts are native
    /// safe.
422
    #[allow(dead_code)]
423 424 425 426 427 428
    pub fn is_native_safe(&self) -> bool {
        match self.v {
            MuType_::Int(_) => true,
            MuType_::Float => true,
            MuType_::Double => true,
            MuType_::Void => true,
429 430
            MuType_::Array(ref elem_ty, _)
            | MuType_::Vector(ref elem_ty, _) => elem_ty.is_native_safe(),
431 432 433 434 435 436 437
            MuType_::UPtr(_) => true,
            MuType_::UFuncPtr(_) => true,
            MuType_::Hybrid(ref tag) => {
                let map = HYBRID_TAG_MAP.read().unwrap();
                let hybrid_ty = map.get(tag).unwrap();

                let ref fix_tys = hybrid_ty.fix_tys;
qinsoon's avatar
qinsoon committed
438
                let ref var_ty = hybrid_ty.var_ty;
439

440 441
                var_ty.is_native_safe()
                    && fix_tys
qinsoon's avatar
qinsoon committed
442 443
                        .into_iter()
                        .map(|ty| ty.is_native_safe())
444
                        .fold(true, |ret, this| ret && this)
qinsoon's avatar
qinsoon committed
445
            }
446 447 448 449 450
            MuType_::Struct(ref tag) => {
                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
451 452 453
                field_tys
                    .into_iter()
                    .map(|ty| ty.is_native_safe())
454
                    .fold(true, |ret, this| ret && this)
qinsoon's avatar
qinsoon committed
455
            }
456
            _ => false
qinsoon's avatar
qinsoon committed
457 458 459
        }
    }

460 461
    /// gets the element type of an array type, returns None if the type is not
    /// an array type
qinsoon's avatar
qinsoon committed
462 463 464
    pub fn get_elem_ty(&self) -> Option<P<MuType>> {
        match self.v {
            MuType_::Array(ref elem_ty, _) => Some(elem_ty.clone()),
465
            _ => None
qinsoon's avatar
qinsoon committed
466 467 468
        }
    }

469 470 471
    /// gets the signature of a funcref or ufuncptr type
    pub fn get_sig(&self) -> Option<P<MuFuncSig>> {
        match self.v {
472 473 474 475
            MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig) => {
                Some(sig.clone())
            }
            _ => None
476 477 478
        }
    }

qinsoon's avatar
qinsoon committed
479 480
    /// gets a field's type of a struct type,
    /// returns None if the type is not a struct or hybrid type
qinsoon's avatar
qinsoon committed
481 482 483 484 485 486 487
    pub fn get_field_ty(&self, index: usize) -> Option<P<MuType>> {
        match self.v {
            MuType_::Struct(ref tag) => {
                let map_lock = STRUCT_TAG_MAP.read().unwrap();
                let struct_inner = map_lock.get(tag).unwrap();

                Some(struct_inner.tys[index].clone())
qinsoon's avatar
qinsoon committed
488
            }
qinsoon's avatar
qinsoon committed
489 490 491 492 493
            MuType_::Hybrid(ref tag) => {
                let map_lock = HYBRID_TAG_MAP.read().unwrap();
                let hybrid_inner = map_lock.get(tag).unwrap();

                Some(hybrid_inner.fix_tys[index].clone())
qinsoon's avatar
qinsoon committed
494
            }
495
            _ => None
qinsoon's avatar
qinsoon committed
496 497 498
        }
    }

499 500
    /// gets the var part type of a hybrid type, returns None if the type is not
    /// a hybrid type
qinsoon's avatar
qinsoon committed
501 502 503 504 505 506 507
    pub fn get_hybrid_varpart_ty(&self) -> Option<P<MuType>> {
        match self.v {
            MuType_::Hybrid(ref tag) => {
                let map_lock = HYBRID_TAG_MAP.read().unwrap();
                let hybrid_inner = map_lock.get(tag).unwrap();

                Some(hybrid_inner.var_ty.clone())
qinsoon's avatar
qinsoon committed
508
            }
509
            _ => None
qinsoon's avatar
qinsoon committed
510 511 512
        }
    }

513 514
    /// gets the referent type for Ref/IRef/WeakRef/UPtr, returns None if the
    /// type is not any mentioned type.
515
    pub fn get_referent_ty(&self) -> Option<P<MuType>> {
qinsoon's avatar
qinsoon committed
516 517
        use types::MuType_::*;
        match self.v {
518 519 520 521
            Ref(ref ty) | IRef(ref ty) | WeakRef(ref ty) | UPtr(ref ty) => {
                Some(ty.clone())
            }
            _ => None
qinsoon's avatar
qinsoon committed
522 523
        }
    }
qinsoon's avatar
qinsoon committed
524

525 526
    /// gets the function signature for FuncRef or UFuncPtr, return None if the
    /// type is not those two types
qinsoon's avatar
qinsoon committed
527 528
    pub fn get_func_sig(&self) -> Option<P<MuFuncSig>> {
        match self.v {
529 530 531 532
            MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig) => {
                Some(sig.clone())
            }
            _ => None
qinsoon's avatar
qinsoon committed
533 534 535
        }
    }

536 537 538 539
    /// gets the length (in bit) of a integer/pointer type (assume pointer types
    /// are always 64 bits)
    // FIXME: should deprecate this function, and get the length from
    // BackendType
qinsoon's avatar
qinsoon committed
540 541 542 543
    pub fn get_int_length(&self) -> Option<usize> {
        use types::MuType_::*;
        match self.v {
            Int(len) => Some(len),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
544
            Ref(_) | IRef(_) | WeakRef(_) | UPtr(_) | ThreadRef | StackRef | FutexRef
545 546 547 548
            | Tagref64 | FuncRef(_) | UFuncPtr(_) => Some(64),

            #[cfg(feature = "realtime")]
            RegionRef => Some(64),
549 550 551 552
            #[cfg(feature = "realtime")]
            TimeVal => Some(64),
            #[cfg(feature = "realtime")]
            TimerRef => Some(64),
553 554

            _ => None
qinsoon's avatar
qinsoon committed
555 556
        }
    }
qinsoon's avatar
fix  
qinsoon committed
557 558 559 560 561 562 563 564 565 566 567 568

    /// prints a struct type
    pub fn print_details(&self) -> String {
        match self.v {
            MuType_::Struct(ref tag) => {
                let lock = STRUCT_TAG_MAP.read().unwrap();
                format!("{} = {}", tag, lock.get(tag).unwrap())
            }
            MuType_::Hybrid(ref tag) => {
                let lock = HYBRID_TAG_MAP.read().unwrap();
                format!("{} = {}", tag, lock.get(tag).unwrap())
            }
569
            _ => format!("{}", self)
qinsoon's avatar
fix  
qinsoon committed
570 571 572 573 574 575
        }
    }

    /// prints a struct type
    pub fn print_hybrid(&self) -> String {
        match self.v {
576
            _ => panic!()
qinsoon's avatar
fix  
qinsoon committed
577 578
        }
    }
579 580

    //    #[cfg(feature = "realtime")]
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
581
    pub fn contains_iref(&self) -> bool {
582 583 584 585
        let res = match &self.v {
            MuType_::IRef(_) => true,
            MuType_::Array(ty, size) => ty.is_iref() && *size > 0,
            MuType_::Struct(tag) => {
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
586 587
                let struct_map = STRUCT_TAG_MAP.read().unwrap();
                let _struct: &StructType_ = struct_map.get(tag).unwrap();
588 589 590
                let _types = _struct.get_tys();

                for _type in _types {
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
591
                    if _type.is_iref() || _type.contains_iref() {
592
                        return true;
593 594 595 596 597 598 599 600 601 602 603 604
                    }
                }
                false
            }
            MuType_::Hybrid(tag) => {
                let _hybrid_tag_map = HYBRID_TAG_MAP.read().unwrap();
                let _hybrid = _hybrid_tag_map.get(tag).unwrap();

                let fix_tys = _hybrid.get_fix_tys();
                let var_ty = _hybrid.get_var_ty();

                for _type in fix_tys.iter() {
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
605
                    if _type.is_iref() || _type.contains_iref() {
606
                        return true;
607 608 609
                    }
                }

Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
610
                if var_ty.is_iref() || var_ty.contains_iref() {
611
                    return true;
612 613 614 615 616 617 618 619 620
                }

                false
            }
            _ => false
        };

        res
    }
qinsoon's avatar
qinsoon committed
621
}
qinsoon's avatar
qinsoon committed
622

623 624
pub type StructTag = MuName;
pub type HybridTag = MuName;
625

626
/// MuType_ is used for pattern matching for MuType
627
#[derive(PartialEq, Debug, Clone)]
qinsoon's avatar
qinsoon committed
628
pub enum MuType_ {
qinsoon's avatar
qinsoon committed
629
    /// int <length>
qinsoon's avatar
qinsoon committed
630
    Int(usize),
qinsoon's avatar
qinsoon committed
631
    /// float
qinsoon's avatar
qinsoon committed
632
    Float,
qinsoon's avatar
qinsoon committed
633
    /// double
qinsoon's avatar
qinsoon committed
634
    Double,
qinsoon's avatar
qinsoon committed
635

qinsoon's avatar
qinsoon committed
636
    /// ref<T>
qinsoon's avatar
qinsoon committed
637
    Ref(P<MuType>), // Box is needed for non-recursive enum
qinsoon's avatar
qinsoon committed
638
    /// iref<T>: internal reference
qinsoon's avatar
qinsoon committed
639
    IRef(P<MuType>),
qinsoon's avatar
qinsoon committed
640
    /// weakref<T>
qinsoon's avatar
qinsoon committed
641
    WeakRef(P<MuType>),
qinsoon's avatar
qinsoon committed
642

qinsoon's avatar
qinsoon committed
643
    /// uptr<T>: unsafe pointer
qinsoon's avatar
qinsoon committed
644
    UPtr(P<MuType>),
qinsoon's avatar
qinsoon committed
645

qinsoon's avatar
qinsoon committed
646
    /// struct<T1 T2 ...>
qinsoon's avatar
qinsoon committed
647
    Struct(StructTag),
qinsoon's avatar
qinsoon committed
648

qinsoon's avatar
qinsoon committed
649
    /// array<T length>
qinsoon's avatar
qinsoon committed
650
    Array(P<MuType>, usize),
qinsoon's avatar
qinsoon committed
651

652 653
    /// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable
    /// length part
qinsoon's avatar
qinsoon committed
654
    Hybrid(HybridTag),
qinsoon's avatar
qinsoon committed
655

qinsoon's avatar
qinsoon committed
656
    /// void
qinsoon's avatar
qinsoon committed
657
    Void,
qinsoon's avatar
qinsoon committed
658

qinsoon's avatar
qinsoon committed
659
    /// threadref
qinsoon's avatar
qinsoon committed
660
    ThreadRef,
qinsoon's avatar
qinsoon committed
661
    /// stackref
qinsoon's avatar
qinsoon committed
662
    StackRef,
qinsoon's avatar
qinsoon committed
663

qinsoon's avatar
qinsoon committed
664
    /// tagref64: hold a double or an int or an ref<void>
qinsoon's avatar
qinsoon committed
665
    Tagref64,
qinsoon's avatar
qinsoon committed
666

qinsoon's avatar
qinsoon committed
667
    /// vector<T length>
qinsoon's avatar
qinsoon committed
668
    Vector(P<MuType>, usize),
qinsoon's avatar
qinsoon committed
669

qinsoon's avatar
qinsoon committed
670
    /// funcref<@sig>
qinsoon's avatar
qinsoon committed
671
    FuncRef(P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
672

qinsoon's avatar
qinsoon committed
673
    /// ufuncptr<@sig>
674
    UFuncPtr(P<MuFuncSig>),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
675 676
    FutexRef,
    
677 678 679 680
    /// RTMu-specific
    /// Real-Time Threads' attributes
    #[cfg(feature = "realtime")]
    RTAttr,
681
    #[cfg(feature = "realtime")]
682 683 684 685 686
    RegionRef,
    #[cfg(feature = "realtime")]
    TimerRef,
    #[cfg(feature = "realtime")]
    TimeVal
qinsoon's avatar
qinsoon committed
687
}
688

689 690 691 692
impl MuType_ {
    pub fn strong_variant(&self) -> MuType_ {
        match self {
            &MuType_::WeakRef(ref t) => MuType_::Ref(t.clone()),
693
            _ => self.clone()
694 695 696
        }
    }
}
697 698

#[cfg(not(feature = "realtime"))]
699
rodal_enum!(MuType_{(Int: size), Float, Double, (Ref: ty), (IRef: ty), (WeakRef: ty), (UPtr: ty),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
700
    (Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, StackRef, FutexRef, Tagref64,
701 702
    (Vector: ty, size), (FuncRef: ty), (UFuncPtr: ty)});

703 704
#[cfg(feature = "realtime")]
rodal_enum!(MuType_{(Int: size), Float, Double, (Ref: ty), (IRef: ty), (WeakRef: ty), (UPtr: ty),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
705
    (Struct: tag), (Array: ty, size), (Hybrid: tag), Void, ThreadRef, RegionRef, TimerRef, FutexRef, TimeVal, RTAttr, StackRef, Tagref64,
706 707
    (Vector: ty, size), (FuncRef: ty), (UFuncPtr: ty)});

qinsoon's avatar
qinsoon committed
708 709
impl fmt::Display for MuType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
710
        write!(f, "{}", self.v)
qinsoon's avatar
qinsoon committed
711 712 713
    }
}

714
impl fmt::Display for MuType_ {
715 716
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
qinsoon's avatar
qinsoon committed
717
            &MuType_::Int(n) => write!(f, "int<{}>", n),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
718
            &MuType_::Float => write!(f,"float"),
qinsoon's avatar
qinsoon committed
719 720 721 722 723
            &MuType_::Double => write!(f, "double"),
            &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),
724 725 726
            &MuType_::Array(ref ty, size) => {
                write!(f, "array<{} {}>", ty, size)
            }
qinsoon's avatar
qinsoon committed
727 728
            &MuType_::Void => write!(f, "void"),
            &MuType_::ThreadRef => write!(f, "threadref"),
Javad Ebrahimian Amiri's avatar
Javad Ebrahimian Amiri committed
729
            &MuType_::FutexRef => write!(f, "futexref"),
730

731 732
            #[cfg(feature = "realtime")]
            &MuType_::RTAttr => write!(f, "rtattr"),
733 734
            #[cfg(feature = "realtime")]
            &MuType_::RegionRef => write!(f, "regionref"),
735 736 737 738
            #[cfg(feature = "realtime")]
            &MuType_::TimerRef => write!(f, "timerref"),
            #[cfg(feature = "realtime")]
            &MuType_::TimeVal => write!(f, "timeval"),
739

qinsoon's avatar
qinsoon committed
740 741
            &MuType_::StackRef => write!(f, "stackref"),
            &MuType_::Tagref64 => write!(f, "tagref64"),
742 743 744
            &MuType_::Vector(ref ty, size) => {
                write!(f, "vector<{} {}>", ty, size)
            }
qinsoon's avatar
qinsoon committed
745
            &MuType_::FuncRef(ref sig) => write!(f, "funcref<{}>", sig),
746 747
            &MuType_::UFuncPtr(ref sig) => write!(f, "ufuncptr<{}>", sig),
            &MuType_::Struct(ref tag) => write!(f, "{}", tag),
748
            &MuType_::Hybrid(ref tag) => write!(f, "{}", tag)
749 750 751 752
        }
    }
}

753
#[no_mangle]
754 755 756
pub static STRUCT_TAG_MAP_LOC: Option<
    AtomicPtr<RwLock<HashMap<StructTag, StructType_>>>
> = None;
757
#[no_mangle]
758 759 760
pub static HYBRID_TAG_MAP_LOC: Option<
    AtomicPtr<RwLock<HashMap<HybridTag, HybridType_>>>
> = None;
761

qinsoon's avatar
qinsoon committed
762
lazy_static! {
qinsoon's avatar
qinsoon committed
763
    /// storing a map from MuName to StructType_
764
    pub static ref STRUCT_TAG_MAP : RwLock<HashMap<StructTag, StructType_>> =
765 766 767 768
        match &STRUCT_TAG_MAP_LOC {
            &Some(ref ptr) => unsafe{ptr::read(ptr.load(Ordering::Relaxed))},
            &None => RwLock::new(HashMap::new())
        };
769
    /// storing a map from MuName to HybridType_
770
    pub static ref HYBRID_TAG_MAP : RwLock<HashMap<HybridTag, HybridType_>> =
771 772 773 774
        match &HYBRID_TAG_MAP_LOC {
            &Some(ref ptr) => unsafe{ptr::read(ptr.load(Ordering::Relaxed))},
            &None => RwLock::new(HashMap::new())
        };
qinsoon's avatar
qinsoon committed
775 776
}

777 778 779 780 781
impl fmt::Debug for STRUCT_TAG_MAP {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "STRUCT_TAG_MAP_LOC").unwrap();
        let lock = match STRUCT_TAG_MAP.read() {
            Ok(map) => map,
782
            Err(err) => panic!("STRUCT_TAG_MAP reading error: {:#?}", err)
783 784 785 786 787 788 789 790 791 792 793
        };
        writeln!(f, "STRUCT_TAG_MAP content:").unwrap();
        write!(f, "{:#?}", lock)
    }
}

impl fmt::Debug for HYBRID_TAG_MAP {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "HYBRID_TAG_MAP_LOC").unwrap();
        let lock = match HYBRID_TAG_MAP.read() {
            Ok(map) => map,
794
            Err(err) => panic!("HYBRID_TAG_MAP reading error: {:#?}", err)
795 796 797 798 799 800
        };
        writeln!(f, "HYBRID_TAG_MAP content:").unwrap();
        write!(f, "{:#?}", lock)
    }
}

801
rodal_struct!(StructType_ { tys });
802
#[derive(PartialEq, Debug)]
qinsoon's avatar
qinsoon committed
803
pub struct StructType_ {
804
    tys: Vec<P<MuType>>
qinsoon's avatar
qinsoon committed
805 806
}

807
impl fmt::Display for StructType_ {
808
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
809 810 811
        write!(f, "struct<").unwrap();
        for i in 0..self.tys.len() {
            let ty = &self.tys[i];
812
            write!(f, "{}", ty).unwrap();
qinsoon's avatar
qinsoon committed
813 814 815
            if i != self.tys.len() - 1 {
                write!(f, " ").unwrap();
            }
816
        }
qinsoon's avatar
qinsoon committed
817
        write!(f, ">")
qinsoon's avatar
qinsoon committed
818
    }
819 820
}

qinsoon's avatar
qinsoon committed
821
impl StructType_ {
822 823 824 825
    // 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
826
    pub fn set_tys(&mut self, mut list: Vec<P<MuType>>) {
qinsoon's avatar
qinsoon committed
827
        self.tys.clear();
qinsoon's avatar
qinsoon committed
828
        self.tys.append(&mut list);
qinsoon's avatar
qinsoon committed
829
    }
qinsoon's avatar
qinsoon committed
830

qinsoon's avatar
qinsoon committed
831
    pub fn get_tys(&self) -> &Vec<P<MuType>> {
qinsoon's avatar
qinsoon committed
832 833
        &self.tys
    }
qinsoon's avatar
qinsoon committed
834 835
}

836
rodal_struct!(HybridType_ { fix_tys, var_ty });
837
#[derive(PartialEq, Debug)]
838 839
pub struct HybridType_ {
    fix_tys: Vec<P<MuType>>,
840
    var_ty: P<MuType>
841 842 843 844
}

impl HybridType_ {
    pub fn new(fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) -> HybridType_ {
qinsoon's avatar
qinsoon committed
845 846
        HybridType_ {
            fix_tys: fix_tys,
847
            var_ty: var_ty