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
8707cfce
Commit
8707cfce
authored
Nov 11, 2016
by
John Zhang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of gitlab.anu.edu.au:mu/mu-impl-fast
parents
1f818744
28c3fcf9
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
695 additions
and
49 deletions
+695
-49
src/ast/src/types.rs
src/ast/src/types.rs
+11
-0
src/compiler/backend/arch/x86_64/codegen.rs
src/compiler/backend/arch/x86_64/codegen.rs
+1
-1
src/compiler/backend/arch/x86_64/inst_sel.rs
src/compiler/backend/arch/x86_64/inst_sel.rs
+231
-48
src/testutil/mod.rs
src/testutil/mod.rs
+5
-0
tests/test_compiler/test_mem_inst.rs
tests/test_compiler/test_mem_inst.rs
+447
-0
No files found.
src/ast/src/types.rs
View file @
8707cfce
...
@@ -60,6 +60,17 @@ impl MuType {
...
@@ -60,6 +60,17 @@ impl MuType {
v
:
v
v
:
v
}
}
}
}
pub
fn
get_referenced_ty
(
&
self
)
->
Option
<
P
<
MuType
>>
{
use
types
::
MuType_
::
*
;
match
self
.v
{
Ref
(
ref
ty
)
|
IRef
(
ref
ty
)
|
WeakRef
(
ref
ty
)
|
UPtr
(
ref
ty
)
=>
Some
(
ty
.clone
()),
_
=>
None
}
}
}
}
pub
type
StructTag
=
MuName
;
pub
type
StructTag
=
MuName
;
...
...
src/compiler/backend/arch/x86_64/codegen.rs
View file @
8707cfce
...
@@ -74,7 +74,7 @@ pub trait CodeGenerator {
...
@@ -74,7 +74,7 @@ pub trait CodeGenerator {
fn
emit_mov_mem8_imm8
(
&
mut
self
,
dest
:
Mem
,
src
:
i8
);
fn
emit_mov_mem8_imm8
(
&
mut
self
,
dest
:
Mem
,
src
:
i8
);
// lea
// lea
fn
emit_lea_r64
(
&
mut
self
,
dest
:
Reg
,
src
:
Reg
);
fn
emit_lea_r64
(
&
mut
self
,
dest
:
Reg
,
src
:
Mem
);
// and
// and
fn
emit_and_r64_imm32
(
&
mut
self
,
dest
:
Reg
,
src
:
i32
);
fn
emit_and_r64_imm32
(
&
mut
self
,
dest
:
Reg
,
src
:
i32
);
...
...
src/compiler/backend/arch/x86_64/inst_sel.rs
View file @
8707cfce
...
@@ -805,19 +805,16 @@ impl <'a> InstructionSelection {
...
@@ -805,19 +805,16 @@ impl <'a> InstructionSelection {
unimplemented!
()
unimplemented!
()
}
}
}
}
Instruction_
::
GetIRef
(
op_index
)
=>
{
// memory insts: calculate the address, then lea
let
ops
=
inst
.ops
.read
()
.unwrap
();
Instruction_
::
GetIRef
(
_
)
|
Instruction_
::
GetFieldIRef
{
..
}
let
ref
op
=
ops
[
op_index
];
|
Instruction_
::
GetVarPartIRef
{
..
}
let
res_tmp
=
self
.get_result_value
(
node
);
|
Instruction_
::
ShiftIRef
{
..
}
=>
{
let
mem_addr
=
self
.emit_get_mem_from_inst
(
node
,
f_content
,
f_context
,
vm
);
let
hdr_size
=
mm
::
objectmodel
::
OBJECT_HEADER_SIZE
;
let
tmp_res
=
self
.get_result_value
(
node
);
if
hdr_size
==
0
{
self
.emit_move_node_to_value
(
&
res_tmp
,
&
op
,
f_content
,
f_context
,
vm
);
self
.backend
.emit_lea_r64
(
&
tmp_res
,
&
mem_addr
);
}
else
{
self
.emit_lea_base_immoffset
(
&
res_tmp
,
&
op
.clone_value
(),
hdr_size
as
i32
,
vm
);
}
}
}
Instruction_
::
ThreadExit
=>
{
Instruction_
::
ThreadExit
=>
{
...
@@ -973,15 +970,15 @@ impl <'a> InstructionSelection {
...
@@ -973,15 +970,15 @@ impl <'a> InstructionSelection {
})
})
}
}
fn
make_memory_op_base_
offsetreg
(
&
mut
self
,
base
:
&
P
<
Value
>
,
offset
:
&
P
<
Value
>
,
ty
:
P
<
MuType
>
,
vm
:
&
VM
)
->
P
<
Value
>
{
fn
make_memory_op_base_
index
(
&
mut
self
,
base
:
&
P
<
Value
>
,
index
:
&
P
<
Value
>
,
scale
:
u8
,
ty
:
P
<
MuType
>
,
vm
:
&
VM
)
->
P
<
Value
>
{
P
(
Value
{
P
(
Value
{
hdr
:
MuEntityHeader
::
unnamed
(
vm
.next_id
()),
hdr
:
MuEntityHeader
::
unnamed
(
vm
.next_id
()),
ty
:
ty
.clone
(),
ty
:
ty
.clone
(),
v
:
Value_
::
Memory
(
MemoryLocation
::
Address
{
v
:
Value_
::
Memory
(
MemoryLocation
::
Address
{
base
:
base
.clone
(),
base
:
base
.clone
(),
offset
:
Some
(
offset
.clone
())
,
offset
:
None
,
index
:
None
,
index
:
Some
(
index
.clone
())
,
scale
:
None
scale
:
Some
(
scale
)
})
})
})
})
}
}
...
@@ -1256,7 +1253,7 @@ impl <'a> InstructionSelection {
...
@@ -1256,7 +1253,7 @@ impl <'a> InstructionSelection {
fn
emit_udiv
(
fn
emit_udiv
(
&
mut
self
,
&
mut
self
,
op1
:
&
P
<
TreeNode
>
,
op2
:
&
P
<
TreeNode
>
,
op1
:
&
TreeNode
,
op2
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
vm
:
&
VM
)
...
@@ -1295,7 +1292,7 @@ impl <'a> InstructionSelection {
...
@@ -1295,7 +1292,7 @@ impl <'a> InstructionSelection {
fn
emit_idiv
(
fn
emit_idiv
(
&
mut
self
,
&
mut
self
,
op1
:
&
P
<
TreeNode
>
,
op2
:
&
P
<
TreeNode
>
,
op1
:
&
TreeNode
,
op2
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
vm
:
&
VM
)
...
@@ -1875,7 +1872,7 @@ impl <'a> InstructionSelection {
...
@@ -1875,7 +1872,7 @@ impl <'a> InstructionSelection {
self
.backend
.emit_pop_r64
(
&
x86_64
::
RBP
);
self
.backend
.emit_pop_r64
(
&
x86_64
::
RBP
);
}
}
fn
match_cmp_res
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
bool
{
fn
match_cmp_res
(
&
mut
self
,
op
:
&
TreeNode
)
->
bool
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
match
inst
.v
{
match
inst
.v
{
...
@@ -1887,7 +1884,7 @@ impl <'a> InstructionSelection {
...
@@ -1887,7 +1884,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
emit_cmp_res
(
&
mut
self
,
cond
:
&
P
<
TreeNode
>
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
op
::
CmpOp
{
fn
emit_cmp_res
(
&
mut
self
,
cond
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
op
::
CmpOp
{
match
cond
.v
{
match
cond
.v
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
let
ops
=
inst
.ops
.read
()
.unwrap
();
let
ops
=
inst
.ops
.read
()
.unwrap
();
...
@@ -1982,7 +1979,7 @@ impl <'a> InstructionSelection {
...
@@ -1982,7 +1979,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
emit_ireg
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
fn
emit_ireg
(
&
mut
self
,
op
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Instruction
(
_
)
=>
{
TreeNode_
::
Instruction
(
_
)
=>
{
self
.instruction_select
(
op
,
f_content
,
f_context
,
vm
);
self
.instruction_select
(
op
,
f_content
,
f_context
,
vm
);
...
@@ -2021,7 +2018,7 @@ impl <'a> InstructionSelection {
...
@@ -2021,7 +2018,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
emit_fpreg
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
fn
emit_fpreg
(
&
mut
self
,
op
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Instruction
(
_
)
=>
{
TreeNode_
::
Instruction
(
_
)
=>
{
self
.instruction_select
(
op
,
f_content
,
f_context
,
vm
);
self
.instruction_select
(
op
,
f_content
,
f_context
,
vm
);
...
@@ -2037,21 +2034,21 @@ impl <'a> InstructionSelection {
...
@@ -2037,21 +2034,21 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
match_iimm
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
bool
{
fn
match_iimm
(
&
mut
self
,
op
:
&
TreeNode
)
->
bool
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
if
x86_64
::
is_valid_x86_imm
(
pv
)
=>
true
,
TreeNode_
::
Value
(
ref
pv
)
if
x86_64
::
is_valid_x86_imm
(
pv
)
=>
true
,
_
=>
false
_
=>
false
}
}
}
}
fn
node_iimm_to_i32
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
i32
{
fn
node_iimm_to_i32
(
&
mut
self
,
op
:
&
TreeNode
)
->
i32
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
=>
self
.value_iimm_to_i32
(
pv
),
TreeNode_
::
Value
(
ref
pv
)
=>
self
.value_iimm_to_i32
(
pv
),
_
=>
panic!
(
"expected iimm"
)
_
=>
panic!
(
"expected iimm"
)
}
}
}
}
fn
node_iimm_to_value
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
P
<
Value
>
{
fn
node_iimm_to_value
(
&
mut
self
,
op
:
&
TreeNode
)
->
P
<
Value
>
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
pv
.clone
()
pv
.clone
()
...
@@ -2071,7 +2068,7 @@ impl <'a> InstructionSelection {
...
@@ -2071,7 +2068,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
emit_node_addr_to_value
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
fn
emit_node_addr_to_value
(
&
mut
self
,
op
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
match
pv
.v
{
match
pv
.v
{
...
@@ -2108,19 +2105,74 @@ impl <'a> InstructionSelection {
...
@@ -2108,19 +2105,74 @@ impl <'a> InstructionSelection {
TreeNode_
::
Instruction
(
_
)
=>
self
.emit_get_mem_from_inst
(
op
,
f_content
,
f_context
,
vm
)
TreeNode_
::
Instruction
(
_
)
=>
self
.emit_get_mem_from_inst
(
op
,
f_content
,
f_context
,
vm
)
}
}
}
}
fn
emit_get_mem_from_inst
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
fn
emit_get_mem_from_inst
(
&
mut
self
,
op
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
P
<
Value
>
{
let
header_size
=
mm
::
objectmodel
::
OBJECT_HEADER_SIZE
as
i32
;
let
mem
=
self
.emit_get_mem_from_inst_inner
(
op
,
f_content
,
f_context
,
vm
);
P
(
Value
{
hdr
:
MuEntityHeader
::
unnamed
(
vm
.next_id
()),
ty
:
ADDRESS_TYPE
.clone
(),
v
:
Value_
::
Memory
(
mem
)
})
}
fn
addr_const_offset_adjust
(
&
mut
self
,
mem
:
MemoryLocation
,
more_offset
:
u64
,
vm
:
&
VM
)
->
MemoryLocation
{
match
mem
{
MemoryLocation
::
Address
{
base
,
offset
,
index
,
scale
}
=>
{
let
new_offset
=
match
offset
{
Some
(
pv
)
=>
{
let
old_offset
=
pv
.extract_int_const
();
old_offset
+
more_offset
},
None
=>
more_offset
};
MemoryLocation
::
Address
{
base
:
base
,
offset
:
Some
(
self
.make_value_int_const
(
new_offset
,
vm
)),
index
:
index
,
scale
:
scale
}
},
_
=>
panic!
(
"expected an address memory location"
)
}
}
fn
addr_append_index_scale
(
&
mut
self
,
mem
:
MemoryLocation
,
index
:
P
<
Value
>
,
scale
:
u8
,
vm
:
&
VM
)
->
MemoryLocation
{
match
mem
{
MemoryLocation
::
Address
{
base
,
offset
,
..
}
=>
{
MemoryLocation
::
Address
{
base
:
base
,
offset
:
offset
,
index
:
Some
(
index
),
scale
:
Some
(
scale
)
}
},
_
=>
panic!
(
"expected an address memory location"
)
}
}
fn
emit_get_mem_from_inst_inner
(
&
mut
self
,
op
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
->
MemoryLocation
{
let
header_size
=
mm
::
objectmodel
::
OBJECT_HEADER_SIZE
as
u64
;
match
op
.v
{
match
op
.v
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
TreeNode_
::
Instruction
(
ref
inst
)
=>
{
let
ref
ops
=
inst
.ops
.read
()
.unwrap
();
let
ref
ops
=
inst
.ops
.read
()
.unwrap
();
match
inst
.v
{
match
inst
.v
{
// GETIREF -> [base + HDR_SIZE]
Instruction_
::
GetIRef
(
op_index
)
=>
{
Instruction_
::
GetIRef
(
op_index
)
=>
{
let
ref
op
=
ops
[
op_index
];
let
ref
ref_op
=
ops
[
op_index
];
let
ret
=
MemoryLocation
::
Address
{
base
:
ref_op
.clone_value
(),
offset
:
Some
(
self
.make_value_int_const
(
header_size
,
vm
)),
index
:
None
,
scale
:
None
};
self
.make_memory_op_base_offset
(
&
op
.clone_value
(),
header_size
,
ADDRESS_TYPE
.clone
(),
vm
)
trace!
(
"MEM from GETIREF: {}"
,
ret
);
ret
}
}
Instruction_
::
GetFieldIRef
{
is_ptr
,
base
,
index
}
=>
{
Instruction_
::
GetFieldIRef
{
is_ptr
,
base
,
index
}
=>
{
let
ref
base
=
ops
[
base
];
let
ref
base
=
ops
[
base
];
...
@@ -2135,29 +2187,149 @@ impl <'a> InstructionSelection {
...
@@ -2135,29 +2187,149 @@ impl <'a> InstructionSelection {
}
}
};
};
let
ty_info
=
vm
.get_backend_type_info
(
struct_ty
.id
());
let
field_offset
:
i32
=
self
.get_field_offset
(
&
struct_ty
,
index
,
vm
);
let
layout
=
match
ty_info
.struct_layout
.as_ref
()
{
Some
(
layout
)
=>
layout
,
None
=>
panic!
(
"a struct type does not have a layout yet: {:?}"
,
ty_info
)
};
debug_assert!
(
layout
.len
()
>
index
);
let
field_offset
:
i32
=
layout
[
index
]
as
i32
;
match
base
.v
{
match
base
.v
{
// GETFIELDIREF(GETIREF) -> add FIELD_OFFSET to old offset
TreeNode_
::
Instruction
(
Instruction
{
v
:
Instruction_
::
GetIRef
(
op_index
),
ref
ops
,
..
})
=>
{
TreeNode_
::
Instruction
(
Instruction
{
v
:
Instruction_
::
GetIRef
(
op_index
),
ref
ops
,
..
})
=>
{
let
ops_guard
=
ops
.read
()
.unwrap
(
);
let
mem
=
self
.emit_get_mem_from_inst_inner
(
base
,
f_content
,
f_context
,
vm
);
let
re
f
inner
=
ops_guard
[
op_index
]
;
let
re
t
=
self
.addr_const_offset_adjust
(
mem
,
field_offset
as
u64
,
vm
)
;
self
.make_memory_op_base_offset
(
&
inner
.clone_value
(),
header_size
+
field_offset
,
ADDRESS_TYPE
.clone
(),
vm
)
trace!
(
"MEM from GETFIELDIREF(GETIREF): {}"
,
ret
);
ret
},
},
// GETFIELDIREF(ireg) -> [base + FIELD_OFFSET]
_
=>
{
let
tmp
=
self
.emit_ireg
(
base
,
f_content
,
f_context
,
vm
);
let
ret
=
MemoryLocation
::
Address
{
base
:
tmp
,
offset
:
Some
(
self
.make_value_int_const
(
field_offset
as
u64
,
vm
)),
index
:
None
,
scale
:
None
};
trace!
(
"MEM from GETFIELDIREF(ireg): {}"
,
ret
);
ret
}
}
}
Instruction_
::
GetVarPartIRef
{
is_ptr
,
base
}
=>
{
let
ref
base
=
ops
[
base
];
let
struct_ty
=
match
base
.clone_value
()
.ty
.get_referenced_ty
()
{
Some
(
ty
)
=>
ty
,
None
=>
panic!
(
"expecting an iref or uptr in GetVarPartIRef"
)
};
let
fix_part_size
=
vm
.get_backend_type_info
(
struct_ty
.id
())
.size
;
match
base
.v
{
// GETVARPARTIREF(GETIREF) -> add FIX_PART_SIZE to old offset
TreeNode_
::
Instruction
(
Instruction
{
v
:
Instruction_
::
GetIRef
(
_
),
..
})
=>
{
let
mem
=
self
.emit_get_mem_from_inst_inner
(
base
,
f_content
,
f_context
,
vm
);
let
ret
=
self
.addr_const_offset_adjust
(
mem
,
fix_part_size
as
u64
,
vm
);
trace!
(
"MEM from GETIVARPARTIREF(GETIREF): {}"
,
ret
);
ret
},
// GETVARPARTIREF(ireg) -> [base + VAR_PART_SIZE]
_
=>
{
_
=>
{
let
tmp
=
self
.emit_ireg
(
base
,
f_content
,
f_context
,
vm
);
let
tmp
=
self
.emit_ireg
(
base
,
f_content
,
f_context
,
vm
);
self
.make_memory_op_base_offset
(
&
tmp
,
field_offset
,
ADDRESS_TYPE
.clone
(),
vm
)
let
ret
=
MemoryLocation
::
Address
{
base
:
tmp
,
offset
:
Some
(
self
.make_value_int_const
(
fix_part_size
as
u64
,
vm
)),
index
:
None
,
scale
:
None
};
trace!
(
"MEM from GETVARPARTIREF(ireg): {}"
,
ret
);
ret
}
}
}
}
}
}
Instruction_
::
ShiftIRef
{
is_ptr
,
base
,
offset
}
=>
{
let
ref
base
=
ops
[
base
];
let
ref
offset
=
ops
[
offset
];
let
tmp_res
=
self
.get_result_value
(
op
);
let
ref
base_ty
=
base
.clone_value
()
.ty
;
let
ele_ty
=
match
base_ty
.get_referenced_ty
()
{
Some
(
ty
)
=>
ty
,
None
=>
panic!
(
"expected op in ShiftIRef of type IRef, found type: {}"
,
base_ty
)
};
let
ele_ty_size
=
vm
.get_backend_type_info
(
ele_ty
.id
())
.size
;
if
self
.match_iimm
(
offset
)
{
let
index
=
self
.node_iimm_to_i32
(
offset
);
let
shift_size
=
ele_ty_size
as
i32
*
index
;
let
mem
=
match
base
.v
{
// SHIFTIREF(GETVARPARTIREF(_), imm) -> add shift_size to old offset
TreeNode_
::
Instruction
(
Instruction
{
v
:
Instruction_
::
GetVarPartIRef
{
..
},
..
})
=>
{
let
mem
=
self
.emit_get_mem_from_inst_inner
(
base
,
f_content
,
f_context
,
vm
);
let
ret
=
self
.addr_const_offset_adjust
(
mem
,
shift_size
as
u64
,
vm
);
trace!
(
"MEM from SHIFTIREF(GETVARPARTIREF(_), imm): {}"
,
ret
);
ret
},
// SHIFTIREF(ireg, imm) -> [base + SHIFT_SIZE]
_
=>
{
let
tmp
=
self
.emit_ireg
(
base
,
f_content
,
f_context
,
vm
);
let
ret
=
MemoryLocation
::
Address
{
base
:
tmp
,
offset
:
Some
(
self
.make_value_int_const
(
shift_size
as
u64
,
vm
)),
index
:
None
,
scale
:
None
};
trace!
(
"MEM from SHIFTIREF(ireg, imm): {}"
,
ret
);
ret
}
};
mem
}
else
{
let
tmp_index
=
self
.emit_ireg
(
offset
,
f_content
,
f_context
,
vm
);
let
scale
:
u8
=
match
ele_ty_size
{
8
|
4
|
2
|
1
=>
ele_ty_size
as
u8
,
_
=>
unimplemented!
()
};
let
mem
=
match
base
.v
{
// SHIFTIREF(GETVARPARTIREF(_), ireg) -> add index and scale
TreeNode_
::
Instruction
(
Instruction
{
v
:
Instruction_
::
GetVarPartIRef
{
..
},
..
})
=>
{
let
mem
=
self
.emit_get_mem_from_inst_inner
(
base
,
f_content
,
f_context
,
vm
);
let
ret
=
self
.addr_append_index_scale
(
mem
,
tmp_index
,
scale
,
vm
);
trace!
(
"MEM from SHIFTIREF(GETVARPARTIREF(_), ireg): {}"
,
ret
);
ret
},
// SHIFTIREF(ireg, ireg) -> base + index * scale
_
=>
{
let
tmp
=
self
.emit_ireg
(
base
,
f_content
,
f_context
,
vm
);
let
ret
=
MemoryLocation
::
Address
{
base
:
tmp
,
offset
:
None
,
index
:
Some
(
tmp_index
),
scale
:
Some
(
scale
)
};
trace!
(
"MEM from SHIFTIREF(ireg, ireg): {}"
,
ret
);
ret
}
};
mem
}
}
_
=>
unimplemented!
()
_
=>
unimplemented!
()
}
}
},
},
...
@@ -2165,7 +2337,7 @@ impl <'a> InstructionSelection {
...
@@ -2165,7 +2337,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
match_funcref_const
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
bool
{
fn
match_funcref_const
(
&
mut
self
,
op
:
&
TreeNode
)
->
bool
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
let
is_const
=
match
pv
.v
{
let
is_const
=
match
pv
.v
{
...
@@ -2185,7 +2357,7 @@ impl <'a> InstructionSelection {
...
@@ -2185,7 +2357,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
node_funcref_const_to_id
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
MuID
{
fn
node_funcref_const_to_id
(
&
mut
self
,
op
:
&
TreeNode
)
->
MuID
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
match
pv
.v
{
match
pv
.v
{
...
@@ -2198,7 +2370,7 @@ impl <'a> InstructionSelection {
...
@@ -2198,7 +2370,7 @@ impl <'a> InstructionSelection {
}
}
#[allow(unused_variables)]
#[allow(unused_variables)]
fn
match_mem
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
)
->
bool
{
fn
match_mem
(
&
mut
self
,
op
:
&
TreeNode
)
->
bool
{
match
op
.v
{
match
op
.v
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
TreeNode_
::
Value
(
ref
pv
)
=>
{
match
pv
.v
{
match
pv
.v
{
...
@@ -2217,7 +2389,7 @@ impl <'a> InstructionSelection {
...
@@ -2217,7 +2389,7 @@ impl <'a> InstructionSelection {
}
}
#[allow(unused_variables)]
#[allow(unused_variables)]
fn
emit_mem
(
&
mut
self
,
op
:
&
P
<
TreeNode
>
,
vm
:
&
VM
)
->
P
<
Value
>
{
fn
emit_mem
(
&
mut
self
,
op
:
&
TreeNode
,
vm
:
&
VM
)
->
P
<
Value
>
{
unimplemented!
()
unimplemented!
()
}
}
...
@@ -2243,7 +2415,7 @@ impl <'a> InstructionSelection {
...
@@ -2243,7 +2415,7 @@ impl <'a> InstructionSelection {
}
}
}
}
fn
emit_move_node_to_value
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
P
<
TreeNode
>
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
{
fn
emit_move_node_to_value
(
&
mut
self
,
dest
:
&
P
<
Value
>
,
src
:
&
TreeNode
,
f_content
:
&
FunctionContent
,
f_context
:
&
mut
FunctionContext
,
vm
:
&
VM
)
{
let
ref
dst_ty
=
dest
.ty
;
let
ref
dst_ty
=
dest
.ty
;
if
!
types
::
is_fp
(
dst_ty
)
&&
types
::
is_scalar
(
dst_ty
)
{
if
!
types
::
is_fp
(
dst_ty
)
&&
types
::
is_scalar
(
dst_ty
)
{
...
@@ -2304,6 +2476,17 @@ impl <'a> InstructionSelection {
...
@@ -2304,6 +2476,17 @@ impl <'a> InstructionSelection {
let
tl
=
self
.emit_get_threadlocal
(
None
,
f_content
,
f_context
,
vm
);
let
tl
=
self
.emit_get_threadlocal
(
None
,
f_content
,
f_context
,
vm
);
self
.emit_load_base_offset
(
exception_arg
,
&
tl
,
*
thread
::
EXCEPTION_OBJ_OFFSET
as
i32
,
vm
);
self
.emit_load_base_offset
(
exception_arg
,
&
tl
,
*
thread
::
EXCEPTION_OBJ_OFFSET
as
i32
,
vm
);
}
}
fn
get_field_offset
(
&
mut
self
,
ty
:
&
P
<
MuType
>
,
index
:
usize
,
vm
:
&
VM
)
->
i32
{
let
ty_info
=
vm
.get_backend_type_info
(
ty
.id
());
let
layout
=
match
ty_info
.struct_layout
.as_ref
()
{
Some
(
layout
)
=>
layout
,
None
=>
panic!
(
"a struct type does not have a layout yet: {:?}"
,
ty_info
)
};
debug_assert!
(
layout
.len
()
>
index
);
layout
[
index
]
as
i32
}
fn
new_callsite_label
(
&
mut
self
,
cur_node
:
Option
<&
TreeNode
>
)
->
String
{
fn
new_callsite_label
(
&
mut
self
,
cur_node
:
Option
<&
TreeNode
>
)
->
String
{
let
ret
=
{
let
ret
=
{
...
...
src/testutil/mod.rs
View file @
8707cfce
...
@@ -7,6 +7,7 @@ use std::sync::Arc;
...
@@ -7,6 +7,7 @@ use std::sync::Arc;
use
std
::
process
::
Command
;
use
std
::
process
::
Command
;
use
std
::
process
::
Output
;
use
std
::
process
::
Output
;
use
std
::
os
::
unix
::
process
::
ExitStatusExt
;
pub
mod
aot
;
pub
mod
aot
;
pub
mod
c_api
;
pub
mod
c_api
;
...
@@ -40,6 +41,10 @@ pub fn exec_nocheck (mut cmd: Command) -> Output {
...
@@ -40,6 +41,10 @@ pub fn exec_nocheck (mut cmd: Command) -> Output {
println!
(
"---err---"
);
println!
(
"---err---"
);
println!
(
"{}"
,
String
::
from_utf8_lossy
(
&
output
.stderr
));
println!
(
"{}"
,
String
::
from_utf8_lossy
(
&
output
.stderr
));
if
output
.status
.signal
()
.is_some
()
{
println!
(
"terminated by a signal: {}"
,
output
.status
.signal
()
.unwrap
());
}
output
output
}
}
...
...
tests/test_compiler/test_mem_inst.rs
View file @
8707cfce
...
@@ -562,5 +562,452 @@ pub fn hybrid_fix_part_insts() -> VM {
...
@@ -562,5 +562,452 @@ pub fn hybrid_fix_part_insts() -> VM {
vm
.define_func_version
(
func_ver
);
vm
.define_func_version
(
func_ver
);
vm
}
#[test]
fn
test_hybrid_var_part
()
{
VM
::
start_logging_trace
();
let
vm
=
Arc
::
new
(
hybrid_var_part_insts
());
let
compiler
=
Compiler
::
new
(
CompilerPolicy
::
default
(),
vm
.clone
());
let
func_id
=
vm
.id_of
(
"hybrid_var_part_insts"
);
{
let
funcs
=
vm
.funcs
()
.read
()
.unwrap
();
let
func
=
funcs
.get
(
&
func_id
)
.unwrap
()
.read
()
.unwrap
();
let
func_vers
=
vm
.func_vers
()
.read
()
.unwrap
();
let
mut
func_ver
=
func_vers
.get
(
&
func
.cur_ver
.unwrap
())
.unwrap
()
.write
()
.unwrap
();
compiler
.compile
(
&
mut
func_ver
);
}
vm
.make_primordial_thread
(
func_id
,
vec!
[]);
backend
::
emit_context
(
&
vm
);
let
executable
=
aot
::
link_primordial
(
vec!
[
"hybrid_var_part_insts"
.to_string
()],
"hybrid_var_part_insts_test"
);
let
output
=
aot
::
execute_nocheck
(
executable
);
assert
!
(
output
.status
.code
()
.is_some
());
let
ret_code
=
output
.status
.code
()
.unwrap
();
println!
(
"return code: {}"
,
ret_code
);
assert
!
(
ret_code
==
20
);
}
pub
fn
hybrid_var_part_insts
()
->
VM
{
let
vm
=
VM
::
new
();
// .typedef @int64 = int<64>
let
int64
=
vm
.declare_type
(
vm
.next_id
(),
MuType_
::
int
(
64
));
vm
.set_name
(
int64
.as_entity
(),
Mu
(
"int64"
));
// .typedef @my_hybrid = hybrid<@int64 @int64 | @int64>
let
my_hybrid
=
vm
.declare_type
(
vm
.next_id
(),
MuType_
::
hybrid
(
"MyHybrid"
.to_string
(),
vec!
[
int64
.clone
(),
int64
.clone
()],
int64
.clone
()));
vm
.set_name
(
my_hybrid
.as_entity
(),
Mu
(
"my_hybrid"
));
// .typedef @ref_hybrid = ref<@my_hybrid>
let
ref_hybrid
=
vm
.declare_type
(
vm
.next_id
(),
MuType_
::
muref
(
my_hybrid
.clone
()));
vm
.set_name
(
ref_hybrid
.as_entity
(),
Mu
(
"ref_hybrid"
));
// .typedef @iref_hybrid = iref<@my_hybrid>
let
iref_hybrid
=
vm
.declare_type
(
vm
.next_id
(),
MuType_
::
iref
(
my_hybrid
.clone
()));
vm
.set_name
(
iref_hybrid
.as_entity
(),
Mu
(
"iref_hybrid"
));
// .typedef @iref_int64 = iref<@int64>
let
iref_int64
=
vm
.declare_type
(
vm
.next_id
(),
MuType_
::
iref
(
int64
.clone
()));
vm
.set_name
(
iref_int64
.as_entity
(),
Mu
(
"iref_int64"
));
// .const @int64_0 <@int64> = 0
let
int64_0
=
vm
.declare_const
(
vm
.next_id
(),
int64
.clone
(),
Constant
::
Int
(
0
));
vm
.set_name
(
int64_0
.as_entity
(),
Mu
(
"int64_0"
));
// .const @int64_1 <@int64> = 1
let
int64_1
=
vm
.declare_const
(
vm
.next_id
(),
int64
.clone
(),
Constant
::
Int
(
1
));
vm
.set_name
(
int64_1
.as_entity
(),
Mu
(
"int64_1"
));
// .const @int64_2 <@int64> = 2
let
int64_2
=
vm
.declare_const
(
vm
.next_id
(),
int64
.clone
(),
Constant
::
Int
(
2
));
vm
.set_name
(
int64_2
.as_entity
(),
Mu
(
"int64_2"
));
// .const @int64_3 <@int64> = 3