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
415d45e8
Commit
415d45e8
authored
May 31, 2017
by
qinsoon
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into open-source
parents
29759a3c
99a65c69
Changes
50
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
3545 additions
and
917 deletions
+3545
-917
.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
-7
ir.rs
src/ast/src/ir.rs
+60
-31
types.rs
src/ast/src/types.rs
+24
-0
asm_backend.rs
src/compiler/backend/arch/x86_64/asm_backend.rs
+255
-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
+1400
-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
+12
-3
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_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 @
415d45e8
...
...
@@ -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 @
415d45e8
# 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 @
415d45e8
...
...
@@ -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 @
29759a3c
<?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 @
415d45e8
...
...
@@ -6,7 +6,6 @@ use op::*;
use
utils
::
vec_utils
;
use
std
::
fmt
;
use
std
::
sync
::
RwLock
;
/// Instruction represents a Mu instruction
#[derive(Debug)]
// RustcEncodable, RustcDecodable, Clone and Display
...
...
@@ -17,7 +16,7 @@ pub struct Instruction {
/// ops field list all the children nodes,
/// and in Instruction_, the children nodes are referred by indices
/// This design makes it easy for the compiler to iterate through all the children
pub
ops
:
RwLock
<
Vec
<
P
<
TreeNode
>
>>
,
pub
ops
:
Vec
<
P
<
TreeNode
>>
,
/// used for pattern matching
pub
v
:
Instruction_
}
...
...
@@ -32,7 +31,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
)));
...
...
@@ -55,7 +54,7 @@ impl Decodable for Instruction {
Ok
(
Instruction
{
hdr
:
hdr
,
value
:
value
,
ops
:
RwLock
::
new
(
ops
)
,
ops
:
ops
,
v
:
v
})
})
...
...
@@ -67,13 +66,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
}
/// is this instruction the terminal inst of its block?
/// Terminal instructions end Mu blocks, and Mu block ends with a terminal instruction.
pub
fn
is_terminal_inst
(
&
self
)
->
bool
{
...
...
@@ -249,7 +255,6 @@ impl Instruction {
/// returns exception target(block ID), returns None if this instruction does not have exceptional branch
pub
fn
get_exception_target
(
&
self
)
->
Option
<
MuID
>
{
use
inst
::
Instruction_
::
*
;
match
self
.v
{
Watchpoint
{
ref
resume
,
..
}
|
Call
{
ref
resume
,
..
}
...
...
@@ -308,7 +313,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 @
415d45e8
...
...
@@ -249,7 +249,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
,
..
}
...
...
@@ -364,6 +364,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
)
}
}
/// FunctionContext contains compilation information about the function
...
...
@@ -560,7 +570,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
...
...
@@ -738,16 +748,17 @@ impl Value {
_
=>
false
}
}
pub
fn
is_
int_
reg
(
&
self
)
->
bool
{
pub
fn
is_reg
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
SSAVar
(
_
)
=>
{
if
self
.ty
.is_scalar
()
&&
!
self
.ty
.is_fp
()
{
true
}
else
{
false
}
}
Value_
::
SSAVar
(
_
)
=>
true
,
_
=>
false
}
}
pub
fn
is_const
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
Constant
(
_
)
=>
true
,
_
=>
false
}
}
...
...
@@ -763,21 +774,6 @@ impl Value {
})
}
pub
fn
is_fp_reg
(
&
self
)
->
bool
{
match
self
.v
{
Value_
::
SSAVar
(
_
)
=>
{
if
self
.ty
.is_scalar
()
&&
self
.ty
.is_fp
()
{
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
,
...
...
@@ -800,6 +796,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
;
...
...
@@ -868,7 +871,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
{
...
...
@@ -878,6 +884,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
(())
})
}
...
...
@@ -886,14 +893,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
);
...
...
@@ -908,7 +917,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
);
...
...
@@ -944,6 +954,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
{
...
...
@@ -957,6 +977,7 @@ impl fmt::Display for SSAVarEntry {
pub
enum
Constant
{
/// all integer constants are stored as u64
Int
(
u64
),
IntEx
(
Vec
<
u64
>
),
/// float constants
Float
(
f32
),
/// double constants
...
...
@@ -977,6 +998,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),
...
...
@@ -1227,6 +1249,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 @
415d45e8
...
...
@@ -117,6 +117,22 @@ impl MuType {
}
}
/// is this type a float type (single-precision floating point)
pub
fn
is_float
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Float
=>
true
,
_
=>
false
}
}
/// is this type a double type (double-precision floating point)
pub
fn
is_double
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
Double
=>
true
,
_
=>
false
}
}
/// is this type a scalar type?
pub
fn
is_scalar
(
&
self
)
->
bool
{
match
self
.v
{
...
...
@@ -173,6 +189,14 @@ impl MuType {
}
}
/// is a type raw pointer?
pub
fn
is_ptr
(
&
self
)
->
bool
{
match
self
.v
{
MuType_
::
UPtr
(
_
)
|
MuType_
::
UFuncPtr
(
_
)
=>
true
,
_
=>
false
}
}
/// is this type an aggregated type? (consisted of other types)
pub
fn
is_aggregate
(
&
self
)
->
bool
{
match
self
.v
{
...
...
src/compiler/backend/arch/x86_64/asm_backend.rs
View file @
415d45e8
This diff is collapsed.
Click to expand it.
src/compiler/backend/arch/x86_64/codegen.rs
View file @
415d45e8
...
...
@@ -39,6 +39,9 @@ pub trait CodeGenerator {
fn
emit_cmp_imm_r
(
&
mut
self
,
op1
:
i32
,
op2
:
Reg
);
fn
emit_cmp_mem_r
(
&
mut
self
,
op1
:
Reg
,
op2
:
Reg
);
fn
emit_test_r_r
(
&
mut
self
,
op1
:
Reg
,
op2
:
Reg
);
fn
emit_test_imm_r
(
&
mut
self
,
op1
:
i32
,
op2
:
Reg
);
// gpr move
// mov imm64 to r64
...
...
@@ -133,16 +136,29 @@ pub trait CodeGenerator {
fn
emit_add_r_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_add_r_mem
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_add_r_imm
(
&
mut
self
,
dest
:
Reg
,
src
:
i32
);
// add with carry
fn
emit_adc_r_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_adc_r_mem
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_adc_r_imm
(
&
mut
self
,
dest
:
Reg
,
src
:
i32
);
// sub
fn
emit_sub_r_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_sub_r_mem
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_sub_r_imm
(
&
mut
self
,
dest
:
Reg
,
src
:
i32
);
// sub with borrow
fn
emit_sbb_r_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_sbb_r_mem
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_sbb_r_imm
(
&
mut
self
,
dest
:
Reg
,
src
:
i32
);
// multiply
fn
emit_mul_r
(
&
mut
self
,
src
:
Reg
);
fn
emit_mul_mem
(
&
mut
self
,
src
:
Mem
);
// signed multiply
fn
emit_imul_r_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
// div
fn
emit_div_r
(
&
mut
self
,
src
:
Reg
);
fn
emit_div_mem
(
&
mut
self
,
src
:
Mem
);
...
...
@@ -155,9 +171,13 @@ pub trait CodeGenerator {
fn
emit_shl_r_cl
(
&
mut
self
,
dest
:
Reg
);
fn
emit_shl_r_imm8
(
&
mut
self
,
dest
:
Reg
,
src
:
i8
);
fn
emit_shld_r_r_cl
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_shr_r_cl
(
&
mut
self
,
dest
:
&
P
<
Value
>
);
fn
emit_shr_r_imm8
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
i8
);
fn
emit_shrd_r_r_cl
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_sar_r_cl
(
&
mut
self
,
dest
:
&
P
<
Value
>
);
fn
emit_sar_r_imm8
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
i8
);
...
...
@@ -166,16 +186,18 @@ pub trait CodeGenerator {
fn
emit_cwd
(
&
mut
self
);
// sign extend ax to dx:ax
fn
emit_jmp
(
&
mut
self
,
dest
:
MuName
);
fn
emit_je
(
&
mut
self
,
dest
:
MuName
);
fn
emit_je
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jne
(
&
mut
self
,
dest
:
MuName
);
fn
emit_ja
(
&
mut
self
,
dest
:
MuName
);
fn
emit_ja
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jae
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jb
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jb
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jbe
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jg
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jg
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jge
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jl
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jl
(
&
mut
self
,
dest
:
MuName
);
fn
emit_jle
(
&
mut
self
,
dest
:
MuName
);
fn
emit_js
(
&
mut
self
,
dest
:
MuName
);
fn
emit_call_near_rel32
(
&
mut
self
,
callsite
:
String
,
func
:
MuName
,
pe
:
Option
<
MuName
>
)
->
ValueLocation
;
fn
emit_call_near_r64
(
&
mut
self
,
callsite
:
String
,
func
:
&
P
<
Value
>
,
pe
:
Option
<
MuName
>
)
->
ValueLocation
;
...
...
@@ -192,33 +214,57 @@ pub trait CodeGenerator {
fn
emit_movsd_f64_mem64
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
P
<
Value
>
);
// load
fn
emit_movsd_mem64_f64
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
P
<
Value
>
);
// store
fn
emit_movss_f32_f32
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
P
<
Value
>
);
fn
emit_movss_f32_mem32
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
P
<
Value
>
);
// load
fn
emit_movss_mem32_f32
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
P
<
Value
>
);
// store
// fp add
fn
emit_addsd_f64_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_addsd_f64_mem64
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_addss_f32_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_addss_f32_mem32
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
// fp sub
fn
emit_subsd_f64_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_subsd_f64_mem64
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_subss_f32_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_subss_f32_mem32
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
// fp div
fn
emit_divsd_f64_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_divsd_f64_mem64
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_divss_f32_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_divss_f32_mem32
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
// fp mul
fn
emit_mulsd_f64_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_mulsd_f64_mem64
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_mulss_f32_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_mulss_f32_mem32
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
// fp comparison
fn
emit_comisd_f64_f64
(
&
mut
self
,
op1
:
Reg
,
op2
:
Reg
);
fn
emit_ucomisd_f64_f64
(
&
mut
self
,
op1
:
Reg
,
op2
:
Reg
);
fn
emit_comiss_f32_f32
(
&
mut
self
,
op1
:
Reg
,
op2
:
Reg
);
fn
emit_ucomiss_f32_f32
(
&
mut
self
,
op1
:
Reg
,
op2
:
Reg
);
// fp conversion
fn
emit_cvtsi2sd_f64_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_cvtsd2si_r_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_cvttsd2si_r_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_cvtsi2ss_f32_r
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_cvtss2si_r_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
// used for unsigned int to fp conversion
fn
emit_cvttsd2si_r_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_cvttss2si_r_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
// unpack low data - interleave low byte
fn
emit_punpckldq_f64_mem128
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
// substract packed double-fp
...
...
@@ -229,4 +275,6 @@ pub trait CodeGenerator {
// move aligned packed double-precision fp values
fn
emit_movapd_f64_mem128
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_movapd_f64_f64
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
fn
emit_movaps_f32_f32
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
}
src/compiler/backend/arch/x86_64/inst_sel.rs
View file @
415d45e8
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/compiler/backend/arch/x86_64/mod.rs
View file @
415d45e8
...
...
@@ -6,7 +6,7 @@ pub mod inst_sel;
mod
codegen
;
pub
use
compiler
::
backend
::
x86_64
::
codegen
::
CodeGenerator
;
mod
asm_backend
;
pub
mod
asm_backend
;
pub
use
compiler
::
backend
::
x86_64
::
asm_backend
::
ASMCodeGen
;
pub
use
compiler
::
backend
::
x86_64
::
asm_backend
::
emit_code
;
pub
use
compiler
::
backend
::
x86_64
::
asm_backend
::
emit_context
;
...
...
@@ -425,8 +425,9 @@ pub fn init_machine_regs_for_func (func_context: &mut FunctionContext) {
pub
fn
number_of_regs_in_group
(
group
:
RegGroup
)
->
usize
{
match
group
{
RegGroup
::
GPR
=>
ALL_GPRs
.len
(),
RegGroup
::
FPR
=>
ALL_FPRs
.len
()
RegGroup
::
GPR
=>
ALL_GPRs
.len
(),
RegGroup
::
GPREX
=>
ALL_GPRs
.len
(),
RegGroup
::
FPR
=>
ALL_FPRs
.len
()
}
}
...
...
@@ -444,13 +445,7 @@ pub fn all_usable_regs() -> &'static Vec<P<Value>> {
pub
fn
pick_group_for_reg
(
reg_id
:
MuID
)
->
RegGroup
{
let
reg
=
all_regs
()
.get
(
&
reg_id
)
.unwrap
();
if
reg
.is_int_reg
()
{
RegGroup
::
GPR
}
else
if
reg
.is_fp_reg
()
{
RegGroup
::
FPR
}
else
{
panic!
(
"expect a machine reg to be either a GPR or a FPR: {}"
,
reg
)
}
RegGroup
::
get_from_value
(
reg
)
}
pub
fn
is_callee_saved
(
reg_id
:
MuID
)
->
bool
{
...
...
src/compiler/backend/code_emission.rs
View file @
415d45e8
...
...
@@ -222,7 +222,7 @@ fn emit_muir_dot_inner(file: &mut File,
match last_inst.v {
TreeNode_::Instruction(ref inst) => {
let
ops = inst.ops.read().unwrap()
;
let
ref ops = inst.ops
;
match inst.v {
Branch1(ref dest) => {
...
...
src/compiler/backend/mod.rs
View file @
415d45e8
...
...
@@ -121,6 +121,10 @@ pub fn resolve_backend_type_info (ty: &MuType, vm: &VM) -> BackendTypeInfo {
size
:
8
,
alignment
:
8
,
struct_layout
:
None
,
elem_padded_size
:
None
,
gc_type
:
mm
::
add_gc_type
(
GCType
::
new_noreftype
(
8
,
8
))
},
128
=>
BackendTypeInfo
{
size
:
16
,
alignment
:
16
,
struct_layout
:
None
,
elem_padded_size
:
None
,
gc_type
:
mm
::
add_gc_type
(
GCType
::
new_noreftype
(
16
,
16
))
},
_
=>
unimplemented!
()
}
},
...
...
@@ -297,7 +301,7 @@ pub fn sequetial_layout(tys: &Vec<P<MuType>>, vm: &VM) -> (ByteSize, ByteSize, V
let
ret
=
layout_struct
(
tys
,
vm
);
(
ret
.size
,
ret
.alignment
,
ret
.struct_layout
.unwrap
())
}
}
#[derive(Clone,
Debug,
RustcEncodable,
RustcDecodable)]
pub
struct
BackendTypeInfo
{
...
...
@@ -343,10 +347,10 @@ impl fmt::Display for BackendTypeInfo {
}
#[derive(Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
RustcEncodable,
RustcDecodable)]
pub
enum
RegGroup
{
GPR
,
FPR
}
pub
enum
RegGroup
{
GPR
,
GPREX
,
FPR
}
impl
RegGroup
{
pub
fn
get
(
ty
:
&
P
<
MuType
>
)
->
RegGroup
{
pub
fn
get
_from_ty
(
ty
:
&
P
<
MuType
>
)
->
RegGroup
{
match
ty
.v
{
// for now, only use 64bits registers
MuType_
::
Int
(
len
)
if
len
==
1
=>
RegGroup
::
GPR
,
...
...
@@ -354,6 +358,7 @@ impl RegGroup {
MuType_
::
Int
(
len
)
if
len
==
16
=>
RegGroup
::
GPR
,
MuType_
::
Int
(
len
)
if
len
==
32
=>
RegGroup
::
GPR
,
MuType_
::
Int
(
len
)
if
len
==
64
=>
RegGroup
::
GPR
,
MuType_
::
Int
(
len
)
if
len
==
128
=>
RegGroup
::
GPREX
,
MuType_
::
Ref
(
_
)
|
MuType_
::
IRef
(
_
)
...
...
@@ -371,4 +376,8 @@ impl RegGroup {
_
=>
unimplemented!
()
}
}
pub
fn
get_from_value
(
val
:
&
P
<
Value
>
)
->
RegGroup
{
RegGroup
::
get_from_ty
(
&
val
.ty
)
}
}
src/compiler/backend/reg_alloc/graph_coloring/liveness.rs
View file @
415d45e8
...
...
@@ -43,7 +43,7 @@ impl InterferenceGraph {
let
node
=
GraphNode
{
temp
:
reg_id
,
color
:
None
,
group
:
backend
::
RegGroup
::
get
(
entry
.ty
()),
group
:
backend
::
RegGroup
::
get
_from_ty
(
entry
.ty
()),
spill_cost
:
0.0f32
};
...
...
src/compiler/backend/reg_alloc/graph_coloring/mod.rs
View file @
415d45e8
...
...
@@ -14,7 +14,6 @@ use compiler::CompilerPass;
use
compiler
::
backend
::
is_callee_saved
;
use
compiler
::
backend
::
init_machine_regs_for_func
;