Fix clippy warnings.
This commit fixes the current set of (stable) clippy warnings in the repo.
This commit is contained in:
committed by
Andrew Brown
parent
1176e4f178
commit
9f506692c2
@@ -168,10 +168,12 @@ pub(crate) enum Literal {
|
||||
impl Literal {
|
||||
pub fn enumerator_for(kind: &OperandKind, value: &'static str) -> Self {
|
||||
let value = match &kind.fields {
|
||||
OperandKindFields::ImmEnum(values) => values.get(value).expect(&format!(
|
||||
"nonexistent value '{}' in enumeration '{}'",
|
||||
value, kind.name
|
||||
)),
|
||||
OperandKindFields::ImmEnum(values) => values.get(value).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"nonexistent value '{}' in enumeration '{}'",
|
||||
value, kind.name
|
||||
)
|
||||
}),
|
||||
_ => panic!("enumerator is for enum values"),
|
||||
};
|
||||
Literal::Enumerator {
|
||||
|
||||
@@ -53,7 +53,7 @@ impl CpuMode {
|
||||
Some(typ) => self
|
||||
.typed_legalize
|
||||
.get(typ)
|
||||
.map(|x| *x)
|
||||
.copied()
|
||||
.unwrap_or_else(|| self.get_default_legalize_code()),
|
||||
None => self
|
||||
.monomorphic_legalize
|
||||
|
||||
@@ -61,8 +61,8 @@ impl InstructionGroup {
|
||||
pub fn by_name(&self, name: &'static str) -> &Instruction {
|
||||
self.instructions
|
||||
.iter()
|
||||
.find(|inst| &inst.name == name)
|
||||
.expect(&format!("unexisting instruction with name {}", name))
|
||||
.find(|inst| inst.name == name)
|
||||
.unwrap_or_else(|| panic!("unexisting instruction with name {}", name))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ impl Bindable for Instruction {
|
||||
|
||||
impl fmt::Display for InstructionContent {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
if self.operands_out.len() > 0 {
|
||||
if !self.operands_out.is_empty() {
|
||||
let operands_out = self
|
||||
.operands_out
|
||||
.iter()
|
||||
@@ -180,7 +180,7 @@ impl fmt::Display for InstructionContent {
|
||||
|
||||
fmt.write_str(&self.name)?;
|
||||
|
||||
if self.operands_in.len() > 0 {
|
||||
if !self.operands_in.is_empty() {
|
||||
let operands_in = self
|
||||
.operands_in
|
||||
.iter()
|
||||
@@ -244,53 +244,70 @@ impl InstructionBuilder {
|
||||
self.operands_in = Some(operands.iter().map(|x| (*x).clone()).collect());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn operands_out(mut self, operands: Vec<&Operand>) -> Self {
|
||||
assert!(self.operands_out.is_none());
|
||||
self.operands_out = Some(operands.iter().map(|x| (*x).clone()).collect());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn constraints(mut self, constraints: Vec<Constraint>) -> Self {
|
||||
assert!(self.constraints.is_none());
|
||||
self.constraints = Some(constraints);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_terminator(mut self, val: bool) -> Self {
|
||||
self.is_terminator = val;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_branch(mut self, val: bool) -> Self {
|
||||
self.is_branch = val;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_indirect_branch(mut self, val: bool) -> Self {
|
||||
self.is_indirect_branch = val;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_call(mut self, val: bool) -> Self {
|
||||
self.is_call = val;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_return(mut self, val: bool) -> Self {
|
||||
self.is_return = val;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn is_ghost(mut self, val: bool) -> Self {
|
||||
self.is_ghost = val;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn can_load(mut self, val: bool) -> Self {
|
||||
self.can_load = val;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn can_store(mut self, val: bool) -> Self {
|
||||
self.can_store = val;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn can_trap(mut self, val: bool) -> Self {
|
||||
self.can_trap = val;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn other_side_effects(mut self, val: bool) -> Self {
|
||||
self.other_side_effects = val;
|
||||
self
|
||||
@@ -534,7 +551,7 @@ impl Bindable for BoundInstruction {
|
||||
}
|
||||
|
||||
/// Checks that the input operands actually match the given format.
|
||||
fn verify_format(inst_name: &str, operands_in: &Vec<Operand>, format: &InstructionFormat) {
|
||||
fn verify_format(inst_name: &str, operands_in: &[Operand], format: &InstructionFormat) {
|
||||
// A format is defined by:
|
||||
// - its number of input value operands,
|
||||
// - its number and names of input immediate operands,
|
||||
@@ -586,10 +603,10 @@ fn verify_format(inst_name: &str, operands_in: &Vec<Operand>, format: &Instructi
|
||||
|
||||
/// Check if this instruction is polymorphic, and verify its use of type variables.
|
||||
fn verify_polymorphic(
|
||||
operands_in: &Vec<Operand>,
|
||||
operands_out: &Vec<Operand>,
|
||||
operands_in: &[Operand],
|
||||
operands_out: &[Operand],
|
||||
format: &InstructionFormat,
|
||||
value_opnums: &Vec<usize>,
|
||||
value_opnums: &[usize],
|
||||
) -> Option<PolymorphicInfo> {
|
||||
// The instruction is polymorphic if it has one free input or output operand.
|
||||
let is_polymorphic = operands_in
|
||||
@@ -633,7 +650,7 @@ fn verify_polymorphic(
|
||||
// If we reached here, it means the type variable indicated as the typevar operand couldn't
|
||||
// control every other input and output type variable. We need to look at the result type
|
||||
// variables.
|
||||
if operands_out.len() == 0 {
|
||||
if operands_out.is_empty() {
|
||||
// No result means no other possible type variable, so it's a type inference failure.
|
||||
match maybe_error_message {
|
||||
Some(msg) => panic!(msg),
|
||||
@@ -670,8 +687,8 @@ fn verify_polymorphic(
|
||||
/// Return a vector of other type variables used, or a string explaining what went wrong.
|
||||
fn is_ctrl_typevar_candidate(
|
||||
ctrl_typevar: &TypeVar,
|
||||
operands_in: &Vec<Operand>,
|
||||
operands_out: &Vec<Operand>,
|
||||
operands_in: &[Operand],
|
||||
operands_out: &[Operand],
|
||||
) -> Result<Vec<TypeVar>, String> {
|
||||
let mut other_typevars = Vec::new();
|
||||
|
||||
@@ -995,8 +1012,7 @@ impl InstructionPredicate {
|
||||
.value_opnums
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, &op_num)| inst.operands_in[op_num].type_var().unwrap() == type_var)
|
||||
.next()
|
||||
.find(|(_, &op_num)| inst.operands_in[op_num].type_var().unwrap() == type_var)
|
||||
.unwrap()
|
||||
.0;
|
||||
InstructionPredicateNode::TypePredicate(TypePredicateNode::TypeVarCheck(
|
||||
|
||||
@@ -42,7 +42,7 @@ impl Stack {
|
||||
pub fn new(regclass: RegClassIndex) -> Self {
|
||||
Self { regclass }
|
||||
}
|
||||
pub fn stack_base_mask(&self) -> &'static str {
|
||||
pub fn stack_base_mask(self) -> &'static str {
|
||||
// TODO: Make this configurable instead of just using the SP.
|
||||
"StackBaseMask(1)"
|
||||
}
|
||||
@@ -253,8 +253,8 @@ impl EncodingRecipeBuilder {
|
||||
}
|
||||
|
||||
pub fn build(self) -> EncodingRecipe {
|
||||
let operands_in = self.operands_in.unwrap_or(Vec::new());
|
||||
let operands_out = self.operands_out.unwrap_or(Vec::new());
|
||||
let operands_in = self.operands_in.unwrap_or_default();
|
||||
let operands_out = self.operands_out.unwrap_or_default();
|
||||
|
||||
// The number of input constraints must match the number of format input operands.
|
||||
if !self.format.has_value_list {
|
||||
@@ -282,7 +282,7 @@ impl EncodingRecipeBuilder {
|
||||
let clobbers_flags = self.clobbers_flags.unwrap_or(true);
|
||||
|
||||
EncodingRecipe {
|
||||
name: self.name.into(),
|
||||
name: self.name,
|
||||
format: self.format,
|
||||
base_size: self.base_size,
|
||||
operands_in,
|
||||
|
||||
@@ -164,7 +164,7 @@ impl RegClassBuilder {
|
||||
name,
|
||||
width: 0,
|
||||
count: stop - start,
|
||||
start: start,
|
||||
start,
|
||||
proto: RegClassProto::SubClass(parent_index),
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ impl RegBankBuilder {
|
||||
self
|
||||
}
|
||||
pub fn pinned_reg(mut self, unit: u16) -> Self {
|
||||
assert!(unit < (self.units as u16));
|
||||
assert!(unit < u16::from(self.units));
|
||||
self.pinned_reg = Some(unit);
|
||||
self
|
||||
}
|
||||
@@ -234,7 +234,7 @@ impl IsaRegsBuilder {
|
||||
}
|
||||
|
||||
pub fn add_bank(&mut self, builder: RegBankBuilder) -> RegBankIndex {
|
||||
let first_unit = if self.banks.len() == 0 {
|
||||
let first_unit = if self.banks.is_empty() {
|
||||
0
|
||||
} else {
|
||||
let last = &self.banks.last().unwrap();
|
||||
@@ -358,8 +358,7 @@ impl IsaRegsBuilder {
|
||||
.unwrap()
|
||||
.subclasses
|
||||
.iter()
|
||||
.find(|x| **x == *i2)
|
||||
.is_some());
|
||||
.any(|x| *x == *i2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -402,7 +401,7 @@ impl IsaRegs {
|
||||
self.classes
|
||||
.values()
|
||||
.find(|&class| class.name == name)
|
||||
.expect(&format!("register class {} not found", name))
|
||||
.unwrap_or_else(|| panic!("register class {} not found", name))
|
||||
.index
|
||||
}
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ impl SettingGroupBuilder {
|
||||
default: bool,
|
||||
) -> BoolSettingIndex {
|
||||
assert!(
|
||||
self.predicates.len() == 0,
|
||||
self.predicates.is_empty(),
|
||||
"predicates must be added after the boolean settings"
|
||||
);
|
||||
self.add_setting(name, comment, ProtoSpecificSetting::Bool(default));
|
||||
@@ -379,7 +379,7 @@ impl SettingGroupBuilder {
|
||||
}
|
||||
|
||||
assert!(
|
||||
group.predicates.len() == 0,
|
||||
group.predicates.is_empty(),
|
||||
"settings_size is the byte size before adding predicates"
|
||||
);
|
||||
group.settings_size = group.byte_size();
|
||||
@@ -393,11 +393,11 @@ impl SettingGroupBuilder {
|
||||
.extend(predicates.into_iter().map(|predicate| {
|
||||
let number = predicate_number;
|
||||
predicate_number += 1;
|
||||
return Predicate {
|
||||
Predicate {
|
||||
name: predicate.name,
|
||||
node: predicate.node,
|
||||
number,
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
group.presets.extend(self.presets);
|
||||
|
||||
@@ -74,7 +74,7 @@ impl Constraint {
|
||||
}
|
||||
|
||||
// Trivially false.
|
||||
if (&ts1.lanes & &ts2.lanes).len() == 0 {
|
||||
if (&ts1.lanes & &ts2.lanes).is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -155,12 +155,7 @@ impl TypeEnvironment {
|
||||
}
|
||||
|
||||
fn add_constraint(&mut self, constraint: Constraint) {
|
||||
if self
|
||||
.constraints
|
||||
.iter()
|
||||
.find(|&item| item == &constraint)
|
||||
.is_some()
|
||||
{
|
||||
if self.constraints.iter().any(|item| *item == constraint) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,7 +252,7 @@ impl TypeEnvironment {
|
||||
.map(|tv| self.get_equivalent(tv).free_typevar())
|
||||
.filter(|opt_tv| {
|
||||
// Filter out singleton types.
|
||||
return opt_tv.is_some();
|
||||
opt_tv.is_some()
|
||||
})
|
||||
.map(|tv| tv.unwrap()),
|
||||
);
|
||||
@@ -306,7 +301,7 @@ impl TypeEnvironment {
|
||||
|
||||
children
|
||||
.entry(parent_tv)
|
||||
.or_insert(HashSet::new())
|
||||
.or_insert_with(HashSet::new)
|
||||
.insert(type_var.clone());
|
||||
}
|
||||
|
||||
@@ -314,7 +309,7 @@ impl TypeEnvironment {
|
||||
for (equivalent_tv, canon_tv) in self.equivalency_map.iter() {
|
||||
children
|
||||
.entry(canon_tv.clone())
|
||||
.or_insert(HashSet::new())
|
||||
.or_insert_with(HashSet::new)
|
||||
.insert(equivalent_tv.clone());
|
||||
}
|
||||
|
||||
@@ -604,7 +599,7 @@ fn infer_definition(
|
||||
/// Perform type inference on an transformation. Return an updated type environment or error.
|
||||
pub(crate) fn infer_transform(
|
||||
src: DefIndex,
|
||||
dst: &Vec<DefIndex>,
|
||||
dst: &[DefIndex],
|
||||
def_pool: &DefPool,
|
||||
var_pool: &mut VarPool,
|
||||
) -> Result<TypeEnvironment, String> {
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::shared::types as shared_types;
|
||||
use cranelift_codegen_shared::constants;
|
||||
|
||||
// Rust name prefix used for the `rust_name` method.
|
||||
static _RUST_NAME_PREFIX: &'static str = "ir::types::";
|
||||
static _RUST_NAME_PREFIX: &str = "ir::types::";
|
||||
|
||||
// ValueType variants (i8, i32, ...) are provided in `shared::types.rs`.
|
||||
|
||||
@@ -242,29 +242,29 @@ impl LaneType {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn by(&self, lanes: u16) -> ValueType {
|
||||
pub fn by(self, lanes: u16) -> ValueType {
|
||||
if lanes == 1 {
|
||||
(*self).into()
|
||||
self.into()
|
||||
} else {
|
||||
ValueType::Vector(VectorType::new(*self, lanes.into()))
|
||||
ValueType::Vector(VectorType::new(self, lanes.into()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_float(&self) -> bool {
|
||||
pub fn is_float(self) -> bool {
|
||||
match self {
|
||||
LaneType::FloatType(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_int(&self) -> bool {
|
||||
pub fn is_int(self) -> bool {
|
||||
match self {
|
||||
LaneType::IntType(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_bool(&self) -> bool {
|
||||
pub fn is_bool(self) -> bool {
|
||||
match self {
|
||||
LaneType::BoolType(_) => true,
|
||||
_ => false,
|
||||
|
||||
@@ -156,33 +156,33 @@ impl TypeVar {
|
||||
let ts = self.get_typeset();
|
||||
|
||||
// Safety checks to avoid over/underflows.
|
||||
assert!(ts.specials.len() == 0, "can't derive from special types");
|
||||
assert!(ts.specials.is_empty(), "can't derive from special types");
|
||||
match derived_func {
|
||||
DerivedFunc::HalfWidth => {
|
||||
assert!(
|
||||
ts.ints.len() == 0 || *ts.ints.iter().min().unwrap() > 8,
|
||||
ts.ints.is_empty() || *ts.ints.iter().min().unwrap() > 8,
|
||||
"can't halve all integer types"
|
||||
);
|
||||
assert!(
|
||||
ts.floats.len() == 0 || *ts.floats.iter().min().unwrap() > 32,
|
||||
ts.floats.is_empty() || *ts.floats.iter().min().unwrap() > 32,
|
||||
"can't halve all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.len() == 0 || *ts.bools.iter().min().unwrap() > 8,
|
||||
ts.bools.is_empty() || *ts.bools.iter().min().unwrap() > 8,
|
||||
"can't halve all boolean types"
|
||||
);
|
||||
}
|
||||
DerivedFunc::DoubleWidth => {
|
||||
assert!(
|
||||
ts.ints.len() == 0 || *ts.ints.iter().max().unwrap() < MAX_BITS,
|
||||
ts.ints.is_empty() || *ts.ints.iter().max().unwrap() < MAX_BITS,
|
||||
"can't double all integer types"
|
||||
);
|
||||
assert!(
|
||||
ts.floats.len() == 0 || *ts.floats.iter().max().unwrap() < MAX_FLOAT_BITS,
|
||||
ts.floats.is_empty() || *ts.floats.iter().max().unwrap() < MAX_FLOAT_BITS,
|
||||
"can't double all float types"
|
||||
);
|
||||
assert!(
|
||||
ts.bools.len() == 0 || *ts.bools.iter().max().unwrap() < MAX_BITS,
|
||||
ts.bools.is_empty() || *ts.bools.iter().max().unwrap() < MAX_BITS,
|
||||
"can't double all boolean types"
|
||||
);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ impl TypeVar {
|
||||
}
|
||||
}
|
||||
|
||||
return TypeVar {
|
||||
TypeVar {
|
||||
content: Rc::new(RefCell::new(TypeVarContent {
|
||||
name: format!("{}({})", derived_func.name(), self.name),
|
||||
doc: "".into(),
|
||||
@@ -213,29 +213,29 @@ impl TypeVar {
|
||||
derived_func,
|
||||
}),
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lane_of(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::LaneOf);
|
||||
self.derived(DerivedFunc::LaneOf)
|
||||
}
|
||||
pub fn as_bool(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::AsBool);
|
||||
self.derived(DerivedFunc::AsBool)
|
||||
}
|
||||
pub fn half_width(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::HalfWidth);
|
||||
self.derived(DerivedFunc::HalfWidth)
|
||||
}
|
||||
pub fn double_width(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::DoubleWidth);
|
||||
self.derived(DerivedFunc::DoubleWidth)
|
||||
}
|
||||
pub fn half_vector(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::HalfVector);
|
||||
self.derived(DerivedFunc::HalfVector)
|
||||
}
|
||||
pub fn double_vector(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::DoubleVector);
|
||||
self.derived(DerivedFunc::DoubleVector)
|
||||
}
|
||||
pub fn to_bitvec(&self) -> TypeVar {
|
||||
return self.derived(DerivedFunc::ToBitVec);
|
||||
self.derived(DerivedFunc::ToBitVec)
|
||||
}
|
||||
|
||||
/// Constrain the range of types this variable can assume to a subset of those in the typeset
|
||||
@@ -347,7 +347,7 @@ pub enum DerivedFunc {
|
||||
}
|
||||
|
||||
impl DerivedFunc {
|
||||
pub fn name(&self) -> &'static str {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
DerivedFunc::LaneOf => "lane_of",
|
||||
DerivedFunc::AsBool => "as_bool",
|
||||
@@ -360,7 +360,7 @@ impl DerivedFunc {
|
||||
}
|
||||
|
||||
/// Returns the inverse function of this one, if it is a bijection.
|
||||
pub fn inverse(&self) -> Option<DerivedFunc> {
|
||||
pub fn inverse(self) -> Option<DerivedFunc> {
|
||||
match self {
|
||||
DerivedFunc::HalfWidth => Some(DerivedFunc::DoubleWidth),
|
||||
DerivedFunc::DoubleWidth => Some(DerivedFunc::HalfWidth),
|
||||
@@ -476,7 +476,7 @@ impl TypeSet {
|
||||
copy.floats = NumSet::new();
|
||||
copy.refs = NumSet::new();
|
||||
copy.bitvecs = NumSet::new();
|
||||
if (&self.lanes - &num_set![1]).len() > 0 {
|
||||
if !(&self.lanes - &num_set![1]).is_empty() {
|
||||
copy.bools = &self.ints | &self.floats;
|
||||
copy.bools = ©.bools | &self.bools;
|
||||
}
|
||||
@@ -512,7 +512,7 @@ impl TypeSet {
|
||||
.iter()
|
||||
.filter(|&&x| x < MAX_BITS)
|
||||
.map(|&x| x * 2)
|
||||
.filter(legal_bool),
|
||||
.filter(|x| legal_bool(*x)),
|
||||
);
|
||||
copy.bitvecs = NumSet::from_iter(
|
||||
self.bitvecs
|
||||
@@ -600,7 +600,7 @@ impl TypeSet {
|
||||
fn get_singleton(&self) -> ValueType {
|
||||
let mut types = self.concrete_types();
|
||||
assert_eq!(types.len(), 1);
|
||||
return types.remove(0);
|
||||
types.remove(0)
|
||||
}
|
||||
|
||||
/// Return the inverse image of self across the derived function func.
|
||||
@@ -615,7 +615,7 @@ impl TypeSet {
|
||||
let mut copy = self.clone();
|
||||
copy.bitvecs = NumSet::new();
|
||||
copy.lanes =
|
||||
NumSet::from_iter((0..MAX_LANES.trailing_zeros() + 1).map(|i| u16::pow(2, i)));
|
||||
NumSet::from_iter((0..=MAX_LANES.trailing_zeros()).map(|i| u16::pow(2, i)));
|
||||
copy
|
||||
}
|
||||
DerivedFunc::AsBool => {
|
||||
@@ -724,11 +724,11 @@ impl TypeSet {
|
||||
}
|
||||
|
||||
fn set_wider_or_equal(s1: &NumSet, s2: &NumSet) -> bool {
|
||||
s1.len() > 0 && s2.len() > 0 && s1.iter().min() >= s2.iter().max()
|
||||
!s1.is_empty() && !s2.is_empty() && s1.iter().min() >= s2.iter().max()
|
||||
}
|
||||
|
||||
fn set_narrower(s1: &NumSet, s2: &NumSet) -> bool {
|
||||
s1.len() > 0 && s2.len() > 0 && s1.iter().min() < s2.iter().max()
|
||||
!s1.is_empty() && !s2.is_empty() && s1.iter().min() < s2.iter().max()
|
||||
}
|
||||
|
||||
impl fmt::Debug for TypeSet {
|
||||
@@ -854,7 +854,7 @@ impl TypeSetBuilder {
|
||||
|
||||
let bools = range_to_set(self.bools.to_range(1..MAX_BITS, None))
|
||||
.into_iter()
|
||||
.filter(legal_bool)
|
||||
.filter(|x| legal_bool(*x))
|
||||
.collect();
|
||||
|
||||
TypeSet::new(
|
||||
@@ -921,9 +921,9 @@ impl Into<Interval> for Range {
|
||||
}
|
||||
}
|
||||
|
||||
fn legal_bool(bits: &RangeBound) -> bool {
|
||||
fn legal_bool(bits: RangeBound) -> bool {
|
||||
// Only allow legal bit widths for bool types.
|
||||
*bits == 1 || (*bits >= 8 && *bits <= MAX_BITS && bits.is_power_of_two())
|
||||
bits == 1 || (bits >= 8 && bits <= MAX_BITS && bits.is_power_of_two())
|
||||
}
|
||||
|
||||
/// Generates a set with all the powers of two included in the range.
|
||||
@@ -939,7 +939,7 @@ fn range_to_set(range: Option<Range>) -> NumSet {
|
||||
assert!(high.is_power_of_two());
|
||||
assert!(low <= high);
|
||||
|
||||
for i in low.trailing_zeros()..high.trailing_zeros() + 1 {
|
||||
for i in low.trailing_zeros()..=high.trailing_zeros() {
|
||||
assert!(1 << i <= RangeBound::max_value());
|
||||
set.insert(1 << i);
|
||||
}
|
||||
|
||||
@@ -255,6 +255,7 @@ fn rewrite_expr(
|
||||
Apply::new(apply_target, args)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn rewrite_def_list(
|
||||
position: PatternPosition,
|
||||
dummy_defs: Vec<DummyDef>,
|
||||
|
||||
@@ -7,7 +7,7 @@ pub(crate) trait MapWithDefault<K, V: Default> {
|
||||
|
||||
impl<K: Eq + Hash, V: Default> MapWithDefault<K, V> for HashMap<K, V> {
|
||||
fn get_or_default(&mut self, k: K) -> &mut V {
|
||||
self.entry(k).or_insert_with(|| V::default())
|
||||
self.entry(k).or_insert_with(V::default)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ fn gen_recipe(recipe: &EncodingRecipe, fmt: &mut Formatter) {
|
||||
let is_regmove = ["RegMove", "RegSpill", "RegFill"].contains(&inst_format.name);
|
||||
|
||||
// Unpack the instruction data.
|
||||
fmtln!(fmt, "if let &InstructionData::{} {{", inst_format.name);
|
||||
fmtln!(fmt, "if let InstructionData::{} {{", inst_format.name);
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("opcode,");
|
||||
for f in &inst_format.imm_fields {
|
||||
@@ -49,7 +49,7 @@ fn gen_recipe(recipe: &EncodingRecipe, fmt: &mut Formatter) {
|
||||
}
|
||||
fmt.line("..");
|
||||
|
||||
fmt.outdented_line("} = inst_data {");
|
||||
fmt.outdented_line("} = *inst_data {");
|
||||
|
||||
// Pass recipe arguments in this order: inputs, imm_fields, outputs.
|
||||
let mut args = String::new();
|
||||
|
||||
@@ -158,8 +158,8 @@ fn emit_recipe_predicates(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
fmt,
|
||||
"fn {}({}: crate::settings::PredicateView, {}: &ir::InstructionData) -> bool {{",
|
||||
func_name,
|
||||
if let Some(_) = isap { "isap" } else { "_" },
|
||||
if let Some(_) = instp { "inst" } else { "_" }
|
||||
if isap.is_some() { "isap" } else { "_" },
|
||||
if instp.is_some() { "inst" } else { "_" }
|
||||
);
|
||||
fmt.indent(|fmt| {
|
||||
match (isap, instp) {
|
||||
@@ -263,13 +263,13 @@ fn emit_recipe_names(isa: &TargetIsa, fmt: &mut Formatter) {
|
||||
}
|
||||
|
||||
/// Returns a set of all the registers involved in fixed register constraints.
|
||||
fn get_fixed_registers(operands_in: &Vec<OperandConstraint>) -> HashSet<Register> {
|
||||
fn get_fixed_registers(operands_in: &[OperandConstraint]) -> HashSet<Register> {
|
||||
HashSet::from_iter(
|
||||
operands_in
|
||||
.iter()
|
||||
.map(|constraint| {
|
||||
if let OperandConstraint::FixedReg(reg) = &constraint {
|
||||
Some(reg.clone())
|
||||
Some(*reg)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -286,13 +286,13 @@ fn get_fixed_registers(operands_in: &Vec<OperandConstraint>) -> HashSet<Register
|
||||
fn emit_operand_constraints(
|
||||
registers: &IsaRegs,
|
||||
recipe: &EncodingRecipe,
|
||||
constraints: &Vec<OperandConstraint>,
|
||||
constraints: &[OperandConstraint],
|
||||
field_name: &'static str,
|
||||
tied_operands: &HashMap<usize, usize>,
|
||||
fixed_registers: &HashSet<Register>,
|
||||
fmt: &mut Formatter,
|
||||
) {
|
||||
if constraints.len() == 0 {
|
||||
if constraints.is_empty() {
|
||||
fmtln!(fmt, "{}: &[],", field_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::unique_table::{UniqueSeqTable, UniqueTable};
|
||||
const TYPESET_LIMIT: usize = 0xff;
|
||||
|
||||
/// Generate an instruction format enumeration.
|
||||
fn gen_formats(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
|
||||
fn gen_formats(formats: &[&InstructionFormat], fmt: &mut Formatter) {
|
||||
fmt.doc_comment(
|
||||
r#"
|
||||
An instruction format
|
||||
@@ -49,7 +49,7 @@ fn gen_formats(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
|
||||
m.arm(
|
||||
format!("InstructionData::{}", format.name),
|
||||
vec![".."],
|
||||
format!("InstructionFormat::{}", format.name),
|
||||
format!("Self::{}", format.name),
|
||||
);
|
||||
}
|
||||
fmt.add_match(m);
|
||||
@@ -65,7 +65,7 @@ fn gen_formats(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
|
||||
/// Every variant must contain an `opcode` field. The size of `InstructionData` should be kept at
|
||||
/// 16 bytes on 64-bit architectures. If more space is needed to represent an instruction, use a
|
||||
/// `ValueList` to store the additional information out of line.
|
||||
fn gen_instruction_data(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
|
||||
fn gen_instruction_data(formats: &[&InstructionFormat], fmt: &mut Formatter) {
|
||||
fmt.line("#[derive(Clone, Debug)]");
|
||||
fmt.line("#[allow(missing_docs)]");
|
||||
fmt.line("pub enum InstructionData {");
|
||||
@@ -93,7 +93,7 @@ fn gen_instruction_data(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter)
|
||||
fmt.line("}");
|
||||
}
|
||||
|
||||
fn gen_arguments_method(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter, is_mut: bool) {
|
||||
fn gen_arguments_method(formats: &[&InstructionFormat], fmt: &mut Formatter, is_mut: bool) {
|
||||
let (method, mut_, rslice, as_slice) = if is_mut {
|
||||
(
|
||||
"arguments_mut",
|
||||
@@ -116,7 +116,7 @@ fn gen_arguments_method(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter,
|
||||
fmt.indent(|fmt| {
|
||||
let mut m = Match::new("*self");
|
||||
for format in formats {
|
||||
let name = format!("InstructionData::{}", format.name);
|
||||
let name = format!("Self::{}", format.name);
|
||||
|
||||
// Formats with a value list put all of their arguments in the list. We don't split
|
||||
// them up, just return it all as variable arguments. (I expect the distinction to go
|
||||
@@ -163,7 +163,7 @@ fn gen_arguments_method(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter,
|
||||
/// - `pub fn put_value_list(&mut self, args: ir::ValueList>`
|
||||
/// - `pub fn eq(&self, &other: Self, &pool) -> bool`
|
||||
/// - `pub fn hash<H: Hasher>(&self, state: &mut H, &pool)`
|
||||
fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Formatter) {
|
||||
fn gen_instruction_data_impl(formats: &[&InstructionFormat], fmt: &mut Formatter) {
|
||||
fmt.line("impl InstructionData {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.doc_comment("Get the opcode of this instruction.");
|
||||
@@ -171,7 +171,7 @@ fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Format
|
||||
fmt.indent(|fmt| {
|
||||
let mut m = Match::new("*self");
|
||||
for format in formats {
|
||||
m.arm(format!("InstructionData::{}", format.name), vec!["opcode", ".."],
|
||||
m.arm(format!("Self::{}", format.name), vec!["opcode", ".."],
|
||||
"opcode".to_string());
|
||||
}
|
||||
fmt.add_match(m);
|
||||
@@ -184,7 +184,7 @@ fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Format
|
||||
fmt.indent(|fmt| {
|
||||
let mut m = Match::new("*self");
|
||||
for format in formats {
|
||||
let name = format!("InstructionData::{}", format.name);
|
||||
let name = format!("Self::{}", format.name);
|
||||
if format.typevar_operand.is_none() {
|
||||
m.arm(name, vec![".."], "None".to_string());
|
||||
} else if format.has_value_list {
|
||||
@@ -227,7 +227,7 @@ fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Format
|
||||
|
||||
for format in formats {
|
||||
if format.has_value_list {
|
||||
m.arm(format!("InstructionData::{}", format.name),
|
||||
m.arm(format!("Self::{}", format.name),
|
||||
vec!["ref mut args", ".."],
|
||||
"Some(args.take())".to_string());
|
||||
}
|
||||
@@ -254,7 +254,7 @@ fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Format
|
||||
fmt.indent(|fmt| {
|
||||
for format in formats {
|
||||
if format.has_value_list {
|
||||
fmtln!(fmt, "InstructionData::{} {{ ref mut args, .. }} => args,", format.name);
|
||||
fmtln!(fmt, "Self::{} {{ ref mut args, .. }} => args,", format.name);
|
||||
}
|
||||
}
|
||||
fmt.line("_ => panic!(\"No value list: {:?}\", self),");
|
||||
@@ -283,7 +283,7 @@ fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Format
|
||||
fmt.line("match (self, other) {");
|
||||
fmt.indent(|fmt| {
|
||||
for format in formats {
|
||||
let name = format!("&InstructionData::{}", format.name);
|
||||
let name = format!("&Self::{}", format.name);
|
||||
let mut members = vec!["opcode"];
|
||||
|
||||
let args_eq = if format.typevar_operand.is_none() {
|
||||
@@ -335,7 +335,7 @@ fn gen_instruction_data_impl(formats: &Vec<&InstructionFormat>, fmt: &mut Format
|
||||
fmt.line("match *self {");
|
||||
fmt.indent(|fmt| {
|
||||
for format in formats {
|
||||
let name = format!("InstructionData::{}", format.name);
|
||||
let name = format!("Self::{}", format.name);
|
||||
let mut members = vec!["opcode"];
|
||||
|
||||
let args = if format.typevar_operand.is_none() {
|
||||
@@ -388,7 +388,7 @@ fn gen_bool_accessor<T: Fn(&Instruction) -> bool>(
|
||||
let mut m = Match::new("self");
|
||||
for inst in all_inst.values() {
|
||||
if get_attr(inst) {
|
||||
m.arm_no_fields(format!("Opcode::{}", inst.camel_name), "true");
|
||||
m.arm_no_fields(format!("Self::{}", inst.camel_name), "true");
|
||||
}
|
||||
}
|
||||
m.arm_no_fields("_", "false");
|
||||
@@ -398,7 +398,7 @@ fn gen_bool_accessor<T: Fn(&Instruction) -> bool>(
|
||||
fmt.empty_line();
|
||||
}
|
||||
|
||||
fn gen_opcodes<'a>(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
fmt.doc_comment(
|
||||
r#"
|
||||
An instruction opcode.
|
||||
@@ -613,7 +613,7 @@ fn get_constraint<'entries, 'table>(
|
||||
}
|
||||
|
||||
assert!(type_var == ctrl_typevar.unwrap());
|
||||
return "Same".into();
|
||||
"Same".into()
|
||||
}
|
||||
|
||||
fn gen_bitset<'a, T: IntoIterator<Item = &'a u16>>(
|
||||
@@ -641,22 +641,22 @@ fn iterable_to_string<I: fmt::Display, T: IntoIterator<Item = I>>(iterable: T) -
|
||||
|
||||
fn typeset_to_string(ts: &TypeSet) -> String {
|
||||
let mut result = format!("TypeSet(lanes={}", iterable_to_string(&ts.lanes));
|
||||
if ts.ints.len() > 0 {
|
||||
if !ts.ints.is_empty() {
|
||||
result += &format!(", ints={}", iterable_to_string(&ts.ints));
|
||||
}
|
||||
if ts.floats.len() > 0 {
|
||||
if !ts.floats.is_empty() {
|
||||
result += &format!(", floats={}", iterable_to_string(&ts.floats));
|
||||
}
|
||||
if ts.bools.len() > 0 {
|
||||
if !ts.bools.is_empty() {
|
||||
result += &format!(", bools={}", iterable_to_string(&ts.bools));
|
||||
}
|
||||
if ts.bitvecs.len() > 0 {
|
||||
if !ts.bitvecs.is_empty() {
|
||||
result += &format!(", bitvecs={}", iterable_to_string(&ts.bitvecs));
|
||||
}
|
||||
if ts.specials.len() > 0 {
|
||||
if !ts.specials.is_empty() {
|
||||
result += &format!(", specials=[{}]", iterable_to_string(&ts.specials));
|
||||
}
|
||||
if ts.refs.len() > 0 {
|
||||
if !ts.refs.is_empty() {
|
||||
result += &format!(", refs={}", iterable_to_string(&ts.refs));
|
||||
}
|
||||
result += ")";
|
||||
@@ -680,7 +680,7 @@ pub fn gen_typesets_table(type_sets: &UniqueTable<TypeSet>, fmt: &mut Formatter)
|
||||
for ts in type_sets.iter() {
|
||||
fmt.line("ir::instructions::ValueTypeSet {");
|
||||
fmt.indent(|fmt| {
|
||||
assert!(ts.bitvecs.len() == 0, "Bitvector types are not emittable.");
|
||||
assert!(ts.bitvecs.is_empty(), "Bitvector types are not emittable.");
|
||||
fmt.comment(typeset_to_string(ts));
|
||||
gen_bitset(&ts.lanes, "lanes", 16, fmt);
|
||||
gen_bitset(&ts.ints, "ints", 8, fmt);
|
||||
@@ -710,6 +710,7 @@ fn gen_type_constraints(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
let mut operand_seqs = UniqueSeqTable::new();
|
||||
|
||||
// Preload table with constraints for typical binops.
|
||||
#[allow(clippy::useless_vec)]
|
||||
operand_seqs.add(&vec!["Same".to_string(); 3]);
|
||||
|
||||
fmt.comment("Table of opcode constraints.");
|
||||
@@ -926,7 +927,7 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo
|
||||
_ => format!("({})", vec!["Value"; inst.value_results.len()].join(", ")),
|
||||
};
|
||||
|
||||
let tmpl = if tmpl_types.len() > 0 {
|
||||
let tmpl = if !tmpl_types.is_empty() {
|
||||
format!("<{}>", tmpl_types.join(", "))
|
||||
} else {
|
||||
"".into()
|
||||
@@ -1005,7 +1006,7 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo
|
||||
// Call to the format constructor,
|
||||
let fcall = format!("self.{}({})", format.name, args.join(", "));
|
||||
|
||||
if inst.value_results.len() == 0 {
|
||||
if inst.value_results.is_empty() {
|
||||
fmtln!(fmt, "{}.0", fcall);
|
||||
return;
|
||||
}
|
||||
@@ -1037,7 +1038,7 @@ fn gen_inst_builder(inst: &Instruction, format: &InstructionFormat, fmt: &mut Fo
|
||||
/// Generate a Builder trait with methods for all instructions.
|
||||
fn gen_builder(
|
||||
instructions: &AllInstructions,
|
||||
formats: &Vec<&InstructionFormat>,
|
||||
formats: &[&InstructionFormat],
|
||||
fmt: &mut Formatter,
|
||||
) {
|
||||
fmt.doc_comment(
|
||||
|
||||
@@ -187,7 +187,7 @@ fn unwrap_inst(transform: &Transform, fmt: &mut Formatter) -> bool {
|
||||
|
||||
// If the definition creates results, detach the values and place them in locals.
|
||||
let mut replace_inst = false;
|
||||
if def.defined_vars.len() > 0 {
|
||||
if !def.defined_vars.is_empty() {
|
||||
if def.defined_vars
|
||||
== def_pool
|
||||
.get(var_pool.get(def.defined_vars[0]).dst_def.unwrap())
|
||||
@@ -266,7 +266,7 @@ fn build_derived_expr(tv: &TypeVar) -> String {
|
||||
///
|
||||
/// The emitted code is a statement redefining the `predicate` variable like this:
|
||||
/// let predicate = predicate && ...
|
||||
fn emit_runtime_typecheck<'a, 'b>(
|
||||
fn emit_runtime_typecheck<'a>(
|
||||
constraint: &'a Constraint,
|
||||
type_sets: &mut UniqueTable<'a, TypeSet>,
|
||||
fmt: &mut Formatter,
|
||||
@@ -586,7 +586,7 @@ fn gen_transform_group<'a>(
|
||||
let inst = &transform.def_pool.get(def_index).apply.inst;
|
||||
inst_to_transforms
|
||||
.entry(inst.camel_name.clone())
|
||||
.or_insert(Vec::new())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(transform);
|
||||
}
|
||||
|
||||
@@ -606,7 +606,7 @@ fn gen_transform_group<'a>(
|
||||
let replace_inst = unwrap_inst(&transforms[0], fmt);
|
||||
fmt.empty_line();
|
||||
|
||||
for (i, transform) in transforms.into_iter().enumerate() {
|
||||
for (i, transform) in transforms.iter().enumerate() {
|
||||
if i > 0 {
|
||||
fmt.empty_line();
|
||||
}
|
||||
@@ -697,7 +697,7 @@ fn gen_isa(
|
||||
|
||||
/// Generate the legalizer files.
|
||||
pub(crate) fn generate(
|
||||
isas: &Vec<TargetIsa>,
|
||||
isas: &[TargetIsa],
|
||||
transform_groups: &TransformGroups,
|
||||
filename_prefix: &str,
|
||||
out_dir: &str,
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::srcgen::Formatter;
|
||||
use cranelift_entity::EntityRef;
|
||||
|
||||
fn gen_regbank(fmt: &mut Formatter, reg_bank: &RegBank) {
|
||||
let names = if reg_bank.names.len() > 0 {
|
||||
let names = if !reg_bank.names.is_empty() {
|
||||
format!(r#""{}""#, reg_bank.names.join(r#"", ""#))
|
||||
} else {
|
||||
"".to_string()
|
||||
|
||||
@@ -81,7 +81,7 @@ fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter)
|
||||
fmtln!(fmt, "f.write_str(match *self {");
|
||||
fmt.indent(|fmt| {
|
||||
for v in values.iter() {
|
||||
fmtln!(fmt, "{}::{} => \"{}\",", name, camel_case(v), v);
|
||||
fmtln!(fmt, "Self::{} => \"{}\",", camel_case(v), v);
|
||||
}
|
||||
});
|
||||
fmtln!(fmt, "})");
|
||||
@@ -98,7 +98,7 @@ fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter)
|
||||
fmtln!(fmt, "match s {");
|
||||
fmt.indent(|fmt| {
|
||||
for v in values.iter() {
|
||||
fmtln!(fmt, "\"{}\" => Ok({}::{}),", v, name, camel_case(v));
|
||||
fmtln!(fmt, "\"{}\" => Ok(Self::{}),", v, camel_case(v));
|
||||
}
|
||||
fmtln!(fmt, "_ => Err(()),");
|
||||
});
|
||||
@@ -198,7 +198,7 @@ fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) {
|
||||
});
|
||||
fmtln!(fmt, "}");
|
||||
|
||||
if group.settings.len() > 0 {
|
||||
if !group.settings.is_empty() {
|
||||
fmt.doc_comment("Dynamic numbered predicate getter.");
|
||||
fmtln!(fmt, "fn numbered_predicate(&self, p: usize) -> bool {");
|
||||
fmt.indent(|fmt| {
|
||||
|
||||
@@ -22,8 +22,7 @@ impl Isa {
|
||||
Isa::all()
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|isa| isa.to_string() == name)
|
||||
.next()
|
||||
.find(|isa| isa.to_string() == name)
|
||||
}
|
||||
|
||||
/// Creates isa target from arch.
|
||||
@@ -55,7 +54,7 @@ impl fmt::Display for Isa {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn define(isas: &Vec<Isa>, shared_defs: &mut SharedDefinitions) -> Vec<TargetIsa> {
|
||||
pub(crate) fn define(isas: &[Isa], shared_defs: &mut SharedDefinitions) -> Vec<TargetIsa> {
|
||||
isas.iter()
|
||||
.map(|isa| match isa {
|
||||
Isa::Riscv => riscv::define(shared_defs),
|
||||
|
||||
@@ -56,7 +56,7 @@ impl<'defs> PerCpuModeEncodings<'defs> {
|
||||
|
||||
fn load_bits(funct3: u16) -> u16 {
|
||||
assert!(funct3 <= 0b111);
|
||||
0b00000 | (funct3 << 5)
|
||||
funct3 << 5
|
||||
}
|
||||
|
||||
fn store_bits(funct3: u16) -> u16 {
|
||||
@@ -91,13 +91,13 @@ fn opimm32_bits(funct3: u16, funct7: u16) -> u16 {
|
||||
|
||||
fn op_bits(funct3: u16, funct7: u16) -> u16 {
|
||||
assert!(funct3 <= 0b111);
|
||||
assert!(funct7 <= 0b1111111);
|
||||
assert!(funct7 <= 0b111_1111);
|
||||
0b01100 | (funct3 << 5) | (funct7 << 8)
|
||||
}
|
||||
|
||||
fn op32_bits(funct3: u16, funct7: u16) -> u16 {
|
||||
assert!(funct3 <= 0b111);
|
||||
assert!(funct7 <= 0b1111111);
|
||||
assert!(funct7 <= 0b111_1111);
|
||||
0b01110 | (funct3 << 5) | (funct7 << 8)
|
||||
}
|
||||
|
||||
@@ -177,11 +177,11 @@ pub(crate) fn define<'defs>(
|
||||
|
||||
// Basic arithmetic binary instructions are encoded in an R-type instruction.
|
||||
for &(inst, inst_imm, f3, f7) in &[
|
||||
(iadd, Some(iadd_imm), 0b000, 0b0000000),
|
||||
(isub, None, 0b000, 0b0100000),
|
||||
(bxor, Some(bxor_imm), 0b100, 0b0000000),
|
||||
(bor, Some(bor_imm), 0b110, 0b0000000),
|
||||
(band, Some(band_imm), 0b111, 0b0000000),
|
||||
(iadd, Some(iadd_imm), 0b000, 0b000_0000),
|
||||
(isub, None, 0b000, 0b010_0000),
|
||||
(bxor, Some(bxor_imm), 0b100, 0b000_0000),
|
||||
(bor, Some(bor_imm), 0b110, 0b000_0000),
|
||||
(band, Some(band_imm), 0b111, 0b000_0000),
|
||||
] {
|
||||
e.add32(e.enc(inst.bind(I32), r_r, op_bits(f3, f7)));
|
||||
e.add64(e.enc(inst.bind(I64), r_r, op_bits(f3, f7)));
|
||||
@@ -194,8 +194,8 @@ pub(crate) fn define<'defs>(
|
||||
}
|
||||
|
||||
// 32-bit ops in RV64.
|
||||
e.add64(e.enc(iadd.bind(I32), r_r, op32_bits(0b000, 0b0000000)));
|
||||
e.add64(e.enc(isub.bind(I32), r_r, op32_bits(0b000, 0b0100000)));
|
||||
e.add64(e.enc(iadd.bind(I32), r_r, op32_bits(0b000, 0b000_0000)));
|
||||
e.add64(e.enc(isub.bind(I32), r_r, op32_bits(0b000, 0b010_0000)));
|
||||
// There are no andiw/oriw/xoriw variations.
|
||||
e.add64(e.enc(iadd_imm.bind(I32), r_ii, opimm32_bits(0b000, 0)));
|
||||
|
||||
@@ -208,7 +208,7 @@ pub(crate) fn define<'defs>(
|
||||
for &(inst, inst_imm, f3, f7) in &[
|
||||
(ishl, ishl_imm, 0b1, 0b0),
|
||||
(ushr, ushr_imm, 0b101, 0b0),
|
||||
(sshr, sshr_imm, 0b101, 0b100000),
|
||||
(sshr, sshr_imm, 0b101, 0b10_0000),
|
||||
] {
|
||||
e.add32(e.enc(inst.bind(I32).bind(I32), r_r, op_bits(f3, f7)));
|
||||
e.add64(e.enc(inst.bind(I64).bind(I64), r_r, op_bits(f3, f7)));
|
||||
@@ -246,20 +246,20 @@ pub(crate) fn define<'defs>(
|
||||
let icmp_i32 = icmp.bind(I32);
|
||||
let icmp_i64 = icmp.bind(I64);
|
||||
e.add32(
|
||||
e.enc(icmp_i32.clone(), r_ricmp, op_bits(0b010, 0b0000000))
|
||||
e.enc(icmp_i32.clone(), r_ricmp, op_bits(0b010, 0b000_0000))
|
||||
.inst_predicate(icmp_instp(&icmp_i32, "slt")),
|
||||
);
|
||||
e.add64(
|
||||
e.enc(icmp_i64.clone(), r_ricmp, op_bits(0b010, 0b0000000))
|
||||
e.enc(icmp_i64.clone(), r_ricmp, op_bits(0b010, 0b000_0000))
|
||||
.inst_predicate(icmp_instp(&icmp_i64, "slt")),
|
||||
);
|
||||
|
||||
e.add32(
|
||||
e.enc(icmp_i32.clone(), r_ricmp, op_bits(0b011, 0b0000000))
|
||||
e.enc(icmp_i32.clone(), r_ricmp, op_bits(0b011, 0b000_0000))
|
||||
.inst_predicate(icmp_instp(&icmp_i32, "ult")),
|
||||
);
|
||||
e.add64(
|
||||
e.enc(icmp_i64.clone(), r_ricmp, op_bits(0b011, 0b0000000))
|
||||
e.enc(icmp_i64.clone(), r_ricmp, op_bits(0b011, 0b000_0000))
|
||||
.inst_predicate(icmp_instp(&icmp_i64, "ult")),
|
||||
);
|
||||
|
||||
@@ -293,15 +293,15 @@ pub(crate) fn define<'defs>(
|
||||
// "M" Standard Extension for Integer Multiplication and Division.
|
||||
// Gated by the `use_m` flag.
|
||||
e.add32(
|
||||
e.enc(imul.bind(I32), r_r, op_bits(0b000, 0b00000001))
|
||||
e.enc(imul.bind(I32), r_r, op_bits(0b000, 0b0000_0001))
|
||||
.isa_predicate(use_m),
|
||||
);
|
||||
e.add64(
|
||||
e.enc(imul.bind(I64), r_r, op_bits(0b000, 0b00000001))
|
||||
e.enc(imul.bind(I64), r_r, op_bits(0b000, 0b0000_0001))
|
||||
.isa_predicate(use_m),
|
||||
);
|
||||
e.add64(
|
||||
e.enc(imul.bind(I32), r_r, op32_bits(0b000, 0b00000001))
|
||||
e.enc(imul.bind(I32), r_r, op32_bits(0b000, 0b0000_0001))
|
||||
.isa_predicate(use_m),
|
||||
);
|
||||
|
||||
|
||||
@@ -33,11 +33,10 @@ impl RecipeGroup {
|
||||
}
|
||||
|
||||
pub fn by_name(&self, name: &str) -> EncodingRecipeNumber {
|
||||
let number = *self
|
||||
*self
|
||||
.name_to_recipe
|
||||
.get(name)
|
||||
.expect(&format!("unknown riscv recipe name {}", name));
|
||||
number
|
||||
.unwrap_or_else(|| panic!("unknown riscv recipe name {}", name))
|
||||
}
|
||||
|
||||
pub fn collect(self) -> Recipes {
|
||||
@@ -97,7 +96,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
EncodingRecipeBuilder::new("Iz", &formats.unary_imm, 4)
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*&formats.unary_imm,
|
||||
&formats.unary_imm,
|
||||
"imm",
|
||||
12,
|
||||
0,
|
||||
@@ -111,7 +110,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
.operands_in(vec![gpr])
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*&formats.int_compare_imm,
|
||||
&formats.int_compare_imm,
|
||||
"imm",
|
||||
12,
|
||||
0,
|
||||
@@ -183,7 +182,7 @@ pub(crate) fn define(shared_defs: &SharedDefinitions, regs: &IsaRegs) -> RecipeG
|
||||
EncodingRecipeBuilder::new("U", &formats.unary_imm, 4)
|
||||
.operands_out(vec![gpr])
|
||||
.inst_predicate(InstructionPredicate::new_is_signed_int(
|
||||
&*&formats.unary_imm,
|
||||
&formats.unary_imm,
|
||||
"imm",
|
||||
32,
|
||||
12,
|
||||
|
||||
@@ -70,7 +70,7 @@ impl PerCpuModeEncodings {
|
||||
{
|
||||
let (recipe, bits) = template.build();
|
||||
let recipe_number = self.add_recipe(recipe);
|
||||
let builder = EncodingBuilder::new(inst.into(), recipe_number, bits);
|
||||
let builder = EncodingBuilder::new(inst, recipe_number, bits);
|
||||
builder_closure(builder).build(&self.recipes, &mut self.inst_pred_reg)
|
||||
}
|
||||
|
||||
@@ -367,6 +367,7 @@ impl PerCpuModeEncodings {
|
||||
|
||||
// Definitions.
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub(crate) fn define(
|
||||
shared_defs: &SharedDefinitions,
|
||||
settings: &SettingGroup,
|
||||
@@ -1916,7 +1917,7 @@ pub(crate) fn define(
|
||||
|
||||
// SIMD integer addition
|
||||
for (ty, opcodes) in &[(I8, &PADDB), (I16, &PADDW), (I32, &PADDD), (I64, &PADDQ)] {
|
||||
let iadd = iadd.bind(vector(ty.clone(), sse_vector_size));
|
||||
let iadd = iadd.bind(vector(*ty, sse_vector_size));
|
||||
e.enc_32_64(iadd, rec_fa.opcodes(*opcodes));
|
||||
}
|
||||
|
||||
@@ -1940,7 +1941,7 @@ pub(crate) fn define(
|
||||
|
||||
// SIMD integer subtraction
|
||||
for (ty, opcodes) in &[(I8, &PSUBB), (I16, &PSUBW), (I32, &PSUBD), (I64, &PSUBQ)] {
|
||||
let isub = isub.bind(vector(ty.clone(), sse_vector_size));
|
||||
let isub = isub.bind(vector(*ty, sse_vector_size));
|
||||
e.enc_32_64(isub, rec_fa.opcodes(*opcodes));
|
||||
}
|
||||
|
||||
@@ -1968,7 +1969,7 @@ pub(crate) fn define(
|
||||
(I16, &PMULLW[..], None),
|
||||
(I32, &PMULLD[..], Some(use_sse41_simd)),
|
||||
] {
|
||||
let imul = imul.bind(vector(ty.clone(), sse_vector_size));
|
||||
let imul = imul.bind(vector(*ty, sse_vector_size));
|
||||
e.enc_32_64_maybe_isap(imul, rec_fa.opcodes(opcodes), *isap);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::shared::formats::Formats;
|
||||
use crate::shared::immediates::Immediates;
|
||||
use crate::shared::types;
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub(crate) fn define(
|
||||
mut all_instructions: &mut AllInstructions,
|
||||
formats: &Formats,
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::shared::types::Float::F64;
|
||||
use crate::shared::types::Int::{I16, I32, I64};
|
||||
use crate::shared::Definitions as SharedDefinitions;
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &InstructionGroup) {
|
||||
let mut group = TransformGroupBuilder::new(
|
||||
"x86_expand",
|
||||
@@ -253,7 +254,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
|
||||
def!(r = popcnt.I64(x)),
|
||||
vec![
|
||||
def!(qv3 = ushr_imm(x, imm64_1)),
|
||||
def!(qc77 = iconst(Literal::constant(&imm.imm64, 0x7777777777777777))),
|
||||
def!(qc77 = iconst(Literal::constant(&imm.imm64, 0x7777_7777_7777_7777))),
|
||||
def!(qv4 = band(qv3, qc77)),
|
||||
def!(qv5 = isub(x, qv4)),
|
||||
def!(qv6 = ushr_imm(qv4, imm64_1)),
|
||||
@@ -264,9 +265,9 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
|
||||
def!(qv11 = isub(qv8, qv10)),
|
||||
def!(qv12 = ushr_imm(qv11, imm64_4)),
|
||||
def!(qv13 = iadd(qv11, qv12)),
|
||||
def!(qc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F0F0F0F0F0F0F))),
|
||||
def!(qc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F_0F0F_0F0F_0F0F))),
|
||||
def!(qv14 = band(qv13, qc0F)),
|
||||
def!(qc01 = iconst(Literal::constant(&imm.imm64, 0x0101010101010101))),
|
||||
def!(qc01 = iconst(Literal::constant(&imm.imm64, 0x0101_0101_0101_0101))),
|
||||
def!(qv15 = imul(qv14, qc01)),
|
||||
def!(r = ushr_imm(qv15, Literal::constant(&imm.imm64, 56))),
|
||||
],
|
||||
@@ -294,7 +295,7 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
|
||||
def!(r = popcnt.I32(x)),
|
||||
vec![
|
||||
def!(lv3 = ushr_imm(x, imm64_1)),
|
||||
def!(lc77 = iconst(Literal::constant(&imm.imm64, 0x77777777))),
|
||||
def!(lc77 = iconst(Literal::constant(&imm.imm64, 0x7777_7777))),
|
||||
def!(lv4 = band(lv3, lc77)),
|
||||
def!(lv5 = isub(x, lv4)),
|
||||
def!(lv6 = ushr_imm(lv4, imm64_1)),
|
||||
@@ -305,9 +306,9 @@ pub(crate) fn define(shared: &mut SharedDefinitions, x86_instructions: &Instruct
|
||||
def!(lv11 = isub(lv8, lv10)),
|
||||
def!(lv12 = ushr_imm(lv11, imm64_4)),
|
||||
def!(lv13 = iadd(lv11, lv12)),
|
||||
def!(lc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F0F0F))),
|
||||
def!(lc0F = iconst(Literal::constant(&imm.imm64, 0x0F0F_0F0F))),
|
||||
def!(lv14 = band(lv13, lc0F)),
|
||||
def!(lc01 = iconst(Literal::constant(&imm.imm64, 0x01010101))),
|
||||
def!(lc01 = iconst(Literal::constant(&imm.imm64, 0x0101_0101))),
|
||||
def!(lv15 = imul(lv14, lc01)),
|
||||
def!(r = ushr_imm(lv15, Literal::constant(&imm.imm64, 24))),
|
||||
],
|
||||
|
||||
@@ -51,14 +51,14 @@ impl<'builder> RecipeGroup<'builder> {
|
||||
pub fn recipe(&self, name: &str) -> &EncodingRecipe {
|
||||
self.recipes
|
||||
.iter()
|
||||
.find(|recipe| &recipe.name == name)
|
||||
.expect(&format!("unknown recipe name: {}. Try template?", name))
|
||||
.find(|recipe| recipe.name == name)
|
||||
.unwrap_or_else(|| panic!("unknown recipe name: {}. Try template?", name))
|
||||
}
|
||||
pub fn template(&self, name: &str) -> &Template {
|
||||
self.templates
|
||||
.iter()
|
||||
.find(|recipe| recipe.name() == name)
|
||||
.expect(&format!("unknown tail recipe name: {}. Try recipe?", name))
|
||||
.unwrap_or_else(|| panic!("unknown tail recipe name: {}. Try recipe?", name))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ impl<'builder> RecipeGroup<'builder> {
|
||||
|
||||
/// Given a sequence of opcode bytes, compute the recipe name prefix and encoding bits.
|
||||
fn decode_opcodes(op_bytes: &[u8], rrr: u16, w: u16) -> (&'static str, u16) {
|
||||
assert!(op_bytes.len() >= 1, "at least one opcode byte");
|
||||
assert!(!op_bytes.is_empty(), "at least one opcode byte");
|
||||
|
||||
let prefix_bytes = &op_bytes[..op_bytes.len() - 1];
|
||||
let (name, mmpp) = match prefix_bytes {
|
||||
@@ -121,7 +121,7 @@ fn decode_opcodes(op_bytes: &[u8], rrr: u16, w: u16) -> (&'static str, u16) {
|
||||
}
|
||||
};
|
||||
|
||||
let opcode_byte = op_bytes[op_bytes.len() - 1] as u16;
|
||||
let opcode_byte = u16::from(op_bytes[op_bytes.len() - 1]);
|
||||
(name, opcode_byte | (mmpp << 8) | (rrr << 12) | w << 15)
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ impl<'builder> Template<'builder> {
|
||||
if let Some(prefixed) = &self.when_prefixed {
|
||||
let mut ret = prefixed.rex();
|
||||
// Forward specialized parameters.
|
||||
ret.op_bytes = self.op_bytes.clone();
|
||||
ret.op_bytes = self.op_bytes;
|
||||
ret.w_bit = self.w_bit;
|
||||
ret.rrr_bits = self.rrr_bits;
|
||||
return ret;
|
||||
@@ -266,18 +266,17 @@ impl<'builder> Template<'builder> {
|
||||
self.recipe.base_size += size_addendum;
|
||||
|
||||
// Branch ranges are relative to the end of the instruction.
|
||||
self.recipe
|
||||
.branch_range
|
||||
.as_mut()
|
||||
.map(|range| range.inst_size += size_addendum);
|
||||
if let Some(range) = self.recipe.branch_range.as_mut() {
|
||||
range.inst_size += size_addendum;
|
||||
}
|
||||
|
||||
self.recipe.emit = replace_put_op(self.recipe.emit, &name);
|
||||
self.recipe.name = name + &self.recipe.name;
|
||||
|
||||
if !self.rex {
|
||||
let operands_in = self.recipe.operands_in.unwrap_or(Vec::new());
|
||||
let operands_in = self.recipe.operands_in.unwrap_or_default();
|
||||
self.recipe.operands_in = Some(replace_nonrex_constraints(self.regs, operands_in));
|
||||
let operands_out = self.recipe.operands_out.unwrap_or(Vec::new());
|
||||
let operands_out = self.recipe.operands_out.unwrap_or_default();
|
||||
self.recipe.operands_out = Some(replace_nonrex_constraints(self.regs, operands_out));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
|
||||
}
|
||||
|
||||
/// Generates all the Rust source files used in Cranelift from the meta-language.
|
||||
pub fn generate(isas: &Vec<isa::Isa>, out_dir: &str) -> Result<(), error::Error> {
|
||||
pub fn generate(isas: &[isa::Isa], out_dir: &str) -> Result<(), error::Error> {
|
||||
// Create all the definitions:
|
||||
// - common definitions.
|
||||
let mut shared_defs = shared::define();
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::shared::formats::Formats;
|
||||
use crate::shared::types;
|
||||
use crate::shared::{entities::EntityRefs, immediates::Immediates};
|
||||
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
pub(crate) fn define(
|
||||
all_instructions: &mut AllInstructions,
|
||||
formats: &Formats,
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::shared::types::Float::{F32, F64};
|
||||
use crate::shared::types::Int::{I128, I16, I32, I64, I8};
|
||||
use cranelift_codegen_shared::condcodes::{CondCode, IntCC};
|
||||
|
||||
#[allow(clippy::many_single_char_names, clippy::cognitive_complexity)]
|
||||
pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGroups {
|
||||
let mut narrow = TransformGroupBuilder::new(
|
||||
"narrow",
|
||||
@@ -766,24 +767,24 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
|
||||
expand.legalize(
|
||||
def!(a = bitrev.I32(x)),
|
||||
vec![
|
||||
def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaaaaaaaa))),
|
||||
def!(a1 = band_imm(x, Literal::constant(&imm.imm64, 0xaaaa_aaaa))),
|
||||
def!(a2 = ushr_imm(a1, imm64_1)),
|
||||
def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x55555555))),
|
||||
def!(a3 = band_imm(x, Literal::constant(&imm.imm64, 0x5555_5555))),
|
||||
def!(a4 = ishl_imm(a3, imm64_1)),
|
||||
def!(b = bor(a2, a4)),
|
||||
def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcccccccc))),
|
||||
def!(b1 = band_imm(b, Literal::constant(&imm.imm64, 0xcccc_cccc))),
|
||||
def!(b2 = ushr_imm(b1, imm64_2)),
|
||||
def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x33333333))),
|
||||
def!(b3 = band_imm(b, Literal::constant(&imm.imm64, 0x3333_3333))),
|
||||
def!(b4 = ishl_imm(b3, imm64_2)),
|
||||
def!(c = bor(b2, b4)),
|
||||
def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0f0f0f0))),
|
||||
def!(c1 = band_imm(c, Literal::constant(&imm.imm64, 0xf0f0_f0f0))),
|
||||
def!(c2 = ushr_imm(c1, imm64_4)),
|
||||
def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f0f0f0f))),
|
||||
def!(c3 = band_imm(c, Literal::constant(&imm.imm64, 0x0f0f_0f0f))),
|
||||
def!(c4 = ishl_imm(c3, imm64_4)),
|
||||
def!(d = bor(c2, c4)),
|
||||
def!(d1 = band_imm(d, Literal::constant(&imm.imm64, 0xff00ff00))),
|
||||
def!(d1 = band_imm(d, Literal::constant(&imm.imm64, 0xff00_ff00))),
|
||||
def!(d2 = ushr_imm(d1, imm64_8)),
|
||||
def!(d3 = band_imm(d, Literal::constant(&imm.imm64, 0x00ff00ff))),
|
||||
def!(d3 = band_imm(d, Literal::constant(&imm.imm64, 0x00ff_00ff))),
|
||||
def!(d4 = ishl_imm(d3, imm64_8)),
|
||||
def!(e = bor(d2, d4)),
|
||||
def!(e1 = ushr_imm(e, imm64_16)),
|
||||
@@ -793,20 +794,20 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
|
||||
);
|
||||
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(&imm.imm64, 0xaaaaaaaaaaaaaaaa);
|
||||
let imm64_0x5555555555555555 = Literal::constant(&imm.imm64, 0x5555555555555555);
|
||||
let imm64_0xaaaaaaaaaaaaaaaa = Literal::constant(&imm.imm64, 0xaaaa_aaaa_aaaa_aaaa);
|
||||
let imm64_0x5555555555555555 = Literal::constant(&imm.imm64, 0x5555_5555_5555_5555);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xcccccccccccccccc = Literal::constant(&imm.imm64, 0xcccccccccccccccc);
|
||||
let imm64_0x3333333333333333 = Literal::constant(&imm.imm64, 0x3333333333333333);
|
||||
let imm64_0xcccccccccccccccc = Literal::constant(&imm.imm64, 0xcccc_cccc_cccc_cccc);
|
||||
let imm64_0x3333333333333333 = Literal::constant(&imm.imm64, 0x3333_3333_3333_3333);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(&imm.imm64, 0xf0f0f0f0f0f0f0f0);
|
||||
let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(&imm.imm64, 0x0f0f0f0f0f0f0f0f);
|
||||
let imm64_0xf0f0f0f0f0f0f0f0 = Literal::constant(&imm.imm64, 0xf0f0_f0f0_f0f0_f0f0);
|
||||
let imm64_0x0f0f0f0f0f0f0f0f = Literal::constant(&imm.imm64, 0x0f0f_0f0f_0f0f_0f0f);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xff00ff00ff00ff00 = Literal::constant(&imm.imm64, 0xff00ff00ff00ff00);
|
||||
let imm64_0x00ff00ff00ff00ff = Literal::constant(&imm.imm64, 0x00ff00ff00ff00ff);
|
||||
let imm64_0xff00ff00ff00ff00 = Literal::constant(&imm.imm64, 0xff00_ff00_ff00_ff00);
|
||||
let imm64_0x00ff00ff00ff00ff = Literal::constant(&imm.imm64, 0x00ff_00ff_00ff_00ff);
|
||||
#[allow(overflowing_literals)]
|
||||
let imm64_0xffff0000ffff0000 = Literal::constant(&imm.imm64, 0xffff0000ffff0000);
|
||||
let imm64_0x0000ffff0000ffff = Literal::constant(&imm.imm64, 0x0000ffff0000ffff);
|
||||
let imm64_0xffff0000ffff0000 = Literal::constant(&imm.imm64, 0xffff_0000_ffff_0000);
|
||||
let imm64_0x0000ffff0000ffff = Literal::constant(&imm.imm64, 0x0000_ffff_0000_ffff);
|
||||
let imm64_32 = Literal::constant(&imm.imm64, 32);
|
||||
|
||||
expand.legalize(
|
||||
@@ -845,11 +846,11 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro
|
||||
|
||||
// Floating-point sign manipulations.
|
||||
for &(ty, const_inst, minus_zero) in &[
|
||||
(F32, f32const, &Literal::bits(&imm.ieee32, 0x80000000)),
|
||||
(F32, f32const, &Literal::bits(&imm.ieee32, 0x8000_0000)),
|
||||
(
|
||||
F64,
|
||||
f64const,
|
||||
&Literal::bits(&imm.ieee64, 0x8000000000000000),
|
||||
&Literal::bits(&imm.ieee64, 0x8000_0000_0000_0000),
|
||||
),
|
||||
] {
|
||||
expand.legalize(
|
||||
|
||||
@@ -139,7 +139,7 @@ impl Formatter {
|
||||
parse_multiline(contents.as_ref())
|
||||
.iter()
|
||||
.map(|l| {
|
||||
if l.len() == 0 {
|
||||
if l.is_empty() {
|
||||
"///".into()
|
||||
} else {
|
||||
format!("/// {}", l)
|
||||
@@ -157,7 +157,7 @@ impl Formatter {
|
||||
let conditions = names
|
||||
.iter()
|
||||
.map(|name| {
|
||||
if fields.len() > 0 {
|
||||
if !fields.is_empty() {
|
||||
format!("{} {{ {} }}", name, fields.join(", "))
|
||||
} else {
|
||||
name.clone()
|
||||
|
||||
@@ -48,8 +48,8 @@ impl<T: PartialEq + Clone> UniqueSeqTable<T> {
|
||||
pub fn new() -> Self {
|
||||
Self { table: Vec::new() }
|
||||
}
|
||||
pub fn add(&mut self, values: &Vec<T>) -> usize {
|
||||
if values.len() == 0 {
|
||||
pub fn add(&mut self, values: &[T]) -> usize {
|
||||
if values.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
if let Some(offset) = find_subsequence(values, &self.table) {
|
||||
@@ -87,19 +87,19 @@ impl<T: PartialEq + Clone> UniqueSeqTable<T> {
|
||||
/// Try to find the subsequence `sub` in the `whole` sequence. Returns None if
|
||||
/// it's not been found, or Some(index) if it has been. Naive implementation
|
||||
/// until proven we need something better.
|
||||
fn find_subsequence<T: PartialEq>(sub: &Vec<T>, whole: &Vec<T>) -> Option<usize> {
|
||||
assert!(sub.len() > 0);
|
||||
fn find_subsequence<T: PartialEq>(sub: &[T], whole: &[T]) -> Option<usize> {
|
||||
assert!(!sub.is_empty());
|
||||
// We want i + sub.len() <= whole.len(), i.e. i < whole.len() + 1 - sub.len().
|
||||
if whole.len() < sub.len() {
|
||||
return None;
|
||||
}
|
||||
let max = whole.len() - sub.len();
|
||||
for i in 0..max + 1 {
|
||||
for i in 0..=max {
|
||||
if whole[i..i + sub.len()] == sub[..] {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -24,6 +24,7 @@ pub fn simple_hash(s: &str) -> usize {
|
||||
/// Compute an open addressed, quadratically probed hash table containing
|
||||
/// `items`. The returned table is a list containing the elements of the
|
||||
/// iterable `items` and `None` in unused slots.
|
||||
#[allow(clippy::float_arithmetic)]
|
||||
pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
|
||||
items: I,
|
||||
num_items: usize,
|
||||
|
||||
@@ -26,13 +26,13 @@ pub enum ArgAction {
|
||||
|
||||
impl From<ArgumentLoc> for ArgAction {
|
||||
fn from(x: ArgumentLoc) -> Self {
|
||||
ArgAction::Assign(x)
|
||||
Self::Assign(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValueConversion> for ArgAction {
|
||||
fn from(x: ValueConversion) -> Self {
|
||||
ArgAction::Convert(x)
|
||||
Self::Convert(x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,17 +59,17 @@ impl ValueConversion {
|
||||
/// Apply this conversion to a type, return the converted type.
|
||||
pub fn apply(self, ty: Type) -> Type {
|
||||
match self {
|
||||
ValueConversion::IntSplit => ty.half_width().expect("Integer type too small to split"),
|
||||
ValueConversion::VectorSplit => ty.half_vector().expect("Not a vector"),
|
||||
ValueConversion::IntBits => Type::int(ty.bits()).expect("Bad integer size"),
|
||||
ValueConversion::Sext(nty) | ValueConversion::Uext(nty) => nty,
|
||||
Self::IntSplit => ty.half_width().expect("Integer type too small to split"),
|
||||
Self::VectorSplit => ty.half_vector().expect("Not a vector"),
|
||||
Self::IntBits => Type::int(ty.bits()).expect("Bad integer size"),
|
||||
Self::Sext(nty) | Self::Uext(nty) => nty,
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this a split conversion that results in two arguments?
|
||||
pub fn is_split(self) -> bool {
|
||||
match self {
|
||||
ValueConversion::IntSplit | ValueConversion::VectorSplit => true,
|
||||
Self::IntSplit | Self::VectorSplit => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,14 +63,14 @@ impl fmt::Display for Reloc {
|
||||
/// already unambiguous, e.g. clif syntax with isa specified. In other contexts, use Debug.
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Reloc::Abs4 => write!(f, "Abs4"),
|
||||
Reloc::Abs8 => write!(f, "Abs8"),
|
||||
Reloc::X86PCRel4 => write!(f, "PCRel4"),
|
||||
Reloc::X86PCRelRodata4 => write!(f, "PCRelRodata4"),
|
||||
Reloc::X86CallPCRel4 => write!(f, "CallPCRel4"),
|
||||
Reloc::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
|
||||
Reloc::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
|
||||
Reloc::Arm32Call | Reloc::Arm64Call | Reloc::RiscvCall => write!(f, "Call"),
|
||||
Self::Abs4 => write!(f, "Abs4"),
|
||||
Self::Abs8 => write!(f, "Abs8"),
|
||||
Self::X86PCRel4 => write!(f, "PCRel4"),
|
||||
Self::X86PCRelRodata4 => write!(f, "PCRelRodata4"),
|
||||
Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
|
||||
Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
|
||||
Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
|
||||
Self::Arm32Call | Self::Arm64Call | Self::RiscvCall => write!(f, "Call"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ fn try_fold_redundant_jump(
|
||||
let arguments_vec: alloc::vec::Vec<_> = first_args
|
||||
.iter()
|
||||
.chain(second_params.iter())
|
||||
.map(|x| *x)
|
||||
.copied()
|
||||
.collect();
|
||||
let value_list = ValueList::from_slice(&arguments_vec, &mut func.dfg.value_lists);
|
||||
|
||||
@@ -255,7 +255,7 @@ fn try_fold_redundant_jump(
|
||||
func.layout.remove_ebb(first_dest); // ...from the layout.
|
||||
}
|
||||
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
/// Redirects `jump` instructions that point to other `jump` instructions to the final destination.
|
||||
|
||||
@@ -55,7 +55,7 @@ impl Stackmap {
|
||||
}
|
||||
}
|
||||
|
||||
Stackmap::from_slice(&vec)
|
||||
Self::from_slice(&vec)
|
||||
}
|
||||
|
||||
/// Create a vec of Bitsets from a slice of bools.
|
||||
|
||||
@@ -74,7 +74,7 @@ where
|
||||
|
||||
let lo_rng = (one << lo) - one;
|
||||
|
||||
BitSet(hi_rng - lo_rng)
|
||||
Self(hi_rng - lo_rng)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -645,13 +645,14 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut FuncCursor<'f> {
|
||||
let prev_op = self.data_flow_graph()[prev].opcode();
|
||||
let inst_op = self.data_flow_graph()[inst].opcode();
|
||||
let curr_op = self.data_flow_graph()[curr].opcode();
|
||||
if prev_op.is_branch() && !prev_op.is_terminator() {
|
||||
if !inst_op.is_terminator() {
|
||||
panic!(
|
||||
"Inserting instruction {} after {}, and before {}",
|
||||
inst_op, prev_op, curr_op
|
||||
)
|
||||
};
|
||||
if prev_op.is_branch()
|
||||
&& !prev_op.is_terminator()
|
||||
&& !inst_op.is_terminator()
|
||||
{
|
||||
panic!(
|
||||
"Inserting instruction {} after {}, and before {}",
|
||||
inst_op, prev_op, curr_op
|
||||
)
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -773,15 +774,16 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> {
|
||||
if let Some(prev) = self.layout().prev_inst(curr) {
|
||||
let prev_op = self.data_flow_graph()[prev].opcode();
|
||||
let inst_op = self.data_flow_graph()[inst].opcode();
|
||||
if prev_op.is_branch() && !prev_op.is_terminator() {
|
||||
if !inst_op.is_terminator() {
|
||||
panic!(
|
||||
"Inserting instruction {} after {} and before {}",
|
||||
self.display_inst(inst),
|
||||
self.display_inst(prev),
|
||||
self.display_inst(curr)
|
||||
)
|
||||
};
|
||||
if prev_op.is_branch()
|
||||
&& !prev_op.is_terminator()
|
||||
&& !inst_op.is_terminator()
|
||||
{
|
||||
panic!(
|
||||
"Inserting instruction {} after {} and before {}",
|
||||
self.display_inst(inst),
|
||||
self.display_inst(prev),
|
||||
self.display_inst(curr)
|
||||
)
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ pub fn magic_u32(d: u32) -> MU32 {
|
||||
|
||||
MU32 {
|
||||
mul_by: q2 + 1,
|
||||
do_add: do_add,
|
||||
do_add,
|
||||
shift_by: p - 32,
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ pub fn magic_u64(d: u64) -> MU64 {
|
||||
|
||||
MU64 {
|
||||
mul_by: q2 + 1,
|
||||
do_add: do_add,
|
||||
do_add,
|
||||
shift_by: p - 64,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ pub struct ConstantData(Vec<u8>);
|
||||
impl FromIterator<u8> for ConstantData {
|
||||
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
|
||||
let v = iter.into_iter().collect();
|
||||
ConstantData(v)
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ impl ConstantData {
|
||||
}
|
||||
|
||||
/// Convert the data to a vector.
|
||||
pub fn to_vec(self) -> Vec<u8> {
|
||||
pub fn into_vec(self) -> Vec<u8> {
|
||||
self.0
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ impl FromStr for ConstantData {
|
||||
/// ```
|
||||
/// use cranelift_codegen::ir::ConstantData;
|
||||
/// let c: ConstantData = "0x000102".parse().unwrap();
|
||||
/// assert_eq!(c.to_vec(), [2, 1, 0]);
|
||||
/// assert_eq!(c.into_vec(), [2, 1, 0]);
|
||||
/// ```
|
||||
fn from_str(s: &str) -> Result<Self, &'static str> {
|
||||
if s.len() <= 2 || &s[0..2] != "0x" {
|
||||
@@ -137,7 +137,7 @@ impl FromStr for ConstantData {
|
||||
.cloned()
|
||||
.collect(); // remove 0x prefix and any intervening _ characters
|
||||
|
||||
if cleaned.len() == 0 {
|
||||
if cleaned.is_empty() {
|
||||
Err("Hexadecimal string must have some digits")
|
||||
} else if cleaned.len() % 2 != 0 {
|
||||
Err("Hexadecimal string must have an even number of digits")
|
||||
@@ -152,7 +152,7 @@ impl FromStr for ConstantData {
|
||||
.or_else(|_| Err("Unable to parse as hexadecimal"))?;
|
||||
buffer.insert(0, byte);
|
||||
}
|
||||
Ok(ConstantData(buffer))
|
||||
Ok(Self(buffer))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,15 +221,13 @@ impl ConstantPool {
|
||||
/// returned.
|
||||
pub fn insert(&mut self, constant_value: ConstantData) -> Constant {
|
||||
if self.values_to_handles.contains_key(&constant_value) {
|
||||
self.values_to_handles.get(&constant_value).unwrap().clone()
|
||||
*self.values_to_handles.get(&constant_value).unwrap()
|
||||
} else {
|
||||
let constant_handle = Constant::new(self.len());
|
||||
self.values_to_handles
|
||||
.insert(constant_value.clone(), constant_handle.clone());
|
||||
self.handles_to_values.insert(
|
||||
constant_handle.clone(),
|
||||
ConstantPoolEntry::new(constant_value),
|
||||
);
|
||||
.insert(constant_value.clone(), constant_handle);
|
||||
self.handles_to_values
|
||||
.insert(constant_handle, ConstantPoolEntry::new(constant_value));
|
||||
constant_handle
|
||||
}
|
||||
}
|
||||
@@ -402,13 +400,13 @@ mod tests {
|
||||
fn add_to_constant_data() {
|
||||
let d = ConstantData::from([1, 2].as_ref());
|
||||
let e = d.append(i16::from(3u8));
|
||||
assert_eq!(e.to_vec(), vec![1, 2, 3, 0])
|
||||
assert_eq!(e.into_vec(), vec![1, 2, 3, 0])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extend_constant_data() {
|
||||
let d = ConstantData::from([1, 2].as_ref());
|
||||
assert_eq!(d.expand_to(4).to_vec(), vec![1, 2, 0, 0])
|
||||
assert_eq!(d.expand_to(4).into_vec(), vec![1, 2, 0, 0])
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -460,7 +458,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn verify_stored_bytes_in_constant_data() {
|
||||
assert_eq!("0x01".parse::<ConstantData>().unwrap().to_vec(), [1]);
|
||||
assert_eq!("0x01".parse::<ConstantData>().unwrap().into_vec(), [1]);
|
||||
assert_eq!(ConstantData::from([1, 0].as_ref()).0, [1, 0]);
|
||||
assert_eq!(ConstantData::from(vec![1, 0, 0, 0]).0, [1, 0, 0, 0]);
|
||||
}
|
||||
@@ -468,7 +466,10 @@ mod tests {
|
||||
#[test]
|
||||
fn check_constant_data_endianness_as_uimm128() {
|
||||
fn parse_to_uimm128(from: &str) -> Vec<u8> {
|
||||
from.parse::<ConstantData>().unwrap().expand_to(16).to_vec()
|
||||
from.parse::<ConstantData>()
|
||||
.unwrap()
|
||||
.expand_to(16)
|
||||
.into_vec()
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
|
||||
@@ -378,7 +378,7 @@ impl ValueDef {
|
||||
/// Unwrap the instruction where the value was defined, or panic.
|
||||
pub fn unwrap_inst(&self) -> Inst {
|
||||
match *self {
|
||||
ValueDef::Result(inst, _) => inst,
|
||||
Self::Result(inst, _) => inst,
|
||||
_ => panic!("Value is not an instruction result"),
|
||||
}
|
||||
}
|
||||
@@ -386,7 +386,7 @@ impl ValueDef {
|
||||
/// Unwrap the EBB there the parameter is defined, or panic.
|
||||
pub fn unwrap_ebb(&self) -> Ebb {
|
||||
match *self {
|
||||
ValueDef::Param(ebb, _) => ebb,
|
||||
Self::Param(ebb, _) => ebb,
|
||||
_ => panic!("Value is not an EBB parameter"),
|
||||
}
|
||||
}
|
||||
@@ -402,7 +402,7 @@ impl ValueDef {
|
||||
/// this value.
|
||||
pub fn num(self) -> usize {
|
||||
match self {
|
||||
ValueDef::Result(_, n) | ValueDef::Param(_, n) => n,
|
||||
Self::Result(_, n) | Self::Param(_, n) => n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ impl Ebb {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(Ebb(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -72,7 +72,7 @@ impl Value {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX / 2 {
|
||||
Some(Value(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -118,7 +118,7 @@ impl StackSlot {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(StackSlot(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -152,7 +152,7 @@ impl GlobalValue {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(GlobalValue(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -174,7 +174,7 @@ impl Constant {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(Constant(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -197,7 +197,7 @@ impl Immediate {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(Immediate(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -225,7 +225,7 @@ impl JumpTable {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(JumpTable(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -258,7 +258,7 @@ impl FuncRef {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(FuncRef(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -287,7 +287,7 @@ impl SigRef {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(SigRef(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -310,7 +310,7 @@ impl Heap {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(Heap(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -334,7 +334,7 @@ impl Table {
|
||||
/// This method is for use by the parser.
|
||||
pub fn with_number(n: u32) -> Option<Self> {
|
||||
if n < u32::MAX {
|
||||
Some(Table(n))
|
||||
Some(Self(n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -371,17 +371,17 @@ pub enum AnyEntity {
|
||||
impl fmt::Display for AnyEntity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
AnyEntity::Function => write!(f, "function"),
|
||||
AnyEntity::Ebb(r) => r.fmt(f),
|
||||
AnyEntity::Inst(r) => r.fmt(f),
|
||||
AnyEntity::Value(r) => r.fmt(f),
|
||||
AnyEntity::StackSlot(r) => r.fmt(f),
|
||||
AnyEntity::GlobalValue(r) => r.fmt(f),
|
||||
AnyEntity::JumpTable(r) => r.fmt(f),
|
||||
AnyEntity::FuncRef(r) => r.fmt(f),
|
||||
AnyEntity::SigRef(r) => r.fmt(f),
|
||||
AnyEntity::Heap(r) => r.fmt(f),
|
||||
AnyEntity::Table(r) => r.fmt(f),
|
||||
Self::Function => write!(f, "function"),
|
||||
Self::Ebb(r) => r.fmt(f),
|
||||
Self::Inst(r) => r.fmt(f),
|
||||
Self::Value(r) => r.fmt(f),
|
||||
Self::StackSlot(r) => r.fmt(f),
|
||||
Self::GlobalValue(r) => r.fmt(f),
|
||||
Self::JumpTable(r) => r.fmt(f),
|
||||
Self::FuncRef(r) => r.fmt(f),
|
||||
Self::SigRef(r) => r.fmt(f),
|
||||
Self::Heap(r) => r.fmt(f),
|
||||
Self::Table(r) => r.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -394,61 +394,61 @@ impl fmt::Debug for AnyEntity {
|
||||
|
||||
impl From<Ebb> for AnyEntity {
|
||||
fn from(r: Ebb) -> Self {
|
||||
AnyEntity::Ebb(r)
|
||||
Self::Ebb(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Inst> for AnyEntity {
|
||||
fn from(r: Inst) -> Self {
|
||||
AnyEntity::Inst(r)
|
||||
Self::Inst(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Value> for AnyEntity {
|
||||
fn from(r: Value) -> Self {
|
||||
AnyEntity::Value(r)
|
||||
Self::Value(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StackSlot> for AnyEntity {
|
||||
fn from(r: StackSlot) -> Self {
|
||||
AnyEntity::StackSlot(r)
|
||||
Self::StackSlot(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GlobalValue> for AnyEntity {
|
||||
fn from(r: GlobalValue) -> Self {
|
||||
AnyEntity::GlobalValue(r)
|
||||
Self::GlobalValue(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JumpTable> for AnyEntity {
|
||||
fn from(r: JumpTable) -> Self {
|
||||
AnyEntity::JumpTable(r)
|
||||
Self::JumpTable(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FuncRef> for AnyEntity {
|
||||
fn from(r: FuncRef) -> Self {
|
||||
AnyEntity::FuncRef(r)
|
||||
Self::FuncRef(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SigRef> for AnyEntity {
|
||||
fn from(r: SigRef) -> Self {
|
||||
AnyEntity::SigRef(r)
|
||||
Self::SigRef(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Heap> for AnyEntity {
|
||||
fn from(r: Heap) -> Self {
|
||||
AnyEntity::Heap(r)
|
||||
Self::Heap(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Table> for AnyEntity {
|
||||
fn from(r: Table) -> Self {
|
||||
AnyEntity::Table(r)
|
||||
Self::Table(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,14 +294,14 @@ impl FromStr for ArgumentPurpose {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, ()> {
|
||||
match s {
|
||||
"normal" => Ok(ArgumentPurpose::Normal),
|
||||
"sret" => Ok(ArgumentPurpose::StructReturn),
|
||||
"link" => Ok(ArgumentPurpose::Link),
|
||||
"fp" => Ok(ArgumentPurpose::FramePointer),
|
||||
"csr" => Ok(ArgumentPurpose::CalleeSaved),
|
||||
"vmctx" => Ok(ArgumentPurpose::VMContext),
|
||||
"sigid" => Ok(ArgumentPurpose::SignatureId),
|
||||
"stack_limit" => Ok(ArgumentPurpose::StackLimit),
|
||||
"normal" => Ok(Self::Normal),
|
||||
"sret" => Ok(Self::StructReturn),
|
||||
"link" => Ok(Self::Link),
|
||||
"fp" => Ok(Self::FramePointer),
|
||||
"csr" => Ok(Self::CalleeSaved),
|
||||
"vmctx" => Ok(Self::VMContext),
|
||||
"sigid" => Ok(Self::SignatureId),
|
||||
"stack_limit" => Ok(Self::StackLimit),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl ExternalName {
|
||||
let mut bytes = [0u8; TESTCASE_NAME_LENGTH];
|
||||
bytes[0..len].copy_from_slice(&vec[0..len]);
|
||||
|
||||
ExternalName::TestCase {
|
||||
Self::TestCase {
|
||||
length: len as u8,
|
||||
ascii: bytes,
|
||||
}
|
||||
@@ -78,7 +78,7 @@ impl ExternalName {
|
||||
/// assert_eq!(name.to_string(), "u123:456");
|
||||
/// ```
|
||||
pub fn user(namespace: u32, index: u32) -> Self {
|
||||
ExternalName::User { namespace, index }
|
||||
Self::User { namespace, index }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,15 +91,15 @@ impl Default for ExternalName {
|
||||
impl fmt::Display for ExternalName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ExternalName::User { namespace, index } => write!(f, "u{}:{}", namespace, index),
|
||||
ExternalName::TestCase { length, ascii } => {
|
||||
Self::User { namespace, index } => write!(f, "u{}:{}", namespace, index),
|
||||
Self::TestCase { length, ascii } => {
|
||||
f.write_char('%')?;
|
||||
for byte in ascii.iter().take(length as usize) {
|
||||
f.write_char(*byte as char)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
ExternalName::LibCall(lc) => write!(f, "%{}", lc),
|
||||
Self::LibCall(lc) => write!(f, "%{}", lc),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ impl FromStr for ExternalName {
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
// Try to parse as a libcall name, otherwise it's a test case.
|
||||
match s.parse() {
|
||||
Ok(lc) => Ok(ExternalName::LibCall(lc)),
|
||||
Ok(lc) => Ok(Self::LibCall(lc)),
|
||||
Err(_) => Ok(Self::testcase(s.as_bytes())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl GlobalValueData {
|
||||
/// Assume that `self` is an `GlobalValueData::Symbol` and return its name.
|
||||
pub fn symbol_name(&self) -> &ExternalName {
|
||||
match *self {
|
||||
GlobalValueData::Symbol { ref name, .. } => name,
|
||||
Self::Symbol { ref name, .. } => name,
|
||||
_ => panic!("only symbols have names"),
|
||||
}
|
||||
}
|
||||
@@ -78,11 +78,8 @@ impl GlobalValueData {
|
||||
/// Return the type of this global.
|
||||
pub fn global_type(&self, isa: &dyn TargetIsa) -> Type {
|
||||
match *self {
|
||||
GlobalValueData::VMContext { .. } | GlobalValueData::Symbol { .. } => {
|
||||
isa.pointer_type()
|
||||
}
|
||||
GlobalValueData::IAddImm { global_type, .. }
|
||||
| GlobalValueData::Load { global_type, .. } => global_type,
|
||||
Self::VMContext { .. } | Self::Symbol { .. } => isa.pointer_type(),
|
||||
Self::IAddImm { global_type, .. } | Self::Load { global_type, .. } => global_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,8 +87,8 @@ impl GlobalValueData {
|
||||
impl fmt::Display for GlobalValueData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
GlobalValueData::VMContext => write!(f, "vmctx"),
|
||||
GlobalValueData::Load {
|
||||
Self::VMContext => write!(f, "vmctx"),
|
||||
Self::Load {
|
||||
base,
|
||||
offset,
|
||||
global_type,
|
||||
@@ -104,12 +101,12 @@ impl fmt::Display for GlobalValueData {
|
||||
base,
|
||||
offset
|
||||
),
|
||||
GlobalValueData::IAddImm {
|
||||
Self::IAddImm {
|
||||
global_type,
|
||||
base,
|
||||
offset,
|
||||
} => write!(f, "iadd_imm.{} {}, {}", global_type, base, offset),
|
||||
GlobalValueData::Symbol {
|
||||
Self::Symbol {
|
||||
ref name,
|
||||
offset,
|
||||
colocated,
|
||||
|
||||
@@ -50,12 +50,12 @@ pub struct Imm64(i64);
|
||||
impl Imm64 {
|
||||
/// Create a new `Imm64` representing the signed number `x`.
|
||||
pub fn new(x: i64) -> Self {
|
||||
Imm64(x)
|
||||
Self(x)
|
||||
}
|
||||
|
||||
/// Return self negated.
|
||||
pub fn wrapping_neg(self) -> Self {
|
||||
Imm64(self.0.wrapping_neg())
|
||||
Self(self.0.wrapping_neg())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ impl IntoBytes for Imm64 {
|
||||
|
||||
impl From<i64> for Imm64 {
|
||||
fn from(x: i64) -> Self {
|
||||
Imm64(x)
|
||||
Self(x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,12 +130,12 @@ pub struct Uimm64(u64);
|
||||
impl Uimm64 {
|
||||
/// Create a new `Uimm64` representing the unsigned number `x`.
|
||||
pub fn new(x: u64) -> Self {
|
||||
Uimm64(x)
|
||||
Self(x)
|
||||
}
|
||||
|
||||
/// Return self negated.
|
||||
pub fn wrapping_neg(self) -> Self {
|
||||
Uimm64(self.0.wrapping_neg())
|
||||
Self(self.0.wrapping_neg())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ impl Into<u64> for Uimm64 {
|
||||
|
||||
impl From<u64> for Uimm64 {
|
||||
fn from(x: u64) -> Self {
|
||||
Uimm64(x)
|
||||
Self(x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ impl Into<i64> for Uimm32 {
|
||||
|
||||
impl From<u32> for Uimm32 {
|
||||
fn from(x: u32) -> Self {
|
||||
Uimm32(x)
|
||||
Self(x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ impl FromStr for Uimm32 {
|
||||
fn from_str(s: &str) -> Result<Self, &'static str> {
|
||||
parse_i64(s).and_then(|x| {
|
||||
if 0 <= x && x <= i64::from(u32::MAX) {
|
||||
Ok(Uimm32(x as u32))
|
||||
Ok(Self(x as u32))
|
||||
} else {
|
||||
Err("Uimm32 out of range")
|
||||
}
|
||||
@@ -329,7 +329,7 @@ impl From<&[u8]> for V128Imm {
|
||||
assert_eq!(slice.len(), 16);
|
||||
let mut buffer = [0; 16];
|
||||
buffer.copy_from_slice(slice);
|
||||
V128Imm(buffer)
|
||||
Self(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ pub struct Offset32(i32);
|
||||
impl Offset32 {
|
||||
/// Create a new `Offset32` representing the signed number `x`.
|
||||
pub fn new(x: i32) -> Self {
|
||||
Offset32(x)
|
||||
Self(x)
|
||||
}
|
||||
|
||||
/// Create a new `Offset32` representing the signed number `x` if possible.
|
||||
@@ -381,7 +381,7 @@ impl Into<i64> for Offset32 {
|
||||
|
||||
impl From<i32> for Offset32 {
|
||||
fn from(x: i32) -> Self {
|
||||
Offset32(x)
|
||||
Self(x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,7 +676,7 @@ fn parse_float(s: &str, w: u8, t: u8) -> Result<u64, &'static str> {
|
||||
impl Ieee32 {
|
||||
/// Create a new `Ieee32` containing the bits of `x`.
|
||||
pub fn with_bits(x: u32) -> Self {
|
||||
Ieee32(x)
|
||||
Self(x)
|
||||
}
|
||||
|
||||
/// Create an `Ieee32` number representing `2.0^n`.
|
||||
@@ -688,7 +688,7 @@ impl Ieee32 {
|
||||
let exponent = (n + bias) as u32;
|
||||
assert!(exponent > 0, "Underflow n={}", n);
|
||||
assert!(exponent < (1 << w) + 1, "Overflow n={}", n);
|
||||
Ieee32(exponent << t)
|
||||
Self(exponent << t)
|
||||
}
|
||||
|
||||
/// Create an `Ieee32` number representing the greatest negative value
|
||||
@@ -702,12 +702,12 @@ impl Ieee32 {
|
||||
|
||||
/// Return self negated.
|
||||
pub fn neg(self) -> Self {
|
||||
Ieee32(self.0 ^ (1 << 31))
|
||||
Self(self.0 ^ (1 << 31))
|
||||
}
|
||||
|
||||
/// Create a new `Ieee32` representing the number `x`.
|
||||
pub fn with_float(x: f32) -> Self {
|
||||
Ieee32(x.to_bits())
|
||||
Self(x.to_bits())
|
||||
}
|
||||
|
||||
/// Get the bitwise representation.
|
||||
@@ -728,7 +728,7 @@ impl FromStr for Ieee32 {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, &'static str> {
|
||||
match parse_float(s, 8, 23) {
|
||||
Ok(b) => Ok(Ieee32(b as u32)),
|
||||
Ok(b) => Ok(Self(b as u32)),
|
||||
Err(s) => Err(s),
|
||||
}
|
||||
}
|
||||
@@ -736,7 +736,7 @@ impl FromStr for Ieee32 {
|
||||
|
||||
impl From<f32> for Ieee32 {
|
||||
fn from(x: f32) -> Self {
|
||||
Ieee32::with_float(x)
|
||||
Self::with_float(x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,7 +749,7 @@ impl IntoBytes for Ieee32 {
|
||||
impl Ieee64 {
|
||||
/// Create a new `Ieee64` containing the bits of `x`.
|
||||
pub fn with_bits(x: u64) -> Self {
|
||||
Ieee64(x)
|
||||
Self(x)
|
||||
}
|
||||
|
||||
/// Create an `Ieee64` number representing `2.0^n`.
|
||||
@@ -761,7 +761,7 @@ impl Ieee64 {
|
||||
let exponent = (n + bias) as u64;
|
||||
assert!(exponent > 0, "Underflow n={}", n);
|
||||
assert!(exponent < (1 << w) + 1, "Overflow n={}", n);
|
||||
Ieee64(exponent << t)
|
||||
Self(exponent << t)
|
||||
}
|
||||
|
||||
/// Create an `Ieee64` number representing the greatest negative value
|
||||
@@ -775,12 +775,12 @@ impl Ieee64 {
|
||||
|
||||
/// Return self negated.
|
||||
pub fn neg(self) -> Self {
|
||||
Ieee64(self.0 ^ (1 << 63))
|
||||
Self(self.0 ^ (1 << 63))
|
||||
}
|
||||
|
||||
/// Create a new `Ieee64` representing the number `x`.
|
||||
pub fn with_float(x: f64) -> Self {
|
||||
Ieee64(x.to_bits())
|
||||
Self(x.to_bits())
|
||||
}
|
||||
|
||||
/// Get the bitwise representation.
|
||||
@@ -801,7 +801,7 @@ impl FromStr for Ieee64 {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, &'static str> {
|
||||
match parse_float(s, 11, 52) {
|
||||
Ok(b) => Ok(Ieee64(b)),
|
||||
Ok(b) => Ok(Self(b)),
|
||||
Err(s) => Err(s),
|
||||
}
|
||||
}
|
||||
@@ -809,13 +809,13 @@ impl FromStr for Ieee64 {
|
||||
|
||||
impl From<f64> for Ieee64 {
|
||||
fn from(x: f64) -> Self {
|
||||
Ieee64::with_float(x)
|
||||
Self::with_float(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Ieee64 {
|
||||
fn from(x: u64) -> Self {
|
||||
Ieee64::with_float(f64::from_bits(x))
|
||||
Self::with_float(f64::from_bits(x))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ pub struct VariableArgs(Vec<Value>);
|
||||
impl VariableArgs {
|
||||
/// Create an empty argument list.
|
||||
pub fn new() -> Self {
|
||||
VariableArgs(Vec::new())
|
||||
Self(Vec::new())
|
||||
}
|
||||
|
||||
/// Add an argument to the end.
|
||||
@@ -168,35 +168,35 @@ impl InstructionData {
|
||||
/// here.
|
||||
pub fn analyze_branch<'a>(&'a self, pool: &'a ValueListPool) -> BranchInfo<'a> {
|
||||
match *self {
|
||||
InstructionData::Jump {
|
||||
Self::Jump {
|
||||
destination,
|
||||
ref args,
|
||||
..
|
||||
} => BranchInfo::SingleDest(destination, args.as_slice(pool)),
|
||||
InstructionData::BranchInt {
|
||||
Self::BranchInt {
|
||||
destination,
|
||||
ref args,
|
||||
..
|
||||
}
|
||||
| InstructionData::BranchFloat {
|
||||
| Self::BranchFloat {
|
||||
destination,
|
||||
ref args,
|
||||
..
|
||||
}
|
||||
| InstructionData::Branch {
|
||||
| Self::Branch {
|
||||
destination,
|
||||
ref args,
|
||||
..
|
||||
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[1..]),
|
||||
InstructionData::BranchIcmp {
|
||||
Self::BranchIcmp {
|
||||
destination,
|
||||
ref args,
|
||||
..
|
||||
} => BranchInfo::SingleDest(destination, &args.as_slice(pool)[2..]),
|
||||
InstructionData::BranchTable {
|
||||
Self::BranchTable {
|
||||
table, destination, ..
|
||||
} => BranchInfo::Table(table, Some(destination)),
|
||||
InstructionData::IndirectJump { table, .. } => BranchInfo::Table(table, None),
|
||||
Self::IndirectJump { table, .. } => BranchInfo::Table(table, None),
|
||||
_ => {
|
||||
debug_assert!(!self.opcode().is_branch());
|
||||
BranchInfo::NotABranch
|
||||
@@ -210,12 +210,12 @@ impl InstructionData {
|
||||
/// Multi-destination branches like `br_table` return `None`.
|
||||
pub fn branch_destination(&self) -> Option<Ebb> {
|
||||
match *self {
|
||||
InstructionData::Jump { destination, .. }
|
||||
| InstructionData::Branch { destination, .. }
|
||||
| InstructionData::BranchInt { destination, .. }
|
||||
| InstructionData::BranchFloat { destination, .. }
|
||||
| InstructionData::BranchIcmp { destination, .. } => Some(destination),
|
||||
InstructionData::BranchTable { .. } | InstructionData::IndirectJump { .. } => None,
|
||||
Self::Jump { destination, .. }
|
||||
| Self::Branch { destination, .. }
|
||||
| Self::BranchInt { destination, .. }
|
||||
| Self::BranchFloat { destination, .. }
|
||||
| Self::BranchIcmp { destination, .. } => Some(destination),
|
||||
Self::BranchTable { .. } | Self::IndirectJump { .. } => None,
|
||||
_ => {
|
||||
debug_assert!(!self.opcode().is_branch());
|
||||
None
|
||||
@@ -229,27 +229,27 @@ impl InstructionData {
|
||||
/// Multi-destination branches like `br_table` return `None`.
|
||||
pub fn branch_destination_mut(&mut self) -> Option<&mut Ebb> {
|
||||
match *self {
|
||||
InstructionData::Jump {
|
||||
Self::Jump {
|
||||
ref mut destination,
|
||||
..
|
||||
}
|
||||
| InstructionData::Branch {
|
||||
| Self::Branch {
|
||||
ref mut destination,
|
||||
..
|
||||
}
|
||||
| InstructionData::BranchInt {
|
||||
| Self::BranchInt {
|
||||
ref mut destination,
|
||||
..
|
||||
}
|
||||
| InstructionData::BranchFloat {
|
||||
| Self::BranchFloat {
|
||||
ref mut destination,
|
||||
..
|
||||
}
|
||||
| InstructionData::BranchIcmp {
|
||||
| Self::BranchIcmp {
|
||||
ref mut destination,
|
||||
..
|
||||
} => Some(destination),
|
||||
InstructionData::BranchTable { .. } => None,
|
||||
Self::BranchTable { .. } => None,
|
||||
_ => {
|
||||
debug_assert!(!self.opcode().is_branch());
|
||||
None
|
||||
@@ -262,10 +262,10 @@ impl InstructionData {
|
||||
/// Any instruction that can call another function reveals its call signature here.
|
||||
pub fn analyze_call<'a>(&'a self, pool: &'a ValueListPool) -> CallInfo<'a> {
|
||||
match *self {
|
||||
InstructionData::Call {
|
||||
Self::Call {
|
||||
func_ref, ref args, ..
|
||||
} => CallInfo::Direct(func_ref, args.as_slice(pool)),
|
||||
InstructionData::CallIndirect {
|
||||
Self::CallIndirect {
|
||||
sig_ref, ref args, ..
|
||||
} => CallInfo::Indirect(sig_ref, &args.as_slice(pool)[1..]),
|
||||
_ => {
|
||||
|
||||
@@ -59,18 +59,18 @@ impl FromStr for LibCall {
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Probestack" => Ok(LibCall::Probestack),
|
||||
"CeilF32" => Ok(LibCall::CeilF32),
|
||||
"CeilF64" => Ok(LibCall::CeilF64),
|
||||
"FloorF32" => Ok(LibCall::FloorF32),
|
||||
"FloorF64" => Ok(LibCall::FloorF64),
|
||||
"TruncF32" => Ok(LibCall::TruncF32),
|
||||
"TruncF64" => Ok(LibCall::TruncF64),
|
||||
"NearestF32" => Ok(LibCall::NearestF32),
|
||||
"NearestF64" => Ok(LibCall::NearestF64),
|
||||
"Memcpy" => Ok(LibCall::Memcpy),
|
||||
"Memset" => Ok(LibCall::Memset),
|
||||
"Memmove" => Ok(LibCall::Memmove),
|
||||
"Probestack" => Ok(Self::Probestack),
|
||||
"CeilF32" => Ok(Self::CeilF32),
|
||||
"CeilF64" => Ok(Self::CeilF64),
|
||||
"FloorF32" => Ok(Self::FloorF32),
|
||||
"FloorF64" => Ok(Self::FloorF64),
|
||||
"TruncF32" => Ok(Self::TruncF32),
|
||||
"TruncF64" => Ok(Self::TruncF64),
|
||||
"NearestF32" => Ok(Self::NearestF32),
|
||||
"NearestF64" => Ok(Self::NearestF64),
|
||||
"Memcpy" => Ok(Self::Memcpy),
|
||||
"Memset" => Ok(Self::Memset),
|
||||
"Memmove" => Ok(Self::Memmove),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
@@ -84,17 +84,17 @@ impl LibCall {
|
||||
pub fn for_inst(opcode: Opcode, ctrl_type: Type) -> Option<Self> {
|
||||
Some(match ctrl_type {
|
||||
types::F32 => match opcode {
|
||||
Opcode::Ceil => LibCall::CeilF32,
|
||||
Opcode::Floor => LibCall::FloorF32,
|
||||
Opcode::Trunc => LibCall::TruncF32,
|
||||
Opcode::Nearest => LibCall::NearestF32,
|
||||
Opcode::Ceil => Self::CeilF32,
|
||||
Opcode::Floor => Self::FloorF32,
|
||||
Opcode::Trunc => Self::TruncF32,
|
||||
Opcode::Nearest => Self::NearestF32,
|
||||
_ => return None,
|
||||
},
|
||||
types::F64 => match opcode {
|
||||
Opcode::Ceil => LibCall::CeilF64,
|
||||
Opcode::Floor => LibCall::FloorF64,
|
||||
Opcode::Trunc => LibCall::TruncF64,
|
||||
Opcode::Nearest => LibCall::NearestF64,
|
||||
Opcode::Ceil => Self::CeilF64,
|
||||
Opcode::Floor => Self::FloorF64,
|
||||
Opcode::Trunc => Self::TruncF64,
|
||||
Opcode::Nearest => Self::NearestF64,
|
||||
_ => return None,
|
||||
},
|
||||
_ => return None,
|
||||
|
||||
@@ -20,7 +20,7 @@ impl From<Inst> for ProgramPoint {
|
||||
fn from(inst: Inst) -> Self {
|
||||
let idx = inst.index();
|
||||
debug_assert!(idx < (u32::MAX / 2) as usize);
|
||||
ProgramPoint((idx * 2) as u32)
|
||||
Self((idx * 2) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ impl From<Ebb> for ProgramPoint {
|
||||
fn from(ebb: Ebb) -> Self {
|
||||
let idx = ebb.index();
|
||||
debug_assert!(idx < (u32::MAX / 2) as usize);
|
||||
ProgramPoint((idx * 2 + 1) as u32)
|
||||
Self((idx * 2 + 1) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,21 +55,21 @@ impl ExpandedProgramPoint {
|
||||
/// Get the instruction we know is inside.
|
||||
pub fn unwrap_inst(self) -> Inst {
|
||||
match self {
|
||||
ExpandedProgramPoint::Inst(x) => x,
|
||||
ExpandedProgramPoint::Ebb(x) => panic!("expected inst: {}", x),
|
||||
Self::Inst(x) => x,
|
||||
Self::Ebb(x) => panic!("expected inst: {}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Inst> for ExpandedProgramPoint {
|
||||
fn from(inst: Inst) -> Self {
|
||||
ExpandedProgramPoint::Inst(inst)
|
||||
Self::Inst(inst)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ebb> for ExpandedProgramPoint {
|
||||
fn from(ebb: Ebb) -> Self {
|
||||
ExpandedProgramPoint::Ebb(ebb)
|
||||
Self::Ebb(ebb)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +85,9 @@ impl From<ValueDef> for ExpandedProgramPoint {
|
||||
impl From<ProgramPoint> for ExpandedProgramPoint {
|
||||
fn from(pp: ProgramPoint) -> Self {
|
||||
if pp.0 & 1 == 0 {
|
||||
ExpandedProgramPoint::Inst(Inst::from_u32(pp.0 / 2))
|
||||
Self::Inst(Inst::from_u32(pp.0 / 2))
|
||||
} else {
|
||||
ExpandedProgramPoint::Ebb(Ebb::from_u32(pp.0 / 2))
|
||||
Self::Ebb(Ebb::from_u32(pp.0 / 2))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,8 +95,8 @@ impl From<ProgramPoint> for ExpandedProgramPoint {
|
||||
impl fmt::Display for ExpandedProgramPoint {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ExpandedProgramPoint::Inst(x) => write!(f, "{}", x),
|
||||
ExpandedProgramPoint::Ebb(x) => write!(f, "{}", x),
|
||||
Self::Inst(x) => write!(f, "{}", x),
|
||||
Self::Ebb(x) => write!(f, "{}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ pub struct SourceLoc(u32);
|
||||
impl SourceLoc {
|
||||
/// Create a new source location with the given bits.
|
||||
pub fn new(bits: u32) -> Self {
|
||||
SourceLoc(bits)
|
||||
Self(bits)
|
||||
}
|
||||
|
||||
/// Is this the default source location?
|
||||
@@ -37,7 +37,7 @@ impl SourceLoc {
|
||||
|
||||
impl Default for SourceLoc {
|
||||
fn default() -> Self {
|
||||
SourceLoc(!0)
|
||||
Self(!0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ impl Type {
|
||||
/// Get a type with the same number of lanes as `self`, but using `lane` as the lane type.
|
||||
fn replace_lanes(self, lane: Self) -> Self {
|
||||
debug_assert!(lane.is_lane() && !self.is_special());
|
||||
Type((lane.0 & 0x0f) | (self.0 & 0xf0))
|
||||
Self((lane.0 & 0x0f) | (self.0 & 0xf0))
|
||||
}
|
||||
|
||||
/// Get a type with the same number of lanes as this type, but with the lanes replaced by
|
||||
@@ -262,7 +262,7 @@ impl Type {
|
||||
let log2_lanes: u32 = n.trailing_zeros();
|
||||
let new_type = u32::from(self.0) + (log2_lanes << 4);
|
||||
if new_type < 0x100 {
|
||||
Some(Type(new_type as u8))
|
||||
Some(Self(new_type as u8))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -273,7 +273,7 @@ impl Type {
|
||||
/// There is no `double_vector()` method. Use `t.by(2)` instead.
|
||||
pub fn half_vector(self) -> Option<Self> {
|
||||
if self.is_vector() {
|
||||
Some(Type(self.0 - 0x10))
|
||||
Some(Self(self.0 - 0x10))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ pub enum ValueLoc {
|
||||
|
||||
impl Default for ValueLoc {
|
||||
fn default() -> Self {
|
||||
ValueLoc::Unassigned
|
||||
Self::Unassigned
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ impl ValueLoc {
|
||||
/// Is this an assigned location? (That is, not `Unassigned`).
|
||||
pub fn is_assigned(self) -> bool {
|
||||
match self {
|
||||
ValueLoc::Unassigned => false,
|
||||
Self::Unassigned => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ impl ValueLoc {
|
||||
/// Get the register unit of this location, or panic.
|
||||
pub fn unwrap_reg(self) -> RegUnit {
|
||||
match self {
|
||||
ValueLoc::Reg(ru) => ru,
|
||||
Self::Reg(ru) => ru,
|
||||
_ => panic!("Expected register: {:?}", self),
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ impl ValueLoc {
|
||||
/// Get the stack slot of this location, or panic.
|
||||
pub fn unwrap_stack(self) -> StackSlot {
|
||||
match self {
|
||||
ValueLoc::Stack(ss) => ss,
|
||||
Self::Stack(ss) => ss,
|
||||
_ => panic!("Expected stack slot: {:?}", self),
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ pub enum ArgumentLoc {
|
||||
|
||||
impl Default for ArgumentLoc {
|
||||
fn default() -> Self {
|
||||
ArgumentLoc::Unassigned
|
||||
Self::Unassigned
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ impl ArgumentLoc {
|
||||
/// Is this an assigned location? (That is, not `Unassigned`).
|
||||
pub fn is_assigned(self) -> bool {
|
||||
match self {
|
||||
ArgumentLoc::Unassigned => false,
|
||||
Self::Unassigned => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ impl ArgumentLoc {
|
||||
/// Is this a register location?
|
||||
pub fn is_reg(self) -> bool {
|
||||
match self {
|
||||
ArgumentLoc::Reg(_) => true,
|
||||
Self::Reg(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ impl ArgumentLoc {
|
||||
/// Is this a stack location?
|
||||
pub fn is_stack(self) -> bool {
|
||||
match self {
|
||||
ArgumentLoc::Stack(_) => true,
|
||||
Self::Stack(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ impl CallConv {
|
||||
match triple.default_calling_convention() {
|
||||
// Default to System V for unknown targets because most everything
|
||||
// uses System V.
|
||||
Ok(CallingConvention::SystemV) | Err(()) => CallConv::SystemV,
|
||||
Ok(CallingConvention::WindowsFastcall) => CallConv::WindowsFastcall,
|
||||
Ok(CallingConvention::SystemV) | Err(()) => Self::SystemV,
|
||||
Ok(CallingConvention::WindowsFastcall) => Self::WindowsFastcall,
|
||||
Ok(unimp) => unimplemented!("calling convention: {:?}", unimp),
|
||||
}
|
||||
}
|
||||
@@ -39,28 +39,28 @@ impl CallConv {
|
||||
pub fn for_libcall(isa: &dyn TargetIsa) -> Self {
|
||||
match isa.flags().libcall_call_conv() {
|
||||
LibcallCallConv::IsaDefault => isa.default_call_conv(),
|
||||
LibcallCallConv::Fast => CallConv::Fast,
|
||||
LibcallCallConv::Cold => CallConv::Cold,
|
||||
LibcallCallConv::SystemV => CallConv::SystemV,
|
||||
LibcallCallConv::WindowsFastcall => CallConv::WindowsFastcall,
|
||||
LibcallCallConv::BaldrdashSystemV => CallConv::BaldrdashSystemV,
|
||||
LibcallCallConv::BaldrdashWindows => CallConv::BaldrdashWindows,
|
||||
LibcallCallConv::Probestack => CallConv::Probestack,
|
||||
LibcallCallConv::Fast => Self::Fast,
|
||||
LibcallCallConv::Cold => Self::Cold,
|
||||
LibcallCallConv::SystemV => Self::SystemV,
|
||||
LibcallCallConv::WindowsFastcall => Self::WindowsFastcall,
|
||||
LibcallCallConv::BaldrdashSystemV => Self::BaldrdashSystemV,
|
||||
LibcallCallConv::BaldrdashWindows => Self::BaldrdashWindows,
|
||||
LibcallCallConv::Probestack => Self::Probestack,
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the calling convention extending the Windows Fastcall ABI?
|
||||
pub fn extends_windows_fastcall(&self) -> bool {
|
||||
pub fn extends_windows_fastcall(self) -> bool {
|
||||
match self {
|
||||
CallConv::WindowsFastcall | CallConv::BaldrdashWindows => true,
|
||||
Self::WindowsFastcall | Self::BaldrdashWindows => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the calling convention extending the Baldrdash ABI?
|
||||
pub fn extends_baldrdash(&self) -> bool {
|
||||
pub fn extends_baldrdash(self) -> bool {
|
||||
match self {
|
||||
CallConv::BaldrdashSystemV | CallConv::BaldrdashWindows => true,
|
||||
Self::BaldrdashSystemV | Self::BaldrdashWindows => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -69,13 +69,13 @@ impl CallConv {
|
||||
impl fmt::Display for CallConv {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
CallConv::Fast => "fast",
|
||||
CallConv::Cold => "cold",
|
||||
CallConv::SystemV => "system_v",
|
||||
CallConv::WindowsFastcall => "windows_fastcall",
|
||||
CallConv::BaldrdashSystemV => "baldrdash_system_v",
|
||||
CallConv::BaldrdashWindows => "baldrdash_windows",
|
||||
CallConv::Probestack => "probestack",
|
||||
Self::Fast => "fast",
|
||||
Self::Cold => "cold",
|
||||
Self::SystemV => "system_v",
|
||||
Self::WindowsFastcall => "windows_fastcall",
|
||||
Self::BaldrdashSystemV => "baldrdash_system_v",
|
||||
Self::BaldrdashWindows => "baldrdash_windows",
|
||||
Self::Probestack => "probestack",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -84,13 +84,13 @@ impl str::FromStr for CallConv {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"fast" => Ok(CallConv::Fast),
|
||||
"cold" => Ok(CallConv::Cold),
|
||||
"system_v" => Ok(CallConv::SystemV),
|
||||
"windows_fastcall" => Ok(CallConv::WindowsFastcall),
|
||||
"baldrdash_system_v" => Ok(CallConv::BaldrdashSystemV),
|
||||
"baldrdash_windows" => Ok(CallConv::BaldrdashWindows),
|
||||
"probestack" => Ok(CallConv::Probestack),
|
||||
"fast" => Ok(Self::Fast),
|
||||
"cold" => Ok(Self::Cold),
|
||||
"system_v" => Ok(Self::SystemV),
|
||||
"windows_fastcall" => Ok(Self::WindowsFastcall),
|
||||
"baldrdash_system_v" => Ok(Self::BaldrdashSystemV),
|
||||
"baldrdash_windows" => Ok(Self::BaldrdashWindows),
|
||||
"probestack" => Ok(Self::Probestack),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ pub struct RegClassIndex(u8);
|
||||
|
||||
impl EntityRef for RegClassIndex {
|
||||
fn new(idx: usize) -> Self {
|
||||
RegClassIndex(idx as u8)
|
||||
Self(idx as u8)
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
@@ -247,7 +247,7 @@ impl EntityRef for RegClassIndex {
|
||||
|
||||
impl From<RegClass> for RegClassIndex {
|
||||
fn from(rc: RegClass) -> Self {
|
||||
RegClassIndex(rc.index)
|
||||
Self(rc.index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -389,14 +389,17 @@ fn expand_br_table_conds(
|
||||
let mut pos = FuncCursor::new(func).at_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
|
||||
// Ignore the lint for this loop as the range needs to be 0 to table_size
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 0..table_size {
|
||||
let dest = pos.func.jump_tables[table].as_slice()[i];
|
||||
let t = pos.ins().icmp_imm(IntCC::Equal, arg, i as i64);
|
||||
pos.ins().brnz(t, dest, &[]);
|
||||
// Jump to the next case.
|
||||
if i < table_size - 1 {
|
||||
pos.ins().jump(cond_failed_ebb[i], &[]);
|
||||
pos.insert_ebb(cond_failed_ebb[i]);
|
||||
let ebb = cond_failed_ebb[i];
|
||||
pos.ins().jump(ebb, &[]);
|
||||
pos.insert_ebb(ebb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +702,7 @@ fn narrow_icmp_imm(
|
||||
|
||||
let imm_low = pos
|
||||
.ins()
|
||||
.iconst(ty_half, imm & (1u128 << ty_half.bits() - 1) as i64);
|
||||
.iconst(ty_half, imm & (1u128 << (ty_half.bits() - 1)) as i64);
|
||||
let imm_high = pos
|
||||
.ins()
|
||||
.iconst(ty_half, imm.wrapping_shr(ty_half.bits().into()));
|
||||
|
||||
@@ -18,13 +18,12 @@
|
||||
clippy::assign_op_pattern,
|
||||
clippy::empty_line_after_outer_attr,
|
||||
// Hard to avoid in generated code:
|
||||
clippy::cyclomatic_complexity,
|
||||
clippy::cognitive_complexity,
|
||||
clippy::too_many_arguments,
|
||||
// Code generator doesn't have a way to collapse identical arms:
|
||||
clippy::match_same_arms,
|
||||
// These are relatively minor style issues, but would be easy to fix:
|
||||
clippy::new_without_default,
|
||||
clippy::new_without_default_derive,
|
||||
clippy::should_implement_trait,
|
||||
clippy::len_without_is_empty))]
|
||||
#![cfg_attr(
|
||||
@@ -35,7 +34,6 @@
|
||||
clippy::nonminimal_bool,
|
||||
clippy::option_map_unwrap_or,
|
||||
clippy::option_map_unwrap_or_else,
|
||||
clippy::print_allocout,
|
||||
clippy::unicode_not_nfc,
|
||||
clippy::use_self
|
||||
)
|
||||
|
||||
@@ -71,7 +71,7 @@ fn create_pre_header(
|
||||
domtree: &DominatorTree,
|
||||
) -> Ebb {
|
||||
let pool = &mut ListPool::<Value>::new();
|
||||
let header_args_values: Vec<Value> = func.dfg.ebb_params(header).into_iter().cloned().collect();
|
||||
let header_args_values = func.dfg.ebb_params(header).to_vec();
|
||||
let header_args_types: Vec<Type> = header_args_values
|
||||
.clone()
|
||||
.into_iter()
|
||||
|
||||
@@ -348,7 +348,7 @@ impl RedundantReloadRemover {
|
||||
impl AvailEnv {
|
||||
// Create a new one.
|
||||
fn new(size: usize) -> Self {
|
||||
let mut env = AvailEnv {
|
||||
let mut env = Self {
|
||||
map: Vec::<Option<SlotInfo>>::new(),
|
||||
};
|
||||
env.map.resize(size, None);
|
||||
@@ -494,9 +494,9 @@ impl RedundantReloadRemover {
|
||||
debug_assert!(!self.processing_stack.is_empty());
|
||||
let ProcessingStackElem {
|
||||
avail_env,
|
||||
cursor: _,
|
||||
diversions,
|
||||
} = &mut self.processing_stack.last_mut().unwrap();
|
||||
..
|
||||
} = self.processing_stack.last_mut().unwrap();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
debug_assert!(
|
||||
@@ -588,12 +588,7 @@ impl RedundantReloadRemover {
|
||||
invalidate_regs_written_by_inst(locations, diversions, dfg, avail_env, inst);
|
||||
}
|
||||
}
|
||||
InstructionData::RegMove {
|
||||
opcode: _,
|
||||
arg: _,
|
||||
src,
|
||||
dst,
|
||||
} => {
|
||||
InstructionData::RegMove { src, dst, .. } => {
|
||||
// These happen relatively rarely, but just frequently enough that it's worth
|
||||
// tracking the copy (at the machine level, it's really a copy) in `avail_env`.
|
||||
avail_env.copy_reg(*src, *dst);
|
||||
@@ -817,9 +812,9 @@ impl RedundantReloadRemover {
|
||||
for i in 0..num_ebbs {
|
||||
let mut pi = cfg.pred_iter(Ebb::from_u32(i));
|
||||
let mut n_pi = ZeroOneOrMany::Zero;
|
||||
if let Some(_) = pi.next() {
|
||||
if pi.next().is_some() {
|
||||
n_pi = ZeroOneOrMany::One;
|
||||
if let Some(_) = pi.next() {
|
||||
if pi.next().is_some() {
|
||||
n_pi = ZeroOneOrMany::Many;
|
||||
// We don't care if there are more than two preds, so stop counting now.
|
||||
}
|
||||
@@ -886,7 +881,7 @@ impl RedundantReloadRemover {
|
||||
let ctx = Context {
|
||||
cur: EncCursor::new(func, isa),
|
||||
reginfo: isa.register_info(),
|
||||
cfg: cfg,
|
||||
cfg,
|
||||
state: self,
|
||||
};
|
||||
let mut total_regunits = 0;
|
||||
|
||||
@@ -30,7 +30,7 @@ pub enum Affinity {
|
||||
|
||||
impl Default for Affinity {
|
||||
fn default() -> Self {
|
||||
Affinity::Unassigned
|
||||
Self::Unassigned
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,25 +41,25 @@ impl Affinity {
|
||||
/// Use the `Default` implementation for that.
|
||||
pub fn new(constraint: &OperandConstraint) -> Self {
|
||||
if constraint.kind == ConstraintKind::Stack {
|
||||
Affinity::Stack
|
||||
Self::Stack
|
||||
} else {
|
||||
Affinity::Reg(constraint.regclass.into())
|
||||
Self::Reg(constraint.regclass.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an affinity that matches an ABI argument for `isa`.
|
||||
pub fn abi(arg: &AbiParam, isa: &dyn TargetIsa) -> Self {
|
||||
match arg.location {
|
||||
ArgumentLoc::Unassigned => Affinity::Unassigned,
|
||||
ArgumentLoc::Reg(_) => Affinity::Reg(isa.regclass_for_abi_type(arg.value_type).into()),
|
||||
ArgumentLoc::Stack(_) => Affinity::Stack,
|
||||
ArgumentLoc::Unassigned => Self::Unassigned,
|
||||
ArgumentLoc::Reg(_) => Self::Reg(isa.regclass_for_abi_type(arg.value_type).into()),
|
||||
ArgumentLoc::Stack(_) => Self::Stack,
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this the `Unassigned` affinity?
|
||||
pub fn is_unassigned(self) -> bool {
|
||||
match self {
|
||||
Affinity::Unassigned => true,
|
||||
Self::Unassigned => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ impl Affinity {
|
||||
/// Is this the `Reg` affinity?
|
||||
pub fn is_reg(self) -> bool {
|
||||
match self {
|
||||
Affinity::Reg(_) => true,
|
||||
Self::Reg(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@ impl Affinity {
|
||||
/// Is this the `Stack` affinity?
|
||||
pub fn is_stack(self) -> bool {
|
||||
match self {
|
||||
Affinity::Stack => true,
|
||||
Self::Stack => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -86,8 +86,8 @@ impl Affinity {
|
||||
/// satisfies the constraint.
|
||||
pub fn merge(&mut self, constraint: &OperandConstraint, reginfo: &RegInfo) {
|
||||
match *self {
|
||||
Affinity::Unassigned => *self = Self::new(constraint),
|
||||
Affinity::Reg(rc) => {
|
||||
Self::Unassigned => *self = Self::new(constraint),
|
||||
Self::Reg(rc) => {
|
||||
// If the preferred register class is a subclass of the constraint, there's no need
|
||||
// to change anything.
|
||||
if constraint.kind != ConstraintKind::Stack && !constraint.regclass.has_subclass(rc)
|
||||
@@ -96,11 +96,11 @@ impl Affinity {
|
||||
// we just keep our previous affinity.
|
||||
if let Some(subclass) = constraint.regclass.intersect_index(reginfo.rc(rc)) {
|
||||
// This constraint shrinks our preferred register class.
|
||||
*self = Affinity::Reg(subclass);
|
||||
*self = Self::Reg(subclass);
|
||||
}
|
||||
}
|
||||
}
|
||||
Affinity::Stack => {}
|
||||
Self::Stack => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ impl<'a> Context<'a> {
|
||||
let dfg = &mut self.cur.func.dfg;
|
||||
let old_args: Vec<_> = {
|
||||
let args = dfg[branch].take_value_list().expect("ebb parameters");
|
||||
args.as_slice(&dfg.value_lists).iter().map(|x| *x).collect()
|
||||
args.as_slice(&dfg.value_lists).iter().copied().collect()
|
||||
};
|
||||
let (branch_args, ebb_params) = old_args.split_at(num_fixed);
|
||||
|
||||
@@ -159,16 +159,13 @@ impl<'a> Context<'a> {
|
||||
/// Returns whether we should introduce a new branch.
|
||||
fn should_split_edge(&self, target: Ebb) -> bool {
|
||||
// We should split the edge if the target has any parameters.
|
||||
if self.cur.func.dfg.ebb_params(target).len() > 0 {
|
||||
if !self.cur.func.dfg.ebb_params(target).is_empty() {
|
||||
return true;
|
||||
};
|
||||
|
||||
// Or, if the target has more than one block reaching it.
|
||||
debug_assert!(self.cfg.pred_iter(target).next() != None);
|
||||
if let Some(_) = self.cfg.pred_iter(target).skip(1).next() {
|
||||
return true;
|
||||
};
|
||||
|
||||
false
|
||||
self.cfg.pred_iter(target).nth(1).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +551,7 @@ impl<'a> Context<'a> {
|
||||
let is_reload = match &self.cur.func.dfg[inst] {
|
||||
InstructionData::Unary {
|
||||
opcode: Opcode::Fill,
|
||||
arg: _,
|
||||
..
|
||||
} => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
@@ -200,7 +200,7 @@ impl RegDiversions {
|
||||
}
|
||||
debug_assert!(!entry_diversions.map.contains_key(target));
|
||||
let iter = self.current.iter();
|
||||
let mut entry_divert = RegDiversions::new();
|
||||
let mut entry_divert = Self::new();
|
||||
entry_divert.current.extend(iter);
|
||||
entry_diversions.map.insert(EntryRegDiversionsValue {
|
||||
key: target,
|
||||
@@ -225,7 +225,7 @@ impl RegDiversions {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
/// Return an object that can display the diversions.
|
||||
@@ -237,7 +237,7 @@ impl RegDiversions {
|
||||
impl EntryRegDiversions {
|
||||
/// Create a new empty entry diversion, to associate diversions to each EBB entry.
|
||||
pub fn new() -> Self {
|
||||
EntryRegDiversions {
|
||||
Self {
|
||||
map: SparseMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,9 +259,9 @@ impl UFEntry {
|
||||
/// Decode a table entry.
|
||||
fn decode(x: i32) -> Self {
|
||||
if x < 0 {
|
||||
UFEntry::Link(Value::from_u32((!x) as u32))
|
||||
Self::Link(Value::from_u32((!x) as u32))
|
||||
} else {
|
||||
UFEntry::Rank(x as u32)
|
||||
Self::Rank(x as u32)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,6 @@ pub type CodegenResult<T> = Result<T, CodegenError>;
|
||||
|
||||
impl From<VerifierErrors> for CodegenError {
|
||||
fn from(e: VerifierErrors) -> Self {
|
||||
CodegenError::Verifier(e)
|
||||
Self::Verifier(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ pub mod detail {
|
||||
/// offset field has a different meaning when the detail is a preset.
|
||||
pub fn is_preset(self) -> bool {
|
||||
match self {
|
||||
Detail::Preset => true,
|
||||
Self::Preset => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,15 +597,14 @@ fn simplify(pos: &mut FuncCursor, inst: Inst, native_word_width: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
InstructionData::Unary { opcode, arg } => match opcode {
|
||||
Opcode::AdjustSpDown => {
|
||||
InstructionData::Unary { opcode, arg } => {
|
||||
if let Opcode::AdjustSpDown = opcode {
|
||||
if let Some(imm) = resolve_imm64_value(&pos.func.dfg, arg) {
|
||||
// Note this works for both positive and negative immediate values.
|
||||
pos.func.dfg.replace(inst).adjust_sp_down_imm(imm);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
|
||||
InstructionData::BinaryImm { opcode, arg, imm } => {
|
||||
let ty = pos.func.dfg.ctrl_typevar(inst);
|
||||
@@ -626,27 +625,25 @@ fn simplify(pos: &mut FuncCursor, inst: Inst, native_word_width: u32) {
|
||||
imm: prev_imm,
|
||||
} = &pos.func.dfg[arg_inst]
|
||||
{
|
||||
if opcode == *prev_opcode {
|
||||
if ty == pos.func.dfg.ctrl_typevar(arg_inst) {
|
||||
let lhs: i64 = imm.into();
|
||||
let rhs: i64 = (*prev_imm).into();
|
||||
let new_imm = match opcode {
|
||||
Opcode::BorImm => lhs | rhs,
|
||||
Opcode::BandImm => lhs & rhs,
|
||||
Opcode::BxorImm => lhs ^ rhs,
|
||||
Opcode::IaddImm => lhs.wrapping_add(rhs),
|
||||
Opcode::ImulImm => lhs.wrapping_mul(rhs),
|
||||
_ => panic!("can't happen"),
|
||||
};
|
||||
let new_imm = immediates::Imm64::from(new_imm);
|
||||
let new_arg = *prev_arg;
|
||||
pos.func
|
||||
.dfg
|
||||
.replace(inst)
|
||||
.BinaryImm(opcode, ty, new_imm, new_arg);
|
||||
imm = new_imm;
|
||||
arg = new_arg;
|
||||
}
|
||||
if opcode == *prev_opcode && ty == pos.func.dfg.ctrl_typevar(arg_inst) {
|
||||
let lhs: i64 = imm.into();
|
||||
let rhs: i64 = (*prev_imm).into();
|
||||
let new_imm = match opcode {
|
||||
Opcode::BorImm => lhs | rhs,
|
||||
Opcode::BandImm => lhs & rhs,
|
||||
Opcode::BxorImm => lhs ^ rhs,
|
||||
Opcode::IaddImm => lhs.wrapping_add(rhs),
|
||||
Opcode::ImulImm => lhs.wrapping_mul(rhs),
|
||||
_ => panic!("can't happen"),
|
||||
};
|
||||
let new_imm = immediates::Imm64::from(new_imm);
|
||||
let new_arg = *prev_arg;
|
||||
pos.func
|
||||
.dfg
|
||||
.replace(inst)
|
||||
.BinaryImm(opcode, ty, new_imm, new_arg);
|
||||
imm = new_imm;
|
||||
arg = new_arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -679,17 +676,14 @@ fn simplify(pos: &mut FuncCursor, inst: Inst, native_word_width: u32) {
|
||||
| (Opcode::SshrImm, 0) => {
|
||||
// Alias the result value with the original argument.
|
||||
replace_single_result_with_alias(&mut pos.func.dfg, inst, arg);
|
||||
return;
|
||||
}
|
||||
(Opcode::ImulImm, 0) | (Opcode::BandImm, 0) => {
|
||||
// Replace by zero.
|
||||
pos.func.dfg.replace(inst).iconst(ty, 0);
|
||||
return;
|
||||
}
|
||||
(Opcode::BorImm, -1) => {
|
||||
// Replace by minus one.
|
||||
pos.func.dfg.replace(inst).iconst(ty, -1);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -789,9 +783,9 @@ fn branch_opt(pos: &mut FuncCursor, inst: Inst) {
|
||||
|
||||
BranchOptInfo {
|
||||
br_inst: inst,
|
||||
cmp_arg: cmp_arg,
|
||||
cmp_arg,
|
||||
args: br_args.clone(),
|
||||
new_opcode: new_opcode,
|
||||
new_opcode,
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
|
||||
@@ -141,7 +141,7 @@ mod details {
|
||||
|
||||
impl Default for PassTimes {
|
||||
fn default() -> Self {
|
||||
PassTimes {
|
||||
Self {
|
||||
pass: [Default::default(); NUM_PASSES],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,14 +104,14 @@ where
|
||||
if range.0 >= range.1 || !loc.is_assigned() {
|
||||
return;
|
||||
}
|
||||
if !ranges.contains_key(&label) {
|
||||
ranges.insert(label, Vec::new());
|
||||
}
|
||||
ranges.get_mut(&label).unwrap().push(ValueLocRange {
|
||||
loc,
|
||||
start: range.0,
|
||||
end: range.1,
|
||||
});
|
||||
ranges
|
||||
.entry(label)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(ValueLocRange {
|
||||
loc,
|
||||
start: range.0,
|
||||
end: range.1,
|
||||
});
|
||||
};
|
||||
|
||||
let mut end_offset = 0;
|
||||
@@ -130,7 +130,7 @@ where
|
||||
add_range(*label, (*start_offset, end_offset), *last_loc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
true
|
||||
});
|
||||
|
||||
let srcloc = func.srclocs[inst];
|
||||
@@ -152,7 +152,7 @@ where
|
||||
}
|
||||
|
||||
// New source locations range started: abandon all tracked values.
|
||||
if last_srcloc.is_some() && last_srcloc.as_ref().unwrap() > &srcloc {
|
||||
if last_srcloc.is_some() && last_srcloc.unwrap() > srcloc {
|
||||
for (_, label, start_offset, last_loc) in &tracked_values {
|
||||
add_range(*label, (*start_offset, end_offset), *last_loc);
|
||||
}
|
||||
@@ -193,7 +193,7 @@ where
|
||||
|
||||
// Optimize ranges in-place
|
||||
for (_, label_ranges) in ranges.iter_mut() {
|
||||
assert!(label_ranges.len() > 0);
|
||||
assert!(!label_ranges.is_empty());
|
||||
label_ranges.sort_by(|a, b| a.start.cmp(&b.start).then_with(|| a.end.cmp(&b.end)));
|
||||
|
||||
// Merge ranges
|
||||
@@ -245,7 +245,7 @@ pub struct ComparableSourceLoc(SourceLoc);
|
||||
|
||||
impl From<SourceLoc> for ComparableSourceLoc {
|
||||
fn from(s: SourceLoc) -> Self {
|
||||
ComparableSourceLoc(s)
|
||||
Self(s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ impl VerifierErrors {
|
||||
/// Return a new `VerifierErrors` struct.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
VerifierErrors(Vec::new())
|
||||
Self(Vec::new())
|
||||
}
|
||||
|
||||
/// Return whether no errors were reported.
|
||||
@@ -196,7 +196,7 @@ impl VerifierErrors {
|
||||
|
||||
impl From<Vec<VerifierError>> for VerifierErrors {
|
||||
fn from(v: Vec<VerifierError>) -> Self {
|
||||
VerifierErrors(v)
|
||||
Self(v)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,9 +268,9 @@ pub fn write_ebb_header(
|
||||
writeln!(w, "):")
|
||||
}
|
||||
|
||||
fn write_valueloc(w: &mut dyn Write, loc: &ValueLoc, regs: &RegInfo) -> fmt::Result {
|
||||
fn write_valueloc(w: &mut dyn Write, loc: ValueLoc, regs: &RegInfo) -> fmt::Result {
|
||||
match loc {
|
||||
ValueLoc::Reg(r) => write!(w, "{}", regs.display_regunit(*r)),
|
||||
ValueLoc::Reg(r) => write!(w, "{}", regs.display_regunit(r)),
|
||||
ValueLoc::Stack(ss) => write!(w, "{}", ss),
|
||||
ValueLoc::Unassigned => write!(w, "?"),
|
||||
}
|
||||
@@ -289,7 +289,7 @@ fn write_value_range_markers(
|
||||
for i in (0..rng.len()).rev() {
|
||||
if rng[i].start == offset {
|
||||
write!(&mut result, " {}@", val)?;
|
||||
write_valueloc(&mut result, &rng[i].loc, regs)?;
|
||||
write_valueloc(&mut result, rng[i].loc, regs)?;
|
||||
shown.insert(val);
|
||||
break;
|
||||
}
|
||||
@@ -303,7 +303,7 @@ fn write_value_range_markers(
|
||||
}
|
||||
}
|
||||
}
|
||||
if result.len() > 0 {
|
||||
if !result.is_empty() {
|
||||
writeln!(w, ";{1:0$}; {2}", indent + 24, "", result)?;
|
||||
}
|
||||
Ok(())
|
||||
@@ -330,21 +330,24 @@ fn decorate_ebb<FW: FuncWriter>(
|
||||
write_value_aliases(w, aliases, a, indent)?;
|
||||
}
|
||||
|
||||
if isa.is_some() && !func.offsets.is_empty() {
|
||||
let encinfo = isa.unwrap().encoding_info();
|
||||
let regs = &isa.unwrap().register_info();
|
||||
for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) {
|
||||
func_w.write_instruction(w, func, aliases, isa, inst, indent)?;
|
||||
if size > 0 {
|
||||
if let Some(val_ranges) = annotations.value_ranges {
|
||||
write_value_range_markers(w, val_ranges, regs, offset + size, indent)?;
|
||||
if let Some(isa) = isa {
|
||||
if !func.offsets.is_empty() {
|
||||
let encinfo = isa.encoding_info();
|
||||
let regs = &isa.register_info();
|
||||
for (offset, inst, size) in func.inst_offsets(ebb, &encinfo) {
|
||||
func_w.write_instruction(w, func, aliases, Some(isa), inst, indent)?;
|
||||
if size > 0 {
|
||||
if let Some(val_ranges) = annotations.value_ranges {
|
||||
write_value_range_markers(w, val_ranges, regs, offset + size, indent)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
for inst in func.layout.ebb_insts(ebb) {
|
||||
func_w.write_instruction(w, func, aliases, isa, inst, indent)?;
|
||||
}
|
||||
}
|
||||
|
||||
for inst in func.layout.ebb_insts(ebb) {
|
||||
func_w.write_instruction(w, func, aliases, isa, inst, indent)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user