From f928cc81881fe6e85a0bf7e9698130e22a6b5d7e Mon Sep 17 00:00:00 2001 From: Will Glynn Date: Sun, 7 Oct 2018 13:31:42 -0500 Subject: [PATCH] Hide instruction encoding behind isa::Instructions::push() --- src/isa.rs | 45 +++++++++++++++++++++++++++++++---- src/validation/func.rs | 53 +++++++++++------------------------------- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/src/isa.rs b/src/isa.rs index 01cadb7..776c78d 100644 --- a/src/isa.rs +++ b/src/isa.rs @@ -93,6 +93,22 @@ pub struct Target { 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)] pub enum Instruction { /// Push a local variable or an argument from the specified depth. @@ -303,11 +319,32 @@ pub struct Instructions { } impl Instructions { - pub fn new(instructions: I) -> Self - where I: IntoIterator - { + pub fn with_capacity(capacity: usize) -> Self { 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"), + } } } diff --git a/src/validation/func.rs b/src/validation/func.rs index 0481e21..f7a975e 100644 --- a/src/validation/func.rs +++ b/src/validation/func.rs @@ -1406,7 +1406,7 @@ impl<'a> FunctionValidationContext<'a> { } 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, } -/// 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. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] struct LabelId(usize); @@ -1653,23 +1637,23 @@ enum Label { } struct Sink { - ins: Vec, - labels: Vec<(Label, Vec)>, + ins: isa::Instructions, + labels: Vec<(Label, Vec)>, } impl Sink { fn with_instruction_capacity(capacity: usize) -> Sink { Sink { - ins: Vec::with_capacity(capacity), + ins: isa::Instructions::with_capacity(capacity), labels: Vec::new(), } } fn cur_pc(&self) -> u32 { - self.ins.len() as u32 + self.ins.current_pc() } - fn pc_or_placeholder Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 { + fn pc_or_placeholder isa::Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 { match self.labels[label.0] { (Label::Resolved(dst_pc), _) => dst_pc, (Label::NotResolved, ref mut unresolved) => { @@ -1690,7 +1674,7 @@ impl Sink { drop_keep, } = target; 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 { dst_pc, drop_keep: drop_keep.into(), @@ -1703,7 +1687,7 @@ impl Sink { drop_keep, } = target; 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 { dst_pc, drop_keep: drop_keep.into(), @@ -1716,7 +1700,7 @@ impl Sink { drop_keep, } = target; 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 { dst_pc, drop_keep: drop_keep.into(), @@ -1729,7 +1713,7 @@ impl Sink { let pc = self.cur_pc(); let mut isa_targets = Vec::new(); 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::Target { dst_pc, @@ -1766,26 +1750,15 @@ impl Sink { // particular label. let unresolved_rels = mem::replace(&mut self.labels[label.0].1, Vec::new()); for reloc in unresolved_rels { - match reloc { - 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"), - } - } + self.ins.patch_relocation(reloc, dst_pc); } // Mark this label as resolved. self.labels[label.0] = (Label::Resolved(dst_pc), Vec::new()); } - /// Consume this Sink and returns isa::Instruction. - fn into_inner(self) -> Vec { + /// Consume this Sink and returns isa::Instructions. + fn into_inner(self) -> isa::Instructions { // At this moment all labels should be resolved. assert!({ self.labels.iter().all(|(state, unresolved)|