Hide instruction encoding behind isa::Instructions::push()
This commit is contained in:
parent
14857145d1
commit
f928cc8188
45
src/isa.rs
45
src/isa.rs
|
@ -93,6 +93,22 @@ pub struct Target {
|
||||||
pub drop_keep: DropKeep,
|
pub drop_keep: DropKeep,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A relocation entry that specifies.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Reloc {
|
||||||
|
/// Patch the destination of the branch instruction (br, br_eqz, br_nez)
|
||||||
|
/// at the specified pc.
|
||||||
|
Br {
|
||||||
|
pc: u32,
|
||||||
|
},
|
||||||
|
/// Patch the specified destination index inside of br_table instruction at
|
||||||
|
/// the specified pc.
|
||||||
|
BrTable {
|
||||||
|
pc: u32,
|
||||||
|
idx: usize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
/// Push a local variable or an argument from the specified depth.
|
/// Push a local variable or an argument from the specified depth.
|
||||||
|
@ -303,11 +319,32 @@ pub struct Instructions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instructions {
|
impl Instructions {
|
||||||
pub fn new<I>(instructions: I) -> Self
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
where I: IntoIterator<Item=Instruction>
|
|
||||||
{
|
|
||||||
Instructions {
|
Instructions {
|
||||||
vec: instructions.into_iter().collect()
|
vec: Vec::with_capacity(capacity),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_pc(&self) -> u32 {
|
||||||
|
self.vec.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, instruction: Instruction) {
|
||||||
|
self.vec.push(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn patch_relocation(&mut self, reloc: Reloc, dst_pc: u32) {
|
||||||
|
match reloc {
|
||||||
|
Reloc::Br { pc } => match self.vec[pc as usize] {
|
||||||
|
Instruction::Br(ref mut target)
|
||||||
|
| Instruction::BrIfEqz(ref mut target)
|
||||||
|
| Instruction::BrIfNez(ref mut target) => target.dst_pc = dst_pc,
|
||||||
|
_ => panic!("branch relocation points to a non-branch instruction"),
|
||||||
|
},
|
||||||
|
Reloc::BrTable { pc, idx } => match self.vec[pc as usize] {
|
||||||
|
Instruction::BrTable(ref mut targets) => targets[idx].dst_pc = dst_pc,
|
||||||
|
_ => panic!("brtable relocation points to not brtable instruction"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1406,7 +1406,7 @@ impl<'a> FunctionValidationContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_code(self) -> isa::Instructions {
|
fn into_code(self) -> isa::Instructions {
|
||||||
isa::Instructions::new(self.sink.into_inner())
|
self.sink.into_inner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1626,22 +1626,6 @@ struct Target {
|
||||||
drop_keep: isa::DropKeep,
|
drop_keep: isa::DropKeep,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A relocation entry that specifies.
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Reloc {
|
|
||||||
/// Patch the destination of the branch instruction (br, br_eqz, br_nez)
|
|
||||||
/// at the specified pc.
|
|
||||||
Br {
|
|
||||||
pc: u32,
|
|
||||||
},
|
|
||||||
/// Patch the specified destination index inside of br_table instruction at
|
|
||||||
/// the specified pc.
|
|
||||||
BrTable {
|
|
||||||
pc: u32,
|
|
||||||
idx: usize,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Identifier of a label.
|
/// Identifier of a label.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
struct LabelId(usize);
|
struct LabelId(usize);
|
||||||
|
@ -1653,23 +1637,23 @@ enum Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Sink {
|
struct Sink {
|
||||||
ins: Vec<isa::Instruction>,
|
ins: isa::Instructions,
|
||||||
labels: Vec<(Label, Vec<Reloc>)>,
|
labels: Vec<(Label, Vec<isa::Reloc>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink {
|
impl Sink {
|
||||||
fn with_instruction_capacity(capacity: usize) -> Sink {
|
fn with_instruction_capacity(capacity: usize) -> Sink {
|
||||||
Sink {
|
Sink {
|
||||||
ins: Vec::with_capacity(capacity),
|
ins: isa::Instructions::with_capacity(capacity),
|
||||||
labels: Vec::new(),
|
labels: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_pc(&self) -> u32 {
|
fn cur_pc(&self) -> u32 {
|
||||||
self.ins.len() as u32
|
self.ins.current_pc()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pc_or_placeholder<F: FnOnce() -> Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 {
|
fn pc_or_placeholder<F: FnOnce() -> isa::Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 {
|
||||||
match self.labels[label.0] {
|
match self.labels[label.0] {
|
||||||
(Label::Resolved(dst_pc), _) => dst_pc,
|
(Label::Resolved(dst_pc), _) => dst_pc,
|
||||||
(Label::NotResolved, ref mut unresolved) => {
|
(Label::NotResolved, ref mut unresolved) => {
|
||||||
|
@ -1690,7 +1674,7 @@ impl Sink {
|
||||||
drop_keep,
|
drop_keep,
|
||||||
} = target;
|
} = target;
|
||||||
let pc = self.cur_pc();
|
let pc = self.cur_pc();
|
||||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::Br { pc });
|
let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::Br { pc });
|
||||||
self.ins.push(isa::Instruction::Br(isa::Target {
|
self.ins.push(isa::Instruction::Br(isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
drop_keep: drop_keep.into(),
|
drop_keep: drop_keep.into(),
|
||||||
|
@ -1703,7 +1687,7 @@ impl Sink {
|
||||||
drop_keep,
|
drop_keep,
|
||||||
} = target;
|
} = target;
|
||||||
let pc = self.cur_pc();
|
let pc = self.cur_pc();
|
||||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::Br { pc });
|
let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::Br { pc });
|
||||||
self.ins.push(isa::Instruction::BrIfEqz(isa::Target {
|
self.ins.push(isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
drop_keep: drop_keep.into(),
|
drop_keep: drop_keep.into(),
|
||||||
|
@ -1716,7 +1700,7 @@ impl Sink {
|
||||||
drop_keep,
|
drop_keep,
|
||||||
} = target;
|
} = target;
|
||||||
let pc = self.cur_pc();
|
let pc = self.cur_pc();
|
||||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::Br { pc });
|
let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::Br { pc });
|
||||||
self.ins.push(isa::Instruction::BrIfNez(isa::Target {
|
self.ins.push(isa::Instruction::BrIfNez(isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
drop_keep: drop_keep.into(),
|
drop_keep: drop_keep.into(),
|
||||||
|
@ -1729,7 +1713,7 @@ impl Sink {
|
||||||
let pc = self.cur_pc();
|
let pc = self.cur_pc();
|
||||||
let mut isa_targets = Vec::new();
|
let mut isa_targets = Vec::new();
|
||||||
for (idx, &Target { label, drop_keep }) in targets.iter().chain(iter::once(&default)).enumerate() {
|
for (idx, &Target { label, drop_keep }) in targets.iter().chain(iter::once(&default)).enumerate() {
|
||||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::BrTable { pc, idx });
|
let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::BrTable { pc, idx });
|
||||||
isa_targets.push(
|
isa_targets.push(
|
||||||
isa::Target {
|
isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
|
@ -1766,26 +1750,15 @@ impl Sink {
|
||||||
// particular label.
|
// particular label.
|
||||||
let unresolved_rels = mem::replace(&mut self.labels[label.0].1, Vec::new());
|
let unresolved_rels = mem::replace(&mut self.labels[label.0].1, Vec::new());
|
||||||
for reloc in unresolved_rels {
|
for reloc in unresolved_rels {
|
||||||
match reloc {
|
self.ins.patch_relocation(reloc, dst_pc);
|
||||||
Reloc::Br { pc } => match self.ins[pc as usize] {
|
|
||||||
isa::Instruction::Br(ref mut target)
|
|
||||||
| isa::Instruction::BrIfEqz(ref mut target)
|
|
||||||
| isa::Instruction::BrIfNez(ref mut target) => target.dst_pc = dst_pc,
|
|
||||||
_ => panic!("branch relocation points to a non-branch instruction"),
|
|
||||||
},
|
|
||||||
Reloc::BrTable { pc, idx } => match self.ins[pc as usize] {
|
|
||||||
isa::Instruction::BrTable(ref mut targets) => targets[idx].dst_pc = dst_pc,
|
|
||||||
_ => panic!("brtable relocation points to not brtable instruction"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this label as resolved.
|
// Mark this label as resolved.
|
||||||
self.labels[label.0] = (Label::Resolved(dst_pc), Vec::new());
|
self.labels[label.0] = (Label::Resolved(dst_pc), Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume this Sink and returns isa::Instruction.
|
/// Consume this Sink and returns isa::Instructions.
|
||||||
fn into_inner(self) -> Vec<isa::Instruction> {
|
fn into_inner(self) -> isa::Instructions {
|
||||||
// At this moment all labels should be resolved.
|
// At this moment all labels should be resolved.
|
||||||
assert!({
|
assert!({
|
||||||
self.labels.iter().all(|(state, unresolved)|
|
self.labels.iter().all(|(state, unresolved)|
|
||||||
|
|
Loading…
Reference in New Issue