Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mu-impl-fast
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
40
Issues
40
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
mu
mu-impl-fast
Commits
f83e4dde
Commit
f83e4dde
authored
Oct 20, 2016
by
qinsoon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[wip] debugging
parent
b77b1887
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
348 additions
and
123 deletions
+348
-123
Cargo.toml
Cargo.toml
+1
-1
src/ast/src/ir.rs
src/ast/src/ir.rs
+8
-1
src/compiler/backend/arch/x86_64/inst_sel.rs
src/compiler/backend/arch/x86_64/inst_sel.rs
+5
-0
src/compiler/backend/code_emission.rs
src/compiler/backend/code_emission.rs
+6
-0
src/compiler/backend/peephole_opt.rs
src/compiler/backend/peephole_opt.rs
+6
-0
src/compiler/backend/reg_alloc/graph_coloring/coloring.rs
src/compiler/backend/reg_alloc/graph_coloring/coloring.rs
+29
-22
src/compiler/backend/reg_alloc/graph_coloring/liveness.rs
src/compiler/backend/reg_alloc/graph_coloring/liveness.rs
+68
-13
src/compiler/backend/reg_alloc/graph_coloring/mod.rs
src/compiler/backend/reg_alloc/graph_coloring/mod.rs
+89
-0
src/compiler/backend/reg_alloc/mod.rs
src/compiler/backend/reg_alloc/mod.rs
+2
-85
src/compiler/mod.rs
src/compiler/mod.rs
+4
-0
src/compiler/passes/control_flow.rs
src/compiler/passes/control_flow.rs
+6
-1
src/compiler/passes/def_use.rs
src/compiler/passes/def_use.rs
+5
-0
src/compiler/passes/mod.rs
src/compiler/passes/mod.rs
+3
-0
src/compiler/passes/trace_gen.rs
src/compiler/passes/trace_gen.rs
+6
-0
src/compiler/passes/tree_gen.rs
src/compiler/passes/tree_gen.rs
+6
-0
tests/test_compiler/test_regalloc.rs
tests/test_compiler/test_regalloc.rs
+104
-0
No files found.
Cargo.toml
View file @
f83e4dde
...
...
@@ -5,7 +5,7 @@ authors = [ "Your name <you@example.com>" ]
build
=
"build.rs"
[lib]
crate-type
=
[
"staticlib"
,
"rlib"
]
crate-type
=
[
"staticlib"
,
"rlib"
,
"dylib"
]
[features]
default
=
["aot"]
...
...
src/ast/src/ir.rs
View file @
f83e4dde
...
...
@@ -256,7 +256,14 @@ impl FunctionContext {
op
:
pick_op_code_for_ssa
(
&
val
.ty
),
v
:
TreeNode_
::
Value
(
val
)
})
}
}
pub
fn
get_temp_display
(
&
self
,
id
:
MuID
)
->
String
{
match
self
.get_value
(
id
)
{
Some
(
entry
)
=>
format!
(
"{}"
,
entry
.value
()),
None
=>
"CANT_FOUND_ID"
.to_string
()
}
}
pub
fn
get_value
(
&
self
,
id
:
MuID
)
->
Option
<&
SSAVarEntry
>
{
self
.values
.get
(
&
id
)
...
...
src/compiler/backend/arch/x86_64/inst_sel.rs
View file @
f83e4dde
...
...
@@ -21,6 +21,7 @@ use compiler::machine_code::CompiledFunction;
use
compiler
::
frame
::
Frame
;
use
std
::
collections
::
HashMap
;
use
std
::
any
::
Any
;
pub
struct
InstructionSelection
{
name
:
&
'static
str
,
...
...
@@ -1286,6 +1287,10 @@ impl CompilerPass for InstructionSelection {
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
#[allow(unused_variables)]
fn
start_function
(
&
mut
self
,
vm
:
&
VM
,
func_ver
:
&
mut
MuFunctionVersion
)
{
debug!
(
"{}"
,
self
.name
());
...
...
src/compiler/backend/code_emission.rs
View file @
f83e4dde
...
...
@@ -5,6 +5,8 @@ use ast::ir::*;
use
vm
::
VM
;
use
compiler
::
backend
::
emit_code
;
use
std
::
any
::
Any
;
pub
struct
CodeEmission
{
name
:
&
'static
str
}
...
...
@@ -22,6 +24,10 @@ impl CompilerPass for CodeEmission {
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
fn
visit_function
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
{
emit_code
(
func
,
vm
);
}
...
...
src/compiler/backend/peephole_opt.rs
View file @
f83e4dde
...
...
@@ -3,6 +3,8 @@ use ast::ir::*;
use
vm
::
VM
;
use
compiler
::
machine_code
::
CompiledFunction
;
use
std
::
any
::
Any
;
pub
struct
PeepholeOptimization
{
name
:
&
'static
str
}
...
...
@@ -54,6 +56,10 @@ impl CompilerPass for PeepholeOptimization {
fn
name
(
&
self
)
->
&
'static
str
{
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
fn
visit_function
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
{
let
compiled_funcs
=
vm
.compiled_funcs
()
.read
()
.unwrap
();
...
...
src/compiler/backend/reg_alloc/graph_coloring/coloring.rs
View file @
f83e4dde
...
...
@@ -15,7 +15,11 @@ use std::collections::HashMap;
const
COALESCING
:
bool
=
true
;
pub
struct
GraphColoring
{
pub
struct
GraphColoring
<
'a
>
{
pub
func
:
&
'a
mut
MuFunctionVersion
,
pub
cf
:
&
'a
mut
CompiledFunction
,
pub
vm
:
&
'a
VM
,
pub
ig
:
InterferenceGraph
,
precolored
:
LinkedHashSet
<
Node
>
,
...
...
@@ -44,12 +48,18 @@ pub struct GraphColoring {
select_stack
:
Vec
<
Node
>
}
impl
GraphColoring
{
pub
fn
start
(
func
:
&
mut
MuFunctionVersion
,
cf
:
&
mut
CompiledFunction
,
vm
:
&
VM
)
->
Result
<
GraphColoring
,
RegAllocFailure
>
{
impl
<
'a
>
GraphColoring
<
'a
>
{
pub
fn
start
(
func
:
&
'a
mut
MuFunctionVersion
,
cf
:
&
'a
mut
CompiledFunction
,
vm
:
&
'a
VM
)
->
Result
<
GraphColoring
<
'a
>
,
RegAllocFailure
>
{
cf
.mc
()
.trace_mc
();
let
ig
=
graph_coloring
::
build_inteference_graph
(
cf
,
func
);
let
mut
coloring
=
GraphColoring
{
ig
:
graph_coloring
::
build_inteference_graph
(
cf
,
func
),
func
:
func
,
cf
:
cf
,
vm
:
vm
,
ig
:
ig
,
precolored
:
LinkedHashSet
::
new
(),
colors
:
{
...
...
@@ -82,21 +92,14 @@ impl GraphColoring {
select_stack
:
Vec
::
new
()
};
match
coloring
.regalloc
(
func
,
cf
,
vm
)
{
Ok
(
_
)
=>
Ok
(
coloring
),
Err
(
fail
)
=>
Err
(
fail
)
}
coloring
.regalloc
()
}
fn
regalloc
(
&
mut
self
,
func
:
&
mut
MuFunctionVersion
,
cf
:
&
mut
CompiledFunction
,
vm
:
&
VM
)
->
Result
<
()
,
RegAllocFailure
>
{
fn
regalloc
(
mut
self
)
->
Result
<
GraphColoring
<
'a
>
,
RegAllocFailure
>
{
trace!
(
"Initializing coloring allocator..."
);
trace!
(
"---InterenceGraph---"
);
self
.ig
.print
();
trace!
(
"---All temps---"
);
for
entry
in
func
.context.values
.values
()
{
trace!
(
"{}"
,
entry
);
}
self
.ig
.print
(
&
self
.func.context
);
// precolor for all machine registers
for
reg
in
backend
::
all_regs
()
.values
()
{
...
...
@@ -117,7 +120,11 @@ impl GraphColoring {
self
.initial
.push
(
node
);
let
outdegree
=
self
.ig
.outdegree_of
(
node
);
self
.degree
.insert
(
node
,
outdegree
);
trace!
(
"{} has a degree of {}"
,
self
.node_info
(
node
),
outdegree
);
trace!
(
"{} has a degree of {}"
,
{
let
id
=
self
.ig
.get_temp_of
(
node
);
self
.func.context
.get_temp_display
(
id
)
},
outdegree
);
}
}
...
...
@@ -152,12 +159,12 @@ impl GraphColoring {
}
}
self
.rewrite_program
(
func
,
cf
,
vm
);
self
.rewrite_program
();
GraphColoring
::
start
(
func
,
cf
,
vm
);
return
GraphColoring
::
start
(
self
.func
,
self
.cf
,
self
.
vm
);
}
Ok
(
()
)
Ok
(
self
)
}
fn
build
(
&
mut
self
)
{
...
...
@@ -612,23 +619,23 @@ impl GraphColoring {
Ok
(())
}
fn
rewrite_program
(
&
mut
self
,
func
:
&
mut
MuFunctionVersion
,
cf
:
&
mut
CompiledFunction
,
vm
:
&
VM
)
{
fn
rewrite_program
(
&
mut
self
)
{
let
spills
=
self
.spills
();
let
mut
spilled_mem
=
HashMap
::
new
();
// allocating frame slots for every spilled temp
for
reg_id
in
spills
.iter
()
{
let
ssa_entry
=
match
func
.context
.get_value
(
*
reg_id
)
{
let
ssa_entry
=
match
self
.
func.context
.get_value
(
*
reg_id
)
{
Some
(
entry
)
=>
entry
,
None
=>
panic!
(
"The spilled register {} is not in func context"
,
reg_id
)
};
let
mem
=
cf
.frame
.alloc_slot_for_spilling
(
ssa_entry
.value
()
.clone
(),
vm
);
let
mem
=
self
.cf.frame
.alloc_slot_for_spilling
(
ssa_entry
.value
()
.clone
(),
self
.
vm
);
spilled_mem
.insert
(
*
reg_id
,
mem
);
}
let
new_temps
=
backend
::
spill_rewrite
(
&
spilled_mem
,
func
,
cf
,
vm
);
let
new_temps
=
backend
::
spill_rewrite
(
&
spilled_mem
,
self
.func
,
self
.cf
,
self
.
vm
);
//
// self.spilled_nodes.clear();
//
...
...
src/compiler/backend/reg_alloc/graph_coloring/liveness.rs
View file @
f83e4dde
...
...
@@ -124,14 +124,19 @@ impl InterferenceGraph {
fn
add_move
(
&
mut
self
,
src
:
Node
,
dst
:
Node
)
{
self
.moves
.insert
(
Move
{
from
:
src
,
to
:
dst
});
}
pub
fn
is_same_group
(
&
self
,
node1
:
Node
,
node2
:
Node
)
->
bool
{
self
.nodes_property
.get
(
&
node1
)
.unwrap
()
.group
==
self
.nodes_property
.get
(
&
node2
)
.unwrap
()
.group
}
pub
fn
add_interference_edge
(
&
mut
self
,
from
:
Node
,
to
:
Node
)
{
// only if two nodes are from the same RegGroup,
// they may interefere
if
self
.nodes_property
.get
(
&
from
)
.unwrap
()
.group
==
self
.nodes_property
.get
(
&
to
)
.unwrap
()
.group
{
self
.matrix
.as_mut
()
.unwrap
()[(
from
.
0
,
to
.
0
)]
=
true
;
}
self
.matrix
.as_mut
()
.unwrap
()[(
from
.
0
,
to
.
0
)]
=
true
;
}
pub
fn
is_interferenced_with
(
&
self
,
node1
:
Node
,
node2
:
Node
)
->
bool
{
self
.matrix
.as_ref
()
.unwrap
()[(
node1
.
0
,
node2
.
0
)]
||
self
.matrix
.as_ref
()
.unwrap
()[(
node2
.
0
,
node1
.
0
)]
}
pub
fn
color_node
(
&
mut
self
,
node
:
Node
,
color
:
MuID
)
{
...
...
@@ -207,18 +212,21 @@ impl InterferenceGraph {
self
.outdegree_of
(
node
)
+
self
.indegree_of
(
node
)
}
pub
fn
print
(
&
self
)
{
pub
fn
print
(
&
self
,
context
:
&
FunctionContext
)
{
println!
(
""
);
println!
(
"Interference Graph"
);
println!
(
"nodes:"
);
for
id
in
self
.nodes
.keys
()
{
println!
(
"Reg {} -> {:?}"
,
id
,
self
.nodes
.get
(
&
id
)
.unwrap
());
let
val
=
context
.get_value
(
*
id
)
.unwrap
()
.value
();
println!
(
"Reg {} -> {:?}"
,
val
,
self
.nodes
.get
(
&
id
)
.unwrap
());
}
println!
(
"color:"
);
for
(
n
,
c
)
in
self
.nodes_property
.iter
()
{
println!
(
"{:?} -> Color/Reg {:?}"
,
n
,
c
);
for
(
node
,
color
)
in
self
.nodes_property
.iter
()
{
let
node_val
=
context
.get_value
(
self
.get_temp_of
(
*
node
))
.unwrap
()
.value
();
let
color_val
=
context
.get_value
(
color
.temp
)
.unwrap
()
.value
();
println!
(
"Reg {} of {:?} -> Color/Reg {}"
,
node_val
,
node
,
color_val
);
}
println!
(
"moves:"
);
for
mov
in
self
.moves
.iter
()
{
...
...
@@ -242,8 +250,11 @@ impl InterferenceGraph {
if
matrix
[(
i
,
j
)]
{
let
from_node
=
node_to_reg_id
.get
(
&
Node
(
i
))
.unwrap
();
let
to_node
=
node_to_reg_id
.get
(
&
Node
(
j
))
.unwrap
();
println!
(
"Reg {} -> Reg {}"
,
from_node
,
to_node
);
let
from_val
=
context
.get_value
(
*
from_node
)
.unwrap
()
.value
();
let
to_val
=
context
.get_value
(
*
to_node
)
.unwrap
()
.value
();
println!
(
"Reg {} -> Reg {}"
,
from_val
,
to_val
);
}
}
}
...
...
@@ -355,14 +366,29 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
Some
(
liveout
)
=>
liveout
.to_vec
(),
None
=>
panic!
(
"cannot find liveout for block {}"
,
block
)
});
if
cfg!
(
debug_assertions
)
{
trace!
(
"Block{}: live out"
,
block
);
for
ele
in
current_live
.iter
()
{
trace!
(
"{}"
,
func
.context
.get_temp_display
(
*
ele
));
}
}
let
range
=
cf
.mc
()
.get_block_range
(
&
block
);
if
range
.is_none
()
{
warn!
(
"Block{}: has no range (no instructions?)"
,
block
);
continue
;
}
trace!
(
"Block{}: range = {:?}"
,
block
,
range
.as_ref
()
.unwrap
());
// for every inst I in reverse order
for
i
in
range
.unwrap
()
.rev
()
{
if
cfg!
(
debug_assertions
)
{
trace!
(
"Block{}: Inst{}: start. current_live:"
,
block
,
i
);
for
ele
in
current_live
.iter
()
{
trace!
(
"{}"
,
func
.context
.get_temp_display
(
*
ele
));
}
}
let
src
:
Option
<
MuID
>
=
{
if
cf
.mc
()
.is_move
(
i
)
{
let
src
=
cf
.mc
()
.get_inst_reg_uses
(
i
);
...
...
@@ -377,6 +403,9 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
if
src
.len
()
==
1
{
let
node1
=
ig
.get_node
(
src
[
0
]);
let
node2
=
ig
.get_node
(
dst
[
0
]);
trace!
(
"add move between {} and {}"
,
func
.context
.get_temp_display
(
src
[
0
]),
func
.context
.get_temp_display
(
dst
[
0
]));
ig
.add_move
(
node1
,
node2
);
Some
(
src
[
0
])
...
...
@@ -388,21 +417,34 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
None
}
};
trace!
(
"Block{}: Inst{}: src={:?}"
,
block
,
i
,
src
);
// for every definition D in I
for
d
in
cf
.mc
()
.get_inst_reg_defines
(
i
)
{
trace!
(
"Block{}: Inst{}: for definition {}"
,
block
,
i
,
func
.context
.get_temp_display
(
d
));
// add an interference from D to every element E in Current_Live - {D}
// creating nodes if necessary
for
e
in
current_live
.iter
()
{
trace!
(
"Block{}: Inst{}: for each live {}"
,
block
,
i
,
func
.context
.get_temp_display
(
*
e
));
if
src
.is_none
()
||
(
src
.is_some
()
&&
*
e
!=
src
.unwrap
())
{
let
from
=
ig
.get_node
(
d
);
let
to
=
ig
.get_node
(
*
e
);
if
!
ig
.is_same_node
(
from
,
to
)
&&
!
ig
.is_adj
(
from
,
to
)
{
if
!
ig
.is_same_node
(
from
,
to
)
&&
ig
.is_same_group
(
from
,
to
)
&&
!
ig
.is_adj
(
from
,
to
)
{
if
!
ig
.is_colored
(
from
)
{
trace!
(
"Block{}: Inst{}: add interference between {} and {}"
,
block
,
i
,
func
.context
.get_temp_display
(
d
),
func
.context
.get_temp_display
(
*
e
));
ig
.add_interference_edge
(
from
,
to
);
}
if
!
ig
.is_colored
(
to
)
{
trace!
(
"Block{}: Inst{}: add interference between {} and {}"
,
block
,
i
,
func
.context
.get_temp_display
(
*
e
),
func
.context
.get_temp_display
(
d
));
ig
.add_interference_edge
(
to
,
from
);
}
}
...
...
@@ -412,15 +454,28 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
// for every definition D in I
for
d
in
cf
.mc
()
.get_inst_reg_defines
(
i
)
{
trace!
(
"Block{}: Inst{}: remove define {} from current_live"
,
block
,
i
,
func
.context
.get_temp_display
(
d
));
// remove D from Current_Live
current_live
.remove
(
&
d
);
}
// for every use U in I
for
u
in
cf
.mc
()
.get_inst_reg_uses
(
i
)
{
trace!
(
"Block{}: Inst{}: add use {} to current_live"
,
block
,
i
,
func
.context
.get_temp_display
(
u
));
// add U to Current_live
current_live
.insert
(
u
);
}
if
cfg!
(
debug_assertions
)
{
trace!
(
"Block{}: Inst{}: done. current_live:"
,
block
,
i
);
for
ele
in
current_live
.iter
()
{
trace!
(
"{}"
,
func
.context
.get_temp_display
(
*
ele
));
}
}
}
}
...
...
src/compiler/backend/reg_alloc/graph_coloring/mod.rs
View file @
f83e4dde
...
...
@@ -5,3 +5,92 @@ pub use compiler::backend::reg_alloc::graph_coloring::liveness::InterferenceGrap
//pub use compiler::backend::reg_alloc::graph_coloring::liveness::build as build_inteference_graph;
pub
use
compiler
::
backend
::
reg_alloc
::
graph_coloring
::
liveness
::
build_chaitin_briggs
as
build_inteference_graph
;
pub
use
compiler
::
backend
::
reg_alloc
::
graph_coloring
::
coloring
::
GraphColoring
;
use
ast
::
ir
::
*
;
use
vm
::
VM
;
use
compiler
;
use
compiler
::
CompilerPass
;
use
compiler
::
PassExecutionResult
;
use
compiler
::
backend
::
init_machine_regs_for_func
;
use
compiler
::
backend
;
use
compiler
::
backend
::
reg_alloc
::
RegAllocFailure
;
use
std
::
collections
::
HashMap
;
use
std
::
any
::
Any
;
pub
struct
RegisterAllocation
{
name
:
&
'static
str
,
}
impl
RegisterAllocation
{
pub
fn
new
()
->
RegisterAllocation
{
RegisterAllocation
{
name
:
"Register Allocation"
,
}
}
#[allow(unused_variables)]
fn
coloring
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
->
Result
<
(),
RegAllocFailure
>
{
let
compiled_funcs
=
vm
.compiled_funcs
()
.read
()
.unwrap
();
let
mut
cf
=
compiled_funcs
.get
(
&
func
.id
())
.unwrap
()
.write
()
.unwrap
();
// initialize machine registers for the function context
init_machine_regs_for_func
(
&
mut
func
.context
);
let
coloring
=
match
GraphColoring
::
start
(
func
,
&
mut
cf
,
vm
)
{
Ok
(
coloring
)
=>
coloring
,
Err
(
_
)
=>
panic!
(
"error during coloring - unexpected"
)
};
// replace regs
trace!
(
"Replacing Registers..."
);
for
node
in
coloring
.ig
.nodes
()
{
let
temp
=
coloring
.ig
.get_temp_of
(
node
);
// skip machine registers
if
temp
<
MACHINE_ID_END
{
continue
;
}
else
{
let
alias
=
coloring
.get_alias
(
node
);
let
machine_reg
=
match
coloring
.ig
.get_color_of
(
alias
)
{
Some
(
reg
)
=>
reg
,
None
=>
panic!
(
"Reg{}/{:?} (aliased as Reg{}/{:?}) is not assigned with a color"
,
coloring
.ig
.get_temp_of
(
node
),
node
,
coloring
.ig
.get_temp_of
(
alias
),
alias
)
};
trace!
(
"replacing {} with {}"
,
temp
,
machine_reg
);
coloring
.cf
.mc_mut
()
.replace_reg
(
temp
,
machine_reg
);
coloring
.cf.temps
.insert
(
temp
,
machine_reg
);
}
}
coloring
.cf
.mc
()
.trace_mc
();
Ok
(())
}
}
impl
CompilerPass
for
RegisterAllocation
{
fn
name
(
&
self
)
->
&
'static
str
{
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
fn
execute
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
->
PassExecutionResult
{
debug!
(
"---CompilerPass {} for {}---"
,
self
.name
(),
func
);
match
self
.coloring
(
vm
,
func
)
{
// skip slow path
Ok
(
_
)
=>
PassExecutionResult
::
ProceedTo
(
compiler
::
PASS_PEEPHOLE
),
// go back to instruction selection for spilled operands
Err
(
RegAllocFailure
::
FailedForSpilling
)
=>
PassExecutionResult
::
GoBackTo
(
compiler
::
PASS_INST_SEL
),
}
}
}
src/compiler/backend/reg_alloc/mod.rs
View file @
f83e4dde
#![allow(dead_code)]
use
ast
::
ir
::
*
;
use
vm
::
VM
;
use
compiler
;
use
compiler
::
CompilerPass
;
use
compiler
::
PassExecutionResult
;
use
compiler
::
backend
::
init_machine_regs_for_func
;
use
compiler
::
backend
;
use
std
::
collections
::
HashMap
;
mod
graph_coloring
;
pub
mod
graph_coloring
;
pub
enum
RegAllocFailure
{
FailedForSpilling
,
}
pub
struct
RegisterAllocation
{
name
:
&
'static
str
,
}
impl
RegisterAllocation
{
pub
fn
new
()
->
RegisterAllocation
{
RegisterAllocation
{
name
:
"Register Allcoation"
,
}
}
#[allow(unused_variables)]
fn
coloring
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
->
Result
<
(),
RegAllocFailure
>
{
let
compiled_funcs
=
vm
.compiled_funcs
()
.read
()
.unwrap
();
let
mut
cf
=
compiled_funcs
.get
(
&
func
.id
())
.unwrap
()
.write
()
.unwrap
();
// initialize machine registers for the function context
init_machine_regs_for_func
(
&
mut
func
.context
);
let
coloring
=
match
graph_coloring
::
GraphColoring
::
start
(
func
,
&
mut
cf
,
vm
)
{
Ok
(
coloring
)
=>
coloring
,
Err
(
_
)
=>
panic!
(
"error during coloring - unexpected"
)
};
// replace regs
trace!
(
"Replacing Registers..."
);
for
node
in
coloring
.ig
.nodes
()
{
let
temp
=
coloring
.ig
.get_temp_of
(
node
);
// skip machine registers
if
temp
<
MACHINE_ID_END
{
continue
;
}
else
{
let
alias
=
coloring
.get_alias
(
node
);
let
machine_reg
=
match
coloring
.ig
.get_color_of
(
alias
)
{
Some
(
reg
)
=>
reg
,
None
=>
panic!
(
"Reg{}/{:?} (aliased as Reg{}/{:?}) is not assigned with a color"
,
coloring
.ig
.get_temp_of
(
node
),
node
,
coloring
.ig
.get_temp_of
(
alias
),
alias
)
};
trace!
(
"replacing {} with {}"
,
temp
,
machine_reg
);
cf
.mc_mut
()
.replace_reg
(
temp
,
machine_reg
);
cf
.temps
.insert
(
temp
,
machine_reg
);
}
}
cf
.mc
()
.trace_mc
();
Ok
(())
}
}
impl
CompilerPass
for
RegisterAllocation
{
fn
name
(
&
self
)
->
&
'static
str
{
self
.name
}
fn
execute
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
->
PassExecutionResult
{
debug!
(
"---CompilerPass {} for {}---"
,
self
.name
(),
func
);
match
self
.coloring
(
vm
,
func
)
{
// skip slow path
Ok
(
_
)
=>
PassExecutionResult
::
ProceedTo
(
compiler
::
PASS_PEEPHOLE
),
// go back to instruction selection for spilled operands
Err
(
RegAllocFailure
::
FailedForSpilling
)
=>
PassExecutionResult
::
GoBackTo
(
compiler
::
PASS_INST_SEL
),
}
}
}
pub
use
compiler
::
backend
::
reg_alloc
::
graph_coloring
::
RegisterAllocation
;
\ No newline at end of file
src/compiler/mod.rs
View file @
f83e4dde
...
...
@@ -63,6 +63,10 @@ impl Compiler {
drop
(
_
p
);
hprof
::
profiler
()
.print_timing
();
}
pub
fn
get_policy
(
&
self
)
->
&
RefCell
<
CompilerPolicy
>
{
&
self
.policy
}
}
pub
struct
CompilerPolicy
{
...
...
src/compiler/passes/control_flow.rs
View file @
f83e4dde
...
...
@@ -2,9 +2,10 @@ use ast::ir::*;
use
ast
::
inst
::
Instruction_
::
*
;
use
utils
::
vec_utils
::
as_str
as
vector_as_str
;
use
vm
::
VM
;
use
compiler
::
CompilerPass
;
use
std
::
any
::
Any
;
pub
struct
ControlFlowAnalysis
{
name
:
&
'static
str
}
...
...
@@ -195,6 +196,10 @@ impl CompilerPass for ControlFlowAnalysis {
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
#[allow(unused_variables)]
fn
visit_function
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
{
let
mut
stack
:
Vec
<
MuID
>
=
vec!
[];
...
...
src/compiler/passes/def_use.rs
View file @
f83e4dde
...
...
@@ -3,6 +3,7 @@ use ast::ptr::*;
use
vm
::
VM
;
use
compiler
::
CompilerPass
;
use
std
::
any
::
Any
;
pub
struct
DefUse
{
name
:
&
'static
str
,
...
...
@@ -37,6 +38,10 @@ impl CompilerPass for DefUse {
fn
name
(
&
self
)
->
&
'static
str
{
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
#[allow(unused_variables)]
fn
start_block
(
&
mut
self
,
vm
:
&
VM
,
func_context
:
&
mut
FunctionContext
,
block
:
&
mut
Block
)
{
...
...
src/compiler/passes/mod.rs
View file @
f83e4dde
...
...
@@ -32,9 +32,12 @@ pub enum PassExecutionResult {
GoBackTo
(
PassID
)
}
use
std
::
any
::
Any
;
#[allow(unused_variables)]
pub
trait
CompilerPass
{
fn
name
(
&
self
)
->
&
'static
str
;
fn
as_any
(
&
self
)
->
&
Any
;
fn
execute
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
->
PassExecutionResult
{
debug!
(
"---CompilerPass {} for {}---"
,
self
.name
(),
func
);
...
...
src/compiler/passes/trace_gen.rs
View file @
f83e4dde
...
...
@@ -2,6 +2,8 @@ use ast::ir::*;
use
vm
::
VM
;
use
compiler
::
CompilerPass
;
use
std
::
any
::
Any
;
pub
struct
TraceGen
{
name
:
&
'static
str
}
...
...
@@ -16,6 +18,10 @@ impl CompilerPass for TraceGen {
fn
name
(
&
self
)
->
&
'static
str
{
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
#[allow(unused_variables)]
fn
visit_function
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
{
...
...
src/compiler/passes/tree_gen.rs
View file @
f83e4dde
...
...
@@ -6,6 +6,8 @@ use vm::VM;
use
compiler
::
CompilerPass
;
use
compiler
::
PassExecutionResult
;
use
std
::
any
::
Any
;
pub
struct
TreeGen
{
name
:
&
'static
str
}
...
...
@@ -24,6 +26,10 @@ impl CompilerPass for TreeGen {
fn
name
(
&
self
)
->
&
'static
str
{
self
.name
}
fn
as_any
(
&
self
)
->
&
Any
{
self
}
fn
execute
(
&
mut
self
,
vm
:
&
VM
,
func
:
&
mut
MuFunctionVersion
)
->
PassExecutionResult
{
debug!
(
"---CompilerPass {} for {}---"
,
self
.name
(),
func
);
...
...
tests/test_compiler/test_regalloc.rs
View file @
f83e4dde
...
...
@@ -73,6 +73,110 @@ fn test_ir_liveness_fac() {
assert
!
(
vec_utils
::
is_identical_to_str_ignore_order
(
block_2_liveout
,
expect
));
}
use
mu
::
compiler
::
backend
::
reg_alloc
::
graph_coloring
::
GraphColoring
;
use
mu
::
compiler
::
backend
::
reg_alloc
::
graph_coloring
::
InterferenceGraph
;
use
mu
::
compiler
::
backend
::
init_machine_regs_for_func
;
use
std
::
any
::
Any
;
struct
InspectInterferenceGraph
{
name
:
&
'static
str
,
ig
:
Option
<
InterferenceGraph
>
,
}
impl
InspectInterferenceGraph
{
pub
fn
new
()
->
InspectInterferenceGraph
{
InspectInterferenceGraph
{
name
:
"Inspect Interference Graph"
,
ig
:
None
}
}
}