Add an internal MutableSourceMap trait.
Use the SourceMap for mapping during parsing too.
This commit is contained in:
@@ -5,12 +5,11 @@
|
|||||||
//
|
//
|
||||||
// ====--------------------------------------------------------------------------------------====//
|
// ====--------------------------------------------------------------------------------------====//
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use cretonne::ir::{Function, Ebb, Inst, Opcode, Value, Type, FunctionName, StackSlot,
|
use cretonne::ir::{Function, Ebb, Inst, Opcode, Value, Type, FunctionName, StackSlotData,
|
||||||
StackSlotData, JumpTable, JumpTableData};
|
JumpTable, JumpTableData};
|
||||||
use cretonne::ir::types::{VOID, Signature, ArgumentType, ArgumentExtension};
|
use cretonne::ir::types::{VOID, Signature, ArgumentType, ArgumentExtension};
|
||||||
use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64};
|
use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64};
|
||||||
use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE};
|
use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE};
|
||||||
@@ -20,7 +19,7 @@ use testfile::{TestFile, Details, Comment};
|
|||||||
use error::{Location, Error, Result};
|
use error::{Location, Error, Result};
|
||||||
use lexer::{self, Lexer, Token};
|
use lexer::{self, Lexer, Token};
|
||||||
use testcommand::TestCommand;
|
use testcommand::TestCommand;
|
||||||
use sourcemap;
|
use sourcemap::{SourceMap, MutableSourceMap};
|
||||||
|
|
||||||
/// Parse the entire `text` into a list of functions.
|
/// Parse the entire `text` into a list of functions.
|
||||||
///
|
///
|
||||||
@@ -65,10 +64,7 @@ pub struct Parser<'a> {
|
|||||||
// file by number. We need to map these numbers to real references.
|
// file by number. We need to map these numbers to real references.
|
||||||
struct Context {
|
struct Context {
|
||||||
function: Function,
|
function: Function,
|
||||||
stack_slots: HashMap<u32, StackSlot>, // ssNN
|
map: SourceMap,
|
||||||
jump_tables: HashMap<u32, JumpTable>, // jtNN
|
|
||||||
ebbs: HashMap<Ebb, Ebb>, // ebbNN
|
|
||||||
values: HashMap<Value, Value>, // vNN, vxNN
|
|
||||||
|
|
||||||
// Remember the location of every instruction.
|
// Remember the location of every instruction.
|
||||||
inst_locs: Vec<(Inst, Location)>,
|
inst_locs: Vec<(Inst, Location)>,
|
||||||
@@ -78,36 +74,25 @@ impl Context {
|
|||||||
fn new(f: Function) -> Context {
|
fn new(f: Function) -> Context {
|
||||||
Context {
|
Context {
|
||||||
function: f,
|
function: f,
|
||||||
stack_slots: HashMap::new(),
|
map: SourceMap::new(),
|
||||||
jump_tables: HashMap::new(),
|
|
||||||
ebbs: HashMap::new(),
|
|
||||||
values: HashMap::new(),
|
|
||||||
inst_locs: Vec::new(),
|
inst_locs: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new stack slot and add a mapping number -> StackSlot.
|
// Allocate a new stack slot and add a mapping number -> StackSlot.
|
||||||
fn add_ss(&mut self, number: u32, data: StackSlotData, loc: &Location) -> Result<()> {
|
fn add_ss(&mut self, number: u32, data: StackSlotData, loc: &Location) -> Result<()> {
|
||||||
if self.stack_slots.insert(number, self.function.stack_slots.push(data)).is_some() {
|
self.map.def_ss(number, self.function.stack_slots.push(data), loc)
|
||||||
err!(loc, "duplicate stack slot: ss{}", number)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new jump table and add a mapping number -> JumpTable.
|
// Allocate a new jump table and add a mapping number -> JumpTable.
|
||||||
fn add_jt(&mut self, number: u32, data: JumpTableData, loc: &Location) -> Result<()> {
|
fn add_jt(&mut self, number: u32, data: JumpTableData, loc: &Location) -> Result<()> {
|
||||||
if self.jump_tables.insert(number, self.function.jump_tables.push(data)).is_some() {
|
self.map.def_jt(number, self.function.jump_tables.push(data), loc)
|
||||||
err!(loc, "duplicate jump table: jt{}", number)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve a reference to a jump table.
|
// Resolve a reference to a jump table.
|
||||||
fn get_jt(&self, number: u32, loc: &Location) -> Result<JumpTable> {
|
fn get_jt(&self, number: u32, loc: &Location) -> Result<JumpTable> {
|
||||||
match self.jump_tables.get(&number) {
|
match self.map.get_jt(number) {
|
||||||
Some(&jt) => Ok(jt),
|
Some(jt) => Ok(jt),
|
||||||
None => err!(loc, "undefined jump table jt{}", number),
|
None => err!(loc, "undefined jump table jt{}", number),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,20 +101,7 @@ impl Context {
|
|||||||
fn add_ebb(&mut self, src_ebb: Ebb, loc: &Location) -> Result<Ebb> {
|
fn add_ebb(&mut self, src_ebb: Ebb, loc: &Location) -> Result<Ebb> {
|
||||||
let ebb = self.function.dfg.make_ebb();
|
let ebb = self.function.dfg.make_ebb();
|
||||||
self.function.layout.append_ebb(ebb);
|
self.function.layout.append_ebb(ebb);
|
||||||
if self.ebbs.insert(src_ebb, ebb).is_some() {
|
self.map.def_ebb(src_ebb, ebb, loc).and(Ok(ebb))
|
||||||
err!(loc, "duplicate EBB: {}", src_ebb)
|
|
||||||
} else {
|
|
||||||
Ok(ebb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a value mapping src_val -> data.
|
|
||||||
fn add_value(&mut self, src_val: Value, data: Value, loc: &Location) -> Result<()> {
|
|
||||||
if self.values.insert(src_val, data).is_some() {
|
|
||||||
err!(loc, "duplicate value: {}", src_val)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the location of an instuction.
|
// Record the location of an instuction.
|
||||||
@@ -140,41 +112,6 @@ impl Context {
|
|||||||
// The parser creates all instructions with Ebb and Value references using the source file
|
// The parser creates all instructions with Ebb and Value references using the source file
|
||||||
// numbering. These references need to be rewritten after parsing is complete since forward
|
// numbering. These references need to be rewritten after parsing is complete since forward
|
||||||
// references are allowed.
|
// references are allowed.
|
||||||
|
|
||||||
// Rewrite an Ebb reference.
|
|
||||||
fn rewrite_ebb(map: &HashMap<Ebb, Ebb>, ebb: &mut Ebb, loc: &Location) -> Result<()> {
|
|
||||||
match map.get(ebb) {
|
|
||||||
Some(&new) => {
|
|
||||||
*ebb = new;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
None => err!(loc, "undefined reference: {}", ebb),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewrite a value reference.
|
|
||||||
fn rewrite_value(map: &HashMap<Value, Value>, val: &mut Value, loc: &Location) -> Result<()> {
|
|
||||||
match map.get(val) {
|
|
||||||
Some(&new) => {
|
|
||||||
*val = new;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
None => err!(loc, "undefined reference: {}", val),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewrite a slice of value references.
|
|
||||||
fn rewrite_values(map: &HashMap<Value, Value>,
|
|
||||||
vals: &mut [Value],
|
|
||||||
loc: &Location)
|
|
||||||
-> Result<()> {
|
|
||||||
for val in vals {
|
|
||||||
try!(Self::rewrite_value(map, val, loc));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewrite all EBB and value references in the function.
|
|
||||||
fn rewrite_references(&mut self) -> Result<()> {
|
fn rewrite_references(&mut self) -> Result<()> {
|
||||||
for &(inst, loc) in &self.inst_locs {
|
for &(inst, loc) in &self.inst_locs {
|
||||||
match self.function.dfg[inst] {
|
match self.function.dfg[inst] {
|
||||||
@@ -189,7 +126,7 @@ impl Context {
|
|||||||
InstructionData::BinaryImmRev { ref mut arg, .. } |
|
InstructionData::BinaryImmRev { ref mut arg, .. } |
|
||||||
InstructionData::ExtractLane { ref mut arg, .. } |
|
InstructionData::ExtractLane { ref mut arg, .. } |
|
||||||
InstructionData::BranchTable { ref mut arg, .. } => {
|
InstructionData::BranchTable { ref mut arg, .. } => {
|
||||||
try!(Self::rewrite_value(&self.values, arg, &loc));
|
try!(self.map.rewrite_value(arg, &loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Binary { ref mut args, .. } |
|
InstructionData::Binary { ref mut args, .. } |
|
||||||
@@ -197,30 +134,30 @@ impl Context {
|
|||||||
InstructionData::InsertLane { ref mut args, .. } |
|
InstructionData::InsertLane { ref mut args, .. } |
|
||||||
InstructionData::IntCompare { ref mut args, .. } |
|
InstructionData::IntCompare { ref mut args, .. } |
|
||||||
InstructionData::FloatCompare { ref mut args, .. } => {
|
InstructionData::FloatCompare { ref mut args, .. } => {
|
||||||
try!(Self::rewrite_values(&self.values, args, &loc));
|
try!(self.map.rewrite_values(args, &loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Ternary { ref mut args, .. } => {
|
InstructionData::Ternary { ref mut args, .. } => {
|
||||||
try!(Self::rewrite_values(&self.values, args, &loc));
|
try!(self.map.rewrite_values(args, &loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Jump { ref mut data, .. } => {
|
InstructionData::Jump { ref mut data, .. } => {
|
||||||
try!(Self::rewrite_ebb(&self.ebbs, &mut data.destination, &loc));
|
try!(self.map.rewrite_ebb(&mut data.destination, &loc));
|
||||||
try!(Self::rewrite_values(&self.values, &mut data.arguments, &loc));
|
try!(self.map.rewrite_values(&mut data.arguments, &loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Branch { ref mut data, .. } => {
|
InstructionData::Branch { ref mut data, .. } => {
|
||||||
try!(Self::rewrite_value(&self.values, &mut data.arg, &loc));
|
try!(self.map.rewrite_value(&mut data.arg, &loc));
|
||||||
try!(Self::rewrite_ebb(&self.ebbs, &mut data.destination, &loc));
|
try!(self.map.rewrite_ebb(&mut data.destination, &loc));
|
||||||
try!(Self::rewrite_values(&self.values, &mut data.arguments, &loc));
|
try!(self.map.rewrite_values(&mut data.arguments, &loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Call { ref mut data, .. } => {
|
InstructionData::Call { ref mut data, .. } => {
|
||||||
try!(Self::rewrite_values(&self.values, &mut data.args, &loc));
|
try!(self.map.rewrite_values(&mut data.args, &loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionData::Return { ref mut data, .. } => {
|
InstructionData::Return { ref mut data, .. } => {
|
||||||
try!(Self::rewrite_values(&self.values, &mut data.args, &loc));
|
try!(self.map.rewrite_values(&mut data.args, &loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +167,7 @@ impl Context {
|
|||||||
for jt in self.function.jump_tables.keys() {
|
for jt in self.function.jump_tables.keys() {
|
||||||
for ebb in self.function.jump_tables[jt].as_mut_slice() {
|
for ebb in self.function.jump_tables[jt].as_mut_slice() {
|
||||||
if *ebb != NO_EBB {
|
if *ebb != NO_EBB {
|
||||||
try!(Self::rewrite_ebb(&self.ebbs, ebb, &loc));
|
try!(self.map.rewrite_ebb(ebb, &loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -512,7 +449,7 @@ impl<'a> Parser<'a> {
|
|||||||
let details = Details {
|
let details = Details {
|
||||||
location: location,
|
location: location,
|
||||||
comments: mem::replace(&mut self.comments, Vec::new()),
|
comments: mem::replace(&mut self.comments, Vec::new()),
|
||||||
map: sourcemap::new(ctx.values, ctx.ebbs, ctx.stack_slots, ctx.jump_tables),
|
map: ctx.map,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((ctx.function, details))
|
Ok((ctx.function, details))
|
||||||
@@ -777,7 +714,7 @@ impl<'a> Parser<'a> {
|
|||||||
let t = try!(self.match_type("expected EBB argument type"));
|
let t = try!(self.match_type("expected EBB argument type"));
|
||||||
// Allocate the EBB argument and add the mapping.
|
// Allocate the EBB argument and add the mapping.
|
||||||
let value = ctx.function.dfg.append_ebb_arg(ebb, t);
|
let value = ctx.function.dfg.append_ebb_arg(ebb, t);
|
||||||
ctx.add_value(vx, value, &vx_location)
|
ctx.map.def_value(vx, value, &vx_location)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse an instruction, append it to `ebb`.
|
// Parse an instruction, append it to `ebb`.
|
||||||
@@ -856,7 +793,7 @@ impl<'a> Parser<'a> {
|
|||||||
// Now map the source result values to the just created instruction results.
|
// Now map the source result values to the just created instruction results.
|
||||||
// Pass a reference to `ctx.values` instead of `ctx` itself since the `Values` iterator
|
// Pass a reference to `ctx.values` instead of `ctx` itself since the `Values` iterator
|
||||||
// holds a reference to `ctx.function`.
|
// holds a reference to `ctx.function`.
|
||||||
self.add_values(&mut ctx.values,
|
self.add_values(&mut ctx.map,
|
||||||
results.into_iter(),
|
results.into_iter(),
|
||||||
ctx.function.dfg.inst_results(inst))
|
ctx.function.dfg.inst_results(inst))
|
||||||
}
|
}
|
||||||
@@ -888,8 +825,8 @@ impl<'a> Parser<'a> {
|
|||||||
// layout of the blocks.
|
// layout of the blocks.
|
||||||
let ctrl_src_value = inst_data.typevar_operand()
|
let ctrl_src_value = inst_data.typevar_operand()
|
||||||
.expect("Constraints <-> Format inconsistency");
|
.expect("Constraints <-> Format inconsistency");
|
||||||
ctx.function.dfg.value_type(match ctx.values.get(&ctrl_src_value) {
|
ctx.function.dfg.value_type(match ctx.map.get_value(ctrl_src_value) {
|
||||||
Some(&v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
return err!(self.loc,
|
return err!(self.loc,
|
||||||
"cannot determine type of operand {}",
|
"cannot determine type of operand {}",
|
||||||
@@ -932,18 +869,12 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add mappings for a list of source values to their corresponding new values.
|
// Add mappings for a list of source values to their corresponding new values.
|
||||||
fn add_values<S, V>(&self,
|
fn add_values<S, V>(&self, map: &mut SourceMap, results: S, new_results: V) -> Result<()>
|
||||||
values: &mut HashMap<Value, Value>,
|
|
||||||
results: S,
|
|
||||||
new_results: V)
|
|
||||||
-> Result<()>
|
|
||||||
where S: Iterator<Item = Value>,
|
where S: Iterator<Item = Value>,
|
||||||
V: Iterator<Item = Value>
|
V: Iterator<Item = Value>
|
||||||
{
|
{
|
||||||
for (src, val) in results.zip(new_results) {
|
for (src, val) in results.zip(new_results) {
|
||||||
if values.insert(src, val).is_some() {
|
try!(map.def_value(src, val, &self.loc));
|
||||||
return err!(self.loc, "duplicate result value: {}", src);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use cretonne::ir::{StackSlot, JumpTable, Ebb, Value};
|
use cretonne::ir::{StackSlot, JumpTable, Ebb, Value};
|
||||||
use cretonne::ir::entities::AnyEntity;
|
use cretonne::ir::entities::AnyEntity;
|
||||||
|
use error::{Result, Location};
|
||||||
|
|
||||||
/// Mapping from source entity names to entity references that are valid in the parsed function.
|
/// Mapping from source entity names to entity references that are valid in the parsed function.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -22,6 +23,26 @@ pub struct SourceMap {
|
|||||||
|
|
||||||
/// Read-only interface which is exposed outside the parser crate.
|
/// Read-only interface which is exposed outside the parser crate.
|
||||||
impl SourceMap {
|
impl SourceMap {
|
||||||
|
/// Look up a value entity by its source number.
|
||||||
|
pub fn get_value(&self, src: Value) -> Option<Value> {
|
||||||
|
self.values.get(&src).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Look up a EBB entity by its source number.
|
||||||
|
pub fn get_ebb(&self, src: Ebb) -> Option<Ebb> {
|
||||||
|
self.ebbs.get(&src).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Look up a stack slot entity by its source number.
|
||||||
|
pub fn get_ss(&self, src_num: u32) -> Option<StackSlot> {
|
||||||
|
self.stack_slots.get(&src_num).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Look up a jump table entity by its source number.
|
||||||
|
pub fn get_jt(&self, src_num: u32) -> Option<JumpTable> {
|
||||||
|
self.jump_tables.get(&src_num).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
/// Look up an entity by source name.
|
/// Look up an entity by source name.
|
||||||
/// Returns the entity reference corresponding to `name`, if it exists.
|
/// Returns the entity reference corresponding to `name`, if it exists.
|
||||||
pub fn lookup_str(&self, name: &str) -> Option<AnyEntity> {
|
pub fn lookup_str(&self, name: &str) -> Option<AnyEntity> {
|
||||||
@@ -29,25 +50,51 @@ impl SourceMap {
|
|||||||
match ent {
|
match ent {
|
||||||
"v" => {
|
"v" => {
|
||||||
Value::direct_with_number(num)
|
Value::direct_with_number(num)
|
||||||
.and_then(|v| self.values.get(&v).cloned())
|
.and_then(|v| self.get_value(v))
|
||||||
.map(AnyEntity::Value)
|
.map(AnyEntity::Value)
|
||||||
}
|
}
|
||||||
"vx" => {
|
"vx" => {
|
||||||
Value::table_with_number(num)
|
Value::table_with_number(num)
|
||||||
.and_then(|v| self.values.get(&v).cloned())
|
.and_then(|v| self.get_value(v))
|
||||||
.map(AnyEntity::Value)
|
.map(AnyEntity::Value)
|
||||||
}
|
}
|
||||||
"ebb" => {
|
"ebb" => Ebb::with_number(num).and_then(|e| self.get_ebb(e)).map(AnyEntity::Ebb),
|
||||||
Ebb::with_number(num)
|
"ss" => self.get_ss(num).map(AnyEntity::StackSlot),
|
||||||
.and_then(|e| self.ebbs.get(&e).cloned())
|
"jt" => self.get_jt(num).map(AnyEntity::JumpTable),
|
||||||
.map(AnyEntity::Ebb)
|
|
||||||
}
|
|
||||||
"ss" => self.stack_slots.get(&num).cloned().map(AnyEntity::StackSlot),
|
|
||||||
"jt" => self.jump_tables.get(&num).cloned().map(AnyEntity::JumpTable),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rewrite an Ebb reference.
|
||||||
|
pub fn rewrite_ebb(&self, ebb: &mut Ebb, loc: &Location) -> Result<()> {
|
||||||
|
match self.get_ebb(*ebb) {
|
||||||
|
Some(new) => {
|
||||||
|
*ebb = new;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
None => err!(loc, "undefined reference: {}", ebb),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rewrite a value reference.
|
||||||
|
pub fn rewrite_value(&self, val: &mut Value, loc: &Location) -> Result<()> {
|
||||||
|
match self.get_value(*val) {
|
||||||
|
Some(new) => {
|
||||||
|
*val = new;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
None => err!(loc, "undefined reference: {}", val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rewrite a slice of value references.
|
||||||
|
pub fn rewrite_values(&self, vals: &mut [Value], loc: &Location) -> Result<()> {
|
||||||
|
for val in vals {
|
||||||
|
try!(self.rewrite_value(val, loc));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of decimal digits at the end of `s`.
|
/// Get the number of decimal digits at the end of `s`.
|
||||||
@@ -67,17 +114,60 @@ fn split_entity_name(name: &str) -> Option<(&str, u32)> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new SourceMap from all the individual mappings.
|
|
||||||
pub fn new(values: HashMap<Value, Value>,
|
/// Interface for mutating a source map.
|
||||||
ebbs: HashMap<Ebb, Ebb>,
|
///
|
||||||
stack_slots: HashMap<u32, StackSlot>,
|
/// This interface is provided for the parser itself, it is not made available outside the crate.
|
||||||
jump_tables: HashMap<u32, JumpTable>)
|
pub trait MutableSourceMap {
|
||||||
-> SourceMap {
|
fn new() -> Self;
|
||||||
|
|
||||||
|
/// Define a value mapping from the source name `src` to the final `entity`.
|
||||||
|
fn def_value(&mut self, src: Value, entity: Value, loc: &Location) -> Result<()>;
|
||||||
|
fn def_ebb(&mut self, src: Ebb, entity: Ebb, loc: &Location) -> Result<()>;
|
||||||
|
fn def_ss(&mut self, src_num: u32, entity: StackSlot, loc: &Location) -> Result<()>;
|
||||||
|
fn def_jt(&mut self, src_num: u32, entity: JumpTable, loc: &Location) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MutableSourceMap for SourceMap {
|
||||||
|
fn new() -> SourceMap {
|
||||||
SourceMap {
|
SourceMap {
|
||||||
values: values,
|
values: HashMap::new(),
|
||||||
ebbs: ebbs,
|
ebbs: HashMap::new(),
|
||||||
stack_slots: stack_slots,
|
stack_slots: HashMap::new(),
|
||||||
jump_tables: jump_tables,
|
jump_tables: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_value(&mut self, src: Value, entity: Value, loc: &Location) -> Result<()> {
|
||||||
|
if self.values.insert(src, entity).is_some() {
|
||||||
|
err!(loc, "duplicate value: {}", src)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_ebb(&mut self, src: Ebb, entity: Ebb, loc: &Location) -> Result<()> {
|
||||||
|
if self.ebbs.insert(src, entity).is_some() {
|
||||||
|
err!(loc, "duplicate EBB: {}", src)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_ss(&mut self, src_num: u32, entity: StackSlot, loc: &Location) -> Result<()> {
|
||||||
|
if self.stack_slots.insert(src_num, entity).is_some() {
|
||||||
|
err!(loc, "duplicate stack slot: ss{}", src_num)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_jt(&mut self, src_num: u32, entity: JumpTable, loc: &Location) -> Result<()> {
|
||||||
|
if self.jump_tables.insert(src_num, entity).is_some() {
|
||||||
|
err!(loc, "duplicate jump table: jt{}", src_num)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user