Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mu-impl-fast
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
40
Issues
40
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
mu
mu-impl-fast
Commits
fe287e80
Commit
fe287e80
authored
Jun 01, 2017
by
Isaac Gariano
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into 'aarch64'
Merging master to aarch64 See merge request
!9
parents
0ec81e6a
99a65c69
Changes
51
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
51 changed files
with
3715 additions
and
1095 deletions
+3715
-1095
.gitignore
.gitignore
+4
-2
.gitlab-ci.yml
.gitlab-ci.yml
+53
-22
Cargo.toml
Cargo.toml
+2
-1
mu.iml
mu.iml
+0
-22
inst.rs
src/ast/src/inst.rs
+12
-6
ir.rs
src/ast/src/ir.rs
+60
-31
types.rs
src/ast/src/types.rs
+146
-132
asm_backend.rs
src/compiler/backend/arch/x86_64/asm_backend.rs
+254
-105
codegen.rs
src/compiler/backend/arch/x86_64/codegen.rs
+54
-6
inst_sel.rs
src/compiler/backend/arch/x86_64/inst_sel.rs
+1403
-441
mod.rs
src/compiler/backend/arch/x86_64/mod.rs
+5
-10
code_emission.rs
src/compiler/backend/code_emission.rs
+1
-1
mod.rs
src/compiler/backend/mod.rs
+14
-6
liveness.rs
src/compiler/backend/reg_alloc/graph_coloring/liveness.rs
+1
-1
mod.rs
src/compiler/backend/reg_alloc/graph_coloring/mod.rs
+0
-1
mod.rs
src/compiler/backend/reg_alloc/validate/mod.rs
+2
-0
def_use.rs
src/compiler/passes/def_use.rs
+1
-1
gen_mov_phi.rs
src/compiler/passes/gen_mov_phi.rs
+7
-8
inlining.rs
src/compiler/passes/inlining.rs
+14
-7
tree_gen.rs
src/compiler/passes/tree_gen.rs
+4
-4
lib.rs
src/lib.rs
+1
-0
entrypoints.rs
src/runtime/entrypoints.rs
+40
-0
math.rs
src/runtime/math.rs
+27
-0
thread.rs
src/runtime/thread.rs
+1
-0
aot.rs
src/testutil/aot.rs
+4
-0
c_api.rs
src/testutil/c_api.rs
+0
-43
mod.rs
src/testutil/mod.rs
+0
-1
irnodes.rs
src/vm/api/api_impl/irnodes.rs
+1
-0
muirbuilder.rs
src/vm/api/api_impl/muirbuilder.rs
+36
-30
muvm.rs
src/vm/api/api_impl/muvm.rs
+13
-13
vm.rs
src/vm/vm.rs
+55
-23
ir_macros.rs
tests/ir_macros.rs
+31
-27
mod.rs
tests/test_compiler/mod.rs
+2
-1
test_alloc.rs
tests/test_compiler/test_alloc.rs
+0
-1
test_binop.rs
tests/test_compiler/test_binop.rs
+0
-2
test_call.rs
tests/test_compiler/test_call.rs
+95
-1
test_controlflow.rs
tests/test_compiler/test_controlflow.rs
+282
-4
test_convop.rs
tests/test_compiler/test_convop.rs
+0
-2
test_exception.rs
tests/test_compiler/test_exception.rs
+0
-1
test_floatingpoint.rs
tests/test_compiler/test_floatingpoint.rs
+117
-20
test_global.rs
tests/test_compiler/test_global.rs
+0
-1
test_inline.rs
tests/test_compiler/test_inline.rs
+0
-2
test_int.rs
tests/test_compiler/test_int.rs
+0
-1
test_int128.rs
tests/test_compiler/test_int128.rs
+788
-0
test_mem_inst.rs
tests/test_compiler/test_mem_inst.rs
+0
-1
test_regalloc.rs
tests/test_compiler/test_regalloc.rs
+0
-58
test_ir.rs
tests/test_ir/test_ir.rs
+0
-1
test_types.rs
tests/test_ir/test_types.rs
+44
-44
test_rpython.py
tests/test_jit/test_rpython.py
+67
-6
test_som.py
tests/test_jit/test_som.py
+64
-0
util.py
tests/test_jit/util.py
+10
-5
No files found.
.gitignore
View file @
fe287e80
...
...
@@ -11,8 +11,10 @@ Cargo.lock
*.pyc
*.o
*.dylib
mu-client-pypy
**mu-client-pypy**
**RPySOM**
.gitignore
cmake-build-debug/*
Notes/*
CMakeLists.txt
\ No newline at end of file
CMakeLists.txt
*.iml
.gitlab-ci.yml
View file @
fe287e80
# This file is a template, and might need editing before it works on your project.
# Unofficial language image. Look for the different tagged releases at:
# https://hub.docker.com/r/scorpil/rust/tags/
image
:
"
qinsoon/ubuntu-zebu-test:la
s
test"
image
:
"
qinsoon/ubuntu-zebu-test:latest"
# Optional: Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
...
...
@@ -18,36 +18,60 @@ image: "qinsoon/ubuntu-zebu-test:lastest"
#- apt-get install -yqq --no-install-recommends build-essential
# Use cargo to test the project
cache
:
key
:
"
$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
paths
:
-
.cargo/registry/cache
-
.cargo/registry/index
-
target
-
Cargo.lock
# cache:
# key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
# paths:
# - .cargo/registry/cache
# - .cargo/registry/index
# - target
# - Cargo.lock
stages
:
-
build
-
test
build_vm
:
stage
:
build
script
:
-
rustc --version
-
time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo build --release
build_test
:
stage
:
build
script
:
-
rustc --version
-
time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo test --release --no-run
artifacts
:
paths
:
-
target/release/libmu.so
-
target/release/libmu.a
before_script
:
-
time CARGO_HOME=.cargo RUST_BACKTRACE=1 CC=clang cargo test --no-run
-
export PATH=$PATH:/root/.cargo/bin
-
export MU_ZEBU=$CI_PROJECT_DIR
-
export ZEBU_BUILD=release
-
export CARGO_HOME=.cargo
-
export CC=clang
test:cargo:api
:
stage
:
test
script
:
-
CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test
test_api 2> /dev/null
-
RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release
test_api 2> /dev/null
test:cargo:ir
:
stage
:
test
script
:
-
CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test
test_ir 2> /dev/null
-
RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release
test_ir 2> /dev/null
test:cargo:compiler
:
stage
:
test
script
:
-
CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test
test_compiler 2> /dev/null
-
RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release
test_compiler 2> /dev/null
test:cargo:runtime
:
stage
:
test
script
:
-
CARGO_HOME=.cargo RUST_BACKTRACE=1 RUST_TEST_THREADS=1 CC=clang cargo test
test_runtime 2> /dev/null
-
RUST_BACKTRACE=1 RUST_TEST_THREADS=1 cargo test --release
test_runtime 2> /dev/null
testjit:milestones
:
stage
:
test
...
...
@@ -98,17 +122,24 @@ testjit:otherops:
testjit:rpython
:
stage
:
test
script
:
-
if [ -d "tests/test_jit/mu-client-pypy" ]; then rm -Rf tests/test_jit/mu-client-pypy; fi
-
git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git tests/test_jit/mu-client-pypy
-
cd tests/test_jit/mu-client-pypy
-
git checkout mu-rewrite
-
git apply pypy.patch
-
cd $CI_PROJECT_DIR/tests/test_jit
-
LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy MU_ZEBU=$CI_PROJECT_DIR pytest test_rpython*.py -v
cache
:
key
:
"
$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
paths
:
-
.cargo/registry/cache
-
.cargo/registry/index
-
target
-
Cargo.lock
-
tests/test_jit/mu-client-pypy
-
MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy pytest test_rpython*.py -v
testjit:som
:
stage
:
test
script
:
-
if [ -d "tests/test_jit/RPySOM" ]; then rm -Rf tests/test_jit/RPySOM; fi
-
git clone https://github.com/microvm/RPySOM.git tests/test_jit/RPySOM
-
cd tests/test_jit/RPySOM; git submodule init; git submodule update; cd $CI_PROJECT_DIR
-
if [ -d "tests/test_jit/mu-client-pypy" ]; then rm -Rf tests/test_jit/mu-client-pypy; fi
-
git clone https://gitlab.anu.edu.au/mu/mu-client-pypy.git tests/test_jit/mu-client-pypy
-
cd tests/test_jit/mu-client-pypy
-
git checkout mu-rewrite
-
git apply pypy.patch
-
cd $CI_PROJECT_DIR/tests/test_jit
-
MU_LOG_LEVEL=info LD_LIBRARY_PATH=. RUST_BACKTRACE=1 PYTHONPATH=mu-client-pypy:RPySOM/src RPYSOM=RPySOM pytest test_som.py -v
\ No newline at end of file
Cargo.toml
View file @
fe287e80
...
...
@@ -33,4 +33,5 @@ rustc-serialize = "*"
time
=
"0.1.34"
maplit
=
"0.1.4"
docopt
=
"0.6"
petgraph
=
"0.4.1"
\ No newline at end of file
petgraph
=
"0.4.1"
extprim
=
"*"
\ No newline at end of file
mu.iml
deleted
100644 → 0
View file @
0ec81e6a
<?xml version="1.0" encoding="UTF-8"?>
<module
type=
"RUST_MODULE"
version=
"4"
>
<component
name=
"FacetManager"
>
<facet
type=
"Python"
name=
"Python"
>
<configuration
sdkName=
""
/>
</facet>
</component>
<component
name=
"NewModuleRootManager"
inherit-compiler-output=
"true"
>
<exclude-output
/>
<content
url=
"file://$MODULE_DIR$"
>
<sourceFolder
url=
"file://$MODULE_DIR$/src"
isTestSource=
"false"
/>
<sourceFolder
url=
"file://$MODULE_DIR$/examples"
isTestSource=
"false"
/>
<sourceFolder
url=
"file://$MODULE_DIR$/tests"
isTestSource=
"true"
/>
<sourceFolder
url=
"file://$MODULE_DIR$/benches"
isTestSource=
"true"
/>
<excludeFolder
url=
"file://$MODULE_DIR$/target"
/>
</content>
<orderEntry
type=
"inheritedJdk"
/>
<orderEntry
type=
"sourceFolder"
forTests=
"false"
/>
<orderEntry
type=
"library"
name=
"Rust <mu>"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Cargo <mu>"
level=
"project"
/>
</component>
</module>
\ No newline at end of file
src/ast/src/inst.rs
View file @
fe287e80
...
...
@@ -7,14 +7,13 @@ use ir_semantics;
use
utils
::
vec_utils
;
use
std
::
fmt
;
use
std
::
sync
::
RwLock
;
#[derive(Debug)]
// this implements RustcEncodable, RustcDecodable, Clone and Display
pub
struct
Instruction
{
pub
hdr
:
MuEntityHeader
,
pub
value
:
Option
<
Vec
<
P
<
Value
>>>
,
pub
ops
:
RwLock
<
Vec
<
P
<
TreeNode
>
>>
,
pub
ops
:
Vec
<
P
<
TreeNode
>>
,
pub
v
:
Instruction_
}
...
...
@@ -27,7 +26,7 @@ impl Encodable for Instruction {
try!
(
s
.emit_struct_field
(
"hdr"
,
0
,
|
s
|
self
.hdr
.encode
(
s
)));
try!
(
s
.emit_struct_field
(
"value"
,
1
,
|
s
|
self
.value
.encode
(
s
)));
let
ops
=
&
self
.ops
.read
()
.unwrap
()
;
let
ref
ops
=
self
.ops
;
try!
(
s
.emit_struct_field
(
"ops"
,
2
,
|
s
|
ops
.encode
(
s
)));
try!
(
s
.emit_struct_field
(
"v"
,
3
,
|
s
|
self
.v
.encode
(
s
)));
...
...
@@ -50,7 +49,7 @@ impl Decodable for Instruction {
Ok
(
Instruction
{
hdr
:
hdr
,
value
:
value
,
ops
:
RwLock
::
new
(
ops
)
,
ops
:
ops
,
v
:
v
})
})
...
...
@@ -62,13 +61,20 @@ impl Clone for Instruction {
Instruction
{
hdr
:
self
.hdr
.clone
(),
value
:
self
.value
.clone
(),
ops
:
RwLock
::
new
(
self
.ops
.read
()
.unwrap
()
.clone
()
),
ops
:
self
.ops
.clone
(
),
v
:
self
.v
.clone
()
}
}
}
impl
Instruction
{
pub
fn
clone_with_id
(
&
self
,
new_id
:
MuID
)
->
Instruction
{
let
mut
clone
=
self
.clone
();
clone
.hdr
=
self
.hdr
.clone_with_id
(
new_id
);
clone
}
pub
fn
has_exception_clause
(
&
self
)
->
bool
{
ir_semantics
::
is_potentially_excepting_instruction
(
&
self
.v
)
}
...
...
@@ -133,7 +139,7 @@ impl Instruction {
impl
fmt
::
Display
for
Instruction
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
let
ops
=
&
self
.ops
.read
()
.unwrap
()
;
let
ref
ops
=
self
.ops
;
if
self
.value
.is_some
()
{
write!
(
f
,
"{} = {}"
,
vec_utils
::
as_str
(
self
.value
.as_ref
()
.unwrap
()),
self
.v
.debug_str
(
ops
))
}
else
{
...
...
src/ast/src/ir.rs
View file @
fe287e80
...
...
@@ -242,7 +242,7 @@ impl MuFunctionVersion {
for
inst
in
block_content
.body
.iter
()
{
match
inst
.v
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
let
ops
=
inst
.ops
.read
()
.unwrap
()
;
let
ref
ops
=
inst
.ops
;
match
inst
.v
{
Instruction_
::
ExprCall
{
ref
data
,
..
}
...
...
@@ -358,6 +358,16 @@ impl FunctionContent {
None
=>
panic!
(
"cannot find block #{}"
,
id
)
}
}
pub
fn
get_block_by_name
(
&
self
,
name
:
String
)
->
&
Block
{
for
block
in
self
.blocks
.values
()
{
if
block
.name
()
.unwrap
()
==
name
{
return
block
;
}
}
panic!
(
"cannot find block {}"
,
name
)
}
}
#[derive(Default,
Debug,
RustcEncodable,
RustcDecodable)]
...
...
@@ -535,7 +545,7 @@ impl BlockContent {
match
last_inst
.v
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
let
ops
=
inst
.ops
.read
()
.unwrap
()
;
let
ref
ops
=
inst
.ops
;
match
inst
.v
{
Instruction_
::
Return
(
_
)
|
Instruction_
::
ThreadExit
...
...
@@ -702,16 +712,17 @@ impl Value {
_
=>
false
}
}
pub
fn
is_
int_
reg
(
&
self
)
->
bool
{
pub
fn
is_reg
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
SSAVar
(
_
)
=>
{
if
is_scalar
(
&
self
.ty
)
&&
!
is_fp
(
&
self
.ty
)
{
true
}
else
{
false
}
}
Value_
::
SSAVar
(
_
)
=>
true
,
_
=>
false
}
}
pub
fn
is_const
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
Constant
(
_
)
=>
true
,
_
=>
false
}
}
...
...
@@ -724,21 +735,6 @@ impl Value {
})
}
pub
fn
is_fp_reg
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
SSAVar
(
_
)
=>
{
if
is_scalar
(
&
self
.ty
)
&&
is_fp
(
&
self
.ty
)
{
true
}
else
{
false
}
},
Value_
::
Constant
(
Constant
::
Double
(
_
))
=>
true
,
Value_
::
Constant
(
Constant
::
Float
(
_
))
=>
true
,
_
=>
false
}
}
pub
fn
is_int_const
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
Constant
(
Constant
::
Int
(
_
))
=>
true
,
...
...
@@ -761,6 +757,13 @@ impl Value {
_
=>
None
}
}
pub
fn
extract_memory_location
(
&
self
)
->
Option
<
MemoryLocation
>
{
match
self
.v
{
Value_
::
Memory
(
ref
loc
)
=>
Some
(
loc
.clone
()),
_
=>
None
}
}
}
const
DISPLAY_ID
:
bool
=
true
;
...
...
@@ -826,7 +829,10 @@ pub struct SSAVarEntry {
use_count
:
AtomicUsize
,
// this field is only used during TreeGeneration pass
expr
:
Option
<
Instruction
>
expr
:
Option
<
Instruction
>
,
// some ssa vars (such as int128) needs to be split into smaller vars
split
:
Option
<
Vec
<
P
<
Value
>>>
}
impl
Encodable
for
SSAVarEntry
{
...
...
@@ -836,6 +842,7 @@ impl Encodable for SSAVarEntry {
let
count
=
self
.use_count
.load
(
Ordering
::
SeqCst
);
try!
(
s
.emit_struct_field
(
"use_count"
,
1
,
|
s
|
s
.emit_usize
(
count
)));
try!
(
s
.emit_struct_field
(
"expr"
,
2
,
|
s
|
self
.expr
.encode
(
s
)));
try!
(
s
.emit_struct_field
(
"split"
,
3
,
|
s
|
self
.split
.encode
(
s
)));
Ok
(())
})
}
...
...
@@ -844,14 +851,16 @@ impl Encodable for SSAVarEntry {
impl
Decodable
for
SSAVarEntry
{
fn
decode
<
D
:
Decoder
>
(
d
:
&
mut
D
)
->
Result
<
SSAVarEntry
,
D
::
Error
>
{
d
.read_struct
(
"SSAVarEntry"
,
3
,
|
d
|
{
let
val
=
try!
(
d
.read_struct_field
(
"val"
,
0
,
|
d
|
Decodable
::
decode
(
d
)));
let
val
=
try!
(
d
.read_struct_field
(
"val"
,
0
,
|
d
|
Decodable
::
decode
(
d
)));
let
count
=
try!
(
d
.read_struct_field
(
"use_count"
,
1
,
|
d
|
d
.read_usize
()));
let
expr
=
try!
(
d
.read_struct_field
(
"expr"
,
2
,
|
d
|
Decodable
::
decode
(
d
)));
let
expr
=
try!
(
d
.read_struct_field
(
"expr"
,
2
,
|
d
|
Decodable
::
decode
(
d
)));
let
split
=
try!
(
d
.read_struct_field
(
"split"
,
3
,
|
d
|
Decodable
::
decode
(
d
)));
let
ret
=
SSAVarEntry
{
val
:
val
,
use_count
:
ATOMIC_USIZE_INIT
,
expr
:
expr
expr
:
expr
,
split
:
split
};
ret
.use_count
.store
(
count
,
Ordering
::
SeqCst
);
...
...
@@ -866,7 +875,8 @@ impl SSAVarEntry {
let
ret
=
SSAVarEntry
{
val
:
val
,
use_count
:
ATOMIC_USIZE_INIT
,
expr
:
None
expr
:
None
,
split
:
None
};
ret
.use_count
.store
(
0
,
Ordering
::
SeqCst
);
...
...
@@ -902,6 +912,16 @@ impl SSAVarEntry {
debug_assert!
(
self
.has_expr
());
self
.expr
.take
()
.unwrap
()
}
pub
fn
has_split
(
&
self
)
->
bool
{
self
.split
.is_some
()
}
pub
fn
set_split
(
&
mut
self
,
vec
:
Vec
<
P
<
Value
>>
)
{
self
.split
=
Some
(
vec
);
}
pub
fn
get_split
(
&
self
)
->
&
Option
<
Vec
<
P
<
Value
>>>
{
&
self
.split
}
}
impl
fmt
::
Display
for
SSAVarEntry
{
...
...
@@ -913,6 +933,7 @@ impl fmt::Display for SSAVarEntry {
#[derive(Debug,
Clone,
PartialEq,
RustcEncodable,
RustcDecodable)]
pub
enum
Constant
{
Int
(
u64
),
IntEx
(
Vec
<
u64
>
),
Float
(
f32
),
Double
(
f64
),
// IRef(Address),
...
...
@@ -929,6 +950,7 @@ impl fmt::Display for Constant {
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
match
self
{
&
Constant
::
Int
(
v
)
=>
write!
(
f
,
"{}"
,
v
as
i64
),
&
Constant
::
IntEx
(
ref
v
)
=>
write!
(
f
,
"IntEx {:?}"
,
v
),
&
Constant
::
Float
(
v
)
=>
write!
(
f
,
"{}"
,
v
),
&
Constant
::
Double
(
v
)
=>
write!
(
f
,
"{}"
,
v
),
// &Constant::IRef(v) => write!(f, "{}", v),
...
...
@@ -1163,6 +1185,13 @@ impl MuEntityHeader {
None
=>
None
}
}
pub
fn
clone_with_id
(
&
self
,
new_id
:
MuID
)
->
MuEntityHeader
{
let
mut
clone
=
self
.clone
();
clone
.id
=
new_id
;
clone
}
}
impl
PartialEq
for
MuEntityHeader
{
...
...
src/ast/src/types.rs
View file @
fe287e80
...
...
@@ -59,6 +59,7 @@ lazy_static! {
UINT128_TYPE
.clone
(),
FLOAT_TYPE
.clone
(),
DOUBLE_TYPE
.clone
(),
FLOAT_TYPE
.clone
(),
VOID_TYPE
.clone
()
];
}
...
...
@@ -103,28 +104,166 @@ impl MuType {
}
}
pub
fn
get_struct_hybrid_tag
(
&
self
)
->
Option
<
MuName
>
{
pub
fn
is_ref
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Hybrid
(
ref
name
)
|
MuType_
::
Struct
(
ref
name
)
=>
Some
(
name
.clone
()),
_
=>
None
MuType_
::
Ref
(
_
)
=>
true
,
_
=>
false
}
}
pub
fn
is_ref
(
&
self
)
->
bool
{
pub
fn
is_
i
ref
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Ref
(
_
)
=>
true
,
MuType_
::
I
Ref
(
_
)
=>
true
,
_
=>
false
}
}
pub
fn
is_iref
(
&
self
)
->
bool
{
pub
fn
is_fp
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Float
|
MuType_
::
Double
=>
true
,
_
=>
false
}
}
pub
fn
is_float
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Float
=>
true
,
_
=>
false
}
}
pub
fn
is_double
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Double
=>
true
,
_
=>
false
}
}
/// is a type raw pointer?
pub
fn
is_ptr
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
UPtr
(
_
)
|
MuType_
::
UFuncPtr
(
_
)
=>
true
,
_
=>
false
}
}
/// this a type reference type (located in heap)?
pub
fn
is_reference
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Ref
(
_
)
|
MuType_
::
IRef
(
_
)
|
MuType_
::
WeakRef
(
_
)
=>
true
,
_
=>
false
}
}
/// this is a aggregated type (consited of other types)
pub
fn
is_aggregate
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Struct
(
_
)
|
MuType_
::
Hybrid
(
_
)
|
MuType_
::
Array
(
_
,
_
)
=>
true
,
_
=>
false
}
}
/// is a type scalar type?
pub
fn
is_scalar
(
&
self
)
->
bool
{
match
self
.v
{
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
,
_
=>
false
}
}
/// is a type traced by the garbage collector?
/// Note: An aggregated type is traced if any of its part is traced.
pub
fn
is_traced
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Ref
(
_
)
=>
true
,
MuType_
::
IRef
(
_
)
=>
true
,
MuType_
::
WeakRef
(
_
)
=>
true
,
MuType_
::
Array
(
ref
elem_ty
,
_
)
|
MuType_
::
Vector
(
ref
elem_ty
,
_
)
=>
elem_ty
.is_traced
(),
MuType_
::
ThreadRef
|
MuType_
::
StackRef
|
MuType_
::
Tagref64
=>
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
;
let
ref
var_ty
=
hybrid_ty
.var_ty
;
var_ty
.is_traced
()
||
fix_tys
.into_iter
()
.map
(|
ty
|
ty
.is_traced
())
.fold
(
false
,
|
ret
,
this
|
ret
||
this
)
},
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
;
field_tys
.into_iter
()
.map
(|
ty
|
ty
.is_traced
())
.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.
pub
fn
is_native_safe
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Int
(
_
)
=>
true
,
MuType_
::
Float
=>
true
,
MuType_
::
Double
=>
true
,
MuType_
::
Void
=>
true
,
MuType_
::
Array
(
ref
elem_ty
,
_
)
|
MuType_
::
Vector
(
ref
elem_ty
,
_
)
=>
elem_ty
.is_native_safe
(),
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
;
let
ref
var_ty
=
hybrid_ty
.var_ty
;
var_ty
.is_native_safe
()
&&
fix_tys
.into_iter
()
.map
(|
ty
|
ty
.is_native_safe
())
.fold
(
true
,
|
ret
,
this
|
ret
&&
this
)
},
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
;
field_tys
.into_iter
()
.map
(|
ty
|
ty
.is_native_safe
())
.fold
(
true
,
|
ret
,
this
|
ret
&&
this
)
},
_
=>
false
}
}
pub
fn
get_struct_hybrid_tag
(
&
self
)
->
Option
<
MuName
>
{
match
self
.v
{
MuType_
::
Hybrid
(
ref
name
)
|
MuType_
::
Struct
(
ref
name
)
=>
Some
(
name
.clone
()),
_
=>
None
}
}
pub
fn
get_elem_ty
(
&
self
)
->
Option
<
P
<
MuType
>>
{
match
self
.v
{
MuType_
::
Array
(
ref
elem_ty
,
_
)
=>
Some
(
elem_ty
.clone
()),
...
...
@@ -475,131 +614,6 @@ impl MuType_ {
}
}
/// is a type floating-point type?
pub
fn
is_fp
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
MuType_
::
Float
|
MuType_
::
Double
=>
true
,
_
=>
false
}
}
/// is a type raw pointer?
pub
fn
is_ptr
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
MuType_
::
UPtr
(
_
)
|
MuType_
::
UFuncPtr
(
_
)
=>
true
,
_
=>
false
}
}
/// this a type reference type (located in heap)?
pub
fn
is_reference
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
MuType_
::
Ref
(
_
)
|
MuType_
::
IRef
(
_
)
|
MuType_
::
WeakRef
(
_
)
=>
true
,
_
=>
false
}
}
/// this is a aggregated type (consited of other types)
pub
fn
is_aggregate
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
MuType_
::
Struct
(
_
)
|
MuType_
::
Hybrid
(
_
)
|
MuType_
::
Array
(
_
,
_
)
=>
true
,
_
=>
false
}
}
/// is a type scalar type?
pub
fn
is_scalar
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
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
,
_
=>
false
}
}
/// is a type traced by the garbage collector?
/// Note: An aggregated type is traced if any of its part is traced.
pub
fn
is_traced
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
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
tag
)
=>
{
let
map
=
HYBRID_TAG_MAP
.read
()
.unwrap
();
let
hybrid_ty
=
map
.get
(
tag
)
.unwrap
();
let
ref
fix_tys
=
hybrid_ty
.fix_tys
;
let
ref
var_ty
=
hybrid_ty
.var_ty
;
is_traced
(
var_ty
)
||
fix_tys
.into_iter
()
.map
(|
ty
|
is_traced
(
ty
))
.fold
(
false
,
|
ret
,
this
|
ret
||
this
)
},
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
;
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.
pub
fn
is_native_safe
(
ty
:
&
MuType
)
->
bool
{
match
ty
.v
{
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
tag
)
=>
{
let
map
=
HYBRID_TAG_MAP
.read
()
.unwrap
();
let
hybrid_ty
=
map
.get
(
tag
)
.unwrap
();
let
ref
fix_tys
=
hybrid_ty
.fix_tys
;
let
ref
var_ty
=
hybrid_ty
.var_ty
;
is_native_safe
(
var_ty
)
&&
fix_tys
.into_iter
()
.map
(|
ty
|
is_native_safe
(
&
ty
))
.fold
(
true
,
|
ret
,
this
|
ret
&&
this
)
},
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
;
field_tys
.into_iter
()
.map
(|
ty
|
is_native_safe
(
&
ty
))
.fold
(
true
,
|
ret
,
this
|
ret
&&
this
)
},