Lint fixes (#99)
* Replace a single-character string literal with a character literal. * Use is_some() instead of comparing with Some(_). * Add code-quotes around type names in comments. * Use !...is_empty() instead of len() != 0. * Tidy up redundant returns. * Remove redundant .clone() calls. * Remove unnecessary explicit lifetime parameters. * Tidy up unnecessary '&'s. * Add parens to make operator precedence explicit. * Use debug_assert_eq instead of debug_assert with ==. * Replace a &Vec argument with a &[...]. * Replace `a = a op b` with `a op= b`. * Avoid unnecessary closures. * Avoid .iter() and .iter_mut() for iterating over containers. * Remove unneeded qualification.
This commit is contained in:
committed by
Jakob Stoklund Olesen
parent
3693735874
commit
0c7316ae28
@@ -60,7 +60,7 @@ impl Context {
|
|||||||
///
|
///
|
||||||
/// The `isa` argument is currently unused, but the verifier will soon be able to also
|
/// The `isa` argument is currently unused, but the verifier will soon be able to also
|
||||||
/// check ISA-dependent constraints.
|
/// check ISA-dependent constraints.
|
||||||
pub fn verify<'a>(&self, isa: Option<&TargetIsa>) -> verifier::Result {
|
pub fn verify(&self, isa: Option<&TargetIsa>) -> verifier::Result {
|
||||||
verifier::verify_context(&self.func, &self.cfg, &self.domtree, isa)
|
verifier::verify_context(&self.func, &self.cfg, &self.domtree, isa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,17 +88,17 @@ impl CondCode for IntCC {
|
|||||||
impl Display for IntCC {
|
impl Display for IntCC {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use self::IntCC::*;
|
use self::IntCC::*;
|
||||||
f.write_str(match self {
|
f.write_str(match *self {
|
||||||
&Equal => "eq",
|
Equal => "eq",
|
||||||
&NotEqual => "ne",
|
NotEqual => "ne",
|
||||||
&SignedGreaterThan => "sgt",
|
SignedGreaterThan => "sgt",
|
||||||
&SignedGreaterThanOrEqual => "sge",
|
SignedGreaterThanOrEqual => "sge",
|
||||||
&SignedLessThan => "slt",
|
SignedLessThan => "slt",
|
||||||
&SignedLessThanOrEqual => "sle",
|
SignedLessThanOrEqual => "sle",
|
||||||
&UnsignedGreaterThan => "ugt",
|
UnsignedGreaterThan => "ugt",
|
||||||
&UnsignedGreaterThanOrEqual => "uge",
|
UnsignedGreaterThanOrEqual => "uge",
|
||||||
&UnsignedLessThan => "ult",
|
UnsignedLessThan => "ult",
|
||||||
&UnsignedLessThanOrEqual => "ule",
|
UnsignedLessThanOrEqual => "ule",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,21 +219,21 @@ impl CondCode for FloatCC {
|
|||||||
impl Display for FloatCC {
|
impl Display for FloatCC {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
use self::FloatCC::*;
|
use self::FloatCC::*;
|
||||||
f.write_str(match self {
|
f.write_str(match *self {
|
||||||
&Ordered => "ord",
|
Ordered => "ord",
|
||||||
&Unordered => "uno",
|
Unordered => "uno",
|
||||||
&Equal => "eq",
|
Equal => "eq",
|
||||||
&NotEqual => "ne",
|
NotEqual => "ne",
|
||||||
&OrderedNotEqual => "one",
|
OrderedNotEqual => "one",
|
||||||
&UnorderedOrEqual => "ueq",
|
UnorderedOrEqual => "ueq",
|
||||||
&LessThan => "lt",
|
LessThan => "lt",
|
||||||
&LessThanOrEqual => "le",
|
LessThanOrEqual => "le",
|
||||||
&GreaterThan => "gt",
|
GreaterThan => "gt",
|
||||||
&GreaterThanOrEqual => "ge",
|
GreaterThanOrEqual => "ge",
|
||||||
&UnorderedOrLessThan => "ult",
|
UnorderedOrLessThan => "ult",
|
||||||
&UnorderedOrLessThanOrEqual => "ule",
|
UnorderedOrLessThanOrEqual => "ule",
|
||||||
&UnorderedOrGreaterThan => "ugt",
|
UnorderedOrGreaterThan => "ugt",
|
||||||
&UnorderedOrGreaterThanOrEqual => "uge",
|
UnorderedOrGreaterThanOrEqual => "uge",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,10 +247,11 @@ impl DataFlowGraph {
|
|||||||
// Try to create short alias chains by finding the original source value.
|
// Try to create short alias chains by finding the original source value.
|
||||||
// This also avoids the creation of loops.
|
// This also avoids the creation of loops.
|
||||||
let original = self.resolve_aliases(src);
|
let original = self.resolve_aliases(src);
|
||||||
assert!(dest != original,
|
assert_ne!(dest,
|
||||||
"Aliasing {} to {} would create a loop",
|
original,
|
||||||
dest,
|
"Aliasing {} to {} would create a loop",
|
||||||
src);
|
dest,
|
||||||
|
src);
|
||||||
let ty = self.value_type(original);
|
let ty = self.value_type(original);
|
||||||
assert_eq!(self.value_type(dest),
|
assert_eq!(self.value_type(dest),
|
||||||
ty,
|
ty,
|
||||||
@@ -326,8 +327,8 @@ pub enum ValueDef {
|
|||||||
impl ValueDef {
|
impl ValueDef {
|
||||||
/// Unwrap the instruction where the value was defined, or panic.
|
/// Unwrap the instruction where the value was defined, or panic.
|
||||||
pub fn unwrap_inst(&self) -> Inst {
|
pub fn unwrap_inst(&self) -> Inst {
|
||||||
match self {
|
match *self {
|
||||||
&ValueDef::Res(inst, _) => inst,
|
ValueDef::Res(inst, _) => inst,
|
||||||
_ => panic!("Value is not an instruction result"),
|
_ => panic!("Value is not an instruction result"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ impl Signature {
|
|||||||
pub struct DisplaySignature<'a>(&'a Signature, Option<&'a RegInfo>);
|
pub struct DisplaySignature<'a>(&'a Signature, Option<&'a RegInfo>);
|
||||||
|
|
||||||
fn write_list(f: &mut fmt::Formatter,
|
fn write_list(f: &mut fmt::Formatter,
|
||||||
args: &Vec<ArgumentType>,
|
args: &[ArgumentType],
|
||||||
regs: Option<&RegInfo>)
|
regs: Option<&RegInfo>)
|
||||||
-> fmt::Result {
|
-> fmt::Result {
|
||||||
match args.split_first() {
|
match args.split_first() {
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ fn format_float(bits: u64, w: u8, t: u8, f: &mut Formatter) -> fmt::Result {
|
|||||||
let max_e_bits = (1u64 << w) - 1;
|
let max_e_bits = (1u64 << w) - 1;
|
||||||
let t_bits = bits & ((1u64 << t) - 1); // Trailing significand.
|
let t_bits = bits & ((1u64 << t) - 1); // Trailing significand.
|
||||||
let e_bits = (bits >> t) & max_e_bits; // Biased exponent.
|
let e_bits = (bits >> t) & max_e_bits; // Biased exponent.
|
||||||
let sign_bit = (bits >> w + t) & 1;
|
let sign_bit = (bits >> (w + t)) & 1;
|
||||||
|
|
||||||
let bias: i32 = (1 << (w - 1)) - 1;
|
let bias: i32 = (1 << (w - 1)) - 1;
|
||||||
let e = e_bits as i32 - bias; // Unbiased exponent.
|
let e = e_bits as i32 - bias; // Unbiased exponent.
|
||||||
@@ -381,7 +381,7 @@ fn parse_float(s: &str, w: u8, t: u8) -> Result<u64, &'static str> {
|
|||||||
debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
|
debug_assert!((t + w + 1).is_power_of_two(), "Unexpected IEEE format size");
|
||||||
|
|
||||||
let (sign_bit, s2) = if s.starts_with('-') {
|
let (sign_bit, s2) = if s.starts_with('-') {
|
||||||
(1u64 << t + w, &s[1..])
|
(1u64 << (t + w), &s[1..])
|
||||||
} else if s.starts_with('+') {
|
} else if s.starts_with('+') {
|
||||||
(0, &s[1..])
|
(0, &s[1..])
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -286,23 +286,23 @@ impl InstructionData {
|
|||||||
/// Any instruction that can transfer control to another EBB reveals its possible destinations
|
/// Any instruction that can transfer control to another EBB reveals its possible destinations
|
||||||
/// here.
|
/// here.
|
||||||
pub fn analyze_branch<'a>(&'a self, pool: &'a ValueListPool) -> BranchInfo<'a> {
|
pub fn analyze_branch<'a>(&'a self, pool: &'a ValueListPool) -> BranchInfo<'a> {
|
||||||
match self {
|
match *self {
|
||||||
&InstructionData::Jump {
|
InstructionData::Jump {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)),
|
} => BranchInfo::SingleDest(destination, args.as_slice(pool)),
|
||||||
&InstructionData::Branch {
|
InstructionData::Branch {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[1..]),
|
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[1..]),
|
||||||
&InstructionData::BranchIcmp {
|
InstructionData::BranchIcmp {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[2..]),
|
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[2..]),
|
||||||
&InstructionData::BranchTable { table, .. } => BranchInfo::Table(table),
|
InstructionData::BranchTable { table, .. } => BranchInfo::Table(table),
|
||||||
_ => BranchInfo::NotABranch,
|
_ => BranchInfo::NotABranch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,10 +312,10 @@ impl InstructionData {
|
|||||||
///
|
///
|
||||||
/// Multi-destination branches like `br_table` return `None`.
|
/// Multi-destination branches like `br_table` return `None`.
|
||||||
pub fn branch_destination(&self) -> Option<Ebb> {
|
pub fn branch_destination(&self) -> Option<Ebb> {
|
||||||
match self {
|
match *self {
|
||||||
&InstructionData::Jump { destination, .. } => Some(destination),
|
InstructionData::Jump { destination, .. } => Some(destination),
|
||||||
&InstructionData::Branch { destination, .. } => Some(destination),
|
InstructionData::Branch { destination, .. } => Some(destination),
|
||||||
&InstructionData::BranchIcmp { destination, .. } => Some(destination),
|
InstructionData::BranchIcmp { destination, .. } => Some(destination),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,11 +337,11 @@ impl InstructionData {
|
|||||||
///
|
///
|
||||||
/// Any instruction that can call another function reveals its call signature here.
|
/// Any instruction that can call another function reveals its call signature here.
|
||||||
pub fn analyze_call<'a>(&'a self, pool: &'a ValueListPool) -> CallInfo<'a> {
|
pub fn analyze_call<'a>(&'a self, pool: &'a ValueListPool) -> CallInfo<'a> {
|
||||||
match self {
|
match *self {
|
||||||
&InstructionData::Call { func_ref, ref args, .. } => {
|
InstructionData::Call { func_ref, ref args, .. } => {
|
||||||
CallInfo::Direct(func_ref, &args.as_slice(pool))
|
CallInfo::Direct(func_ref, args.as_slice(pool))
|
||||||
}
|
}
|
||||||
&InstructionData::IndirectCall { sig_ref, ref args, .. } => {
|
InstructionData::IndirectCall { sig_ref, ref args, .. } => {
|
||||||
CallInfo::Indirect(sig_ref, &args.as_slice(pool)[1..])
|
CallInfo::Indirect(sig_ref, &args.as_slice(pool)[1..])
|
||||||
}
|
}
|
||||||
_ => CallInfo::NotACall,
|
_ => CallInfo::NotACall,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ impl JumpTableData {
|
|||||||
/// Enumerate over all `(idx, dest)` pairs in the table in order.
|
/// Enumerate over all `(idx, dest)` pairs in the table in order.
|
||||||
///
|
///
|
||||||
/// This returns an iterator that skips any empty slots in the table.
|
/// This returns an iterator that skips any empty slots in the table.
|
||||||
pub fn entries<'a>(&'a self) -> Entries {
|
pub fn entries(&self) -> Entries {
|
||||||
Entries(self.table.iter().cloned().enumerate())
|
Entries(self.table.iter().cloned().enumerate())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,16 +98,16 @@ impl Default for ArgumentLoc {
|
|||||||
impl ArgumentLoc {
|
impl ArgumentLoc {
|
||||||
/// Is this an assigned location? (That is, not `Unassigned`).
|
/// Is this an assigned location? (That is, not `Unassigned`).
|
||||||
pub fn is_assigned(&self) -> bool {
|
pub fn is_assigned(&self) -> bool {
|
||||||
match self {
|
match *self {
|
||||||
&ArgumentLoc::Unassigned => false,
|
ArgumentLoc::Unassigned => false,
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a register location?
|
/// Is this a register location?
|
||||||
pub fn is_reg(&self) -> bool {
|
pub fn is_reg(&self) -> bool {
|
||||||
match self {
|
match *self {
|
||||||
&ArgumentLoc::Reg(_) => true,
|
ArgumentLoc::Reg(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ pub static RELOC_NAMES: [&'static str; 1] = ["Call"];
|
|||||||
|
|
||||||
// Emit single-byte opcode.
|
// Emit single-byte opcode.
|
||||||
fn put_op1<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
|
fn put_op1<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
|
||||||
debug_assert!(bits & 0x0f00 == 0, "Invalid encoding bits for Op1*");
|
debug_assert_eq!(bits & 0x0f00, 0, "Invalid encoding bits for Op1*");
|
||||||
sink.put1(bits as u8);
|
sink.put1(bits as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit two-byte opcode: 0F XX
|
// Emit two-byte opcode: 0F XX
|
||||||
fn put_op2<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
|
fn put_op2<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
|
||||||
debug_assert!(bits & 0x0f00 == 0x0400, "Invalid encoding bits for Op2*");
|
debug_assert_eq!(bits & 0x0f00, 0x0400, "Invalid encoding bits for Op2*");
|
||||||
sink.put1(0x0f);
|
sink.put1(0x0f);
|
||||||
sink.put1(bits as u8);
|
sink.put1(bits as u8);
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ const PREFIX: [u8; 3] = [0x66, 0xf3, 0xf2];
|
|||||||
|
|
||||||
// Emit single-byte opcode with mandatory prefix.
|
// Emit single-byte opcode with mandatory prefix.
|
||||||
fn put_mp1<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
|
fn put_mp1<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
|
||||||
debug_assert!(bits & 0x0c00 == 0, "Invalid encoding bits for Mp1*");
|
debug_assert_eq!(bits & 0x0c00, 0, "Invalid encoding bits for Mp1*");
|
||||||
let pp = (bits >> 8) & 3;
|
let pp = (bits >> 8) & 3;
|
||||||
sink.put1(PREFIX[(pp - 1) as usize]);
|
sink.put1(PREFIX[(pp - 1) as usize]);
|
||||||
sink.put1(bits as u8);
|
sink.put1(bits as u8);
|
||||||
|
|||||||
@@ -21,18 +21,13 @@ pub fn do_licm(func: &mut Function,
|
|||||||
let invariant_inst = remove_loop_invariant_instructions(lp, func, cfg, loop_analysis);
|
let invariant_inst = remove_loop_invariant_instructions(lp, func, cfg, loop_analysis);
|
||||||
// Then we create the loop's pre-header and fill it with the invariant instructions
|
// Then we create the loop's pre-header and fill it with the invariant instructions
|
||||||
// Then we remove the invariant instructions from the loop body
|
// Then we remove the invariant instructions from the loop body
|
||||||
if invariant_inst.len() > 0 {
|
if !invariant_inst.is_empty() {
|
||||||
// If the loop has a natural pre-header we use it, otherwise we create it.
|
// If the loop has a natural pre-header we use it, otherwise we create it.
|
||||||
let mut pos;
|
let mut pos;
|
||||||
match has_pre_header(&func.layout,
|
match has_pre_header(&func.layout, cfg, domtree, loop_analysis.loop_header(lp)) {
|
||||||
cfg,
|
|
||||||
domtree,
|
|
||||||
loop_analysis.loop_header(lp).clone()) {
|
|
||||||
None => {
|
None => {
|
||||||
let pre_header = create_pre_header(loop_analysis.loop_header(lp).clone(),
|
let pre_header =
|
||||||
func,
|
create_pre_header(loop_analysis.loop_header(lp), func, cfg, domtree);
|
||||||
cfg,
|
|
||||||
domtree);
|
|
||||||
pos = Cursor::new(&mut func.layout);
|
pos = Cursor::new(&mut func.layout);
|
||||||
pos.goto_bottom(pre_header);
|
pos.goto_bottom(pre_header);
|
||||||
pos.prev_inst();
|
pos.prev_inst();
|
||||||
@@ -47,7 +42,7 @@ pub fn do_licm(func: &mut Function,
|
|||||||
// The last instruction of the pre-header is the termination instruction (usually
|
// The last instruction of the pre-header is the termination instruction (usually
|
||||||
// a jump) so we need to insert just before this.
|
// a jump) so we need to insert just before this.
|
||||||
for inst in invariant_inst {
|
for inst in invariant_inst {
|
||||||
pos.insert_inst(inst.clone());
|
pos.insert_inst(inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,7 +141,7 @@ fn remove_loop_invariant_instructions(lp: Loop,
|
|||||||
for ebb in postorder_ebbs_loop(loop_analysis, cfg, lp).iter().rev() {
|
for ebb in postorder_ebbs_loop(loop_analysis, cfg, lp).iter().rev() {
|
||||||
// Arguments of the EBB are loop values
|
// Arguments of the EBB are loop values
|
||||||
for val in func.dfg.ebb_args(*ebb) {
|
for val in func.dfg.ebb_args(*ebb) {
|
||||||
loop_values.insert(val.clone());
|
loop_values.insert(*val);
|
||||||
}
|
}
|
||||||
pos.goto_top(*ebb);
|
pos.goto_top(*ebb);
|
||||||
while let Some(inst) = pos.next_inst() {
|
while let Some(inst) = pos.next_inst() {
|
||||||
@@ -164,7 +159,7 @@ fn remove_loop_invariant_instructions(lp: Loop,
|
|||||||
// If the instruction is not loop-invariant we push its results in the set of
|
// If the instruction is not loop-invariant we push its results in the set of
|
||||||
// loop values
|
// loop values
|
||||||
for out in func.dfg.inst_results(inst) {
|
for out in func.dfg.inst_results(inst) {
|
||||||
loop_values.insert(out.clone());
|
loop_values.insert(*out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +171,7 @@ fn remove_loop_invariant_instructions(lp: Loop,
|
|||||||
fn postorder_ebbs_loop(loop_analysis: &LoopAnalysis, cfg: &ControlFlowGraph, lp: Loop) -> Vec<Ebb> {
|
fn postorder_ebbs_loop(loop_analysis: &LoopAnalysis, cfg: &ControlFlowGraph, lp: Loop) -> Vec<Ebb> {
|
||||||
let mut grey = HashSet::new();
|
let mut grey = HashSet::new();
|
||||||
let mut black = HashSet::new();
|
let mut black = HashSet::new();
|
||||||
let mut stack = vec![loop_analysis.loop_header(lp).clone()];
|
let mut stack = vec![loop_analysis.loop_header(lp)];
|
||||||
let mut postorder = Vec::new();
|
let mut postorder = Vec::new();
|
||||||
|
|
||||||
while !stack.is_empty() {
|
while !stack.is_empty() {
|
||||||
@@ -187,13 +182,13 @@ fn postorder_ebbs_loop(loop_analysis: &LoopAnalysis, cfg: &ControlFlowGraph, lp:
|
|||||||
stack.push(node);
|
stack.push(node);
|
||||||
// Get any children we've never seen before.
|
// Get any children we've never seen before.
|
||||||
for child in cfg.get_successors(node) {
|
for child in cfg.get_successors(node) {
|
||||||
if loop_analysis.is_in_loop(child.clone(), lp) && !grey.contains(child) {
|
if loop_analysis.is_in_loop(*child, lp) && !grey.contains(child) {
|
||||||
stack.push(child.clone());
|
stack.push(*child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !black.contains(&node) {
|
} else if !black.contains(&node) {
|
||||||
postorder.push(node.clone());
|
postorder.push(node);
|
||||||
black.insert(node.clone());
|
black.insert(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postorder
|
postorder
|
||||||
|
|||||||
@@ -50,14 +50,14 @@ impl AllocatableSet {
|
|||||||
/// It is an error to take a register that doesn't have all of its register units available.
|
/// It is an error to take a register that doesn't have all of its register units available.
|
||||||
pub fn take(&mut self, rc: RegClass, reg: RegUnit) {
|
pub fn take(&mut self, rc: RegClass, reg: RegUnit) {
|
||||||
let (idx, bits) = bitmask(rc, reg);
|
let (idx, bits) = bitmask(rc, reg);
|
||||||
debug_assert!((self.avail[idx] & bits) == bits, "Not available");
|
debug_assert_eq!(self.avail[idx] & bits, bits, "Not available");
|
||||||
self.avail[idx] &= !bits;
|
self.avail[idx] &= !bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make `reg` available for allocation again.
|
/// Make `reg` available for allocation again.
|
||||||
pub fn free(&mut self, rc: RegClass, reg: RegUnit) {
|
pub fn free(&mut self, rc: RegClass, reg: RegUnit) {
|
||||||
let (idx, bits) = bitmask(rc, reg);
|
let (idx, bits) = bitmask(rc, reg);
|
||||||
debug_assert!((self.avail[idx] & bits) == 0, "Not allocated");
|
debug_assert_eq!(self.avail[idx] & bits, 0, "Not allocated");
|
||||||
self.avail[idx] |= bits;
|
self.avail[idx] |= bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ impl Iterator for RegSetIter {
|
|||||||
let unit = unit_offset + word.trailing_zeros() as RegUnit;
|
let unit = unit_offset + word.trailing_zeros() as RegUnit;
|
||||||
|
|
||||||
// Clear that lowest bit so we won't find it again.
|
// Clear that lowest bit so we won't find it again.
|
||||||
*word = *word & (*word - 1);
|
*word &= *word - 1;
|
||||||
|
|
||||||
return Some(unit);
|
return Some(unit);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ impl Pressure {
|
|||||||
|
|
||||||
/// Reset all counts to 0, both base and transient.
|
/// Reset all counts to 0, both base and transient.
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
for e in self.toprc.iter_mut() {
|
for e in &mut self.toprc {
|
||||||
e.base_count = 0;
|
e.base_count = 0;
|
||||||
e.transient_count = 0;
|
e.transient_count = 0;
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ impl Pressure {
|
|||||||
|
|
||||||
/// Reset all transient counts to 0.
|
/// Reset all transient counts to 0.
|
||||||
pub fn reset_transient(&mut self) {
|
pub fn reset_transient(&mut self) {
|
||||||
for e in self.toprc.iter_mut() {
|
for e in &mut self.toprc {
|
||||||
e.transient_count = 0;
|
e.transient_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ impl<'a> Context<'a> {
|
|||||||
// Create a live range for the new reload.
|
// Create a live range for the new reload.
|
||||||
let affinity = Affinity::Reg(cand.regclass.into());
|
let affinity = Affinity::Reg(cand.regclass.into());
|
||||||
self.liveness.create_dead(reg, dfg.value_def(reg), affinity);
|
self.liveness.create_dead(reg, dfg.value_def(reg), affinity);
|
||||||
self.liveness.extend_locally(reg, ebb, inst, &pos.layout);
|
self.liveness.extend_locally(reg, ebb, inst, pos.layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite arguments.
|
// Rewrite arguments.
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ impl<'a> Context<'a> {
|
|||||||
// Add register def to pressure, spill if needed.
|
// Add register def to pressure, spill if needed.
|
||||||
while let Err(mask) = self.pressure.take_transient(op.regclass) {
|
while let Err(mask) = self.pressure.take_transient(op.regclass) {
|
||||||
dbg!("Need {} reg from {} throughs", op.regclass, throughs.len());
|
dbg!("Need {} reg from {} throughs", op.regclass, throughs.len());
|
||||||
self.spill_from(mask, throughs, dfg, &pos.layout);
|
self.spill_from(mask, throughs, dfg, pos.layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
use verifier;
|
use verifier;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::result;
|
|
||||||
|
|
||||||
/// A compilation error.
|
/// A compilation error.
|
||||||
///
|
///
|
||||||
@@ -32,7 +31,7 @@ pub enum CtonError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A Cretonne compilation result.
|
/// A Cretonne compilation result.
|
||||||
pub type CtonResult = result::Result<(), CtonError>;
|
pub type CtonResult = Result<(), CtonError>;
|
||||||
|
|
||||||
impl fmt::Display for CtonError {
|
impl fmt::Display for CtonError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool {
|
|||||||
pub fn do_simple_gvn(func: &mut Function, cfg: &mut ControlFlowGraph) {
|
pub fn do_simple_gvn(func: &mut Function, cfg: &mut ControlFlowGraph) {
|
||||||
let mut visible_values: HashMap<InstructionData, Inst> = HashMap::new();
|
let mut visible_values: HashMap<InstructionData, Inst> = HashMap::new();
|
||||||
|
|
||||||
let domtree = DominatorTree::with_function(func, &cfg);
|
let domtree = DominatorTree::with_function(func, cfg);
|
||||||
|
|
||||||
// Visit EBBs in a reverse post-order.
|
// Visit EBBs in a reverse post-order.
|
||||||
let mut pos = Cursor::new(&mut func.layout);
|
let mut pos = Cursor::new(&mut func.layout);
|
||||||
@@ -47,7 +47,7 @@ pub fn do_simple_gvn(func: &mut Function, cfg: &mut ControlFlowGraph) {
|
|||||||
use std::collections::hash_map::Entry::*;
|
use std::collections::hash_map::Entry::*;
|
||||||
match entry {
|
match entry {
|
||||||
Occupied(mut entry) => {
|
Occupied(mut entry) => {
|
||||||
if domtree.dominates(*entry.get(), inst, &pos.layout) {
|
if domtree.dominates(*entry.get(), inst, pos.layout) {
|
||||||
func.dfg.replace_with_aliases(inst, *entry.get());
|
func.dfg.replace_with_aliases(inst, *entry.get());
|
||||||
pos.remove_inst_and_step_back();
|
pos.remove_inst_and_step_back();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl TopoOrder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.stack.pop();
|
self.stack.pop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -229,21 +229,21 @@ impl<'a> Verifier<'a> {
|
|||||||
self.verify_value(inst, res)?;
|
self.verify_value(inst, res)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
match &self.func.dfg[inst] {
|
match self.func.dfg[inst] {
|
||||||
&MultiAry { ref args, .. } => {
|
MultiAry { ref args, .. } => {
|
||||||
self.verify_value_list(inst, args)?;
|
self.verify_value_list(inst, args)?;
|
||||||
}
|
}
|
||||||
&Jump {
|
Jump {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} |
|
} |
|
||||||
&Branch {
|
Branch {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} |
|
} |
|
||||||
&BranchIcmp {
|
BranchIcmp {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
@@ -251,41 +251,41 @@ impl<'a> Verifier<'a> {
|
|||||||
self.verify_ebb(inst, destination)?;
|
self.verify_ebb(inst, destination)?;
|
||||||
self.verify_value_list(inst, args)?;
|
self.verify_value_list(inst, args)?;
|
||||||
}
|
}
|
||||||
&BranchTable { table, .. } => {
|
BranchTable { table, .. } => {
|
||||||
self.verify_jump_table(inst, table)?;
|
self.verify_jump_table(inst, table)?;
|
||||||
}
|
}
|
||||||
&Call { func_ref, ref args, .. } => {
|
Call { func_ref, ref args, .. } => {
|
||||||
self.verify_func_ref(inst, func_ref)?;
|
self.verify_func_ref(inst, func_ref)?;
|
||||||
self.verify_value_list(inst, args)?;
|
self.verify_value_list(inst, args)?;
|
||||||
}
|
}
|
||||||
&IndirectCall { sig_ref, ref args, .. } => {
|
IndirectCall { sig_ref, ref args, .. } => {
|
||||||
self.verify_sig_ref(inst, sig_ref)?;
|
self.verify_sig_ref(inst, sig_ref)?;
|
||||||
self.verify_value_list(inst, args)?;
|
self.verify_value_list(inst, args)?;
|
||||||
}
|
}
|
||||||
&StackLoad { stack_slot, .. } |
|
StackLoad { stack_slot, .. } |
|
||||||
&StackStore { stack_slot, .. } => {
|
StackStore { stack_slot, .. } => {
|
||||||
self.verify_stack_slot(inst, stack_slot)?;
|
self.verify_stack_slot(inst, stack_slot)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exhaustive list so we can't forget to add new formats
|
// Exhaustive list so we can't forget to add new formats
|
||||||
&Nullary { .. } |
|
Nullary { .. } |
|
||||||
&Unary { .. } |
|
Unary { .. } |
|
||||||
&UnaryImm { .. } |
|
UnaryImm { .. } |
|
||||||
&UnaryIeee32 { .. } |
|
UnaryIeee32 { .. } |
|
||||||
&UnaryIeee64 { .. } |
|
UnaryIeee64 { .. } |
|
||||||
&Binary { .. } |
|
Binary { .. } |
|
||||||
&BinaryImm { .. } |
|
BinaryImm { .. } |
|
||||||
&Ternary { .. } |
|
Ternary { .. } |
|
||||||
&InsertLane { .. } |
|
InsertLane { .. } |
|
||||||
&ExtractLane { .. } |
|
ExtractLane { .. } |
|
||||||
&IntCompare { .. } |
|
IntCompare { .. } |
|
||||||
&IntCompareImm { .. } |
|
IntCompareImm { .. } |
|
||||||
&FloatCompare { .. } |
|
FloatCompare { .. } |
|
||||||
&HeapLoad { .. } |
|
HeapLoad { .. } |
|
||||||
&HeapStore { .. } |
|
HeapStore { .. } |
|
||||||
&Load { .. } |
|
Load { .. } |
|
||||||
&Store { .. } |
|
Store { .. } |
|
||||||
&RegMove { .. } => {}
|
RegMove { .. } => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -627,14 +627,14 @@ impl<'a> Verifier<'a> {
|
|||||||
got_succs.extend(cfg.get_successors(ebb));
|
got_succs.extend(cfg.get_successors(ebb));
|
||||||
|
|
||||||
let missing_succs: Vec<Ebb> = expected_succs.difference(&got_succs).cloned().collect();
|
let missing_succs: Vec<Ebb> = expected_succs.difference(&got_succs).cloned().collect();
|
||||||
if missing_succs.len() != 0 {
|
if !missing_succs.is_empty() {
|
||||||
return err!(ebb,
|
return err!(ebb,
|
||||||
"cfg lacked the following successor(s) {:?}",
|
"cfg lacked the following successor(s) {:?}",
|
||||||
missing_succs);
|
missing_succs);
|
||||||
}
|
}
|
||||||
|
|
||||||
let excess_succs: Vec<Ebb> = got_succs.difference(&expected_succs).cloned().collect();
|
let excess_succs: Vec<Ebb> = got_succs.difference(&expected_succs).cloned().collect();
|
||||||
if excess_succs.len() != 0 {
|
if !excess_succs.is_empty() {
|
||||||
return err!(ebb, "cfg had unexpected successor(s) {:?}", excess_succs);
|
return err!(ebb, "cfg had unexpected successor(s) {:?}", excess_succs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,14 +642,14 @@ impl<'a> Verifier<'a> {
|
|||||||
got_preds.extend(cfg.get_predecessors(ebb).iter().map(|&(_, inst)| inst));
|
got_preds.extend(cfg.get_predecessors(ebb).iter().map(|&(_, inst)| inst));
|
||||||
|
|
||||||
let missing_preds: Vec<Inst> = expected_preds.difference(&got_preds).cloned().collect();
|
let missing_preds: Vec<Inst> = expected_preds.difference(&got_preds).cloned().collect();
|
||||||
if missing_preds.len() != 0 {
|
if !missing_preds.is_empty() {
|
||||||
return err!(ebb,
|
return err!(ebb,
|
||||||
"cfg lacked the following predecessor(s) {:?}",
|
"cfg lacked the following predecessor(s) {:?}",
|
||||||
missing_preds);
|
missing_preds);
|
||||||
}
|
}
|
||||||
|
|
||||||
let excess_preds: Vec<Inst> = got_preds.difference(&expected_preds).cloned().collect();
|
let excess_preds: Vec<Inst> = got_preds.difference(&expected_preds).cloned().collect();
|
||||||
if excess_preds.len() != 0 {
|
if !excess_preds.is_empty() {
|
||||||
return err!(ebb, "cfg had unexpected predecessor(s) {:?}", excess_preds);
|
return err!(ebb, "cfg had unexpected predecessor(s) {:?}", excess_preds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ impl Directive {
|
|||||||
return Err(Error::Syntax(format!("invalid variable name in regex: {}", rest)));
|
return Err(Error::Syntax(format!("invalid variable name in regex: {}", rest)));
|
||||||
}
|
}
|
||||||
let var = rest[0..varlen].to_string();
|
let var = rest[0..varlen].to_string();
|
||||||
if !rest[varlen..].starts_with("=") {
|
if !rest[varlen..].starts_with('=') {
|
||||||
return Err(Error::Syntax(format!("expected '=' after variable '{}' in regex: {}",
|
return Err(Error::Syntax(format!("expected '=' after variable '{}' in regex: {}",
|
||||||
var,
|
var,
|
||||||
rest)));
|
rest)));
|
||||||
@@ -196,7 +196,7 @@ impl Checker {
|
|||||||
// Check if `pat` matches in `range`.
|
// Check if `pat` matches in `range`.
|
||||||
state.recorder.directive(dct_idx);
|
state.recorder.directive(dct_idx);
|
||||||
if let Some((match_begin, match_end)) = state.match_positive(pat, range)? {
|
if let Some((match_begin, match_end)) = state.match_positive(pat, range)? {
|
||||||
if let &Directive::Unordered(_) = dct {
|
if let Directive::Unordered(_) = *dct {
|
||||||
// This was an unordered unordered match.
|
// This was an unordered unordered match.
|
||||||
// Keep track of the largest matched position, but leave `last_ordered` alone.
|
// Keep track of the largest matched position, but leave `last_ordered` alone.
|
||||||
state.max_match = max(state.max_match, match_end);
|
state.max_match = max(state.max_match, match_end);
|
||||||
@@ -231,7 +231,7 @@ impl Checker {
|
|||||||
// Verify any pending `not:` directives after the last ordered directive.
|
// Verify any pending `not:` directives after the last ordered directive.
|
||||||
for (not_idx, not_begin, rx) in nots.drain(..) {
|
for (not_idx, not_begin, rx) in nots.drain(..) {
|
||||||
state.recorder.directive(not_idx);
|
state.recorder.directive(not_idx);
|
||||||
if let Some(_) = rx.find(&text[not_begin..]) {
|
if rx.find(&text[not_begin..]).is_some() {
|
||||||
// Matched `not:` pattern.
|
// Matched `not:` pattern.
|
||||||
// TODO: Use matched range for an error message.
|
// TODO: Use matched range for an error message.
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
//! A list of directives is typically extracted from a file containing a test case. The test case
|
//! A list of directives is typically extracted from a file containing a test case. The test case
|
||||||
//! is then run through the program under test, and its output matched against the directives.
|
//! is then run through the program under test, and its output matched against the directives.
|
||||||
//!
|
//!
|
||||||
//! See the [CheckerBuilder](struct.CheckerBuilder.html) and [Checker](struct.Checker.html) types
|
//! See the [`CheckerBuilder`](struct.CheckerBuilder.html) and [`Checker`](struct.Checker.html)
|
||||||
//! for the main library API.
|
//! types for the main library API.
|
||||||
//!
|
//!
|
||||||
//! # Directives
|
//! # Directives
|
||||||
//!
|
//!
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ pub enum IsaSpec {
|
|||||||
impl IsaSpec {
|
impl IsaSpec {
|
||||||
/// If the `IsaSpec` contains exactly 1 `TargetIsa` we return a reference to it
|
/// If the `IsaSpec` contains exactly 1 `TargetIsa` we return a reference to it
|
||||||
pub fn unique_isa(&self) -> Option<&TargetIsa> {
|
pub fn unique_isa(&self) -> Option<&TargetIsa> {
|
||||||
if let &IsaSpec::Some(ref isa_vec) = self {
|
if let IsaSpec::Some(ref isa_vec) = *self {
|
||||||
if isa_vec.len() == 1 {
|
if isa_vec.len() == 1 {
|
||||||
return Some(&*isa_vec[0]);
|
return Some(&*isa_vec[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ impl<'a> Lexer<'a> {
|
|||||||
|
|
||||||
// Scan a single-char token.
|
// Scan a single-char token.
|
||||||
fn scan_char(&mut self, tok: Token<'a>) -> Result<LocatedToken<'a>, LocatedError> {
|
fn scan_char(&mut self, tok: Token<'a>) -> Result<LocatedToken<'a>, LocatedError> {
|
||||||
assert!(self.lookahead != None);
|
assert_ne!(self.lookahead, None);
|
||||||
let loc = self.loc();
|
let loc = self.loc();
|
||||||
self.next_ch();
|
self.next_ch();
|
||||||
token(tok, loc)
|
token(tok, loc)
|
||||||
@@ -184,7 +184,7 @@ impl<'a> Lexer<'a> {
|
|||||||
-> Result<LocatedToken<'a>, LocatedError> {
|
-> Result<LocatedToken<'a>, LocatedError> {
|
||||||
let loc = self.loc();
|
let loc = self.loc();
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
assert!(self.lookahead != None);
|
assert_ne!(self.lookahead, None);
|
||||||
self.next_ch();
|
self.next_ch();
|
||||||
}
|
}
|
||||||
token(tok, loc)
|
token(tok, loc)
|
||||||
@@ -206,7 +206,7 @@ impl<'a> Lexer<'a> {
|
|||||||
fn scan_comment(&mut self) -> Result<LocatedToken<'a>, LocatedError> {
|
fn scan_comment(&mut self) -> Result<LocatedToken<'a>, LocatedError> {
|
||||||
let loc = self.loc();
|
let loc = self.loc();
|
||||||
let text = self.rest_of_line();
|
let text = self.rest_of_line();
|
||||||
return token(Token::Comment(text), loc);
|
token(Token::Comment(text), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan a number token which can represent either an integer or floating point number.
|
// Scan a number token which can represent either an integer or floating point number.
|
||||||
@@ -305,8 +305,8 @@ impl<'a> Lexer<'a> {
|
|||||||
// decoded token.
|
// decoded token.
|
||||||
fn numbered_entity(prefix: &str, number: u32) -> Option<Token<'a>> {
|
fn numbered_entity(prefix: &str, number: u32) -> Option<Token<'a>> {
|
||||||
match prefix {
|
match prefix {
|
||||||
"v" => Value::with_number(number).map(|v| Token::Value(v)),
|
"v" => Value::with_number(number).map(Token::Value),
|
||||||
"ebb" => Ebb::with_number(number).map(|ebb| Token::Ebb(ebb)),
|
"ebb" => Ebb::with_number(number).map(Token::Ebb),
|
||||||
"ss" => Some(Token::StackSlot(number)),
|
"ss" => Some(Token::StackSlot(number)),
|
||||||
"jt" => Some(Token::JumpTable(number)),
|
"jt" => Some(Token::JumpTable(number)),
|
||||||
"fn" => Some(Token::FuncRef(number)),
|
"fn" => Some(Token::FuncRef(number)),
|
||||||
@@ -339,7 +339,7 @@ impl<'a> Lexer<'a> {
|
|||||||
};
|
};
|
||||||
if is_vector {
|
if is_vector {
|
||||||
if number <= u16::MAX as u32 {
|
if number <= u16::MAX as u32 {
|
||||||
base_type.by(number as u16).map(|t| Token::Type(t))
|
base_type.by(number as u16).map(Token::Type)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -352,7 +352,7 @@ impl<'a> Lexer<'a> {
|
|||||||
let loc = self.loc();
|
let loc = self.loc();
|
||||||
let begin = self.pos + 1;
|
let begin = self.pos + 1;
|
||||||
|
|
||||||
assert!(self.lookahead == Some('%'));
|
assert_eq!(self.lookahead, Some('%'));
|
||||||
|
|
||||||
while let Some(c) = self.next_ch() {
|
while let Some(c) = self.next_ch() {
|
||||||
if !(c.is_ascii() && c.is_alphanumeric() || c == '_') {
|
if !(c.is_ascii() && c.is_alphanumeric() || c == '_') {
|
||||||
@@ -368,7 +368,7 @@ impl<'a> Lexer<'a> {
|
|||||||
let loc = self.loc();
|
let loc = self.loc();
|
||||||
let begin = self.pos + 1;
|
let begin = self.pos + 1;
|
||||||
|
|
||||||
assert!(self.lookahead == Some('#'));
|
assert_eq!(self.lookahead, Some('#'));
|
||||||
|
|
||||||
while let Some(c) = self.next_ch() {
|
while let Some(c) = self.next_ch() {
|
||||||
if !char::is_digit(c, 16) {
|
if !char::is_digit(c, 16) {
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ impl<'a> Parser<'a> {
|
|||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.lookahead;
|
self.lookahead
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin gathering comments associated with `entity`.
|
// Begin gathering comments associated with `entity`.
|
||||||
@@ -397,7 +397,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
fn error(&self, message: &str) -> Error {
|
fn error(&self, message: &str) -> Error {
|
||||||
Error {
|
Error {
|
||||||
location: self.loc.clone(),
|
location: self.loc,
|
||||||
message: message.to_string(),
|
message: message.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1066,7 +1066,7 @@ impl<'a> Parser<'a> {
|
|||||||
self.consume();
|
self.consume();
|
||||||
self.parse_instruction(results, encoding, result_locations, ctx, ebb)?;
|
self.parse_instruction(results, encoding, result_locations, ctx, ebb)?;
|
||||||
}
|
}
|
||||||
_ if results.len() != 0 => return err!(self.loc, "expected -> or ="),
|
_ if !results.is_empty() => return err!(self.loc, "expected -> or ="),
|
||||||
_ => self.parse_instruction(results, encoding, result_locations, ctx, ebb)?,
|
_ => self.parse_instruction(results, encoding, result_locations, ctx, ebb)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ impl MutableSourceMap for SourceMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()> {
|
fn def_entity(&mut self, entity: AnyEntity, loc: &Location) -> Result<()> {
|
||||||
if self.locations.insert(entity, loc.clone()).is_some() {
|
if self.locations.insert(entity, *loc).is_some() {
|
||||||
err!(loc, "duplicate entity: {}", entity)
|
err!(loc, "duplicate entity: {}", entity)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user