Use vector to keep unresolved references.
This commit is contained in:
parent
4e9f39444c
commit
3f10ba6666
|
@ -1,5 +1,4 @@
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use std::collections::HashMap;
|
|
||||||
use parity_wasm::elements::{Opcode, BlockType, ValueType, TableElementType, Func, FuncBody};
|
use parity_wasm::elements::{Opcode, BlockType, ValueType, TableElementType, Func, FuncBody};
|
||||||
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX};
|
||||||
use validation::context::ModuleContext;
|
use validation::context::ModuleContext;
|
||||||
|
@ -1538,6 +1537,7 @@ struct Target {
|
||||||
drop_keep: DropKeep,
|
drop_keep: DropKeep,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
enum Reloc {
|
enum Reloc {
|
||||||
Br {
|
Br {
|
||||||
pc: u32,
|
pc: u32,
|
||||||
|
@ -1550,6 +1550,8 @@ enum Reloc {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
struct LabelId(usize);
|
struct LabelId(usize);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
enum Label {
|
enum Label {
|
||||||
Resolved(u32),
|
Resolved(u32),
|
||||||
NotResolved,
|
NotResolved,
|
||||||
|
@ -1557,8 +1559,7 @@ enum Label {
|
||||||
|
|
||||||
struct Sink {
|
struct Sink {
|
||||||
ins: Vec<isa::Instruction>,
|
ins: Vec<isa::Instruction>,
|
||||||
labels: Vec<Label>,
|
labels: Vec<(Label, Vec<Reloc>)>,
|
||||||
unresolved: HashMap<LabelId, Vec<Reloc>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink {
|
impl Sink {
|
||||||
|
@ -1567,7 +1568,6 @@ impl Sink {
|
||||||
Sink {
|
Sink {
|
||||||
ins: Vec::new(),
|
ins: Vec::new(),
|
||||||
labels: Vec::new(),
|
labels: Vec::new(),
|
||||||
unresolved: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1577,11 +1577,9 @@ impl Sink {
|
||||||
|
|
||||||
fn pc_or_placeholder<F: FnOnce() -> Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 {
|
fn pc_or_placeholder<F: FnOnce() -> 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 => {
|
(Label::NotResolved, ref mut unresolved) => {
|
||||||
self.unresolved
|
unresolved
|
||||||
.entry(label)
|
|
||||||
.or_insert(Vec::new())
|
|
||||||
.push(reloc_creator());
|
.push(reloc_creator());
|
||||||
u32::max_value()
|
u32::max_value()
|
||||||
}
|
}
|
||||||
|
@ -1669,7 +1667,7 @@ impl Sink {
|
||||||
fn new_label(&mut self) -> LabelId {
|
fn new_label(&mut self) -> LabelId {
|
||||||
let label_idx = self.labels.len();
|
let label_idx = self.labels.len();
|
||||||
self.labels.push(
|
self.labels.push(
|
||||||
Label::NotResolved,
|
(Label::NotResolved, Vec::new()),
|
||||||
);
|
);
|
||||||
LabelId(label_idx)
|
LabelId(label_idx)
|
||||||
}
|
}
|
||||||
|
@ -1678,14 +1676,16 @@ impl Sink {
|
||||||
///
|
///
|
||||||
/// Panics if the label is already resolved.
|
/// Panics if the label is already resolved.
|
||||||
fn resolve_label(&mut self, label: LabelId) {
|
fn resolve_label(&mut self, label: LabelId) {
|
||||||
if let Label::Resolved(_) = self.labels[label.0] {
|
use std::mem;
|
||||||
|
|
||||||
|
if let (Label::Resolved(_), _) = self.labels[label.0] {
|
||||||
panic!("Trying to resolve already resolved label");
|
panic!("Trying to resolve already resolved label");
|
||||||
}
|
}
|
||||||
let dst_pc = self.cur_pc();
|
let dst_pc = self.cur_pc();
|
||||||
|
|
||||||
// Patch all relocations that was previously recorded for this
|
// Patch all relocations that was previously recorded for this
|
||||||
// particular label.
|
// particular label.
|
||||||
let unresolved_rels = self.unresolved.remove(&label).unwrap_or(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 {
|
match reloc {
|
||||||
Reloc::Br { pc } => match self.ins[pc as usize] {
|
Reloc::Br { pc } => match self.ins[pc as usize] {
|
||||||
|
@ -1702,11 +1702,19 @@ impl Sink {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this label as resolved.
|
// Mark this label as resolved.
|
||||||
self.labels[label.0] = Label::Resolved(dst_pc);
|
self.labels[label.0] = (Label::Resolved(dst_pc), Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_inner(self) -> Vec<isa::Instruction> {
|
fn into_inner(self) -> Vec<isa::Instruction> {
|
||||||
assert!(self.unresolved.is_empty());
|
// At this moment all labels should be resolved.
|
||||||
|
assert!({
|
||||||
|
self.labels.iter().all(|(state, unresolved)|
|
||||||
|
match (state, unresolved) {
|
||||||
|
(Label::Resolved(_), unresolved) if unresolved.is_empty() => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, "there are unresolved labels left: {:?}", self.labels);
|
||||||
self.ins
|
self.ins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue